summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Nino Diaz <antonio.ninodiaz@arm.com>2018-05-23 09:09:41 +0100
committerAntonio Nino Diaz <antonio.ninodiaz@arm.com>2018-05-23 13:50:18 +0100
commit46f996d793cc106191915152b5f5a31fc7a92c19 (patch)
tree955e99063dd2b163cba79d82f789334e4c25eb49
parent07f3f63028847760e8910bb8d861900b3d1cfda3 (diff)
downloadarm-trusted-firmware-46f996d793cc106191915152b5f5a31fc7a92c19.tar.gz
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: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
-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 a72407e88..1971516b8 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 598762e2a..64d8cf89e 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 */