Read CPU IDs from FDT in tests, so they work under FVP.
Bug: 117551008
Change-Id: I14e24e86631f9e7c16ad69decf676b343ac9f252
diff --git a/build/toolchain/embedded.gni b/build/toolchain/embedded.gni
index e74fb6f..462bbfa 100644
--- a/build/toolchain/embedded.gni
+++ b/build/toolchain/embedded.gni
@@ -362,13 +362,13 @@
"gic_version",
"gicd_base_address",
"gicr_base_address",
+ "max_cpus",
"toolchain_args",
])
cpu = "${invoker.cpu}+fp"
# Nonsense values because they are required but shouldn't be used.
heap_pages = 0
- max_cpus = 1
max_vms = 1
}
}
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 5ca57ab..045d1f3 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -50,7 +50,6 @@
"abort.c",
"api.c",
"cpu.c",
- "fdt_handler.c",
"mm.c",
"mpool.c",
"panic.c",
@@ -59,6 +58,7 @@
deps = [
":fdt",
+ ":fdt_handler",
":memiter",
":std",
"//src/arch/${plat_arch}/hypervisor",
@@ -93,6 +93,19 @@
]
}
+source_set("fdt_handler") {
+ sources = [
+ "fdt_handler.c",
+ ]
+ deps = [
+ ":fdt",
+ ]
+
+ if (is_debug) {
+ deps += [ ":dlog" ]
+ }
+}
+
# Flattened Device Tree (FDT) utilities.
source_set("fdt") {
sources = [
diff --git a/test/hftest/BUILD.gn b/test/hftest/BUILD.gn
index a18a252..3900c36 100644
--- a/test/hftest/BUILD.gn
+++ b/test/hftest/BUILD.gn
@@ -110,6 +110,7 @@
"hftest_common.c",
]
deps = [
+ "//src:fdt_handler",
"//src:memiter",
"//src:panic",
"//src:std",
diff --git a/test/hftest/hftest_common.c b/test/hftest/hftest_common.c
index 4a3f0df..8c8d334 100644
--- a/test/hftest/hftest_common.c
+++ b/test/hftest/hftest_common.c
@@ -18,6 +18,8 @@
#include "hf/arch/vm/power_mgmt.h"
+#include "hf/boot_params.h"
+#include "hf/fdt_handler.h"
#include "hf/memiter.h"
#include "hf/std.h"
@@ -131,12 +133,13 @@
}
static void run_test(hftest_test_fn set_up, hftest_test_fn test,
- hftest_test_fn tear_down)
+ hftest_test_fn tear_down, const struct fdt_header *fdt)
{
/* Prepare the context. */
struct hftest_context *ctx = hftest_get_context();
memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
ctx->abort = abort;
+ ctx->fdt = fdt;
/* Run any set up functions. */
if (set_up) {
@@ -166,7 +169,8 @@
/**
* Runs the given test case.
*/
-void hftest_run(struct memiter suite_name, struct memiter test_name)
+void hftest_run(struct memiter suite_name, struct memiter test_name,
+ const struct fdt_header *fdt)
{
size_t i;
bool found_suite = false;
@@ -209,7 +213,7 @@
case HFTEST_KIND_TEST:
if (memiter_iseq(&test_name, test->name)) {
run_test(suite_set_up, test->fn,
- suite_tear_down);
+ suite_tear_down, fdt);
return;
}
break;
@@ -244,3 +248,38 @@
HFTEST_LOG("");
HFTEST_LOG(" Run the named test from the named test suite.");
}
+
+static uintptr_t vcpu_index_to_id(size_t index)
+{
+ /* For now we use indices as IDs for vCPUs. */
+ return index;
+}
+
+/**
+ * Get the ID of the CPU with the given index.
+ */
+uintptr_t hftest_get_cpu_id(size_t index)
+{
+ struct boot_params params;
+ struct fdt_node n;
+ const struct fdt_header *fdt = hftest_get_context()->fdt;
+
+ if (fdt == NULL) {
+ /*
+ * We must be in a service VM, so apply the mapping that Hafnium
+ * uses for vCPU IDs.
+ */
+ return vcpu_index_to_id(index);
+ }
+
+ /* Find physical CPU ID from FDT. */
+ if (!fdt_root_node(&n, fdt)) {
+ FAIL("FDT failed validation.");
+ }
+ if (!fdt_find_child(&n, "")) {
+ FAIL("Unable to find FDT root node.");
+ }
+ fdt_find_cpus(&n, params.cpu_ids, ¶ms.cpu_count);
+
+ return params.cpu_ids[index];
+}
diff --git a/test/hftest/inc/hftest.h b/test/hftest/inc/hftest.h
index d22cadf..bcffe5c 100644
--- a/test/hftest/inc/hftest.h
+++ b/test/hftest/inc/hftest.h
@@ -90,5 +90,7 @@
*/
#define HFTEST_LOG_INDENT " "
+uintptr_t hftest_get_cpu_id(size_t index);
+
/* Above this point is the public API. Now include the implementation. */
#include <hftest_impl.h>
diff --git a/test/hftest/inc/hftest_common.h b/test/hftest/inc/hftest_common.h
index fa35aab..d141076 100644
--- a/test/hftest/inc/hftest_common.h
+++ b/test/hftest/inc/hftest_common.h
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "hf/fdt.h"
#include "hf/memiter.h"
#include "hftest_impl.h"
@@ -22,5 +23,6 @@
void hftest_use_list(struct hftest_test list[], size_t count);
void hftest_json(void);
-void hftest_run(struct memiter suite_name, struct memiter test_name);
+void hftest_run(struct memiter suite_name, struct memiter test_name,
+ const struct fdt_header *fdt);
void hftest_help(void);
diff --git a/test/hftest/inc/hftest_impl.h b/test/hftest/inc/hftest_impl.h
index 13b49f1..64eeac4 100644
--- a/test/hftest/inc/hftest_impl.h
+++ b/test/hftest/inc/hftest_impl.h
@@ -18,6 +18,7 @@
#include <stdnoreturn.h>
+#include "hf/fdt.h"
#include "hf/spci.h"
#include "hf/std.h"
@@ -133,6 +134,9 @@
uint32_t failures;
noreturn void (*abort)(void);
+ /* These are used in primary VMs. */
+ const struct fdt_header *fdt;
+
/* These are used in services. */
struct spci_message *send;
struct spci_message *recv;
diff --git a/test/hftest/linux_main.c b/test/hftest/linux_main.c
index 3cb58d1..6ff258b 100644
--- a/test/hftest/linux_main.c
+++ b/test/hftest/linux_main.c
@@ -15,6 +15,7 @@
*/
#include <stdalign.h>
+#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -54,7 +55,7 @@
memiter_init(&suite_name, argv[2], strnlen_s(argv[2], 64));
memiter_init(&test_name, argv[3], strnlen_s(argv[3], 64));
- hftest_run(suite_name, test_name);
+ hftest_run(suite_name, test_name, NULL);
return;
}
diff --git a/test/hftest/standalone_main.c b/test/hftest/standalone_main.c
index b4938e6..c1bfa1a 100644
--- a/test/hftest/standalone_main.c
+++ b/test/hftest/standalone_main.c
@@ -84,7 +84,7 @@
HFTEST_LOG("Unable to parse test.");
return;
}
- hftest_run(suite_name, test_name);
+ hftest_run(suite_name, test_name, fdt);
return;
}
diff --git a/test/vmapi/primary_only/faults.c b/test/vmapi/primary_only/faults.c
index f24e61f..1adeb5b 100644
--- a/test/vmapi/primary_only/faults.c
+++ b/test/vmapi/primary_only/faults.c
@@ -61,8 +61,8 @@
/* Start secondary cpu while holding lock. */
sl_lock(&s.lock);
- EXPECT_EQ(cpu_start(1, other_stack, sizeof(other_stack), rx_reader,
- (uintptr_t)&s),
+ EXPECT_EQ(cpu_start(hftest_get_cpu_id(1), other_stack,
+ sizeof(other_stack), rx_reader, (uintptr_t)&s),
true);
/* Wait for CPU to release the lock. */
diff --git a/test/vmapi/primary_only/primary_only.c b/test/vmapi/primary_only/primary_only.c
index 6cb8f46..d715d19 100644
--- a/test/vmapi/primary_only/primary_only.c
+++ b/test/vmapi/primary_only/primary_only.c
@@ -117,9 +117,10 @@
/* Start secondary while holding lock. */
sl_lock(&lock);
- EXPECT_EQ(cpu_start(1, other_stack, sizeof(other_stack), vm_cpu_entry,
- (uintptr_t)&lock),
- true);
+ EXPECT_EQ(
+ cpu_start(hftest_get_cpu_id(1), other_stack,
+ sizeof(other_stack), vm_cpu_entry, (uintptr_t)&lock),
+ true);
/* Wait for CPU to release the lock. */
sl_lock(&lock);
diff --git a/test/vmapi/primary_with_secondaries/run_race.c b/test/vmapi/primary_with_secondaries/run_race.c
index 2062de1..bd832c7 100644
--- a/test/vmapi/primary_with_secondaries/run_race.c
+++ b/test/vmapi/primary_with_secondaries/run_race.c
@@ -89,8 +89,8 @@
SERVICE_SELECT(SERVICE_VM0, "check_state", mb.send);
/* Start second vCPU. */
- ASSERT_TRUE(cpu_start(1, stack, sizeof(stack), vm_cpu_entry,
- (uintptr_t)&mb));
+ ASSERT_TRUE(cpu_start(hftest_get_cpu_id(1), stack, sizeof(stack),
+ vm_cpu_entry, (uintptr_t)&mb));
/* Run on a loop until the secondary VM is done. */
EXPECT_TRUE(run_loop(&mb));