From 9944f55761c4d5cc1feefaf5e33bf7fb83d8f5f3 Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Thu, 9 Dec 2021 11:20:13 +0000 Subject: [PATCH] feat(ff-a): forward FFA_VERSION from SPMD to SPMC Introduced by FF-A v1.1 we must forward a call to FFA_VERSION to the SPMC so that the ffa version of the caller can be stored for later use. Since the return of FFA_VERSION is not wrapped in a FF-A call we need to use a direct message request to do this forwarding. For the spmd_handler in the SPMC to hand off to the correct function we use w2 to specify a target framework function. Therefore we must update PSCI CPU_OFF to do this as well. Change-Id: Ibaa6832b66f1597b3d65aa8986034f0c5916016d Signed-off-by: Daniel Boulby --- services/std_svc/spmd/spmd_main.c | 72 ++++++++++++++++++++++++++-- services/std_svc/spmd/spmd_pm.c | 20 ++------ services/std_svc/spmd/spmd_private.h | 12 ++++- 3 files changed, 83 insertions(+), 21 deletions(-) diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c index f5de54966..7a063fe6d 100644 --- a/services/std_svc/spmd/spmd_main.c +++ b/services/std_svc/spmd/spmd_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -90,6 +90,21 @@ static uint64_t spmd_smc_forward(uint32_t smc_fid, uint64_t x4, void *handle); +/****************************************************************************** + * Builds an SPMD to SPMC direct message request. + *****************************************************************************/ +void spmd_build_spmc_message(gp_regs_t *gpregs, uint8_t target_func, + unsigned long long message) +{ + write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_MSG_SEND_DIRECT_REQ_SMC32); + write_ctx_reg(gpregs, CTX_GPREG_X1, + (SPMD_DIRECT_MSG_ENDPOINT_ID << FFA_DIRECT_MSG_SOURCE_SHIFT) | + spmd_spmc_id_get()); + write_ctx_reg(gpregs, CTX_GPREG_X2, BIT(31) | target_func); + write_ctx_reg(gpregs, CTX_GPREG_X3, message); +} + + /******************************************************************************* * This function takes an SPMC context pointer and performs a synchronous * SPMC entry. @@ -543,8 +558,59 @@ uint64_t spmd_smc_handler(uint32_t smc_fid, (ctx->state == SPMC_STATE_RESET)) { ret = FFA_ERROR_NOT_SUPPORTED; } else if (!secure_origin) { - ret = MAKE_FFA_VERSION(spmc_attrs.major_version, - spmc_attrs.minor_version); + gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); + uint64_t rc; + + if (spmc_attrs.major_version == 1 && + spmc_attrs.minor_version == 0) { + ret = MAKE_FFA_VERSION(spmc_attrs.major_version, + spmc_attrs.minor_version); + SMC_RET8(handle, (uint32_t)ret, + FFA_TARGET_INFO_MBZ, + FFA_TARGET_INFO_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + break; + } + /* Save non-secure system registers context */ + cm_el1_sysregs_context_save(NON_SECURE); +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_save(NON_SECURE); +#endif + + /* + * The incoming request has FFA_VERSION as X0 smc_fid + * and requested version in x1. Prepare a direct request + * from SPMD to SPMC with FFA_VERSION framework function + * identifier in X2 and requested version in X3. + */ + spmd_build_spmc_message(gpregs, + SPMD_FWK_MSG_FFA_VERSION_REQ, + input_version); + + rc = spmd_spm_core_sync_entry(ctx); + + if ((rc != 0ULL) || + (SMC_GET_GP(gpregs, CTX_GPREG_X0) != + FFA_MSG_SEND_DIRECT_RESP_SMC32) || + (SMC_GET_GP(gpregs, CTX_GPREG_X2) != + (SPMD_FWK_MSG_BIT | + SPMD_FWK_MSG_FFA_VERSION_RESP))) { + ERROR("Failed to forward FFA_VERSION\n"); + ret = FFA_ERROR_NOT_SUPPORTED; + } else { + ret = SMC_GET_GP(gpregs, CTX_GPREG_X3); + } + + /* + * Return here after SPMC has handled FFA_VERSION. + * The returned SPMC version is held in X3. + * Forward this version in X0 to the non-secure caller. + */ + return spmd_smc_forward(ret, true, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, gpregs); } else { ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR); diff --git a/services/std_svc/spmd/spmd_pm.c b/services/std_svc/spmd/spmd_pm.c index 6ebafcaa7..b71916130 100644 --- a/services/std_svc/spmd/spmd_pm.c +++ b/services/std_svc/spmd/spmd_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -19,21 +19,6 @@ static struct { spinlock_t lock; } g_spmd_pm; -/******************************************************************************* - * spmd_build_spmc_message - * - * Builds an SPMD to SPMC direct message request. - ******************************************************************************/ -static void spmd_build_spmc_message(gp_regs_t *gpregs, unsigned long long message) -{ - write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_MSG_SEND_DIRECT_REQ_SMC32); - write_ctx_reg(gpregs, CTX_GPREG_X1, - (SPMD_DIRECT_MSG_ENDPOINT_ID << FFA_DIRECT_MSG_SOURCE_SHIFT) | - spmd_spmc_id_get()); - write_ctx_reg(gpregs, CTX_GPREG_X2, FFA_PARAM_MBZ); - write_ctx_reg(gpregs, CTX_GPREG_X3, message); -} - /******************************************************************************* * spmd_pm_secondary_ep_register ******************************************************************************/ @@ -137,7 +122,8 @@ static int32_t spmd_cpu_off_handler(u_register_t unused) assert(ctx->state != SPMC_STATE_OFF); /* Build an SPMD to SPMC direct message request. */ - spmd_build_spmc_message(get_gpregs_ctx(&ctx->cpu_ctx), PSCI_CPU_OFF); + spmd_build_spmc_message(get_gpregs_ctx(&ctx->cpu_ctx), + SPMD_FWK_MSG_PSCI, PSCI_CPU_OFF); rc = spmd_spm_core_sync_entry(ctx); if (rc != 0ULL) { diff --git a/services/std_svc/spmd/spmd_private.h b/services/std_svc/spmd/spmd_private.h index 1fe506524..4cd6a744b 100644 --- a/services/std_svc/spmd/spmd_private.h +++ b/services/std_svc/spmd/spmd_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -64,6 +64,16 @@ typedef struct spmd_spm_core_context { #define SPMD_DIRECT_MSG_ENDPOINT_ID U(FFA_ENDPOINT_ID_MAX - 1) +/* Define SPMD target function IDs for framework messages to the SPMC */ +#define SPMD_FWK_MSG_BIT BIT(31) +#define SPMD_FWK_MSG_PSCI U(0) +#define SPMD_FWK_MSG_FFA_VERSION_REQ U(0x8) +#define SPMD_FWK_MSG_FFA_VERSION_RESP U(0x9) + +/* Function to build SPMD to SPMC message */ +void spmd_build_spmc_message(gp_regs_t *gpregs, uint8_t target, + unsigned long long message); + /* Functions used to enter/exit SPMC synchronously */ uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *ctx); __dead2 void spmd_spm_core_sync_exit(uint64_t rc);