fix(interrupts): deny new direct request message from endpoint
Please refer to detailed description in the comment preceding the
helper function introduced in cactus_interrupt.c file.
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: Ie70d68514dac44211767d611db6d84991a8b48c6
diff --git a/spm/cactus/cactus_interrupt.c b/spm/cactus/cactus_interrupt.c
index 35fdf30..16785db 100644
--- a/spm/cactus/cactus_interrupt.c
+++ b/spm/cactus/cactus_interrupt.c
@@ -59,6 +59,46 @@
spin_unlock(&sp_handler_lock[intid]);
}
+/*
+ * Cactus SP does not implement application threads. Hence, once the Cactus SP
+ * sends the managed exit response to the direct request originator, execution
+ * is still frozen in interrupt handler context.
+ * Though it moves to WAITING state, it is not able to accept new direct request
+ * message from any endpoint. It can only receive a direct request message with
+ * the command CACTUS_RESUME_AFTER_MANAGED_EXIT from the originator of the
+ * suspended direct request message in order to return from the interrupt
+ * handler context and resume the processing of suspended request.
+ */
+void send_managed_exit_response(void)
+{
+ struct ffa_value ffa_ret;
+ bool waiting_resume_after_managed_exit;
+
+ /* Send managed exit response. */
+ ffa_ret = cactus_response(g_ffa_id, g_dir_req_source_id,
+ MANAGED_EXIT_INTERRUPT_ID);
+ waiting_resume_after_managed_exit = true;
+
+ while (waiting_resume_after_managed_exit) {
+
+ waiting_resume_after_managed_exit =
+ (ffa_func_id(ffa_ret) != FFA_MSG_SEND_DIRECT_REQ_SMC32 &&
+ ffa_func_id(ffa_ret) != FFA_MSG_SEND_DIRECT_REQ_SMC64) ||
+ ffa_dir_msg_source(ffa_ret) != g_dir_req_source_id ||
+ cactus_get_cmd(ffa_ret) != CACTUS_RESUME_AFTER_MANAGED_EXIT;
+
+ if (waiting_resume_after_managed_exit) {
+ ERROR("Expected a direct message request from endpoint"
+ " %x with command CACTUS_RESUME_AFTER_MANAGED_EXIT\n",
+ g_dir_req_source_id);
+ ffa_ret = cactus_error_resp(g_ffa_id,
+ ffa_dir_msg_source(ffa_ret),
+ CACTUS_ERROR_TEST);
+ }
+ }
+ VERBOSE("Resuming the suspended command\n");
+}
+
void cactus_interrupt_handler_irq(void)
{
uint32_t intid = spm_interrupt_get();
@@ -72,8 +112,7 @@
*/
VERBOSE("vIRQ: Sending ME response to %x\n",
g_dir_req_source_id);
- cactus_response(g_ffa_id, g_dir_req_source_id,
- managed_exit_interrupt_id);
+ send_managed_exit_response();
} else {
switch (intid) {
case IRQ_TWDOG_INTID:
@@ -114,8 +153,7 @@
*/
VERBOSE("vFIQ: Sending ME response to %x\n",
g_dir_req_source_id);
- cactus_response(g_ffa_id, g_dir_req_source_id,
- MANAGED_EXIT_INTERRUPT_ID);
+ send_managed_exit_response();
break;
default:
/*
diff --git a/spm/cactus/cactus_tests/cactus_test_interrupts.c b/spm/cactus/cactus_tests/cactus_test_interrupts.c
index c438050..7f3de0c 100644
--- a/spm/cactus/cactus_tests/cactus_test_interrupts.c
+++ b/spm/cactus/cactus_tests/cactus_test_interrupts.c
@@ -82,8 +82,8 @@
*/
VERBOSE("SP%x: received Managed Exit as response\n",
vm_id);
- ffa_ret = ffa_msg_send_direct_req64(vm_id, fwd_dest,
- 0, 0, 0, 0, 0);
+ ffa_ret = cactus_resume_after_managed_exit(vm_id,
+ fwd_dest);
}
}
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 fa850c7..01fa2ee 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_interrupts.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_interrupts.c
@@ -75,10 +75,12 @@
* 6. Check whether the pending non-secure timer interrupt successfully got
* handled in TFTF.
*
- * 7. Send a direct message request command to resume Cactus's execution.
- * It resumes in the sleep loop and completes it. It then returns with
- * a direct message response. Check if time lapsed is greater than
- * sleeping time.
+ * 7. Send a new sleep command to Cactus SP. An error response must be sent
+ * back by the Cactus SP with CACTUS_ERROR_TEST as the error code.
+ *
+ * 8. Send a command asking the SP to resume after managed exit. SP resumes in
+ * the suspended sleep loop and completes it. It then returns with a direct
+ * message response. Check if time lapsed is greater than sleeping time.
*
*/
test_result_t test_ffa_ns_interrupt_managed_exit(void)
@@ -116,11 +118,19 @@
}
/*
- * Send a dummy direct message request to relinquish CPU cycles.
- * This resumes Cactus in the sleep routine.
+ * Send a command asking the SP to resume after managed exit. This
+ * effectively resumes the Cactus in the sleep routine. Note that
+ * Cactus should return error if the current endpoint sent a new
+ * command.
*/
- ret_values = ffa_msg_send_direct_req64(SENDER, RECEIVER,
- 0, 0, 0, 0, 0);
+ ret_values = cactus_sleep_cmd(SENDER, RECEIVER, SLEEP_TIME);
+
+ if (cactus_get_response(ret_values) != CACTUS_ERROR &&
+ cactus_error_code(ret_values) != CACTUS_ERROR_TEST) {
+ return TEST_RESULT_FAIL;
+ }
+
+ ret_values = cactus_resume_after_managed_exit(SENDER, RECEIVER);
if (!is_ffa_direct_response(ret_values)) {
return TEST_RESULT_FAIL;
@@ -320,11 +330,19 @@
}
/*
- * Send a dummy direct message request to relinquish CPU cycles.
- * This resumes Cactus in the sleep routine.
+ * Send a command asking the SP to resume after managed exit. This
+ * effectively resumes the Cactus in the sleep routine. Note that
+ * Cactus should return error if the current endpoint sent a new
+ * command.
*/
- ret_values = ffa_msg_send_direct_req64(SENDER, RECEIVER,
- 0, 0, 0, 0, 0);
+ ret_values = cactus_sleep_cmd(SENDER, RECEIVER, SLEEP_TIME);
+
+ if (cactus_get_response(ret_values) != CACTUS_ERROR &&
+ cactus_error_code(ret_values) != CACTUS_ERROR_TEST) {
+ return TEST_RESULT_FAIL;
+ }
+
+ ret_values = cactus_resume_after_managed_exit(SENDER, RECEIVER);
if (!is_ffa_direct_response(ret_values)) {
return TEST_RESULT_FAIL;
@@ -422,11 +440,19 @@
}
/*
- * Send a dummy direct message request to relinquish CPU cycles.
- * This resumes Cactus in the sleep routine.
+ * Send a command asking the SP to resume after managed exit. This
+ * effectively resumes the Cactus in the sleep routine. Note that
+ * Cactus should return error if the current endpoint sent a new
+ * command.
*/
- ret_values = ffa_msg_send_direct_req64(SENDER, RECEIVER,
- 0, 0, 0, 0, 0);
+ ret_values = cactus_sleep_cmd(SENDER, RECEIVER, SLEEP_TIME);
+
+ if (cactus_get_response(ret_values) != CACTUS_ERROR &&
+ cactus_error_code(ret_values) != CACTUS_ERROR_TEST) {
+ return TEST_RESULT_FAIL;
+ }
+
+ ret_values = cactus_resume_after_managed_exit(SENDER, RECEIVER);
if (!is_ffa_direct_response(ret_values)) {
return TEST_RESULT_FAIL;
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
index f00c803..ea264b4 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
@@ -1346,7 +1346,7 @@
/*
* Resume setter Cactus in the handling of CACTUS_NOTIFICATIONS_SET_CMD.
*/
- ret = ffa_msg_send_direct_req64(HYP_ID, sender, 0, 0, 0, 0, 0);
+ ret = cactus_resume_after_managed_exit(HYP_ID, sender);
/* Expected result to CACTUS_NOTIFICATIONS_SET_CMD. */
if (!is_expected_cactus_response(ret, CACTUS_SUCCESS, 0)) {