From e81aef98355afb516659cad658e56b2494f9fc83 Mon Sep 17 00:00:00 2001 From: Balint Dobszay Date: Tue, 23 Jul 2024 16:28:58 +0200 Subject: [PATCH 1/2] core: ffa: read S-EL0 SP properties from manifest So far the properties of S-EL0 SPs have been hardcoded when queried by FFA_PARTITION_INFO_GET. This was supposed to be a temporary workaround, so replace this with reading the properties from the SP's manifest which is the proper solution. Acked-by: Jens Wiklander Signed-off-by: Balint Dobszay --- .../arm/include/kernel/secure_partition.h | 3 +- core/arch/arm/kernel/secure_partition.c | 67 ++++++++++++++++++- core/arch/arm/kernel/spmc_sp_handler.c | 15 +++++ core/arch/arm/kernel/thread_spmc.c | 6 ++ 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/core/arch/arm/include/kernel/secure_partition.h b/core/arch/arm/include/kernel/secure_partition.h index 9924148cb79..f8374ba576e 100644 --- a/core/arch/arm/include/kernel/secure_partition.h +++ b/core/arch/arm/include/kernel/secure_partition.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* - * Copyright (c) 2020-2023, Arm Limited. + * Copyright (c) 2020-2024, Arm Limited. */ #ifndef __KERNEL_SECURE_PARTITION_H #define __KERNEL_SECURE_PARTITION_H @@ -33,6 +33,7 @@ struct sp_session { TEE_UUID ffa_uuid; uint32_t ns_int_mode; uint32_t ns_int_mode_inherited; + uint32_t props; TAILQ_ENTRY(sp_session) link; }; diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c index 46f35578851..7a5aabe329c 100644 --- a/core/arch/arm/kernel/secure_partition.c +++ b/core/arch/arm/kernel/secure_partition.c @@ -53,6 +53,13 @@ #define SP_MANIFEST_NS_INT_MANAGED_EXIT (0x1) #define SP_MANIFEST_NS_INT_SIGNALED (0x2) +#define SP_MANIFEST_EXEC_STATE_AARCH64 (0x0) +#define SP_MANIFEST_EXEC_STATE_AARCH32 (0x1) + +#define SP_MANIFEST_DIRECT_REQ_RECEIVE BIT(0) +#define SP_MANIFEST_DIRECT_REQ_SEND BIT(1) +#define SP_MANIFEST_INDIRECT_REQ BIT(2) + #define SP_PKG_HEADER_MAGIC (0x474b5053) #define SP_PKG_HEADER_VERSION_V1 (0x1) #define SP_PKG_HEADER_VERSION_V2 (0x2) @@ -119,8 +126,6 @@ TEE_Result sp_partition_info_get(uint32_t ffa_vers, void *buf, size_t buf_size, bool count_only) { TEE_Result res = TEE_SUCCESS; - uint32_t part_props = FFA_PART_PROP_DIRECT_REQ_RECV | - FFA_PART_PROP_DIRECT_REQ_SEND; struct sp_session *s = NULL; TAILQ_FOREACH(s, &open_sp_sessions, link) { @@ -137,7 +142,7 @@ TEE_Result sp_partition_info_get(uint32_t ffa_vers, void *buf, size_t buf_size, res = spmc_fill_partition_entry(ffa_vers, buf, buf_size, *elem_count, s->endpoint_id, 1, - part_props, uuid_words); + s->props, uuid_words); } *elem_count += 1; } @@ -257,6 +262,9 @@ static TEE_Result sp_create_session(struct sp_sessions_head *open_sessions, s->boot_order = boot_order; + /* Other properties are filled later, based on the SP's manifest */ + s->props = FFA_PART_PROP_IS_PE_ID; + res = new_session_id(&s->endpoint_id); if (res) goto err; @@ -1432,6 +1440,51 @@ static TEE_Result read_ffa_version(const void *fdt, struct sp_session *s) return TEE_SUCCESS; } +static TEE_Result read_sp_exec_state(const void *fdt, struct sp_session *s) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + uint32_t exec_state = 0; + + res = sp_dt_get_u32(fdt, 0, "execution-state", &exec_state); + if (res) { + EMSG("Mandatory property is missing: execution-state"); + return res; + } + + /* Currently only AArch64 SPs are supported */ + if (exec_state == SP_MANIFEST_EXEC_STATE_AARCH64) { + s->props |= FFA_PART_PROP_AARCH64_STATE; + } else { + EMSG("Invalid execution-state value: %"PRIu32, exec_state); + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static TEE_Result read_sp_msg_types(const void *fdt, struct sp_session *s) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + uint32_t msg_method = 0; + + res = sp_dt_get_u32(fdt, 0, "messaging-method", &msg_method); + if (res) { + EMSG("Mandatory property is missing: messaging-method"); + return res; + } + + if (msg_method & SP_MANIFEST_DIRECT_REQ_RECEIVE) + s->props |= FFA_PART_PROP_DIRECT_REQ_RECV; + + if (msg_method & SP_MANIFEST_DIRECT_REQ_SEND) + s->props |= FFA_PART_PROP_DIRECT_REQ_SEND; + + if (msg_method & SP_MANIFEST_INDIRECT_REQ) + IMSG("Indirect messaging is not supported"); + + return TEE_SUCCESS; +} + static TEE_Result sp_init_uuid(const TEE_UUID *bin_uuid, const void * const fdt) { TEE_Result res = TEE_SUCCESS; @@ -1475,6 +1528,14 @@ static TEE_Result sp_init_uuid(const TEE_UUID *bin_uuid, const void * const fdt) if (res) return res; + res = read_sp_exec_state(fdt, sess); + if (res) + return res; + + res = read_sp_msg_types(fdt, sess); + if (res) + return res; + return TEE_SUCCESS; } diff --git a/core/arch/arm/kernel/spmc_sp_handler.c b/core/arch/arm/kernel/spmc_sp_handler.c index 92ce249d060..530ab88a03b 100644 --- a/core/arch/arm/kernel/spmc_sp_handler.c +++ b/core/arch/arm/kernel/spmc_sp_handler.c @@ -898,6 +898,21 @@ ffa_handle_sp_direct_req(struct thread_smc_args *args, return caller_sp; } + if (caller_sp && + !(caller_sp->props & FFA_PART_PROP_DIRECT_REQ_SEND)) { + EMSG("SP 0x%"PRIx16" doesn't support sending direct requests", + caller_sp->endpoint_id); + ffa_set_error(args, FFA_NOT_SUPPORTED); + return caller_sp; + } + + if (!(dst->props & FFA_PART_PROP_DIRECT_REQ_RECV)) { + EMSG("SP 0x%"PRIx16" doesn't support receipt of direct requests", + dst->endpoint_id); + ffa_set_error(args, FFA_NOT_SUPPORTED); + return caller_sp; + } + cpu_spin_lock(&dst->spinlock); if (dst->state != sp_idle) { DMSG("SP is busy"); diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c index e1185a59a71..846856f3b15 100644 --- a/core/arch/arm/kernel/thread_spmc.c +++ b/core/arch/arm/kernel/thread_spmc.c @@ -523,6 +523,12 @@ TEE_Result spmc_fill_partition_entry(uint32_t ffa_vers, void *buf, size_t blen, fpi->partition_properties = part_props; + /* In FF-A 1.0 only bits [2:0] are defined, let's mask others */ + if (ffa_vers < FFA_VERSION_1_1) + fpi->partition_properties &= FFA_PART_PROP_DIRECT_REQ_RECV | + FFA_PART_PROP_DIRECT_REQ_SEND | + FFA_PART_PROP_INDIRECT_MSGS; + if (ffa_vers >= FFA_VERSION_1_1) { if (uuid_words) memcpy(fpi->uuid, uuid_words, FFA_UUID_SIZE); From a51894fe51a93c5585cd5afc43f8c1e38d0f9056 Mon Sep 17 00:00:00 2001 From: Balint Dobszay Date: Tue, 2 Jul 2024 16:22:02 +0200 Subject: [PATCH 2/2] core: ffa: handle VM availability messages for SPs The VM availability messages sent by the hypervisor to an SP should be forwarded to the SP, if the SP has subscribed for these based on the SP manifest. Acked-by: Jens Wiklander Signed-off-by: Balint Dobszay --- core/arch/arm/kernel/secure_partition.c | 36 +++++++++++ core/arch/arm/kernel/spmc_sp_handler.c | 82 ++++++++++++++++++++++--- 2 files changed, 110 insertions(+), 8 deletions(-) diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c index 7a5aabe329c..8e5e52e06b6 100644 --- a/core/arch/arm/kernel/secure_partition.c +++ b/core/arch/arm/kernel/secure_partition.c @@ -60,6 +60,9 @@ #define SP_MANIFEST_DIRECT_REQ_SEND BIT(1) #define SP_MANIFEST_INDIRECT_REQ BIT(2) +#define SP_MANIFEST_VM_CREATED_MSG BIT(0) +#define SP_MANIFEST_VM_DESTROYED_MSG BIT(1) + #define SP_PKG_HEADER_MAGIC (0x474b5053) #define SP_PKG_HEADER_VERSION_V1 (0x1) #define SP_PKG_HEADER_VERSION_V2 (0x2) @@ -1485,6 +1488,35 @@ static TEE_Result read_sp_msg_types(const void *fdt, struct sp_session *s) return TEE_SUCCESS; } +static TEE_Result read_vm_availability_msg(const void *fdt, + struct sp_session *s) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + uint32_t v = 0; + + res = sp_dt_get_u32(fdt, 0, "vm-availability-messages", &v); + + /* This field in the manifest is optional */ + if (res == TEE_ERROR_ITEM_NOT_FOUND) + return TEE_SUCCESS; + + if (res) + return res; + + if (v & ~(SP_MANIFEST_VM_CREATED_MSG | SP_MANIFEST_VM_DESTROYED_MSG)) { + EMSG("Invalid vm-availability-messages value: %"PRIu32, v); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (v & SP_MANIFEST_VM_CREATED_MSG) + s->props |= FFA_PART_PROP_NOTIF_CREATED; + + if (v & SP_MANIFEST_VM_DESTROYED_MSG) + s->props |= FFA_PART_PROP_NOTIF_DESTROYED; + + return TEE_SUCCESS; +} + static TEE_Result sp_init_uuid(const TEE_UUID *bin_uuid, const void * const fdt) { TEE_Result res = TEE_SUCCESS; @@ -1536,6 +1568,10 @@ static TEE_Result sp_init_uuid(const TEE_UUID *bin_uuid, const void * const fdt) if (res) return res; + res = read_vm_availability_msg(fdt, sess); + if (res) + return res; + return TEE_SUCCESS; } diff --git a/core/arch/arm/kernel/spmc_sp_handler.c b/core/arch/arm/kernel/spmc_sp_handler.c index 530ab88a03b..782e4bdef86 100644 --- a/core/arch/arm/kernel/spmc_sp_handler.c +++ b/core/arch/arm/kernel/spmc_sp_handler.c @@ -46,9 +46,6 @@ static TEE_Result ffa_get_dst(struct thread_smc_args *args, { struct sp_session *s = NULL; - if (args->a2 != FFA_PARAM_MBZ) - return FFA_INVALID_PARAMETERS; - s = sp_get_session(FFA_DST(args->a1)); /* Message came from the NW */ @@ -875,11 +872,6 @@ ffa_handle_sp_direct_req(struct thread_smc_args *args, struct sp_session *dst = NULL; TEE_Result res = FFA_OK; - if (args->a2 != FFA_PARAM_MBZ) { - ffa_set_error(args, FFA_INVALID_PARAMETERS); - return caller_sp; - } - res = ffa_get_dst(args, caller_sp, &dst); if (res) { /* Tried to send message to an incorrect endpoint */ @@ -913,6 +905,43 @@ ffa_handle_sp_direct_req(struct thread_smc_args *args, return caller_sp; } + if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) { + switch (args->a2 & FFA_MSG_TYPE_MASK) { + case FFA_MSG_SEND_VM_CREATED: + /* The sender must be the NWd hypervisor (ID 0) */ + if (FFA_SRC(args->a1) != 0 || caller_sp) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + /* The SP must be subscribed for this message */ + if (!(dst->props & FFA_PART_PROP_NOTIF_CREATED)) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + break; + case FFA_MSG_SEND_VM_DESTROYED: + /* The sender must be the NWd hypervisor (ID 0) */ + if (FFA_SRC(args->a1) != 0 || caller_sp) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + /* The SP must be subscribed for this message */ + if (!(dst->props & FFA_PART_PROP_NOTIF_DESTROYED)) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + break; + default: + ffa_set_error(args, FFA_NOT_SUPPORTED); + return caller_sp; + } + } else if (args->a2 != FFA_PARAM_MBZ) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + cpu_spin_lock(&dst->spinlock); if (dst->state != sp_idle) { DMSG("SP is busy"); @@ -962,6 +991,43 @@ ffa_handle_sp_direct_resp(struct thread_smc_args *args, return caller_sp; } + if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) { + switch (args->a2 & FFA_MSG_TYPE_MASK) { + case FFA_MSG_RESP_VM_CREATED: + /* The destination must be the NWd hypervisor (ID 0) */ + if (FFA_DST(args->a1) != 0 || dst) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + /* The SP must be subscribed for this message */ + if (!(dst->props & FFA_PART_PROP_NOTIF_CREATED)) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + break; + case FFA_MSG_RESP_VM_DESTROYED: + /* The destination must be the NWd hypervisor (ID 0) */ + if (FFA_DST(args->a1) != 0 || dst) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + /* The SP must be subscribed for this message */ + if (!(dst->props & FFA_PART_PROP_NOTIF_DESTROYED)) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + break; + default: + ffa_set_error(args, FFA_NOT_SUPPORTED); + return caller_sp; + } + } else if (args->a2 != FFA_PARAM_MBZ) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + if (dst && dst->state != sp_busy) { EMSG("SP is not waiting for a request"); ffa_set_error(args, FFA_INVALID_PARAMETERS);