diff options
author | Madhukar Pappireddy <madhukar.pappireddy@arm.com> | 2021-08-05 15:34:07 -0500 |
---|---|---|
committer | Madhukar Pappireddy <madhukar.pappireddy@arm.com> | 2021-11-05 15:35:57 -0500 |
commit | cd183ef0e73ad74b08e6fbec26b4d95bf57a23c9 (patch) | |
tree | e8b1cd08162961df2f9cd83b7b3284113c508a6d /spm | |
parent | 46d06d7e778b4c17b24b8ff4676cde2288528472 (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.S | 4 | ||||
-rw-r--r-- | spm/cactus/cactus_interrupt.c | 70 | ||||
-rw-r--r-- | spm/cactus/cactus_main.c | 16 | ||||
-rw-r--r-- | spm/cactus/cactus_tests/cactus_message_loop.c | 2 | ||||
-rw-r--r-- | spm/cactus/cactus_tests/cactus_test_interrupts.c | 11 |
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), |