Commit 206d2b37 authored by Antonio Nino Diaz's avatar Antonio Nino Diaz
Browse files

SPM: Allow preemption in non-blocking requests



Change-Id: I1fdc2285a3f6517a715ad6159322543fd5a37a37
Signed-off-by: default avatarAntonio Nino Diaz <antonio.ninodiaz@arm.com>
parent eb1cbb4c
...@@ -348,7 +348,7 @@ static uint64_t spci_service_request_blocking(void *handle, ...@@ -348,7 +348,7 @@ static uint64_t spci_service_request_blocking(void *handle,
} }
/* Jump to the Secure Partition. */ /* Jump to the Secure Partition. */
rx0 = spm_sp_synchronous_entry(sp_ctx); rx0 = spm_sp_synchronous_entry(sp_ctx, 0);
/* Verify returned value */ /* Verify returned value */
if (rx0 != SPRT_PUT_RESPONSE_AARCH64) { if (rx0 != SPRT_PUT_RESPONSE_AARCH64) {
...@@ -454,8 +454,14 @@ static uint64_t spci_service_request_start(void *handle, ...@@ -454,8 +454,14 @@ static uint64_t spci_service_request_start(void *handle,
/* Save the Normal world context */ /* Save the Normal world context */
cm_el1_sysregs_context_save(NON_SECURE); 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. */ /* 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 */ /* Verify returned values */
if (ret == SPRT_PUT_RESPONSE_AARCH64) { if (ret == SPRT_PUT_RESPONSE_AARCH64) {
...@@ -480,7 +486,8 @@ static uint64_t spci_service_request_start(void *handle, ...@@ -480,7 +486,8 @@ static uint64_t spci_service_request_start(void *handle,
*/ */
panic(); 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); ERROR("SPM: %s: Unexpected x0 value 0x%llx\n", __func__, ret);
panic(); panic();
} }
...@@ -554,8 +561,14 @@ static uint64_t spci_service_request_resume(void *handle, u_register_t x1, ...@@ -554,8 +561,14 @@ static uint64_t spci_service_request_resume(void *handle, u_register_t x1,
/* Save the Normal world context */ /* Save the Normal world context */
cm_el1_sysregs_context_save(NON_SECURE); 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. */ /* 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 */ /* Verify returned values */
if (ret == SPRT_PUT_RESPONSE_AARCH64) { if (ret == SPRT_PUT_RESPONSE_AARCH64) {
...@@ -580,7 +593,8 @@ static uint64_t spci_service_request_resume(void *handle, u_register_t x1, ...@@ -580,7 +593,8 @@ static uint64_t spci_service_request_resume(void *handle, u_register_t x1,
*/ */
panic(); 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); ERROR("SPM: %s: Unexpected x0 value 0x%llx\n", __func__, ret);
panic(); panic();
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <debug.h> #include <debug.h>
#include <ehf.h> #include <ehf.h>
#include <errno.h> #include <errno.h>
#include <interrupt_mgmt.h>
#include <platform.h> #include <platform.h>
#include <runtime_svc.h> #include <runtime_svc.h>
#include <smccc.h> #include <smccc.h>
...@@ -167,7 +168,7 @@ int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to) ...@@ -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 * This function takes an SP context pointer and performs a synchronous entry
* into it. * 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; uint64_t rc;
unsigned int linear_id = plat_my_core_pos(); unsigned int linear_id = plat_my_core_pos();
...@@ -186,6 +187,12 @@ uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx) ...@@ -186,6 +187,12 @@ uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx)
tlbivmalle1(); tlbivmalle1();
dsbish(); 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 */ /* Enter Secure Partition */
rc = spm_secure_partition_enter(&sp_ctx->c_rt_ctx); rc = spm_secure_partition_enter(&sp_ctx->c_rt_ctx);
...@@ -215,6 +222,20 @@ __dead2 void spm_sp_synchronous_exit(uint64_t rc) ...@@ -215,6 +222,20 @@ __dead2 void spm_sp_synchronous_exit(uint64_t rc)
panic(); 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. * Jump to each Secure Partition for the first time.
******************************************************************************/ ******************************************************************************/
...@@ -235,7 +256,7 @@ static int32_t spm_init(void) ...@@ -235,7 +256,7 @@ static int32_t spm_init(void)
ctx->state = SP_STATE_RESET; ctx->state = SP_STATE_RESET;
rc = spm_sp_synchronous_entry(ctx); rc = spm_sp_synchronous_entry(ctx, 0);
if (rc != SPRT_YIELD_AARCH64) { if (rc != SPRT_YIELD_AARCH64) {
ERROR("Unexpected return value 0x%llx\n", rc); ERROR("Unexpected return value 0x%llx\n", rc);
panic(); panic();
...@@ -258,10 +279,29 @@ int32_t spm_setup(void) ...@@ -258,10 +279,29 @@ int32_t spm_setup(void)
sp_context_t *ctx; sp_context_t *ctx;
void *sp_base, *rd_base; void *sp_base, *rd_base;
size_t sp_size, rd_size; size_t sp_size, rd_size;
uint64_t flags = 0U;
/* Disable MMU at EL1 (initialized by BL2) */ /* Disable MMU at EL1 (initialized by BL2) */
disable_mmu_icache_el1(); 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; unsigned int i = 0U;
while (1) { while (1) {
......
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
#define SP_C_RT_CTX_SIZE 0x60 #define SP_C_RT_CTX_SIZE 0x60
#define SP_C_RT_CTX_ENTRIES (SP_C_RT_CTX_SIZE >> DWORD_SHIFT) #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__ #ifndef __ASSEMBLY__
#include <spinlock.h> #include <spinlock.h>
...@@ -68,7 +71,7 @@ typedef struct sp_context { ...@@ -68,7 +71,7 @@ typedef struct sp_context {
} sp_context_t; } sp_context_t;
/* Functions used to enter/exit a Secure Partition synchronously */ /* 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); __dead2 void spm_sp_synchronous_exit(uint64_t rc);
/* Assembly helpers */ /* Assembly helpers */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment