diff --git a/include/services/el3_spmc_ffa_memory.h b/include/services/el3_spmc_ffa_memory.h index 8e0c5ae38..2037ecadc 100644 --- a/include/services/el3_spmc_ffa_memory.h +++ b/include/services/el3_spmc_ffa_memory.h @@ -63,6 +63,8 @@ CASSERT(sizeof(struct ffa_comp_mrd) == 16, assert_ffa_comp_mrd_size_mismatch); * typedef ffa_mem_attr8_t - Memory region attributes v1.0. * typedef ffa_mem_attr16_t - Memory region attributes v1.1. * + * * @FFA_MEM_ATTR_NS_BIT: + * Memory security state. * * @FFA_MEM_ATTR_DEVICE_NGNRNE: * Device-nGnRnE. * * @FFA_MEM_ATTR_DEVICE_NGNRE: @@ -84,6 +86,7 @@ CASSERT(sizeof(struct ffa_comp_mrd) == 16, assert_ffa_comp_mrd_size_mismatch); */ typedef uint8_t ffa_mem_attr8_t; typedef uint16_t ffa_mem_attr16_t; +#define FFA_MEM_ATTR_NS_BIT (0x1U << 6) #define FFA_MEM_ATTR_DEVICE_NGNRNE ((1U << 4) | (0x0U << 2)) #define FFA_MEM_ATTR_DEVICE_NGNRE ((1U << 4) | (0x1U << 2)) #define FFA_MEM_ATTR_DEVICE_NGRE ((1U << 4) | (0x2U << 2)) diff --git a/services/std_svc/spm/el3_spmc/spmc.h b/services/std_svc/spm/el3_spmc/spmc.h index 9926c68f5..d62be91eb 100644 --- a/services/std_svc/spm/el3_spmc/spmc.h +++ b/services/std_svc/spm/el3_spmc/spmc.h @@ -37,6 +37,7 @@ #define FFA_ID_MASK U(0xFFFF) #define FFA_PARTITION_ID_SHIFT U(16) #define FFA_FEATURES_BIT31_MASK U(0x1u << 31) +#define FFA_FEATURES_RET_REQ_NS_BIT U(0x1 << 1) #define FFA_RUN_EP_ID(ep_vcpu_ids) \ ((ep_vcpu_ids >> FFA_PARTITION_ID_SHIFT) & FFA_ID_MASK) @@ -170,6 +171,12 @@ struct secure_partition_desc { * Store whether the SP has subscribed to any power management messages. */ uint16_t pwr_mgmt_msgs; + + /* + * Store whether the SP has requested the use of the NS bit for memory + * management transactions if it is using FF-A v1.0. + */ + bool ns_bit_requested; }; /* diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c index c7071abf9..9b8621a73 100644 --- a/services/std_svc/spm/el3_spmc/spmc_main.c +++ b/services/std_svc/spm/el3_spmc/spmc_main.c @@ -990,6 +990,53 @@ err: return spmc_ffa_error_return(handle, ret); } +static uint64_t ffa_feature_success(void *handle, uint32_t arg2) +{ + SMC_RET3(handle, FFA_SUCCESS_SMC32, 0, arg2); +} + +static uint64_t ffa_features_retrieve_request(bool secure_origin, + uint32_t input_properties, + void *handle) +{ + /* + * If we're called by the normal world we don't support any + * additional features. + */ + if (!secure_origin) { + if ((input_properties & FFA_FEATURES_RET_REQ_NS_BIT) != 0U) { + return spmc_ffa_error_return(handle, + FFA_ERROR_NOT_SUPPORTED); + } + + } else { + struct secure_partition_desc *sp = spmc_get_current_sp_ctx(); + /* + * If v1.1 the NS bit must be set otherwise it is an invalid + * call. If v1.0 check and store whether the SP has requested + * the use of the NS bit. + */ + if (sp->ffa_version == MAKE_FFA_VERSION(1, 1)) { + if ((input_properties & + FFA_FEATURES_RET_REQ_NS_BIT) == 0U) { + return spmc_ffa_error_return(handle, + FFA_ERROR_NOT_SUPPORTED); + } + return ffa_feature_success(handle, + FFA_FEATURES_RET_REQ_NS_BIT); + } else { + sp->ns_bit_requested = (input_properties & + FFA_FEATURES_RET_REQ_NS_BIT) != + 0U; + } + if (sp->ns_bit_requested) { + return ffa_feature_success(handle, + FFA_FEATURES_RET_REQ_NS_BIT); + } + } + SMC_RET1(handle, FFA_SUCCESS_SMC32); +} + static uint64_t ffa_features_handler(uint32_t smc_fid, bool secure_origin, uint64_t x1, @@ -1003,21 +1050,34 @@ static uint64_t ffa_features_handler(uint32_t smc_fid, uint32_t function_id = (uint32_t) x1; uint32_t input_properties = (uint32_t) x2; - /* - * We don't currently support any additional input properties - * for any ABI therefore ensure this value is always set to 0. - */ - if (input_properties != 0) { - return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); - } - /* Check if a Feature ID was requested. */ if ((function_id & FFA_FEATURES_BIT31_MASK) == 0U) { /* We currently don't support any additional features. */ return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); } - /* Report if an FF-A ABI is supported. */ + /* + * Handle the cases where we have separate handlers due to additional + * properties. + */ + switch (function_id) { + case FFA_MEM_RETRIEVE_REQ_SMC32: + case FFA_MEM_RETRIEVE_REQ_SMC64: + return ffa_features_retrieve_request(secure_origin, + input_properties, + handle); + } + + /* + * We don't currently support additional input properties for these + * other ABIs therefore ensure this value is set to 0. + */ + if (input_properties != 0U) { + return spmc_ffa_error_return(handle, + FFA_ERROR_NOT_SUPPORTED); + } + + /* Report if any other FF-A ABI is supported. */ switch (function_id) { /* Supported features from both worlds. */ case FFA_ERROR: @@ -1052,8 +1112,6 @@ static uint64_t ffa_features_handler(uint32_t smc_fid, case FFA_SECONDARY_EP_REGISTER_SMC64: case FFA_MSG_SEND_DIRECT_RESP_SMC32: case FFA_MSG_SEND_DIRECT_RESP_SMC64: - case FFA_MEM_RETRIEVE_REQ_SMC32: - case FFA_MEM_RETRIEVE_REQ_SMC64: case FFA_MEM_RELINQUISH: case FFA_MSG_WAIT: diff --git a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c index 920dfca1d..7b9a5265e 100644 --- a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c +++ b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c @@ -876,6 +876,13 @@ static long spmc_ffa_fill_desc(struct mailbox *mbox, goto err_arg; } + /* Ensure the NS bit is set to 0. */ + if ((obj->desc.memory_region_attributes & FFA_MEM_ATTR_NS_BIT) != 0U) { + WARN("%s: NS mem attributes flags MBZ.\n", __func__); + ret = FFA_ERROR_INVALID_PARAMETER; + goto err_arg; + } + /* * We don't currently support any optional flags so ensure none are * requested. @@ -1189,6 +1196,33 @@ err_unlock: return spmc_ffa_error_return(handle, ret); } +/** + * spmc_ffa_mem_retrieve_set_ns_bit - Set the NS bit in the response descriptor + * if the caller implements a version greater + * than FF-A 1.0 or if they have requested + * the functionality. + * TODO: We are assuming that the caller is + * an SP. To support retrieval from the + * normal world this function will need to be + * expanded accordingly. + * @resp: Descriptor populated in callers RX buffer. + * @sp_ctx: Context of the calling SP. + */ +void spmc_ffa_mem_retrieve_set_ns_bit(struct ffa_mtd *resp, + struct secure_partition_desc *sp_ctx) +{ + if (sp_ctx->ffa_version > MAKE_FFA_VERSION(1, 0) || + sp_ctx->ns_bit_requested) { + /* + * Currently memory senders must reside in the normal + * world, and we do not have the functionlaity to change + * the state of memory dynamically. Therefore we can always set + * the NS bit to 1. + */ + resp->memory_region_attributes |= FFA_MEM_ATTR_NS_BIT; + } +} + /** * spmc_ffa_mem_retrieve_req - FFA_MEM_RETRIEVE_REQ implementation. * @smc_fid: FID of SMC @@ -1237,6 +1271,7 @@ spmc_ffa_mem_retrieve_req(uint32_t smc_fid, struct spmc_shmem_obj *obj = NULL; struct mailbox *mbox = spmc_get_mbox_desc(secure_origin); uint32_t ffa_version = get_partition_ffa_version(secure_origin); + struct secure_partition_desc *sp_ctx = spmc_get_current_sp_ctx(); if (!secure_origin) { WARN("%s: unsupported retrieve req direction.\n", __func__); @@ -1330,6 +1365,13 @@ spmc_ffa_mem_retrieve_req(uint32_t smc_fid, goto err_unlock_all; } + /* Ensure the NS bit is set to 0 in the request. */ + if ((req->memory_region_attributes & FFA_MEM_ATTR_NS_BIT) != 0U) { + WARN("%s: NS mem attributes flags MBZ.\n", __func__); + ret = FFA_ERROR_INVALID_PARAMETER; + goto err_unlock_all; + } + if (req->flags != 0U) { if ((req->flags & FFA_MTD_FLAG_TYPE_MASK) != (obj->desc.flags & FFA_MTD_FLAG_TYPE_MASK)) { @@ -1446,6 +1488,9 @@ spmc_ffa_mem_retrieve_req(uint32_t smc_fid, memcpy(resp, &obj->desc, copy_size); } + /* Set the NS bit in the response if applicable. */ + spmc_ffa_mem_retrieve_set_ns_bit(resp, sp_ctx); + spin_unlock(&spmc_shmem_obj_state.lock); spin_unlock(&mbox->lock);