mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-23 13:36:05 +00:00
SPM: Allow preemption in non-blocking requests
Change-Id: I1fdc2285a3f6517a715ad6159322543fd5a37a37 Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
This commit is contained in:
parent
eb1cbb4c83
commit
206d2b3783
3 changed files with 65 additions and 8 deletions
|
@ -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,
|
||||||
/* 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,
|
||||||
*/
|
*/
|
||||||
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,
|
||||||
/* 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,
|
||||||
*/
|
*/
|
||||||
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 @@
|
||||||
#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)
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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 @@
|
||||||
#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 {
|
||||||
} 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 */
|
||||||
|
|
Loading…
Add table
Reference in a new issue