feat(hftest): add service endpoint helpers
Several helper utilities are added for service SPs. These will be
leveraged to build tests to exercise secure interrupt handling in
upcoming patches.
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: I6368984a707c0ac35bc6a291849db183258ec16d
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index 3ec64dd..66e00a2 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -364,6 +364,16 @@
}
/**
+ * Deactivate the physical interrupt.
+ *
+ * Returns 0 on success, or -1 otherwise.
+ */
+static inline int64_t hf_interrupt_deactivate(uint32_t intid)
+{
+ return hf_call(HF_INTERRUPT_DEACTIVATE, intid, intid, 0);
+}
+
+/**
* Injects a virtual interrupt of the given ID into the given target vCPU.
* This doesn't cause the vCPU to actually be run immediately; it will be taken
* when the vCPU is next run, which is up to the scheduler.
diff --git a/test/inc/test/vmapi/ffa.h b/test/inc/test/vmapi/ffa.h
index d02a0cc..c3bd68f 100644
--- a/test/inc/test/vmapi/ffa.h
+++ b/test/inc/test/vmapi/ffa.h
@@ -24,6 +24,19 @@
EXPECT_EQ(ffa_error_code(v), (ffa_error)); \
} while (0)
+#define SERVICE_PARTITION_INFO_GET(service_name, uuid) \
+ struct ffa_partition_info *service_name(void) \
+ { \
+ static struct ffa_partition_info partition; \
+ static bool is_set = false; \
+ if (!is_set) { \
+ ASSERT_EQ(get_ffa_partition_info(uuid, &partition, 1), \
+ 1); \
+ is_set = true; \
+ } \
+ return &partition; \
+ }
+
/*
* The bit 15 of the FF-A ID indicates whether the partition is executing
* in the normal world, in case it is a Virtual Machine (VM); or in the
diff --git a/test/vmapi/ffa_secure_partitions/BUILD.gn b/test/vmapi/ffa_secure_partitions/BUILD.gn
index fb70919..02394d7 100644
--- a/test/vmapi/ffa_secure_partitions/BUILD.gn
+++ b/test/vmapi/ffa_secure_partitions/BUILD.gn
@@ -8,10 +8,31 @@
import("//test/hftest/args.gni")
import("//src/arch/${plat_arch}/args.gni")
+config("config") {
+ include_dirs = [ "inc" ]
+}
+
+source_set("ffa_secure_partitions") {
+ testonly = true
+ public_configs = [
+ ":config",
+ "//src/arch/${plat_arch}:config",
+ ]
+
+ sources = [
+ "ffa_secure_partitions.c",
+ ]
+
+ deps = [
+ "//test/vmapi/common",
+ ]
+}
+
# VM that will control execution of tests in a VM-to-SP set-up
vm_kernel("vm_primary") {
testonly = true
public_configs = [
+ ":config",
"services/arch/${plat_arch}/secure:config",
"//src/arch/${plat_arch}:arch_config",
]
@@ -26,6 +47,7 @@
]
deps = [
+ ":ffa_secure_partitions",
"//src/arch/${plat_arch}/hftest:interrupts_gicv3",
"//src/arch/${plat_arch}/hftest:power_mgmt",
"//test/hftest:hftest_primary_vm",
diff --git a/test/vmapi/ffa_secure_partitions/ffa_secure_partitions.c b/test/vmapi/ffa_secure_partitions/ffa_secure_partitions.c
new file mode 100644
index 0000000..8770803
--- /dev/null
+++ b/test/vmapi/ffa_secure_partitions/ffa_secure_partitions.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2023 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "ffa_secure_partitions.h"
+
+SERVICE_PARTITION_INFO_GET(service1, SERVICE1)
+SERVICE_PARTITION_INFO_GET(service2, SERVICE2)
diff --git a/test/vmapi/ffa_secure_partitions/inc/ffa_secure_partitions.h b/test/vmapi/ffa_secure_partitions/inc/ffa_secure_partitions.h
new file mode 100644
index 0000000..918705d
--- /dev/null
+++ b/test/vmapi/ffa_secure_partitions/inc/ffa_secure_partitions.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2023 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#pragma once
+
+#include "test/hftest.h"
+#include "test/vmapi/ffa.h"
+
+/*
+ * FF-A UUIDs related to the test partitions providing test services to the
+ * Primary VM. These service partitions can either be SPs or VMs, and should
+ * be used only once for either an SP or VM.
+ * This allows for the PVM to communicate with the service partition, regardless
+ * of the ID, which has a bit related to the security state of the partition.
+ * The PVM should use the UUID to retrieve the FF-A ID of the partition, before
+ * attempting to communicate with it. Thus, the code for the PVM becomes
+ * portable between setups where the test service is either a VM or an SP.
+ */
+#define SERVICE1 \
+ &(struct ffa_uuid) \
+ { \
+ { \
+ 0x9458bb2d, 0x353b4ee2, 0xaa25710c, 0x99b73ddc, \
+ } \
+ }
+
+#define SERVICE2 \
+ &(struct ffa_uuid) \
+ { \
+ { \
+ 0xa609f132, 0x6b4f, 0x4c14, 0x9489, \
+ } \
+ }
+
+/*
+ * Helpers to get services information.
+ * Defined with SERVICE_PARTITION_INFO_GET macro.
+ */
+struct ffa_partition_info* service1(void);
+struct ffa_partition_info* service2(void);
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/BUILD.gn b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/BUILD.gn
index 0b94be5..2f26bab 100644
--- a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/BUILD.gn
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/BUILD.gn
@@ -96,6 +96,17 @@
]
}
+source_set("sp_helpers") {
+ testonly = true
+ public_configs = [
+ ":config",
+ "//src/arch/aarch64:arch_config",
+ ]
+ sources = [
+ "sp_helpers.c",
+ ]
+}
+
# SP that will be controlled via communication/scheduling primitives by the
# former SP
vm_kernel("secure_partitions_services") {
@@ -105,6 +116,7 @@
deps = [
":message_loop",
":sp805",
+ ":sp_helpers",
"//src/arch/aarch64/hftest:interrupts",
"//test/hftest:hftest_secure_service",
]
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/el0/BUILD.gn b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/el0/BUILD.gn
index 2db73c7..7341342 100644
--- a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/el0/BUILD.gn
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/el0/BUILD.gn
@@ -13,10 +13,22 @@
]
}
+source_set("sp_helpers") {
+ testonly = true
+ public_configs = [
+ ":config",
+ "//src/arch/aarch64:arch_config",
+ ]
+ sources = [
+ "sp_helpers.c",
+ ]
+}
+
vm_kernel("sel0_partition") {
testonly = true
deps = [
+ ":sp_helpers",
"//src/arch/aarch64/hftest/el0:interrupts",
"//test/hftest:hftest_sel0_partition_base",
"//test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure:message_loop",
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/el0/sp_helpers.c b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/el0/sp_helpers.c
new file mode 100644
index 0000000..262fcf8
--- /dev/null
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/el0/sp_helpers.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2023 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "sp_helpers.h"
+
+#include "partition_services.h"
+
+#define ITERATIONS_PER_MS 15000
+
+uint64_t sp_sleep_active_wait(uint32_t ms)
+{
+ sp_wait_loop(ms * ITERATIONS_PER_MS);
+ return ms;
+}
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/partition_services.h b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/partition_services.h
index b0491ec..a2640e9 100644
--- a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/partition_services.h
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/partition_services.h
@@ -299,3 +299,10 @@
struct ffa_value sp_check_state_transitions_cmd(ffa_vm_id_t test_source,
ffa_vm_id_t companion_sp);
+
+static inline void sp_wait_loop(uint32_t iterations)
+{
+ for (volatile uint64_t loop = 0; loop < iterations; loop++) {
+ /* Wait */
+ }
+}
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/sp_helpers.h b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/sp_helpers.h
new file mode 100644
index 0000000..6bbbd42
--- /dev/null
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/inc/sp_helpers.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2023 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include <stdint.h>
+
+uint64_t sp_sleep_active_wait(uint32_t ms);
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/sp_helpers.c b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/sp_helpers.c
new file mode 100644
index 0000000..3ffd7fc
--- /dev/null
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/sp_helpers.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "sp_helpers.h"
+
+#include "hf/arch/barriers.h"
+#include "hf/arch/irq.h"
+#include "hf/arch/vm/timer.h"
+
+static inline uint64_t virtualcounter_read(void)
+{
+ isb();
+ return read_msr(cntvct_el0);
+}
+
+uint64_t sp_sleep_active_wait(uint32_t ms)
+{
+ uint64_t timer_freq = read_msr(cntfrq_el0);
+
+ uint64_t time1 = virtualcounter_read();
+ volatile uint64_t time2 = time1;
+
+ while ((time2 - time1) < ((ms * timer_freq) / 1000U)) {
+ time2 = virtualcounter_read();
+ }
+
+ return ((time2 - time1) * 1000) / timer_freq;
+}
diff --git a/test/vmapi/primary_with_secondaries/inc/primary_with_secondary.h b/test/vmapi/primary_with_secondaries/inc/primary_with_secondary.h
index 2705170..af05048 100644
--- a/test/vmapi/primary_with_secondaries/inc/primary_with_secondary.h
+++ b/test/vmapi/primary_with_secondaries/inc/primary_with_secondary.h
@@ -44,19 +44,6 @@
} \
}
-#define SERVICE_PARTITION_INFO_GET(service_name, uuid) \
- struct ffa_partition_info* service_name(void) \
- { \
- static struct ffa_partition_info partition; \
- static bool is_set = false; \
- if (!is_set) { \
- ASSERT_EQ(get_ffa_partition_info(uuid, &partition, 1), \
- 1); \
- is_set = true; \
- } \
- return &partition; \
- }
-
/*
* Helpers to get services information.
* Defined with SERVICE_PARTITION_INFO_GET macro.