Commit 46f996d7 authored by Antonio Nino Diaz's avatar Antonio Nino Diaz
Browse files

SPM: Replace SP init flag by generic state enum



Instead of just knowing if the Secure Partition is being initialized or
not, this generic state enum can be used to tell if the Secure Partition
is busy and to add more states in the future if needed.

Also, the spinlock of the secure_partition_context_t structure now only
protects against concurrent accesses to the state of the secure
partition. Previously, it used to lock down the whole structure, thus
preventing one CPU to access any of its fields while another CPU was
executing the partition.

Change-Id: I51215328e2ca8ea2452f92e4a1cb237415958b22
Signed-off-by: default avatarAntonio Nino Diaz <antonio.ninodiaz@arm.com>
parent 07f3f630
...@@ -28,6 +28,58 @@ ...@@ -28,6 +28,58 @@
******************************************************************************/ ******************************************************************************/
static sp_context_t sp_ctx; static sp_context_t sp_ctx;
/*******************************************************************************
* Set state of a Secure Partition context.
******************************************************************************/
void sp_state_set(sp_context_t *sp_ptr, sp_state_t state)
{
spin_lock(&(sp_ptr->state_lock));
sp_ptr->state = state;
spin_unlock(&(sp_ptr->state_lock));
}
/*******************************************************************************
* Wait until the state of a Secure Partition is the specified one and change it
* to the desired state.
******************************************************************************/
void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
{
int success = 0;
while (success == 0) {
spin_lock(&(sp_ptr->state_lock));
if (sp_ptr->state == from) {
sp_ptr->state = to;
success = 1;
}
spin_unlock(&(sp_ptr->state_lock));
}
}
/*******************************************************************************
* Check if the state of a Secure Partition is the specified one and, if so,
* change it to the desired state. Returns 0 on success, -1 on error.
******************************************************************************/
int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
{
int ret = -1;
spin_lock(&(sp_ptr->state_lock));
if (sp_ptr->state == from) {
sp_ptr->state = to;
ret = 0;
}
spin_unlock(&(sp_ptr->state_lock));
return ret;
}
/******************************************************************************* /*******************************************************************************
* This function takes an SP context pointer and prepares the CPU to enter. * This function takes an SP context pointer and prepares the CPU to enter.
******************************************************************************/ ******************************************************************************/
...@@ -68,13 +120,13 @@ static int32_t spm_init(void) ...@@ -68,13 +120,13 @@ static int32_t spm_init(void)
ctx = &sp_ctx; ctx = &sp_ctx;
ctx->sp_init_in_progress = 1; ctx->state = SP_STATE_RESET;
spm_sp_prepare_enter(ctx); spm_sp_prepare_enter(ctx);
rc |= spm_sp_enter(ctx); rc |= spm_sp_enter(ctx);
assert(rc == 0); assert(rc == 0);
ctx->sp_init_in_progress = 0; ctx->state = SP_STATE_IDLE;
INFO("Secure Partition initialized.\n"); INFO("Secure Partition initialized.\n");
...@@ -145,7 +197,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid, ...@@ -145,7 +197,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
/* Save secure state */ /* Save secure state */
cm_el1_sysregs_context_save(SECURE); cm_el1_sysregs_context_save(SECURE);
if (sp_ctx.sp_init_in_progress == 1) { if (sp_ctx.state == SP_STATE_RESET) {
/* /*
* SPM reports completion. The SPM must have * SPM reports completion. The SPM must have
* initiated the original request through a * initiated the original request through a
...@@ -158,8 +210,10 @@ uint64_t spm_smc_handler(uint32_t smc_fid, ...@@ -158,8 +210,10 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
/* spm_secure_partition_exit doesn't return */ /* spm_secure_partition_exit doesn't return */
} }
/* Release the Secure Partition context */ /* Mark Secure Partition as idle */
spin_unlock(&(sp_ctx.lock)); assert(sp_ctx.state == SP_STATE_BUSY);
sp_state_set(&sp_ctx, SP_STATE_IDLE);
/* /*
* This is the result from the Secure partition of an * This is the result from the Secure partition of an
...@@ -181,7 +235,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid, ...@@ -181,7 +235,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
case SP_MEMORY_ATTRIBUTES_GET_AARCH64: case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n"); INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
if (sp_ctx.sp_init_in_progress == 0) { if (sp_ctx.state != SP_STATE_RESET) {
WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n"); WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
SMC_RET1(handle, SPM_NOT_SUPPORTED); SMC_RET1(handle, SPM_NOT_SUPPORTED);
} }
...@@ -192,7 +246,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid, ...@@ -192,7 +246,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
case SP_MEMORY_ATTRIBUTES_SET_AARCH64: case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n"); INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
if (sp_ctx.sp_init_in_progress == 0) { if (sp_ctx.state != SP_STATE_RESET) {
WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n"); WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
SMC_RET1(handle, SPM_NOT_SUPPORTED); SMC_RET1(handle, SPM_NOT_SUPPORTED);
} }
...@@ -236,8 +290,12 @@ uint64_t spm_smc_handler(uint32_t smc_fid, ...@@ -236,8 +290,12 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
/* Save the Normal world context */ /* Save the Normal world context */
cm_el1_sysregs_context_save(NON_SECURE); cm_el1_sysregs_context_save(NON_SECURE);
/* Lock the Secure Partition context. */ /*
spin_lock(&sp_ctx.lock); * Wait until the state of the Secure Partition is IDLE
* and set it to BUSY
*/
sp_state_wait_switch(&sp_ctx,
SP_STATE_IDLE, SP_STATE_BUSY);
/* Jump to the Secure Partition. */ /* Jump to the Secure Partition. */
......
...@@ -35,12 +35,19 @@ ...@@ -35,12 +35,19 @@
#include <stdint.h> #include <stdint.h>
#include <xlat_tables_v2.h> #include <xlat_tables_v2.h>
typedef enum secure_partition_state {
SP_STATE_RESET = 0,
SP_STATE_IDLE,
SP_STATE_BUSY
} sp_state_t;
typedef struct sp_context { typedef struct sp_context {
uint64_t c_rt_ctx; uint64_t c_rt_ctx;
cpu_context_t cpu_ctx; cpu_context_t cpu_ctx;
xlat_ctx_t *xlat_ctx_handle; xlat_ctx_t *xlat_ctx_handle;
unsigned int sp_init_in_progress;
spinlock_t lock; sp_state_t state;
spinlock_t state_lock;
} sp_context_t; } sp_context_t;
/* 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