summaryrefslogtreecommitdiff
path: root/spm
diff options
context:
space:
mode:
authorMadhukar Pappireddy <madhukar.pappireddy@arm.com>2021-08-05 15:34:07 -0500
committerMadhukar Pappireddy <madhukar.pappireddy@arm.com>2021-11-05 15:35:57 -0500
commitcd183ef0e73ad74b08e6fbec26b4d95bf57a23c9 (patch)
treee8b1cd08162961df2f9cd83b7b3284113c508a6d /spm
parent46d06d7e778b4c17b24b8ff4676cde2288528472 (diff)
feat: add support for secure interrupt handling and completion
As per FF-A v1.1 spec, the conduit used by SPM to signal an interrupt to S-EL1 Partition is vIRQ and/or ERET. Depending on the execution state of the vCPU of the target SP, FFA_INTERRUPT ABI and/or Interrupt ID can be used as parameters during eret to the SP. This patch adds support for secure interrupt handling in Cactus SP as well as adds support for FFA_INTERRUPT ABI in the message loop. Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com> Change-Id: I173b9e0af11b6fd2605145391da68dfda04a14f2
Diffstat (limited to 'spm')
-rw-r--r--spm/cactus/aarch64/cactus_exceptions.S4
-rw-r--r--spm/cactus/cactus_interrupt.c70
-rw-r--r--spm/cactus/cactus_main.c16
-rw-r--r--spm/cactus/cactus_tests/cactus_message_loop.c2
-rw-r--r--spm/cactus/cactus_tests/cactus_test_interrupts.c11
5 files changed, 64 insertions, 39 deletions
diff --git a/spm/cactus/aarch64/cactus_exceptions.S b/spm/cactus/aarch64/cactus_exceptions.S
index 31cdbf9..6aec16d 100644
--- a/spm/cactus/aarch64/cactus_exceptions.S
+++ b/spm/cactus/aarch64/cactus_exceptions.S
@@ -101,7 +101,7 @@ unhandled_exception serr_a32
func irq_vector_entry
sub sp, sp, #0x100
save_gp_regs
- bl cactus_irq_handler
+ bl cactus_interrupt_handler
restore_gp_regs
add sp, sp, #0x100
eret
@@ -110,7 +110,7 @@ endfunc irq_vector_entry
func fiq_vector_entry
sub sp, sp, #0x100
save_gp_regs
- bl cactus_fiq_handler
+ bl cactus_interrupt_handler
restore_gp_regs
add sp, sp, #0x100
eret
diff --git a/spm/cactus/cactus_interrupt.c b/spm/cactus/cactus_interrupt.c
index f61df94..31c6a69 100644
--- a/spm/cactus/cactus_interrupt.c
+++ b/spm/cactus/cactus_interrupt.c
@@ -6,46 +6,50 @@
#include <debug.h>
+#include "cactus_message_loop.h"
+#include "cactus_test_cmds.h"
+#include <drivers/arm/sp805.h>
#include <ffa_helpers.h>
#include <sp_helpers.h>
+#include "spm_common.h"
#include <spm_helpers.h>
-#include "cactus_test_cmds.h"
-#include "spm_common.h"
+#include <platform_def.h>
extern ffa_id_t g_ffa_id;
-static void managed_exit_handler(void)
-{
- /*
- * Real SP will save its context here.
- * Send interrupt ID for acknowledgement
- */
- cactus_response(g_ffa_id, HYP_ID, MANAGED_EXIT_INTERRUPT_ID);
-}
-
-int cactus_irq_handler(void)
-{
- uint32_t irq_num;
-
- irq_num = spm_interrupt_get();
-
- ERROR("%s: Interrupt ID %u not handled!\n", __func__, irq_num);
-
- return 0;
-}
-
-int cactus_fiq_handler(void)
+void cactus_interrupt_handler(void)
{
- uint32_t fiq_num;
-
- fiq_num = spm_interrupt_get();
-
- if (fiq_num == MANAGED_EXIT_INTERRUPT_ID) {
- managed_exit_handler();
- } else {
- ERROR("%s: Interrupt ID %u not handled!\n", __func__, fiq_num);
+ uint32_t intid = spm_interrupt_get();
+
+ switch (intid) {
+ case MANAGED_EXIT_INTERRUPT_ID:
+ /*
+ * A secure partition performs its housekeeping and sends a
+ * direct response to signal interrupt completion.
+ * This is a pure virtual interrupt, no need for deactivation.
+ */
+ cactus_response(g_ffa_id, HYP_ID, MANAGED_EXIT_INTERRUPT_ID);
+ break;
+ case IRQ_TWDOG_INTID:
+ /*
+ * Interrupt triggered due to Trusted watchdog timer expiry.
+ * Clear the interrupt and stop the timer.
+ */
+ NOTICE("Trusted WatchDog timer stopped\n");
+ sp805_twdog_stop();
+
+ /* Perform secure interrupt de-activation. */
+ spm_interrupt_deactivate(intid);
+
+ break;
+ default:
+ /*
+ * Currently the only source of secure interrupt is Trusted
+ * Watchdog timer.
+ */
+ ERROR("%s: Interrupt ID %x not handled!\n", __func__,
+ intid);
+ panic();
}
-
- return 0;
}
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 78bb8fc..c80abd9 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -69,14 +69,26 @@ static void __dead2 message_loop(ffa_id_t vm_id, struct mailbox_buffers *mb)
}
if (ffa_func_id(ffa_ret) != FFA_MSG_SEND_DIRECT_REQ_SMC32 &&
- ffa_func_id(ffa_ret) != FFA_MSG_SEND_DIRECT_REQ_SMC64) {
+ ffa_func_id(ffa_ret) != FFA_MSG_SEND_DIRECT_REQ_SMC64 &&
+ ffa_func_id(ffa_ret) != FFA_INTERRUPT) {
ERROR("%s(%u) unknown func id 0x%x\n",
__func__, vm_id, ffa_func_id(ffa_ret));
break;
}
- destination = ffa_dir_msg_dest(ffa_ret);
+ if (ffa_func_id(ffa_ret) == FFA_INTERRUPT) {
+ /*
+ * Received FFA_INTERRUPT in waiting state.
+ * The interrupt id is passed although this is just
+ * informational as we're running with virtual
+ * interrupts unmasked and the interrupt is processed
+ * by the interrupt handler.
+ */
+ ffa_ret = ffa_msg_wait();
+ continue;
+ }
+ destination = ffa_dir_msg_dest(ffa_ret);
if (destination != vm_id) {
ERROR("%s(%u) invalid vm id 0x%x\n",
__func__, vm_id, destination);
diff --git a/spm/cactus/cactus_tests/cactus_message_loop.c b/spm/cactus/cactus_tests/cactus_message_loop.c
index fde7074..c24f6fc 100644
--- a/spm/cactus/cactus_tests/cactus_message_loop.c
+++ b/spm/cactus/cactus_tests/cactus_message_loop.c
@@ -32,7 +32,7 @@ bool cactus_handle_cmd(smc_ret_values *cmd_args, smc_ret_values *ret,
uint64_t in_cmd;
if (cmd_args == NULL || ret == NULL) {
- ERROR("Invalid argumentos passed to %s!\n", __func__);
+ ERROR("Invalid arguments passed to %s!\n", __func__);
return false;
}
diff --git a/spm/cactus/cactus_tests/cactus_test_interrupts.c b/spm/cactus/cactus_tests/cactus_test_interrupts.c
index 5cd53d1..ced5dca 100644
--- a/spm/cactus/cactus_tests/cactus_test_interrupts.c
+++ b/spm/cactus/cactus_tests/cactus_test_interrupts.c
@@ -12,6 +12,8 @@
#include "cactus_message_loop.h"
#include "cactus_test_cmds.h"
+#include <platform.h>
+
CACTUS_CMD_HANDLER(sleep_cmd, CACTUS_SLEEP_CMD)
{
uint64_t time_lapsed;
@@ -37,12 +39,19 @@ CACTUS_CMD_HANDLER(sleep_fwd_cmd, CACTUS_FWD_SLEEP_CMD)
ffa_id_t fwd_dest = cactus_get_fwd_sleep_dest(*args);
uint32_t sleep_ms = cactus_get_sleep_time(*args);
-
VERBOSE("VM%x requested %x to sleep for value %u\n",
ffa_dir_msg_source(*args), fwd_dest, sleep_ms);
ffa_ret = cactus_sleep_cmd(vm_id, fwd_dest, sleep_ms);
+ while (ffa_ret.ret0 == FFA_INTERRUPT) {
+ /* Received FFA_INTERRUPT in blocked state. */
+ VERBOSE("Processing FFA_INTERRUPT while blocked on direct response\n");
+ unsigned int my_core_pos = platform_get_core_pos(read_mpidr_el1());
+
+ ffa_ret = ffa_run(fwd_dest, my_core_pos);
+ }
+
if (!is_ffa_direct_response(ffa_ret)) {
ERROR("Encountered error in CACTUS_FWD_SLEEP_CMD response\n");
return cactus_error_resp(vm_id, ffa_dir_msg_source(*args),