From eaaf517cd1bd8c9d5e3e6d2d202a69a0cbcb45bf Mon Sep 17 00:00:00 2001 From: Raghu Krishnamurthy Date: Sun, 25 Dec 2022 13:02:00 -0800 Subject: [PATCH] feat(spmd): introduce FFA_PARTITION_INFO_GET_REGS Add code in SPMD to forward calls to FFA_PARTITION_INFO_GET_REGS. This is a new ABI that allows getting partition information without the need for rx/tx buffer, that helps in situations where having an rx/tx buffer mapped and available is difficult (ex. uefi runtime services). Currently, the spmc at el3 does not support this new ABI. The new ABI uses registers x8-x17 to return partition information so changes are made to ensure those registers are passed through to the SPMC and restored on the return path. Signed-off-by: Raghu Krishnamurthy Change-Id: I1fe5956763e054e4f8d62292fc1247e7120bb5a4 --- include/arch/aarch64/smccc_helpers.h | 18 +++++++++++ include/services/ffa_svc.h | 5 ++- services/std_svc/spmd/spmd_main.c | 46 ++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/include/arch/aarch64/smccc_helpers.h b/include/arch/aarch64/smccc_helpers.h index 920f2943e..950a811d6 100644 --- a/include/arch/aarch64/smccc_helpers.h +++ b/include/arch/aarch64/smccc_helpers.h @@ -75,6 +75,24 @@ #define SMC_SET_GP(_h, _g, _v) \ write_ctx_reg((get_gpregs_ctx(_h)), (_g), (_v)) + +/* Useful for SMCCCv1.2 */ +#define SMC_RET18(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7, _x8, _x9, \ + _x10, _x11, _x12, _x13, _x14, _x15, _x16, _x17) { \ + SMC_SET_GP(_h, CTX_GPREG_X8, _x8); \ + SMC_SET_GP(_h, CTX_GPREG_X9, _x9); \ + SMC_SET_GP(_h, CTX_GPREG_X10, _x10); \ + SMC_SET_GP(_h, CTX_GPREG_X11, _x11); \ + SMC_SET_GP(_h, CTX_GPREG_X12, _x12); \ + SMC_SET_GP(_h, CTX_GPREG_X13, _x13); \ + SMC_SET_GP(_h, CTX_GPREG_X14, _x14); \ + SMC_SET_GP(_h, CTX_GPREG_X15, _x15); \ + SMC_SET_GP(_h, CTX_GPREG_X16, _x16); \ + SMC_SET_GP(_h, CTX_GPREG_X17, _x17); \ + SMC_RET8(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5), (_x6), \ + (_x7)); \ +} + /* * Convenience macros to access EL3 context registers using handle provided to * SMC handler. These take the offset values defined in context.h diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h index da016fd46..8bc911a68 100644 --- a/include/services/ffa_svc.h +++ b/include/services/ffa_svc.h @@ -24,7 +24,7 @@ /* The macros below are used to identify FFA calls from the SMC function ID */ #define FFA_FNUM_MIN_VALUE U(0x60) -#define FFA_FNUM_MAX_VALUE U(0x87) +#define FFA_FNUM_MAX_VALUE U(0x8B) #define is_ffa_fid(fid) __extension__ ({ \ __typeof__(fid) _fid = (fid); \ ((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) && \ @@ -117,6 +117,7 @@ #define FFA_FNUM_SPM_ID_GET U(0x85) #define FFA_FNUM_MSG_SEND2 U(0x86) #define FFA_FNUM_SECONDARY_EP_REGISTER U(0x87) +#define FFA_FNUM_PARTITION_INFO_GET_REGS U(0x8B) /* FFA SMC32 FIDs */ #define FFA_ERROR FFA_FID(SMC_32, FFA_FNUM_ERROR) @@ -180,6 +181,8 @@ FFA_FID(SMC_64, FFA_FNUM_SECONDARY_EP_REGISTER) #define FFA_NOTIFICATION_INFO_GET_SMC64 \ FFA_FID(SMC_64, FFA_FNUM_NOTIFICATION_INFO_GET) +#define FFA_PARTITION_INFO_GET_REGS_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_PARTITION_INFO_GET_REGS) /* * FF-A partition properties values. diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c index dde162288..3c207ad97 100644 --- a/services/std_svc/spmd/spmd_main.c +++ b/services/std_svc/spmd/spmd_main.c @@ -581,10 +581,40 @@ uint64_t spmd_smc_switch_state(uint32_t smc_fid, #endif cm_set_next_eret_context(secure_state_out); +#if SPMD_SPM_AT_SEL2 + /* + * If SPMC is at SEL2, save additional registers x8-x17, which may + * be used in FF-A calls such as FFA_PARTITION_INFO_GET_REGS. + * Note that technically, all SPMCs can support this, but this code is + * under ifdef to minimize breakage in case other SPMCs do not save + * and restore x8-x17. + * We also need to pass through these registers since not all FF-A ABIs + * modify x8-x17, in which case, SMCCC requires that these registers be + * preserved, so the SPMD passes through these registers and expects the + * SPMC to save and restore (potentially also modify) them. + */ + SMC_RET18(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7), + SMC_GET_GP(handle, CTX_GPREG_X8), + SMC_GET_GP(handle, CTX_GPREG_X9), + SMC_GET_GP(handle, CTX_GPREG_X10), + SMC_GET_GP(handle, CTX_GPREG_X11), + SMC_GET_GP(handle, CTX_GPREG_X12), + SMC_GET_GP(handle, CTX_GPREG_X13), + SMC_GET_GP(handle, CTX_GPREG_X14), + SMC_GET_GP(handle, CTX_GPREG_X15), + SMC_GET_GP(handle, CTX_GPREG_X16), + SMC_GET_GP(handle, CTX_GPREG_X17) + ); + +#else SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4, SMC_GET_GP(handle, CTX_GPREG_X5), SMC_GET_GP(handle, CTX_GPREG_X6), SMC_GET_GP(handle, CTX_GPREG_X7)); +#endif } /******************************************************************************* @@ -1042,7 +1072,23 @@ uint64_t spmd_smc_handler(uint32_t smc_fid, return spmd_ffa_error_return(handle, FFA_ERROR_DENIED); } break; /* Not reached */ +#if MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED + case FFA_PARTITION_INFO_GET_REGS_SMC64: + if (secure_origin) { + /* TODO: Future patches to enable support for this */ + return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); + } + /* Call only supported with SMCCC 1.2+ */ + if (MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION) < 0x10002) { + return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); + } + + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, cookie, + handle, flags); + break; /* Not reached */ +#endif default: WARN("SPM: Unsupported call 0x%08x\n", smc_fid); return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); -- 2.39.5