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>
This commit is contained in:
Antonio Nino Diaz 2018-07-03 19:54:59 +01:00
parent d54f0cab3b
commit 2f48ddae74
3 changed files with 48 additions and 0 deletions

View File

@ -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);

View File

@ -46,6 +46,39 @@ sp_context_t *spm_cpu_get_sp_ctx(unsigned int linear_id)
return cpu_sp_ctx[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

View File

@ -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);