aboutsummaryrefslogtreecommitdiff
path: root/services/std_svc/spm/spci.c
diff options
context:
space:
mode:
authorPaul Beesley <paul.beesley@arm.com>2019-10-14 15:27:12 +0000
committerManish Pandey <manish.pandey2@arm.com>2019-12-20 16:03:32 +0000
commit538b002046b567ed3c431633623f335b90476e40 (patch)
treeab7cad1fed63ba04a30a4d5fa073497038bd0224 /services/std_svc/spm/spci.c
parent3f3c341ae58321ec1b86162916d80b6db9187759 (diff)
downloadtrusted-firmware-a-538b002046b567ed3c431633623f335b90476e40.tar.gz
spm: Remove SPM Alpha 1 prototype and support files
The Secure Partition Manager (SPM) prototype implementation is being removed. This is preparatory work for putting in place a dispatcher component that, in turn, enables partition managers at S-EL2 / S-EL1. This patch removes: - The core service files (std_svc/spm) - The Resource Descriptor headers (include/services) - SPRT protocol support and service definitions - SPCI protocol support and service definitions Change-Id: Iaade6f6422eaf9a71187b1e2a4dffd7fb8766426 Signed-off-by: Paul Beesley <paul.beesley@arm.com> Signed-off-by: Artsem Artsemenka <artsem.artsemenka@arm.com>
Diffstat (limited to 'services/std_svc/spm/spci.c')
-rw-r--r--services/std_svc/spm/spci.c769
1 files changed, 0 insertions, 769 deletions
diff --git a/services/std_svc/spm/spci.c b/services/std_svc/spm/spci.c
deleted file mode 100644
index 2e12a6c6b2..0000000000
--- a/services/std_svc/spm/spci.c
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-
-#include <common/debug.h>
-#include <common/runtime_svc.h>
-#include <lib/el3_runtime/context_mgmt.h>
-#include <lib/smccc.h>
-#include <lib/spinlock.h>
-#include <lib/utils.h>
-#include <services/spci_svc.h>
-#include <services/sprt_svc.h>
-#include <smccc_helpers.h>
-#include <sprt_host.h>
-
-#include "spm_private.h"
-
-/*******************************************************************************
- * Macros to print UUIDs.
- ******************************************************************************/
-#define PRINT_UUID_FORMAT "%08x-%08x-%08x-%08x"
-#define PRINT_UUID_ARGS(x) x[0], x[1], x[2], x[3]
-
-/*******************************************************************************
- * Array of structs that contains information about all handles of Secure
- * Services that are currently open.
- ******************************************************************************/
-typedef enum spci_handle_status {
- HANDLE_STATUS_CLOSED = 0,
- HANDLE_STATUS_OPEN,
-} spci_handle_status_t;
-
-typedef struct spci_handle {
- /* 16-bit value used as reference in all SPCI calls */
- uint16_t handle;
-
- /* Client ID of the client that requested the handle */
- uint16_t client_id;
-
- /* Current status of the handle */
- spci_handle_status_t status;
-
- /*
- * Context of the Secure Partition that provides the Secure Service
- * referenced by this handle.
- */
- sp_context_t *sp_ctx;
-
- /*
- * The same handle might be used for multiple requests, keep a reference
- * counter of them.
- */
- unsigned int num_active_requests;
-} spci_handle_t;
-
-static spci_handle_t spci_handles[PLAT_SPCI_HANDLES_MAX_NUM];
-static spinlock_t spci_handles_lock;
-
-/*
- * Given a handle and a client ID, return the element of the spci_handles
- * array that contains the information of the handle. It can only return open
- * handles. It returns NULL if it couldn't find the element in the array.
- */
-static spci_handle_t *spci_handle_info_get(uint16_t handle, uint16_t client_id)
-{
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(spci_handles); i++) {
- spci_handle_t *h = &(spci_handles[i]);
-
- /* Only check for open handles */
- if (h->status == HANDLE_STATUS_CLOSED) {
- continue;
- }
-
- /* Check if either the handle or the client ID are different */
- if ((h->handle != handle) || (h->client_id != client_id)) {
- continue;
- }
-
- return h;
- }
-
- return NULL;
-}
-
-/*
- * Returns a unique value for a handle. This function must be called while
- * spci_handles_lock is locked. It returns 0 on success, -1 on error.
- */
-static int spci_create_handle_value(uint16_t *handle)
-{
- /*
- * Trivial implementation that relies on the fact that any handle will
- * be closed before 2^16 more handles have been opened.
- */
- static uint16_t handle_count;
-
- *handle = handle_count;
-
- handle_count++;
-
- return 0;
-}
-
-/*******************************************************************************
- * Returns a unique token for a Secure Service request.
- ******************************************************************************/
-static uint32_t spci_create_token_value(void)
-{
- /*
- * Trivial implementation that relies on the fact that any response will
- * be read before 2^32 more service requests have been done.
- */
- static uint32_t token_count;
-
- return token_count++;
-}
-
-/*******************************************************************************
- * This function looks for a Secure Partition that has a Secure Service
- * identified by the given UUID. It returns a handle that the client can use to
- * access the service, and an SPCI_*** error code.
- ******************************************************************************/
-static uint64_t spci_service_handle_open_poll(void *handle, u_register_t x1,
- u_register_t x2, u_register_t x3, u_register_t x4,
- u_register_t x5, u_register_t x6, u_register_t x7)
-{
- unsigned int i;
- sp_context_t *sp_ptr;
- uint16_t service_handle;
-
- /* Bits 31:16 of w7 are reserved (MBZ). */
- assert((x7 & 0xFFFF0000U) == 0);
-
- uint16_t client_id = x7 & 0x0000FFFFU;
- uint32_t uuid[4] = { x1, x2, x3, x4 };
-
- /* Get pointer to the Secure Partition that handles this service */
- sp_ptr = spm_sp_get_by_uuid(&uuid);
- if (sp_ptr == NULL) {
- WARN("SPCI: Service requested by client 0x%04x not found\n",
- client_id);
- WARN("SPCI: UUID: " PRINT_UUID_FORMAT "\n",
- PRINT_UUID_ARGS(uuid));
-
- SMC_RET2(handle, SPCI_NOT_PRESENT, 0);
- }
-
- /* Get lock of the array of handles */
- spin_lock(&spci_handles_lock);
-
- /*
- * We need to record the client ID and Secure Partition that correspond
- * to this handle. Look for the first free entry in the array.
- */
- for (i = 0; i < PLAT_SPCI_HANDLES_MAX_NUM; i++) {
- if (spci_handles[i].status == HANDLE_STATUS_CLOSED) {
- break;
- }
- }
-
- if (i == PLAT_SPCI_HANDLES_MAX_NUM) {
- spin_unlock(&spci_handles_lock);
-
- WARN("SPCI: Can't open more handles. Client 0x%04x\n",
- client_id);
- WARN("SPCI: UUID: " PRINT_UUID_FORMAT "\n",
- PRINT_UUID_ARGS(uuid));
-
- SMC_RET2(handle, SPCI_NO_MEMORY, 0);
- }
-
- /* Create new handle value */
- if (spci_create_handle_value(&service_handle) != 0) {
- spin_unlock(&spci_handles_lock);
-
- WARN("SPCI: Can't create a new handle value. Client 0x%04x\n",
- client_id);
- WARN("SPCI: UUID: " PRINT_UUID_FORMAT "\n",
- PRINT_UUID_ARGS(uuid));
-
- SMC_RET2(handle, SPCI_NO_MEMORY, 0);
- }
-
- /* Save all information about this handle */
- spci_handles[i].status = HANDLE_STATUS_OPEN;
- spci_handles[i].client_id = client_id;
- spci_handles[i].handle = service_handle;
- spci_handles[i].num_active_requests = 0U;
- spci_handles[i].sp_ctx = sp_ptr;
-
- /* Release lock of the array of handles */
- spin_unlock(&spci_handles_lock);
-
- VERBOSE("SPCI: Service handle request by client 0x%04x: 0x%04x\n",
- client_id, service_handle);
- VERBOSE("SPCI: UUID: " PRINT_UUID_FORMAT "\n", PRINT_UUID_ARGS(uuid));
-
- /* The handle is returned in the top 16 bits of x1 */
- SMC_RET2(handle, SPCI_SUCCESS, ((uint32_t)service_handle) << 16);
-}
-
-/*******************************************************************************
- * This function closes a handle that a specific client uses to access a Secure
- * Service. It returns a SPCI_*** error code.
- ******************************************************************************/
-static uint64_t spci_service_handle_close(void *handle, u_register_t x1)
-{
- spci_handle_t *handle_info;
- uint16_t client_id = x1 & 0x0000FFFFU;
- uint16_t service_handle = (x1 >> 16) & 0x0000FFFFU;
-
- spin_lock(&spci_handles_lock);
-
- handle_info = spci_handle_info_get(service_handle, client_id);
-
- if (handle_info == NULL) {
- spin_unlock(&spci_handles_lock);
-
- WARN("SPCI: Tried to close invalid handle 0x%04x by client 0x%04x\n",
- service_handle, client_id);
-
- SMC_RET1(handle, SPCI_INVALID_PARAMETER);
- }
-
- if (handle_info->status != HANDLE_STATUS_OPEN) {
- spin_unlock(&spci_handles_lock);
-
- WARN("SPCI: Tried to close handle 0x%04x by client 0x%04x in status %d\n",
- service_handle, client_id, handle_info->status);
-
- SMC_RET1(handle, SPCI_INVALID_PARAMETER);
- }
-
- if (handle_info->num_active_requests != 0U) {
- spin_unlock(&spci_handles_lock);
-
- /* A handle can't be closed if there are requests left */
- WARN("SPCI: Tried to close handle 0x%04x by client 0x%04x with %d requests left\n",
- service_handle, client_id,
- handle_info->num_active_requests);
-
- SMC_RET1(handle, SPCI_BUSY);
- }
-
- memset(handle_info, 0, sizeof(spci_handle_t));
-
- handle_info->status = HANDLE_STATUS_CLOSED;
-
- spin_unlock(&spci_handles_lock);
-
- VERBOSE("SPCI: Closed handle 0x%04x by client 0x%04x.\n",
- service_handle, client_id);
-
- SMC_RET1(handle, SPCI_SUCCESS);
-}
-
-/*******************************************************************************
- * This function requests a Secure Service from a given handle and client ID.
- ******************************************************************************/
-static uint64_t spci_service_request_blocking(void *handle,
- uint32_t smc_fid, u_register_t x1, u_register_t x2,
- u_register_t x3, u_register_t x4, u_register_t x5,
- u_register_t x6, u_register_t x7)
-{
- spci_handle_t *handle_info;
- sp_context_t *sp_ctx;
- cpu_context_t *cpu_ctx;
- uint32_t rx0;
- u_register_t rx1, rx2, rx3;
- uint16_t request_handle, client_id;
-
- /* Get handle array lock */
- spin_lock(&spci_handles_lock);
-
- /* Get pointer to struct of this open handle and client ID. */
- request_handle = (x7 >> 16U) & 0x0000FFFFU;
- client_id = x7 & 0x0000FFFFU;
-
- handle_info = spci_handle_info_get(request_handle, client_id);
- if (handle_info == NULL) {
- spin_unlock(&spci_handles_lock);
-
- WARN("SPCI_SERVICE_TUN_REQUEST_BLOCKING: Not found.\n");
- WARN(" Handle 0x%04x. Client ID 0x%04x\n", request_handle,
- client_id);
-
- SMC_RET1(handle, SPCI_BUSY);
- }
-
- /* Get pointer to the Secure Partition that handles the service */
- sp_ctx = handle_info->sp_ctx;
- assert(sp_ctx != NULL);
- cpu_ctx = &(sp_ctx->cpu_ctx);
-
- /* Blocking requests are only allowed if the queue is empty */
- if (handle_info->num_active_requests > 0) {
- spin_unlock(&spci_handles_lock);
-
- 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;
-
- /* Release handle lock */
- spin_unlock(&spci_handles_lock);
-
- /* Save the Normal world context */
- cm_el1_sysregs_context_save(NON_SECURE);
-
- /* Wait until the Secure Partition is idle and set it to busy. */
- sp_state_wait_switch(sp_ctx, SP_STATE_IDLE, SP_STATE_BUSY);
-
- /* Pass arguments to the Secure Partition */
- struct sprt_queue_entry_message message = {
- .type = SPRT_MSG_TYPE_SERVICE_TUN_REQUEST,
- .client_id = client_id,
- .service_handle = request_handle,
- .session_id = x6,
- .token = 0, /* No token needed for blocking requests */
- .args = {smc_fid, x1, x2, x3, x4, x5}
- };
-
- spin_lock(&(sp_ctx->spm_sp_buffer_lock));
- int rc = sprt_push_message((void *)sp_ctx->spm_sp_buffer_base, &message,
- SPRT_QUEUE_NUM_BLOCKING);
- spin_unlock(&(sp_ctx->spm_sp_buffer_lock));
- if (rc != 0) {
- /*
- * This shouldn't happen, blocking requests can only be made if
- * the request queue is empty.
- */
- assert(rc == -ENOMEM);
- ERROR("SPCI_SERVICE_TUN_REQUEST_BLOCKING: Queue is full.\n");
- panic();
- }
-
- /* Jump to the Secure Partition. */
- rx0 = spm_sp_synchronous_entry(sp_ctx, 0);
-
- /* Verify returned value */
- if (rx0 != SPRT_PUT_RESPONSE_AARCH64) {
- ERROR("SPM: %s: Unexpected x0 value 0x%x\n", __func__, rx0);
- panic();
- }
-
- rx1 = read_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3);
- rx2 = read_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X4);
- rx3 = read_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X5);
-
- /* Flag Secure Partition as idle. */
- assert(sp_ctx->state == SP_STATE_BUSY);
- sp_state_set(sp_ctx, SP_STATE_IDLE);
-
- /* Decrease count of requests. */
- 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);
- cm_set_next_eret_context(NON_SECURE);
-
- SMC_RET4(handle, SPCI_SUCCESS, rx1, rx2, rx3);
-}
-
-/*******************************************************************************
- * This function handles the returned values from the Secure Partition.
- ******************************************************************************/
-static void spci_handle_returned_values(const cpu_context_t *cpu_ctx,
- uint64_t ret)
-{
- if (ret == SPRT_PUT_RESPONSE_AARCH64) {
- uint32_t token;
- uint64_t x3, x4, x5, x6;
-
- token = read_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1);
- x3 = read_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3);
- x4 = read_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X4);
- x5 = read_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X5);
- x6 = read_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X6);
-
- uint16_t client_id = x6 & 0xFFFFU;
- uint16_t service_handle = x6 >> 16;
-
- int rc = spm_response_add(client_id, service_handle, token,
- x3, x4, x5);
- if (rc != 0) {
- /*
- * This is error fatal because we can't return to the SP
- * from this SMC. The SP has crashed.
- */
- panic();
- }
- } else if ((ret != SPRT_YIELD_AARCH64) &&
- (ret != SPM_SECURE_PARTITION_PREEMPTED)) {
- ERROR("SPM: %s: Unexpected x0 value 0x%llx\n", __func__, ret);
- panic();
- }
-}
-
-/*******************************************************************************
- * This function requests a Secure Service from a given handle and client ID.
- ******************************************************************************/
-static uint64_t spci_service_request_start(void *handle,
- uint32_t smc_fid, u_register_t x1, u_register_t x2,
- u_register_t x3, u_register_t x4, u_register_t x5,
- u_register_t x6, u_register_t x7)
-{
- spci_handle_t *handle_info;
- sp_context_t *sp_ctx;
- cpu_context_t *cpu_ctx;
- uint16_t request_handle, client_id;
- uint32_t token;
-
- /* Get handle array lock */
- spin_lock(&spci_handles_lock);
-
- /* Get pointer to struct of this open handle and client ID. */
- request_handle = (x7 >> 16U) & 0x0000FFFFU;
- client_id = x7 & 0x0000FFFFU;
-
- handle_info = spci_handle_info_get(request_handle, client_id);
- if (handle_info == NULL) {
- spin_unlock(&spci_handles_lock);
-
- WARN("SPCI_SERVICE_TUN_REQUEST_START: Not found.\n"
- " Handle 0x%04x. Client ID 0x%04x\n", request_handle,
- client_id);
-
- SMC_RET1(handle, SPCI_INVALID_PARAMETER);
- }
-
- /* Get pointer to the Secure Partition that handles the service */
- sp_ctx = handle_info->sp_ctx;
- assert(sp_ctx != NULL);
- cpu_ctx = &(sp_ctx->cpu_ctx);
-
- /* Prevent this handle from being closed */
- handle_info->num_active_requests += 1;
-
- spm_sp_request_increase(sp_ctx);
-
- /* Create new token for this request */
- token = spci_create_token_value();
-
- /* Release handle lock */
- spin_unlock(&spci_handles_lock);
-
- /* Pass arguments to the Secure Partition */
- struct sprt_queue_entry_message message = {
- .type = SPRT_MSG_TYPE_SERVICE_TUN_REQUEST,
- .client_id = client_id,
- .service_handle = request_handle,
- .session_id = x6,
- .token = token,
- .args = {smc_fid, x1, x2, x3, x4, x5}
- };
-
- spin_lock(&(sp_ctx->spm_sp_buffer_lock));
- int rc = sprt_push_message((void *)sp_ctx->spm_sp_buffer_base, &message,
- SPRT_QUEUE_NUM_NON_BLOCKING);
- spin_unlock(&(sp_ctx->spm_sp_buffer_lock));
- if (rc != 0) {
- WARN("SPCI_SERVICE_TUN_REQUEST_START: SPRT queue full.\n"
- " Handle 0x%04x. Client ID 0x%04x\n", request_handle,
- client_id);
- SMC_RET1(handle, SPCI_NO_MEMORY);
- }
-
- /* Try to enter the partition. If it's not possible, simply return. */
- if (sp_state_try_switch(sp_ctx, SP_STATE_IDLE, SP_STATE_BUSY) != 0) {
- SMC_RET2(handle, SPCI_SUCCESS, token);
- }
-
- /* Save the Normal world context */
- cm_el1_sysregs_context_save(NON_SECURE);
-
- /*
- * This request is non-blocking and needs to be interruptible by
- * non-secure interrupts. Enable their routing to EL3 during the
- * processing of the Secure Partition's service on this core.
- */
-
- /* Jump to the Secure Partition. */
- uint64_t ret = spm_sp_synchronous_entry(sp_ctx, 1);
-
- /* Handle returned values */
- spci_handle_returned_values(cpu_ctx, ret);
-
- /* Flag Secure Partition as idle. */
- assert(sp_ctx->state == SP_STATE_BUSY);
- sp_state_set(sp_ctx, SP_STATE_IDLE);
-
- /* Restore non-secure state */
- cm_el1_sysregs_context_restore(NON_SECURE);
- cm_set_next_eret_context(NON_SECURE);
-
- SMC_RET2(handle, SPCI_SUCCESS, token);
-}
-
-/*******************************************************************************
- * This function returns the response of a Secure Service given a handle, a
- * client ID and a token. If not available, it will schedule a Secure Partition
- * and give it CPU time.
- ******************************************************************************/
-static uint64_t spci_service_request_resume(void *handle, u_register_t x1,
- u_register_t x7)
-{
- int rc;
- u_register_t rx1 = 0, rx2 = 0, rx3 = 0;
- spci_handle_t *handle_info;
- sp_context_t *sp_ctx;
- cpu_context_t *cpu_ctx;
- uint32_t token = (uint32_t) x1;
- uint16_t client_id = x7 & 0x0000FFFF;
- uint16_t service_handle = (x7 >> 16) & 0x0000FFFF;
-
- /* Get pointer to struct of this open handle and client ID. */
- spin_lock(&spci_handles_lock);
-
- handle_info = spci_handle_info_get(service_handle, client_id);
- if (handle_info == NULL) {
- spin_unlock(&spci_handles_lock);
- WARN("SPCI_SERVICE_REQUEST_RESUME: Not found.\n"
- "Handle 0x%04x. Client ID 0x%04x, Token 0x%08x.\n",
- client_id, service_handle, token);
-
- SMC_RET1(handle, SPCI_INVALID_PARAMETER);
- }
-
- /* Get pointer to the Secure Partition that handles the service */
- sp_ctx = handle_info->sp_ctx;
- assert(sp_ctx != NULL);
- cpu_ctx = &(sp_ctx->cpu_ctx);
-
- spin_unlock(&spci_handles_lock);
-
- /* Look for a valid response in the global queue */
- rc = spm_response_get(client_id, service_handle, token,
- &rx1, &rx2, &rx3);
- if (rc == 0) {
- /* Decrease request count */
- spin_lock(&spci_handles_lock);
- handle_info->num_active_requests -= 1;
- spin_unlock(&spci_handles_lock);
- spm_sp_request_decrease(sp_ctx);
-
- SMC_RET4(handle, SPCI_SUCCESS, rx1, rx2, rx3);
- }
-
- /* Try to enter the partition. If it's not possible, simply return. */
- if (sp_state_try_switch(sp_ctx, SP_STATE_IDLE, SP_STATE_BUSY) != 0) {
- SMC_RET1(handle, SPCI_QUEUED);
- }
-
- /* Save the Normal world context */
- cm_el1_sysregs_context_save(NON_SECURE);
-
- /*
- * This request is non-blocking and needs to be interruptible by
- * non-secure interrupts. Enable their routing to EL3 during the
- * processing of the Secure Partition's service on this core.
- */
-
- /* Jump to the Secure Partition. */
- uint64_t ret = spm_sp_synchronous_entry(sp_ctx, 1);
-
- /* Handle returned values */
- spci_handle_returned_values(cpu_ctx, ret);
-
- /* Flag Secure Partition as idle. */
- assert(sp_ctx->state == SP_STATE_BUSY);
- sp_state_set(sp_ctx, SP_STATE_IDLE);
-
- /* Restore non-secure state */
- cm_el1_sysregs_context_restore(NON_SECURE);
- cm_set_next_eret_context(NON_SECURE);
-
- /* Look for a valid response in the global queue */
- rc = spm_response_get(client_id, service_handle, token,
- &rx1, &rx2, &rx3);
- if (rc != 0) {
- SMC_RET1(handle, SPCI_QUEUED);
- }
-
- /* Decrease request count */
- spin_lock(&spci_handles_lock);
- handle_info->num_active_requests -= 1;
- spin_unlock(&spci_handles_lock);
- spm_sp_request_decrease(sp_ctx);
-
- /* Return response */
- SMC_RET4(handle, SPCI_SUCCESS, rx1, rx2, rx3);
-}
-
-/*******************************************************************************
- * This function returns the response of a Secure Service given a handle, a
- * client ID and a token.
- ******************************************************************************/
-static uint64_t spci_service_get_response(void *handle, u_register_t x1,
- u_register_t x7)
-
-{
- int rc;
- u_register_t rx1 = 0, rx2 = 0, rx3 = 0;
- spci_handle_t *handle_info;
- uint32_t token = (uint32_t) x1;
- uint16_t client_id = x7 & 0x0000FFFF;
- uint16_t service_handle = (x7 >> 16) & 0x0000FFFF;
-
- /* Get pointer to struct of this open handle and client ID. */
-
- spin_lock(&spci_handles_lock);
-
- handle_info = spci_handle_info_get(service_handle, client_id);
- if (handle_info == NULL) {
- spin_unlock(&spci_handles_lock);
- WARN("SPCI_SERVICE_GET_RESPONSE: Not found.\n"
- "Handle 0x%04x. Client ID 0x%04x, Token 0x%08x.\n",
- client_id, service_handle, token);
-
- SMC_RET1(handle, SPCI_INVALID_PARAMETER);
- }
-
- spin_unlock(&spci_handles_lock);
-
- /* Look for a valid response in the global queue */
- rc = spm_response_get(client_id, service_handle, token,
- &rx1, &rx2, &rx3);
-
- if (rc != 0) {
- SMC_RET1(handle, SPCI_QUEUED);
- }
-
- /* Decrease request count */
- spin_lock(&spci_handles_lock);
- handle_info->num_active_requests -= 1;
- sp_context_t *sp_ctx;
- sp_ctx = handle_info->sp_ctx;
- spin_unlock(&spci_handles_lock);
- spm_sp_request_decrease(sp_ctx);
-
- /* Return response */
- SMC_RET4(handle, SPCI_SUCCESS, rx1, rx2, rx3);
-}
-
-/*******************************************************************************
- * This function handles all SMCs in the range reserved for SPCI.
- ******************************************************************************/
-static uintptr_t spci_smc_handler(uint32_t smc_fid, u_register_t x1,
- u_register_t x2, u_register_t x3,
- u_register_t x4, void *cookie, void *handle,
- u_register_t flags)
-{
- uint32_t spci_fid;
-
- /* SPCI only supported from the Non-secure world for now */
- if (is_caller_non_secure(flags) == SMC_FROM_SECURE) {
- SMC_RET1(handle, SMC_UNK);
- }
-
- if ((smc_fid & SPCI_FID_TUN_FLAG) == 0) {
-
- /* Miscellaneous calls */
-
- spci_fid = (smc_fid >> SPCI_FID_MISC_SHIFT) & SPCI_FID_MISC_MASK;
-
- switch (spci_fid) {
-
- case SPCI_FID_VERSION:
- SMC_RET1(handle, SPCI_VERSION_COMPILED);
-
- case SPCI_FID_SERVICE_HANDLE_OPEN:
- {
- if ((smc_fid & SPCI_SERVICE_HANDLE_OPEN_NOTIFY_BIT) != 0) {
- /* Not supported for now */
- WARN("SPCI_SERVICE_HANDLE_OPEN_NOTIFY not supported.\n");
- SMC_RET1(handle, SPCI_INVALID_PARAMETER);
- }
-
- uint64_t x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
- uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
- uint64_t x7 = SMC_GET_GP(handle, CTX_GPREG_X7);
-
- return spci_service_handle_open_poll(handle, x1, x2, x3,
- x4, x5, x6, x7);
- }
- case SPCI_FID_SERVICE_HANDLE_CLOSE:
- return spci_service_handle_close(handle, x1);
-
- case SPCI_FID_SERVICE_REQUEST_BLOCKING:
- {
- uint64_t x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
- uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
- uint64_t x7 = SMC_GET_GP(handle, CTX_GPREG_X7);
-
- return spci_service_request_blocking(handle,
- smc_fid, x1, x2, x3, x4, x5, x6, x7);
- }
-
- case SPCI_FID_SERVICE_REQUEST_START:
- {
- uint64_t x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
- uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
- uint64_t x7 = SMC_GET_GP(handle, CTX_GPREG_X7);
-
- return spci_service_request_start(handle,
- smc_fid, x1, x2, x3, x4, x5, x6, x7);
- }
-
- case SPCI_FID_SERVICE_GET_RESPONSE:
- {
- uint64_t x7 = SMC_GET_GP(handle, CTX_GPREG_X7);
-
- return spci_service_get_response(handle, x1, x7);
- }
-
- default:
- break;
- }
-
- } else {
-
- /* Tunneled calls */
-
- spci_fid = (smc_fid >> SPCI_FID_TUN_SHIFT) & SPCI_FID_TUN_MASK;
-
- switch (spci_fid) {
-
- case SPCI_FID_SERVICE_REQUEST_RESUME:
- {
- uint64_t x7 = SMC_GET_GP(handle, CTX_GPREG_X7);
-
- return spci_service_request_resume(handle, x1, x7);
- }
-
- default:
- break;
- }
- }
-
- WARN("SPCI: Unsupported call 0x%08x\n", smc_fid);
- SMC_RET1(handle, SPCI_NOT_SUPPORTED);
-}
-
-DECLARE_RT_SVC(
- spci_handler,
- OEN_SPCI_START,
- OEN_SPCI_END,
- SMC_TYPE_FAST,
- NULL,
- spci_smc_handler
-);