diff --git a/core/arch/arm/include/kernel/secure_partition.h b/core/arch/arm/include/kernel/secure_partition.h index 9924148cb79..c6e50b1813c 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,8 @@ struct sp_session { TEE_UUID ffa_uuid; uint32_t ns_int_mode; uint32_t ns_int_mode_inherited; + bool notif_vm_created; + bool notif_vm_destroyed; TAILQ_ENTRY(sp_session) link; }; diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c index a557622de48..9ffdf1437bd 100644 --- a/core/arch/arm/kernel/secure_partition.c +++ b/core/arch/arm/kernel/secure_partition.c @@ -53,6 +53,9 @@ #define SP_MANIFEST_NS_INT_MANAGED_EXIT (0x1) #define SP_MANIFEST_NS_INT_SIGNALED (0x2) +#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) @@ -119,10 +122,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 | - FFA_PART_PROP_AARCH64_STATE | - FFA_PART_PROP_IS_PE_ID; struct sp_session *s = NULL; TAILQ_FOREACH(s, &open_sp_sessions, link) { @@ -134,6 +133,15 @@ TEE_Result sp_partition_info_get(uint32_t ffa_vers, void *buf, size_t buf_size, continue; if (!count_only && !res) { uint32_t uuid_words[4] = { 0 }; + uint32_t part_props = FFA_PART_PROP_DIRECT_REQ_RECV | + FFA_PART_PROP_DIRECT_REQ_SEND | + FFA_PART_PROP_AARCH64_STATE | + FFA_PART_PROP_IS_PE_ID; + + if (s->notif_vm_created) + part_props |= FFA_PART_PROP_NOTIF_CREATED; + if (s->notif_vm_destroyed) + part_props |= FFA_PART_PROP_NOTIF_DESTROYED; tee_uuid_to_octets((uint8_t *)uuid_words, &s->ffa_uuid); res = spmc_fill_partition_entry(ffa_vers, buf, buf_size, @@ -1434,6 +1442,38 @@ static TEE_Result read_ffa_version(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) { + s->notif_vm_created = false; + s->notif_vm_destroyed = false; + 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->notif_vm_created = true; + + if (v & SP_MANIFEST_VM_DESTROYED_MSG) + s->notif_vm_destroyed = true; + + return TEE_SUCCESS; +} + static TEE_Result sp_init_uuid(const TEE_UUID *bin_uuid, const void * const fdt) { TEE_Result res = TEE_SUCCESS; @@ -1477,6 +1517,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 92ce249d060..a2ec60b43ca 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 */ @@ -898,6 +890,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 != NULL) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + /* The SP must be subscribed for this message */ + if (!dst->notif_vm_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 != NULL) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + /* The SP must be subscribed for this message */ + if (!dst->notif_vm_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"); @@ -947,6 +976,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 != NULL) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + /* The SP must be subscribed for this message */ + if (!dst->notif_vm_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 != NULL) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + /* The SP must be subscribed for this message */ + if (!dst->notif_vm_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);