summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/std_svc/spm/spm_main.c76
-rw-r--r--services/std_svc/spm/spm_private.h11
2 files changed, 76 insertions, 11 deletions
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index a72407e8..1971516b 100644
--- a/services/std_svc/spm/spm_main.c
+++ b/services/std_svc/spm/spm_main.c
@@ -29,6 +29,58 @@
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.
******************************************************************************/
static void spm_sp_prepare_enter(sp_context_t *sp_ctx)
@@ -68,13 +120,13 @@ static int32_t spm_init(void)
ctx = &sp_ctx;
- ctx->sp_init_in_progress = 1;
+ ctx->state = SP_STATE_RESET;
spm_sp_prepare_enter(ctx);
rc |= spm_sp_enter(ctx);
assert(rc == 0);
- ctx->sp_init_in_progress = 0;
+ ctx->state = SP_STATE_IDLE;
INFO("Secure Partition initialized.\n");
@@ -145,7 +197,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
/* Save secure state */
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
* initiated the original request through a
@@ -158,8 +210,10 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
/* spm_secure_partition_exit doesn't return */
}
- /* Release the Secure Partition context */
- spin_unlock(&(sp_ctx.lock));
+ /* Mark Secure Partition as idle */
+ 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
@@ -181,7 +235,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
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");
SMC_RET1(handle, SPM_NOT_SUPPORTED);
}
@@ -192,7 +246,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
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");
SMC_RET1(handle, SPM_NOT_SUPPORTED);
}
@@ -236,8 +290,12 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
/* Save the Normal world context */
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. */
diff --git a/services/std_svc/spm/spm_private.h b/services/std_svc/spm/spm_private.h
index 598762e2..64d8cf89 100644
--- a/services/std_svc/spm/spm_private.h
+++ b/services/std_svc/spm/spm_private.h
@@ -35,12 +35,19 @@
#include <stdint.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 {
uint64_t c_rt_ctx;
cpu_context_t cpu_ctx;
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;
/* Assembly helpers */