From 206d2b37839c42593e015883fc62450db33f59fd Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Tue, 3 Jul 2018 16:54:33 +0100 Subject: SPM: Allow preemption in non-blocking requests Change-Id: I1fdc2285a3f6517a715ad6159322543fd5a37a37 Signed-off-by: Antonio Nino Diaz --- services/std_svc/spm/spci.c | 24 ++++++++++++++++----- services/std_svc/spm/spm_main.c | 44 ++++++++++++++++++++++++++++++++++++-- services/std_svc/spm/spm_private.h | 5 ++++- 3 files changed, 65 insertions(+), 8 deletions(-) (limited to 'services') diff --git a/services/std_svc/spm/spci.c b/services/std_svc/spm/spci.c index 41b0b00c..5e4ff918 100644 --- a/services/std_svc/spm/spci.c +++ b/services/std_svc/spm/spci.c @@ -348,7 +348,7 @@ static uint64_t spci_service_request_blocking(void *handle, } /* Jump to the Secure Partition. */ - rx0 = spm_sp_synchronous_entry(sp_ctx); + rx0 = spm_sp_synchronous_entry(sp_ctx, 0); /* Verify returned value */ if (rx0 != SPRT_PUT_RESPONSE_AARCH64) { @@ -454,8 +454,14 @@ static uint64_t spci_service_request_start(void *handle, /* Save the Normal world context */ cm_el1_sysregs_context_save(NON_SECURE); + /* + * This request is non-blocking and needs to be interruptible by + * non-secure interrupts. Enable their routing to EL3 during the + * processing of the Secure Partition's service on this core. + */ + /* Jump to the Secure Partition. */ - uint64_t ret = spm_sp_synchronous_entry(sp_ctx); + uint64_t ret = spm_sp_synchronous_entry(sp_ctx, 1); /* Verify returned values */ if (ret == SPRT_PUT_RESPONSE_AARCH64) { @@ -480,7 +486,8 @@ static uint64_t spci_service_request_start(void *handle, */ panic(); } - } else if (ret != SPRT_YIELD_AARCH64) { + } else if ((ret != SPRT_YIELD_AARCH64) && + (ret != SPM_SECURE_PARTITION_PREEMPTED)) { ERROR("SPM: %s: Unexpected x0 value 0x%llx\n", __func__, ret); panic(); } @@ -554,8 +561,14 @@ static uint64_t spci_service_request_resume(void *handle, u_register_t x1, /* Save the Normal world context */ cm_el1_sysregs_context_save(NON_SECURE); + /* + * This request is non-blocking and needs to be interruptible by + * non-secure interrupts. Enable their routing to EL3 during the + * processing of the Secure Partition's service on this core. + */ + /* Jump to the Secure Partition. */ - uint64_t ret = spm_sp_synchronous_entry(sp_ctx); + uint64_t ret = spm_sp_synchronous_entry(sp_ctx, 1); /* Verify returned values */ if (ret == SPRT_PUT_RESPONSE_AARCH64) { @@ -580,7 +593,8 @@ static uint64_t spci_service_request_resume(void *handle, u_register_t x1, */ panic(); } - } else if (ret != SPRT_YIELD_AARCH64) { + } else if ((ret != SPRT_YIELD_AARCH64) && + (ret != SPM_SECURE_PARTITION_PREEMPTED)) { ERROR("SPM: %s: Unexpected x0 value 0x%llx\n", __func__, ret); panic(); } diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c index 050c66cc..5d3cc1a3 100644 --- a/services/std_svc/spm/spm_main.c +++ b/services/std_svc/spm/spm_main.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -167,7 +168,7 @@ int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to) * This function takes an SP context pointer and performs a synchronous entry * into it. ******************************************************************************/ -uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx) +uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx, int can_preempt) { uint64_t rc; unsigned int linear_id = plat_my_core_pos(); @@ -186,6 +187,12 @@ uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx) tlbivmalle1(); dsbish(); + if (can_preempt == 1) { + enable_intr_rm_local(INTR_TYPE_NS, SECURE); + } else { + disable_intr_rm_local(INTR_TYPE_NS, SECURE); + } + /* Enter Secure Partition */ rc = spm_secure_partition_enter(&sp_ctx->c_rt_ctx); @@ -215,6 +222,20 @@ __dead2 void spm_sp_synchronous_exit(uint64_t rc) panic(); } +/******************************************************************************* + * This function is the handler registered for Non secure interrupts by the SPM. + * It validates the interrupt and upon success arranges entry into the normal + * world for handling the interrupt. + ******************************************************************************/ +static uint64_t spm_ns_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == SECURE); + + spm_sp_synchronous_exit(SPM_SECURE_PARTITION_PREEMPTED); +} + /******************************************************************************* * Jump to each Secure Partition for the first time. ******************************************************************************/ @@ -235,7 +256,7 @@ static int32_t spm_init(void) ctx->state = SP_STATE_RESET; - rc = spm_sp_synchronous_entry(ctx); + rc = spm_sp_synchronous_entry(ctx, 0); if (rc != SPRT_YIELD_AARCH64) { ERROR("Unexpected return value 0x%llx\n", rc); panic(); @@ -258,10 +279,29 @@ int32_t spm_setup(void) sp_context_t *ctx; void *sp_base, *rd_base; size_t sp_size, rd_size; + uint64_t flags = 0U; /* Disable MMU at EL1 (initialized by BL2) */ disable_mmu_icache_el1(); + /* + * Non-blocking services can be interrupted by Non-secure interrupts. + * Register an interrupt handler for NS interrupts when generated while + * the CPU is in secure state. They are routed to EL3. + */ + set_interrupt_rm_flag(flags, SECURE); + + uint64_t rc_int = register_interrupt_type_handler(INTR_TYPE_NS, + spm_ns_interrupt_handler, flags); + if (rc_int) { + ERROR("SPM: Failed to register NS interrupt handler with rc = %llx\n", + rc_int); + panic(); + } + + /* + * Setup all Secure Partitions. + */ unsigned int i = 0U; while (1) { diff --git a/services/std_svc/spm/spm_private.h b/services/std_svc/spm/spm_private.h index 7216003b..5414e834 100644 --- a/services/std_svc/spm/spm_private.h +++ b/services/std_svc/spm/spm_private.h @@ -29,6 +29,9 @@ #define SP_C_RT_CTX_SIZE 0x60 #define SP_C_RT_CTX_ENTRIES (SP_C_RT_CTX_SIZE >> DWORD_SHIFT) +/* Value returned by spm_sp_synchronous_entry() when a partition is preempted */ +#define SPM_SECURE_PARTITION_PREEMPTED U(0x1234) + #ifndef __ASSEMBLY__ #include @@ -68,7 +71,7 @@ typedef struct sp_context { } sp_context_t; /* Functions used to enter/exit a Secure Partition synchronously */ -uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx); +uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx, int can_preempt); __dead2 void spm_sp_synchronous_exit(uint64_t rc); /* Assembly helpers */ -- cgit v1.2.3