feat(spmc): enable handling of the NS bit

In FF-A v1.1 the NS bit is used by the SPMC to specify the
security state of a memory region retrieved by a SP.

Enable the SPMC to set the bit for v1.1 callers or v1.0
callers that explicitly request the usage via FFA_FEATURES.

In this implementation the sender of the memory region must
reside in the normal world and the SPMC does not support
changing the security state of memory regions therefore
always set the NS bit if required by the caller.

Signed-off-by: Marc Bonnici <marc.bonnici@arm.com>
Change-Id: I215756b28e2382082933ba1dcc7584e7faf4b36b
This commit is contained in:
Marc Bonnici 2022-04-19 16:52:59 +01:00
parent 7e804f9695
commit 0560b53e71
4 changed files with 124 additions and 11 deletions

View File

@ -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))

View File

@ -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;
};
/*

View File

@ -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:

View File

@ -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);