test: SP can yield cycles while handling secure interrupt
This patch adds a new command to program SP to yield cycles
while handling secure interrupt.
A detailed description of the test is provided in the comments
within the test files.
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: I284aec6eff79332a8fd8090116f3d4c091144854
diff --git a/test/vmapi/ffa_secure_partitions/secure_interrupts.c b/test/vmapi/ffa_secure_partitions/secure_interrupts.c
index 319a9c5..fb48bbc 100644
--- a/test/vmapi/ffa_secure_partitions/secure_interrupts.c
+++ b/test/vmapi/ffa_secure_partitions/secure_interrupts.c
@@ -291,3 +291,52 @@
*/
check_and_disable_trusted_wdog_timer(own_id, target_id);
}
+
+/*
+ * Test that an SP can attempt to yield CPU cycles while handling secure
+ * interrupt by invoking FFA_YIELD.
+ */
+TEST(secure_interrupts, sp_yield_sec_interrupt_handling)
+{
+ struct ffa_value res;
+ ffa_vm_id_t own_id = hf_vm_get_id();
+ struct mailbox_buffers mb = set_up_mailbox();
+ struct ffa_partition_info *service2_info = service2(mb.recv);
+ const ffa_vm_id_t receiver_id = service2_info->vm_id;
+ uint64_t time1;
+ volatile uint64_t time_lapsed;
+ uint64_t timer_freq = read_msr(cntfrq_el0);
+
+ /*
+ * Send command to SP asking it attempt to yield cycles while handling
+ * secure interrupt.
+ */
+ res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
+ true);
+
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+ EXPECT_EQ(sp_resp(res), SP_SUCCESS);
+
+ enable_trigger_trusted_wdog_timer(own_id, receiver_id, 75);
+ time1 = syscounter_read();
+
+ /*
+ * Sleep for 100ms. This ensures secure wdog timer triggers
+ * during this time. SP starts handling secure interrupt but attempts
+ * to yields cycles. However, SPMC just resumes the SP to complete
+ * interrupt handling.
+ */
+ waitms(100);
+
+ /* Lapsed time should be at least equal to sleep time. */
+ time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
+
+ EXPECT_GE(time_lapsed, 100);
+
+ res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
+ false);
+
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+ EXPECT_EQ(sp_resp(res), SP_SUCCESS);
+ check_and_disable_trusted_wdog_timer(own_id, receiver_id);
+}
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
index d5a1e65..c610d97 100644
--- 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
@@ -16,6 +16,8 @@
#define ITERATIONS_PER_MS 15000
+extern bool yield_while_handling_sec_interrupt;
+
uint64_t sp_sleep_active_wait(uint32_t ms)
{
sp_wait_loop(ms * ITERATIONS_PER_MS);
@@ -49,6 +51,15 @@
/* Perform secure interrupt de-activation. */
ASSERT_EQ(hf_interrupt_deactivate(intid), 0);
+
+ if (yield_while_handling_sec_interrupt) {
+ struct ffa_value ret;
+ HFTEST_LOG("Yield cycles while handling secure interrupt");
+ ret = ffa_yield();
+
+ ASSERT_EQ(ret.func, FFA_SUCCESS_32);
+ HFTEST_LOG("Resuming secure interrupt handling");
+ }
exception_handler_set_last_interrupt(intid);
return ffa_msg_wait();
}
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 18dd985..e94b98c 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
@@ -449,3 +449,20 @@
}
struct ffa_value sp_check_partition_info_get_regs_cmd(ffa_vm_id_t test_source);
+
+/**
+ * Command to request an SP to yield while handling a secure interrupt.
+ * The command id is the hex representaton of the string "YSIH".
+ */
+#define SP_YIELD_SEC_INTERRUPT_HANDLING_CMD 0x59534948U
+
+static inline struct ffa_value sp_yield_secure_interrupt_handling_cmd_send(
+ ffa_vm_id_t source, ffa_vm_id_t dest, bool yield)
+{
+ return ffa_msg_send_direct_req(source, dest,
+ SP_YIELD_SEC_INTERRUPT_HANDLING_CMD,
+ yield, 0, 0, 0);
+}
+
+struct ffa_value sp_yield_secure_interrupt_handling_cmd(ffa_vm_id_t source,
+ bool yield);
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/message_loop.c b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/message_loop.c
index 4c62889..1b090bf 100644
--- a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/message_loop.c
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/message_loop.c
@@ -86,6 +86,10 @@
case SP_CHECK_PARTITION_INFO_GET_REGS_CMD:
res = sp_check_partition_info_get_regs_cmd(ffa_sender(res));
break;
+ case SP_YIELD_SEC_INTERRUPT_HANDLING_CMD:
+ res = sp_yield_secure_interrupt_handling_cmd(ffa_sender(res),
+ res.arg4);
+ break;
default:
HFTEST_LOG_FAILURE();
HFTEST_LOG(HFTEST_LOG_INDENT
diff --git a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/secure_interrupts.c b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/secure_interrupts.c
index 9e181b3..2cd05d3 100644
--- a/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/secure_interrupts.c
+++ b/test/vmapi/ffa_secure_partitions/services/arch/aarch64/secure/secure_interrupts.c
@@ -23,6 +23,8 @@
#define PLAT_ARM_TWDOG_BASE 0x2a490000
#define PLAT_ARM_TWDOG_SIZE 0x20000
+bool yield_while_handling_sec_interrupt = false;
+
static void send_managed_exit_response(ffa_vm_id_t dir_req_source_id)
{
struct ffa_value ffa_ret;
@@ -75,6 +77,17 @@
/* Perform secure interrupt de-activation. */
ASSERT_EQ(hf_interrupt_deactivate(intid), 0);
+
+ if (yield_while_handling_sec_interrupt) {
+ struct ffa_value ret;
+ HFTEST_LOG(
+ "Yield cycles while handling secure interrupt");
+ ret = ffa_yield();
+
+ ASSERT_EQ(ret.func, FFA_SUCCESS_32);
+ HFTEST_LOG("Resuming secure interrupt handling");
+ }
+
exception_handler_set_last_interrupt(intid);
}
}
@@ -227,3 +240,12 @@
return sp_success(own_id, source, 0);
}
+
+struct ffa_value sp_yield_secure_interrupt_handling_cmd(ffa_vm_id_t source,
+ bool yield)
+{
+ ffa_vm_id_t own_id = hf_vm_get_id();
+
+ yield_while_handling_sec_interrupt = yield;
+ return sp_success(own_id, source, 0);
+}