diff options
author | Antonio Nino Diaz <antonio.ninodiaz@arm.com> | 2018-07-03 19:54:59 +0100 |
---|---|---|
committer | Antonio Nino Diaz <antonio.ninodiaz@arm.com> | 2018-12-11 15:04:24 +0000 |
commit | 2f48ddae740aa89dde84945bbebed26c17098af2 (patch) | |
tree | 82d1595e32fa4f557e37e75aa49be2a27ba4da48 /services | |
parent | d54f0cab3bfd795f70c607fc6660fcc095bc2192 (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.c | 7 | ||||
-rw-r--r-- | services/std_svc/spm/spm_main.c | 33 | ||||
-rw-r--r-- | services/std_svc/spm/spm_private.h | 8 |
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); |