From 729d7793f830781ff8ed44d144c3346c6e4251a3 Mon Sep 17 00:00:00 2001 From: Achin Gupta Date: Mon, 4 Oct 2021 20:17:45 +0100 Subject: [PATCH] feat(spmc): add support for forwarding a secure interrupt to the SP This patch adds support for forwarding a secure interrupt that preempts the normal world to a SP for top-half interrupt handling. Signed-off-by: Achin Gupta Signed-off-by: Marc Bonnici Change-Id: Iaa6e96f4cf8922ba5b6d128a19359df15e44158d --- services/std_svc/spm/el3_spmc/spmc_main.c | 76 +++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c index 88c13c392..b4ca5ffa2 100644 --- a/services/std_svc/spm/el3_spmc/spmc_main.c +++ b/services/std_svc/spm/el3_spmc/spmc_main.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,11 @@ static struct secure_partition_desc sp_desc[SECURE_PARTITION_COUNT]; */ static struct ns_endpoint_desc ns_ep_desc[NS_PARTITION_COUNT]; +static uint64_t spmc_sp_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie); + /* * Helper function to obtain the array storing the EL3 * Logical Partition descriptors. @@ -1015,6 +1021,7 @@ static uint64_t ffa_features_handler(uint32_t smc_fid, /* Supported features from both worlds. */ case FFA_ERROR: case FFA_SUCCESS_SMC32: + case FFA_INTERRUPT: case FFA_ID_GET: case FFA_FEATURES: case FFA_VERSION: @@ -1639,6 +1646,7 @@ void spmc_populate_attrs(spmc_manifest_attribute_t *spmc_attrs) int32_t spmc_setup(void) { int32_t ret; + uint32_t flags; /* Initialize endpoint descriptors */ initalize_sp_descs(); @@ -1668,6 +1676,21 @@ int32_t spmc_setup(void) /* Register power management hooks with PSCI */ psci_register_spd_pm_hook(&spmc_pm); + /* + * Register an interrupt handler for S-EL1 interrupts + * when generated during code executing in the + * non-secure state. + */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, + spmc_sp_interrupt_handler, + flags); + if (ret != 0) { + ERROR("Failed to register interrupt handler! (%d)\n", ret); + panic(); + } + /* Register init function for deferred init. */ bl31_register_bl32_init(&sp_init); @@ -1753,3 +1776,56 @@ uint64_t spmc_smc_handler(uint32_t smc_fid, } return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); } + +/******************************************************************************* + * This function is the handler registered for S-EL1 interrupts by the SPMC. It + * validates the interrupt and upon success arranges entry into the SP for + * handling the interrupt. + ******************************************************************************/ +static uint64_t spmc_sp_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + struct secure_partition_desc *sp = spmc_get_current_sp_ctx(); + struct sp_exec_ctx *ec; + uint32_t linear_id = plat_my_core_pos(); + + /* Sanity check for a NULL pointer dereference. */ + assert(sp != NULL); + + /* Check the security state when the exception was generated. */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + + /* Panic if not an S-EL1 Partition. */ + if (sp->runtime_el != S_EL1) { + ERROR("Interrupt received for a non S-EL1 SP on core%u.\n", + linear_id); + panic(); + } + + /* Obtain a reference to the SP execution context. */ + ec = spmc_get_sp_ec(sp); + + /* Ensure that the execution context is in waiting state else panic. */ + if (ec->rt_state != RT_STATE_WAITING) { + ERROR("SP EC on core%u is not waiting (%u), it is (%u).\n", + linear_id, RT_STATE_WAITING, ec->rt_state); + panic(); + } + + /* Update the runtime model and state of the partition. */ + ec->rt_model = RT_MODEL_INTR; + ec->rt_state = RT_STATE_RUNNING; + + VERBOSE("SP (0x%x) interrupt start on core%u.\n", sp->sp_id, linear_id); + + /* + * Forward the interrupt to the S-EL1 SP. The interrupt ID is not + * populated as the SP can determine this by itself. + */ + return spmd_smc_switch_state(FFA_INTERRUPT, false, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + handle); +}