aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Bonnici <marc.bonnici@arm.com>2022-04-19 16:52:59 +0100
committerMarc Bonnici <marc.bonnici@arm.com>2022-05-19 15:02:47 +0100
commit0560b53e71ab6daefa8e75665a718605478746a4 (patch)
treec361eaa62cda1086eb8c416a00e35a9ff8eec0bc
parent7e804f9695c48681c91e9e6fc6175eb6997df867 (diff)
downloadtrusted-firmware-a-0560b53e71ab6daefa8e75665a718605478746a4.tar.gz
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
-rw-r--r--include/services/el3_spmc_ffa_memory.h3
-rw-r--r--services/std_svc/spm/el3_spmc/spmc.h7
-rw-r--r--services/std_svc/spm/el3_spmc/spmc_main.c80
-rw-r--r--services/std_svc/spm/el3_spmc/spmc_shared_mem.c45
4 files changed, 124 insertions, 11 deletions
diff --git a/include/services/el3_spmc_ffa_memory.h b/include/services/el3_spmc_ffa_memory.h
index 8e0c5ae38f..2037ecadc0 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 9926c68f52..d62be91ebd 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 c7071abf97..9b8621a736 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 920dfca1de..7b9a5265e8 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.
@@ -1190,6 +1197,33 @@ err_unlock:
}
/**
+ * 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
* @total_length: Total length of retrieve request descriptor if this is
@@ -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);