summaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorAntonio Nino Diaz <antonio.ninodiaz@arm.com>2018-07-03 19:54:59 +0100
committerAntonio Nino Diaz <antonio.ninodiaz@arm.com>2018-12-11 15:04:24 +0000
commit2f48ddae740aa89dde84945bbebed26c17098af2 (patch)
tree82d1595e32fa4f557e37e75aa49be2a27ba4da48 /services
parentd54f0cab3bfd795f70c607fc6660fcc095bc2192 (diff)
SPM: Prevent simultaneous blocking calls
Blocking calls can only succeed if the target Secure Partition is idle. Change-Id: Iabeaa0b8d3e653fd8581fa086758936abfc1c772 Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
Diffstat (limited to 'services')
-rw-r--r--services/std_svc/spm/spci.c7
-rw-r--r--services/std_svc/spm/spm_main.c33
-rw-r--r--services/std_svc/spm/spm_private.h8
3 files changed, 48 insertions, 0 deletions
diff --git a/services/std_svc/spm/spci.c b/services/std_svc/spm/spci.c
index cbb0f3cc..1544ae16 100644
--- a/services/std_svc/spm/spci.c
+++ b/services/std_svc/spm/spci.c
@@ -291,6 +291,12 @@ static uint64_t spci_service_request_blocking(void *handle,
SMC_RET1(handle, SPCI_BUSY);
}
+ if (spm_sp_request_increase_if_zero(sp_ctx) == -1) {
+ spin_unlock(&spci_handles_lock);
+
+ SMC_RET1(handle, SPCI_BUSY);
+ }
+
/* Prevent this handle from being closed */
handle_info->num_active_requests += 1;
@@ -348,6 +354,7 @@ static uint64_t spci_service_request_blocking(void *handle,
spin_lock(&spci_handles_lock);
handle_info->num_active_requests -= 1;
spin_unlock(&spci_handles_lock);
+ spm_sp_request_decrease(sp_ctx);
/* Restore non-secure state */
cm_el1_sysregs_context_restore(NON_SECURE);
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index b1d5dd86..050c66cc 100644
--- a/services/std_svc/spm/spm_main.c
+++ b/services/std_svc/spm/spm_main.c
@@ -47,6 +47,39 @@ sp_context_t *spm_cpu_get_sp_ctx(unsigned int linear_id)
}
/*******************************************************************************
+ * Functions to keep track of how many requests a Secure Partition has received
+ * and hasn't finished.
+ ******************************************************************************/
+void spm_sp_request_increase(sp_context_t *sp_ctx)
+{
+ spin_lock(&(sp_ctx->request_count_lock));
+ sp_ctx->request_count++;
+ spin_unlock(&(sp_ctx->request_count_lock));
+}
+
+void spm_sp_request_decrease(sp_context_t *sp_ctx)
+{
+ spin_lock(&(sp_ctx->request_count_lock));
+ sp_ctx->request_count--;
+ spin_unlock(&(sp_ctx->request_count_lock));
+}
+
+/* Returns 0 if it was originally 0, -1 otherwise. */
+int spm_sp_request_increase_if_zero(sp_context_t *sp_ctx)
+{
+ int ret = -1;
+
+ spin_lock(&(sp_ctx->request_count_lock));
+ if (sp_ctx->request_count == 0U) {
+ sp_ctx->request_count++;
+ ret = 0U;
+ }
+ spin_unlock(&(sp_ctx->request_count_lock));
+
+ return ret;
+}
+
+/*******************************************************************************
* This function returns a pointer to the context of the Secure Partition that
* handles the service specified by an UUID. It returns NULL if the UUID wasn't
* found.
diff --git a/services/std_svc/spm/spm_private.h b/services/std_svc/spm/spm_private.h
index a8234c36..a7bd760b 100644
--- a/services/std_svc/spm/spm_private.h
+++ b/services/std_svc/spm/spm_private.h
@@ -58,6 +58,9 @@ typedef struct sp_context {
sp_state_t state;
spinlock_t state_lock;
+ unsigned int request_count;
+ spinlock_t request_count_lock;
+
/* Base and size of the shared SPM<->SP buffer */
uintptr_t spm_sp_buffer_base;
size_t spm_sp_buffer_size;
@@ -80,6 +83,11 @@ void sp_state_set(sp_context_t *sp_ptr, sp_state_t state);
void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to);
int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to);
+/* Functions to keep track of the number of active requests per SP */
+void spm_sp_request_increase(sp_context_t *sp_ctx);
+void spm_sp_request_decrease(sp_context_t *sp_ctx);
+int spm_sp_request_increase_if_zero(sp_context_t *sp_ctx);
+
/* Functions related to the translation tables management */
xlat_ctx_t *spm_sp_xlat_context_alloc(void);
void sp_map_memory_regions(sp_context_t *sp_ctx);