From 3de378ff8c9430c964cbe9b0c58fa5afc4d237ce Mon Sep 17 00:00:00 2001 From: Marc Bonnici Date: Thu, 9 Dec 2021 18:34:02 +0000 Subject: [PATCH 1/6] feat(spmc): enable parsing of messaging methods from manifest Ensure that the `messaging-methods` entry is populated in an SP's manifest. Currently only direct messaging is supported so alert if this does not match the manifest entry. Signed-off-by: Marc Bonnici Change-Id: I67f1fad71a3507627993a004e0f8579388faf178 --- services/std_svc/spm/el3_spmc/spmc_main.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c index 35def25af..1eb4a30df 100644 --- a/services/std_svc/spm/el3_spmc/spmc_main.c +++ b/services/std_svc/spm/el3_spmc/spmc_main.c @@ -544,6 +544,23 @@ static int sp_manifest_parse(void *sp_manifest, int offset, sp->execution_state = config_32; + ret = fdt_read_uint32(sp_manifest, node, + "messaging-method", &config_32); + if (ret != 0) { + ERROR("Missing Secure Partition messaging method.\n"); + return ret; + } + + /* Validate this entry, we currently only support direct messaging. */ + if ((config_32 & ~(FFA_PARTITION_DIRECT_REQ_RECV | + FFA_PARTITION_DIRECT_REQ_SEND)) != 0U) { + WARN("Invalid Secure Partition messaging method (0x%x)\n", + config_32); + return -EINVAL; + } + + sp->properties = config_32; + ret = fdt_read_uint32(sp_manifest, node, "execution-ctx-count", &config_32); From a7c00505f85684326a223535a319c170d14826f6 Mon Sep 17 00:00:00 2001 From: Marc Bonnici Date: Wed, 24 Nov 2021 10:32:16 +0000 Subject: [PATCH 2/6] feat(spmc): add helper function to obtain hyp structure We assume that the first descriptor in the normal world endpoints is reserved for the hypervisor and add a helper function to enable retrieving this directly. Signed-off-by: Marc Bonnici Change-Id: I67c3589994eb820ef420db6ab7e8bd0825d64455 --- services/std_svc/spm/el3_spmc/spmc_main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c index 1eb4a30df..efa9da804 100644 --- a/services/std_svc/spm/el3_spmc/spmc_main.c +++ b/services/std_svc/spm/el3_spmc/spmc_main.c @@ -81,6 +81,15 @@ struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id) return NULL; } +/* + * Helper function to obtain the descriptor of the Hypervisor or OS kernel. + * We assume that the first descriptor is reserved for this entity. + */ +struct ns_endpoint_desc *spmc_get_hyp_ctx(void) +{ + return &(ns_ep_desc[0]); +} + /****************************************************************************** * This function returns to the place where spmc_sp_synchronous_entry() was * called originally. From f16b6ee3deac93706efe465f399c9542e12d5eeb Mon Sep 17 00:00:00 2001 From: Marc Bonnici Date: Wed, 24 Nov 2021 10:33:48 +0000 Subject: [PATCH 3/6] feat(spmc): add helper function to obtain endpoint mailbox Add a helper function to obtain the relevant mailbox buffers depending on which entity was last run. This will be used in subsequent functionality to populate requested information in the callers RX buffer. Signed-off-by: Marc Bonnici Change-Id: I85959ced4d1454be05a7b3fb6853ed3ab7f0cf3e --- services/std_svc/spm/el3_spmc/spmc.h | 6 ++++++ services/std_svc/spm/el3_spmc/spmc_main.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/services/std_svc/spm/el3_spmc/spmc.h b/services/std_svc/spm/el3_spmc/spmc.h index 0915d0b4c..faa604f53 100644 --- a/services/std_svc/spm/el3_spmc/spmc.h +++ b/services/std_svc/spm/el3_spmc/spmc.h @@ -221,4 +221,10 @@ bool is_ffa_secure_id_valid(uint16_t partition_id); */ struct el3_lp_desc *get_el3_lp_array(void); +/* + * Helper function to obtain the RX/TX buffer pair descriptor of the Hypervisor + * or OS kernel in the normal world or the last SP that was run. + */ +struct mailbox *spmc_get_mbox_desc(bool secure_origin); + #endif /* SPMC_H */ diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c index efa9da804..ed42a29d7 100644 --- a/services/std_svc/spm/el3_spmc/spmc_main.c +++ b/services/std_svc/spm/el3_spmc/spmc_main.c @@ -90,6 +90,20 @@ struct ns_endpoint_desc *spmc_get_hyp_ctx(void) return &(ns_ep_desc[0]); } +/* + * Helper function to obtain the RX/TX buffer pair descriptor of the Hypervisor + * or OS kernel in the normal world or the last SP that was run. + */ +struct mailbox *spmc_get_mbox_desc(bool secure_origin) +{ + /* Obtain the RX/TX buffer pair descriptor. */ + if (secure_origin) { + return &(spmc_get_current_sp_ctx()->mailbox); + } else { + return &(spmc_get_hyp_ctx()->mailbox); + } +} + /****************************************************************************** * This function returns to the place where spmc_sp_synchronous_entry() was * called originally. From 0c7707fdf21fc2a8658f5a4bdfd2f8883d02ada5 Mon Sep 17 00:00:00 2001 From: Marc Bonnici Date: Wed, 8 Dec 2021 14:24:03 +0000 Subject: [PATCH 4/6] feat(spmc): enable handling FFA_VERSION ABI Report the SPMC version to the caller, currently v1.1 and also store the requested version to allow the SPMC to use the corresponding FF-A version in future ABI calls. Signed-off-by: Marc Bonnici Change-Id: I79aafd1e6694cbd4b231bbd0cac5834a71063d79 --- include/services/ffa_svc.h | 1 + services/std_svc/spm/el3_spmc/spmc_main.c | 47 ++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h index 2b4a37741..08365796c 100644 --- a/include/services/ffa_svc.h +++ b/include/services/ffa_svc.h @@ -38,6 +38,7 @@ #define FFA_VERSION_MINOR_SHIFT 0 #define FFA_VERSION_MINOR_MASK U(0xFFFF) #define FFA_VERSION_BIT31_MASK U(0x1u << 31) +#define FFA_VERSION_MASK U(0xFFFFFFFF) #define MAKE_FFA_VERSION(major, minor) \ diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c index ed42a29d7..4a0853e70 100644 --- a/services/std_svc/spm/el3_spmc/spmc_main.c +++ b/services/std_svc/spm/el3_spmc/spmc_main.c @@ -72,7 +72,7 @@ struct sp_exec_ctx *spmc_get_sp_ec(struct secure_partition_desc *sp) /* Helper function to get pointer to SP context from its ID. */ struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id) { - /* Check for SWd Partitions. */ + /* Check for Secure World Partitions. */ for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) { if (sp_desc[i].sp_id == id) { return &(sp_desc[i]); @@ -514,6 +514,47 @@ static uint64_t ffa_error_handler(uint32_t smc_fid, return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); } +static uint64_t ffa_version_handler(uint32_t smc_fid, + bool secure_origin, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags) +{ + uint32_t requested_version = x1 & FFA_VERSION_MASK; + + if (requested_version & FFA_VERSION_BIT31_MASK) { + /* Invalid encoding, return an error. */ + SMC_RET1(handle, FFA_ERROR_NOT_SUPPORTED); + /* Execution stops here. */ + } + + /* Determine the caller to store the requested version. */ + if (secure_origin) { + /* + * Ensure that the SP is reporting the same version as + * specified in its manifest. If these do not match there is + * something wrong with the SP. + * TODO: Should we abort the SP? For now assert this is not + * case. + */ + assert(requested_version == + spmc_get_current_sp_ctx()->ffa_version); + } else { + /* + * If this is called by the normal world, record this + * information in its descriptor. + */ + spmc_get_hyp_ctx()->ffa_version = requested_version; + } + + SMC_RET1(handle, MAKE_FFA_VERSION(FFA_VERSION_MAJOR, + FFA_VERSION_MINOR)); +} + /******************************************************************************* * This function will parse the Secure Partition Manifest. From manifest, it * will fetch details for preparing Secure partition image context and secure @@ -906,6 +947,10 @@ uint64_t spmc_smc_handler(uint32_t smc_fid, { switch (smc_fid) { + case FFA_VERSION: + return ffa_version_handler(smc_fid, secure_origin, x1, x2, x3, + x4, cookie, handle, flags); + case FFA_MSG_SEND_DIRECT_REQ_SMC32: case FFA_MSG_SEND_DIRECT_REQ_SMC64: return direct_req_smc_handler(smc_fid, secure_origin, x1, x2, From 9576fa93a2effc23a533b80dce41d7104a8d200b Mon Sep 17 00:00:00 2001 From: Marc Bonnici Date: Wed, 8 Dec 2021 14:27:40 +0000 Subject: [PATCH 5/6] feat(spmd): enable SPMD to forward FFA_VERSION to EL3 SPMC In order to allow the EL3 SPMC to know the FF-A version of the entity running in the normal world, allow the SPMD to forward the call rather than replying on its behalf. This solution works as the EL3 can ERET directly back to the calling partition however this is not an option when the SPMC resides in a lower exception level. A new approach will be required to support such scenario. Signed-off-by: Marc Bonnici Change-Id: Ic2d6e49c06340167eadefe893c6e1e20b67ab498 --- services/std_svc/spmd/spmd_main.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c index 5b131cd5e..777a96203 100644 --- a/services/std_svc/spmd/spmd_main.c +++ b/services/std_svc/spmd/spmd_main.c @@ -626,7 +626,8 @@ uint64_t spmd_smc_handler(uint32_t smc_fid, * If caller is secure and SPMC was initialized, * return FFA_VERSION of SPMD. * If caller is non secure and SPMC was initialized, - * return SPMC's version. + * forward to the EL3 SPMC if enabled, otherwise return + * the SPMC version if implemented at a lower EL. * Sanity check to "input_version". * If the EL3 SPMC is enabled, ignore the SPMC state as * this is not used. @@ -635,6 +636,17 @@ uint64_t spmd_smc_handler(uint32_t smc_fid, (!is_spmc_at_el3() && (ctx->state == SPMC_STATE_RESET))) { ret = FFA_ERROR_NOT_SUPPORTED; } else if (!secure_origin) { + if (is_spmc_at_el3()) { + /* + * Forward the call directly to the EL3 SPMC, if + * enabled, as we don't need to wrap the call in + * a direct request. + */ + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, cookie, + handle, flags); + } + gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); uint64_t rc; From c2b1434369292081f907c548e496f59e197eb2f1 Mon Sep 17 00:00:00 2001 From: Marc Bonnici Date: Thu, 9 Dec 2021 11:32:30 +0000 Subject: [PATCH 6/6] feat(spmc): add helper to obtain a partitions FF-A version Add a helper function to obtain the FF-A version of a calling partition. This is used to ensure that the SPMC maintains backwards compatibility if the partition implements a lower minor version for the same major version than the SPMC. Signed-off-by: Marc Bonnici Change-Id: I5b364a1e510a999bb0c4cacae28f23f8a42a1e3e --- services/std_svc/spm/el3_spmc/spmc_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c index 4a0853e70..33a25a262 100644 --- a/services/std_svc/spm/el3_spmc/spmc_main.c +++ b/services/std_svc/spm/el3_spmc/spmc_main.c @@ -555,6 +555,18 @@ static uint64_t ffa_version_handler(uint32_t smc_fid, FFA_VERSION_MINOR)); } +/******************************************************************************* + * Helper function to obtain the FF-A version of the calling partition. + ******************************************************************************/ +uint32_t get_partition_ffa_version(bool secure_origin) +{ + if (secure_origin) { + return spmc_get_current_sp_ctx()->ffa_version; + } else { + return spmc_get_hyp_ctx()->ffa_version; + } +} + /******************************************************************************* * This function will parse the Secure Partition Manifest. From manifest, it * will fetch details for preparing Secure partition image context and secure