feat(unittests): add a unit test framework.
This patch adds all the infrastructure needed to run unit tests for
RMM, including a new variant for platform host, called `host_test`.
To build and run the tests:
cmake -DRMM_CONFIG=host_defcfg -DHOST_VARIANT=host_test \
-DCMAKE_BUILD_TYPE=Debug -S ${RMM_SOURCE_DIR} -B ${RMM_BUILD_DIR}
cmake --build ${RMM_BUILD_DIR} -- run-unittests
Signed-off-by: Javier Almansa Sobrino <javier.almansasobrino@arm.com>
Signed-off-by: Soby Mathew <soby.mathew@arm.com>
Change-Id: If16686e111d91c563f8e7281d4ee7ca2864125ae
diff --git a/plat/host/host_test/src/host_harness.c b/plat/host/host_test/src/host_harness.c
new file mode 100644
index 0000000..4357c29
--- /dev/null
+++ b/plat/host/host_test/src/host_harness.c
@@ -0,0 +1,23 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+ */
+
+#include <host_harness.h>
+#include <test_harness.h>
+
+/*
+ * Maps addr to the requested slot buffer and returns a pointer to the
+ * fake VA for the slot (the current addr), so the host can perform R/W
+ * operations on the mapped granule.
+ */
+void *host_buffer_arch_map(enum buffer_slot slot,
+ unsigned long addr, bool ns)
+{
+ return test_buffer_map(slot, addr, ns);
+}
+
+void host_buffer_arch_unmap(void *buf)
+{
+ test_buffer_unmap(buf);
+}
diff --git a/plat/host/host_test/src/test_groups.h.in b/plat/host/host_test/src/test_groups.h.in
new file mode 100644
index 0000000..b3a548c
--- /dev/null
+++ b/plat/host/host_test/src/test_groups.h.in
@@ -0,0 +1,15 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+ */
+
+#ifndef TEST_GROUPS_H
+#define TEST_GROUPS_H
+
+/*
+ * Add an IMPORT_TEST_GROUP for each test group, so the linker can
+ * find the tests.
+ */
+@IMPORT_TEST_GROUPS@
+
+#endif
diff --git a/plat/host/host_test/src/test_helpers.c b/plat/host/host_test/src/test_helpers.c
new file mode 100644
index 0000000..bef4759
--- /dev/null
+++ b/plat/host/host_test/src/test_helpers.c
@@ -0,0 +1,146 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+ */
+
+#include <gic.h>
+#include <host_defs.h>
+#include <host_utils.h>
+#include <platform_api.h>
+#include <rmm_el3_ifc.h>
+#include <xlat_tables.h>
+
+/* Implemented in init.c and needed here */
+void rmm_warmboot_main(void);
+void rmm_main(void);
+
+/*
+ * Define and set the Boot Interface arguments.
+ */
+#define RMM_EL3_IFC_ABI_VERSION (RMM_EL3_IFC_SUPPORTED_VERSION)
+#define RMM_EL3_MAX_CPUS (MAX_CPUS)
+
+static unsigned char el3_rmm_shared_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
+
+/*
+ * Create a basic boot manifest.
+ */
+static struct rmm_core_manifest *boot_manifest =
+ (struct rmm_core_manifest *)el3_rmm_shared_buffer;
+
+/*
+ * Performs some initialization needed before RMM can be run, such as
+ * setting up callbacks for sysreg access.
+ */
+static void setup_sysreg_and_boot_manifest(void)
+{
+ /*
+ * Initialize ID_AA64MMFR0_EL1 with a physical address
+ * range of 18 bits
+ */
+ (void)host_util_set_default_sysreg_cb("id_aa64mmfr0_el1",
+ INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5UL));
+
+ /*
+ * Initialize ICH_VTR_EL2 with 6 preemption bits.
+ * (PREbits is equal number of preemption bits minus one)
+ */
+ (void)host_util_set_default_sysreg_cb("ich_vtr_el2",
+ INPLACE(ICH_VTR_EL2_PRE_BITS, 5UL));
+
+ /* Used to hold CPU Id. Reset to CPUid 0. */
+ (void)host_util_set_default_sysreg_cb("tpidr_el2", 0UL);
+
+ (void)host_util_set_default_sysreg_cb("sctlr_el2", 0UL);
+
+ /* Initialize the boot manifest */
+ boot_manifest->version = RMM_EL3_IFC_SUPPORTED_VERSION;
+ boot_manifest->plat_data = (uintptr_t)NULL;
+}
+
+/*
+ * Function to emulate the turn on of the MMU for the fake_host architecture.
+ */
+static void enable_fake_mmu(void)
+{
+ write_sctlr_el2(SCTLR_EL2_WXN | SCTLR_EL2_M);
+}
+
+static void start_primary_pe(void)
+{
+ host_util_set_cpuid(0U);
+
+ /* Early setup the CpuId into tpidr_el2 */
+ write_tpidr_el2(0U);
+
+ plat_setup(0UL,
+ RMM_EL3_IFC_ABI_VERSION,
+ RMM_EL3_MAX_CPUS,
+ (uintptr_t)&el3_rmm_shared_buffer);
+
+ /*
+ * Enable the MMU. This is needed as some initialization code
+ * called by rmm_main() asserts that the mmu is enabled.
+ */
+ enable_fake_mmu();
+
+ /*
+ * rmm_main() finishhes the warmboot path.
+ *
+ * Note: It is expected that the attestation init will fail.
+ */
+ rmm_main();
+}
+
+static void start_secondary_pe(unsigned int cpuid)
+{
+ host_util_set_cpuid(cpuid);
+
+ /*
+ * Early setup the CpuId into tpidr_el2 for each secondary.
+ */
+ write_tpidr_el2(cpuid);
+
+ plat_warmboot_setup(0UL,
+ RMM_EL3_IFC_ABI_VERSION,
+ RMM_EL3_MAX_CPUS,
+ (uintptr_t)&el3_rmm_shared_buffer);
+
+ /*
+ * Enable the MMU. This is needed to avoid assertions during boot up
+ * that would otherwise occur if the MMU is disabled.
+ */
+ enable_fake_mmu();
+
+ /*
+ * Finalize the warmboot path.
+ * This enables the slot buffer mechanism.
+ */
+ rmm_warmboot_main();
+}
+
+void test_helper_rmm_start(bool secondaries)
+{
+ static bool initialized;
+
+ if (initialized == false) {
+ /* Enable RMM and setup basic structures for each test. */
+ setup_sysreg_and_boot_manifest();
+
+ /* bringup primary CPU */
+ start_primary_pe();
+
+ if (secondaries) {
+ for (unsigned int i = 1U; i < RMM_EL3_MAX_CPUS; i++) {
+ start_secondary_pe(i);
+ }
+ host_util_set_cpuid(0U);
+ }
+ initialized = true;
+ }
+}
+
+unsigned int test_helper_get_nr_granules(void)
+{
+ return HOST_NR_GRANULES;
+}
diff --git a/plat/host/host_test/src/test_main.cpp b/plat/host/host_test/src/test_main.cpp
new file mode 100644
index 0000000..a1c57e8
--- /dev/null
+++ b/plat/host/host_test/src/test_main.cpp
@@ -0,0 +1,13 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+ */
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <test_groups.h>
+
+int main (int argc, char** argv)
+{
+ return CommandLineTestRunner::RunAllTests(argc, argv);
+}