test(interrupts): exercise ns interrupt being signaled to SP
This patch adds a tftf based test to exercise non-secure interrupt
handling being signaled to the Cactus SP by the SPMC while processing
a direct message.
A detailed description is provided in the comment leading the test
function.
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: I2f8511135470d2ca8f567532a1cb7c4ae374af3f
diff --git a/include/runtime_services/cactus_test_cmds.h b/include/runtime_services/cactus_test_cmds.h
index 1e60e0e..d86aa61 100644
--- a/include/runtime_services/cactus_test_cmds.h
+++ b/include/runtime_services/cactus_test_cmds.h
@@ -24,6 +24,10 @@
#define CACTUS_ERROR_FFA_CALL U(3)
#define CACTUS_ERROR_UNHANDLED U(4)
+#define ECHO_VAL1 U(0xa0a0a0a0)
+#define ECHO_VAL2 U(0xb0b0b0b0)
+#define ECHO_VAL3 U(0xc0c0c0c0)
+
/**
* Get command from struct ffa_value.
*/
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_interrupts.c b/tftf/tests/runtime_services/secure_service/test_ffa_interrupts.c
index 1c17513..0759a7c 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_interrupts.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_interrupts.c
@@ -14,10 +14,12 @@
#define SENDER HYP_ID
#define RECEIVER SP_ID(1)
-#define SLEEP_TIME 200U
+#define RECEIVER_2 SP_ID(2)
+#define TIMER_DURATION 50U
+#define SLEEP_TIME 100U
static const struct ffa_uuid expected_sp_uuids[] = {
- {PRIMARY_UUID}
+ {PRIMARY_UUID}, {SECONDARY_UUID}
};
/*
@@ -31,8 +33,27 @@
return 0;
}
+static int program_timer(unsigned long milli_secs)
+{
+ /* Program timer. */
+ timer_irq_received = 0;
+ tftf_timer_register_handler(timer_handler);
+
+ return tftf_program_timer(milli_secs);
+}
+
+static int check_timer_interrupt(void)
+{
+ /* Check that the timer interrupt has been handled in NWd(TFTF). */
+ tftf_cancel_timer();
+ tftf_timer_unregister_handler();
+
+ return timer_irq_received;
+}
+
/*
- * @Test_Aim@ Test non-secure interrupts while executing Secure Partition.
+ * @Test_Aim@ Test non-secure interrupts while a Secure Partition capable
+ * of managed exit is executing.
*
* 1. Enable managed exit interrupt by sending interrupt_enable command to
* Cactus.
@@ -40,7 +61,7 @@
* 2. Register a handler for the non-secure timer interrupt. Program it to fire
* in a certain time.
*
- * 3. Send a blocking request to Cactus to execute in busy loop.
+ * 3. Send a direct request request to Cactus SP to execute in busy loop.
*
* 4. While executing in busy loop, the non-secure timer should
* fire and trap into SPM running at S-EL2 as FIQ.
@@ -61,29 +82,25 @@
* sleeping time.
*
*/
-test_result_t test_ffa_ns_interrupt(void)
+test_result_t test_ffa_ns_interrupt_managed_exit(void)
{
int ret;
struct ffa_value ret_values;
- CHECK_SPMC_TESTING_SETUP(1, 0, expected_sp_uuids);
+ CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
/* Enable managed exit interrupt as FIQ in the secure side. */
if (!spm_set_managed_exit_int(RECEIVER, true)) {
return TEST_RESULT_FAIL;
}
- /* Program timer */
- timer_irq_received = 0;
- tftf_timer_register_handler(timer_handler);
-
- ret = tftf_program_timer(100);
+ ret = program_timer(TIMER_DURATION);
if (ret < 0) {
ERROR("Failed to program timer (%d)\n", ret);
return TEST_RESULT_FAIL;
}
- /* Send request to primary Cactus to sleep for 200ms */
+ /* Send request to primary Cactus to sleep for 100ms. */
ret_values = cactus_sleep_cmd(SENDER, RECEIVER, SLEEP_TIME);
if (!is_ffa_direct_response(ret_values)) {
@@ -99,11 +116,7 @@
return TEST_RESULT_FAIL;
}
- /* Check that the timer interrupt has been handled in NS-world (TFTF) */
- tftf_cancel_timer();
- tftf_timer_unregister_handler();
-
- if (timer_irq_received == 0) {
+ if (check_timer_interrupt() == 0) {
ERROR("Timer interrupt hasn't actually been handled.\n");
return TEST_RESULT_FAIL;
}
@@ -113,22 +126,119 @@
* This resumes Cactus in the sleep routine.
*/
ret_values = ffa_msg_send_direct_req64(SENDER, RECEIVER,
- 0, 0, 0, 0, 0);
+ 0, 0, 0, 0, 0);
if (!is_ffa_direct_response(ret_values)) {
return TEST_RESULT_FAIL;
}
- /* Make sure elapsed time not less than sleep time */
+ if (cactus_get_response(ret_values) == CACTUS_ERROR) {
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Make sure elapsed time not less than sleep time. */
if (cactus_get_response(ret_values) < SLEEP_TIME) {
ERROR("Lapsed time less than requested sleep time\n");
return TEST_RESULT_FAIL;
}
- /* Disable Managed exit interrupt */
+ /* Disable Managed exit interrupt. */
if (!spm_set_managed_exit_int(RECEIVER, false)) {
return TEST_RESULT_FAIL;
}
return TEST_RESULT_SUCCESS;
}
+
+/*
+ * @Test_Aim@ Test the scenario where a non-secure interrupt triggers while a
+ * Secure Partition,that specified action for NS interrupt as SIGNALABLE, is
+ * executing.
+ *
+ * 1. Register a handler for the non-secure timer interrupt. Program it to fire
+ * in a certain time.
+ *
+ * 2. Send a direct request to Cactus SP to execute in busy loop.
+ *
+ * 3. While executing in busy loop, the non-secure timer should fire. Cactus SP
+ * should be preempted by non-secure interrupt.
+ *
+ * 4. Execution traps to SPMC running at S-EL2 as FIQ. SPMC returns control to
+ * the normal world through FFA_INTERRUPT ABI for it to handle the non-secure
+ * interrupt.
+ *
+ * 5. Check whether the pending non-secure timer interrupt successfully got
+ * handled in the normal world by TFTF.
+ *
+ * 6. Resume the Cactus SP using FFA_RUN ABI for it to complete the sleep
+ * routine.
+ *
+ * 7. Ensure the Cactus SP sends the DIRECT RESPONSE message.
+ *
+ * 8. Check if time lapsed is greater than sleep time.
+ *
+ */
+test_result_t test_ffa_ns_interrupt_signaled(void)
+{
+ int ret;
+ struct ffa_value ret_values;
+ unsigned int core_pos = get_current_core_id();
+
+ CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+
+ ret = program_timer(TIMER_DURATION);
+ if (ret < 0) {
+ ERROR("Failed to program timer (%d)\n", ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Send request to secondary Cactus to sleep for 100ms. */
+ ret_values = cactus_sleep_cmd(SENDER, RECEIVER_2, SLEEP_TIME);
+
+ if (check_timer_interrupt() == 0) {
+ ERROR("Timer interrupt hasn't actually been handled.\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /*
+ * Cactus SP should be preempted by non-secure interrupt. SPMC
+ * returns control to the normal world through FFA_INTERRUPT ABI
+ * for it to handle the non-secure interrupt.
+ */
+ if (ffa_func_id(ret_values) != FFA_INTERRUPT) {
+ ERROR("Expected FFA_INTERRUPT as return status!\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /*
+ * Ensure SPMC returns FFA_ERROR with BUSY error code when a direct
+ * request message is sent to the preempted SP.
+ */
+ ret_values = cactus_echo_send_cmd(SENDER, RECEIVER_2, ECHO_VAL1);
+
+ if ((ffa_func_id(ret_values) != FFA_ERROR) ||
+ (ffa_error_code(ret_values) != FFA_ERROR_BUSY)) {
+ ERROR("Expected FFA_ERROR(BUSY)! Got %x(%x)\n",
+ ffa_func_id(ret_values), ffa_error_code(ret_values));
+ return TEST_RESULT_FAIL;
+ }
+
+ /*
+ * Resume the Cactus SP using FFA_RUN ABI for it to complete the
+ * sleep routine and send the direct response message.
+ */
+ VERBOSE("Resuming %x\n", RECEIVER_2);
+ ret_values = ffa_run(RECEIVER_2, core_pos);
+
+ if (!is_ffa_direct_response(ret_values)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Make sure elapsed time not less than sleep time. */
+ if (cactus_get_response(ret_values) < SLEEP_TIME) {
+ ERROR("Lapsed time less than requested sleep time\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index 19033b7..95451c3 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -108,8 +108,10 @@
<testsuite name="FF-A Interrupt"
description="Test non-secure Interrupts" >
- <testcase name="Test NS interrupts"
- function="test_ffa_ns_interrupt" />
+ <testcase name="Test Managed Exit"
+ function="test_ffa_ns_interrupt_managed_exit" />
+ <testcase name="Test NS interrupt Signalable"
+ function="test_ffa_ns_interrupt_signaled" />
<testcase name="Test Secure interrupt handling while SP running"
function="test_ffa_sec_interrupt_sp_running" />
<testcase name="Test Secure interrupt handling while SP waiting"