aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorJelle Sels <jelle.sels@arm.com>2021-03-22 16:57:56 +0100
committerJérôme Forissier <jerome@forissier.org>2021-11-05 11:09:56 +0100
commit3a7bfc345c1a7cd0abe02b6e5554b25720b86a15 (patch)
tree5517fa8de23e1bb6fb11dc73a2d7318efd0b895a /core
parente9907fd739e0b46e0f62f571a36ceaee44fc55f3 (diff)
core: Add FFA_PARTITION_INFO
FFA_PARTITION_INFO is used to query all the Secure Partitions loaded in the system. Signed-off-by: Jelle Sels <jelle.sels@arm.com> Acked-by: Etienne Carriere <etienne.carriere@linaro.org> Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'core')
-rw-r--r--core/arch/arm/include/ffa.h11
-rw-r--r--core/arch/arm/include/kernel/secure_partition.h5
-rw-r--r--core/arch/arm/include/kernel/thread_spmc.h6
-rw-r--r--core/arch/arm/kernel/secure_partition.c41
-rw-r--r--core/arch/arm/kernel/spmc_sp_handler.c6
-rw-r--r--core/arch/arm/kernel/thread_spmc.c123
6 files changed, 166 insertions, 26 deletions
diff --git a/core/arch/arm/include/ffa.h b/core/arch/arm/include/ffa.h
index 20a009ca..0aa91943 100644
--- a/core/arch/arm/include/ffa.h
+++ b/core/arch/arm/include/ffa.h
@@ -95,6 +95,17 @@
/* Special value for MBZ parameters */
#define FFA_PARAM_MBZ U(0x0)
+/*
+ * Flags used for the FFA_PARTITION_INFO_GET return message:
+ * BIT(0): Supports receipt of direct requests
+ * BIT(1): Can send direct requests
+ * BIT(2): Cannot send and receive indirect messages
+ * BIT(3): Does not support receipt of notifications
+ * BIT(4-5): Partition ID is a PE endpoint ID
+ */
+#define FFA_PARTITION_DIRECT_REQ_RECV_SUPPORT BIT(0)
+#define FFA_PARTITION_DIRECT_REQ_SEND_SUPPORT BIT(1)
+
#ifndef __ASSEMBLER__
/* Constituent memory region descriptor */
struct ffa_address_range {
diff --git a/core/arch/arm/include/kernel/secure_partition.h b/core/arch/arm/include/kernel/secure_partition.h
index e153faa6..25937f4c 100644
--- a/core/arch/arm/include/kernel/secure_partition.h
+++ b/core/arch/arm/include/kernel/secure_partition.h
@@ -7,6 +7,7 @@
#include <assert.h>
#include <config.h>
+#include <ffa.h>
#include <kernel/embedded_ts.h>
#include <kernel/thread_spmc.h>
#include <kernel/user_mode_ctx_struct.h>
@@ -73,6 +74,10 @@ static inline struct sp_ctx *to_sp_ctx(struct ts_ctx *ctx)
struct sp_session *sp_get_session(uint32_t session_id);
TEE_Result sp_enter(struct thread_smc_args *args, struct sp_session *sp);
+TEE_Result sp_partition_info_get_all(struct ffa_partition_info *fpi,
+ size_t *elem_count);
+
+TEE_Result sp_find_session_id(const TEE_UUID *uuid, uint32_t *session_id);
#define for_each_secure_partition(_sp) \
SCATTERED_ARRAY_FOREACH(_sp, sp_images, struct embedded_ts)
diff --git a/core/arch/arm/include/kernel/thread_spmc.h b/core/arch/arm/include/kernel/thread_spmc.h
index 3e361c23..38f8abd8 100644
--- a/core/arch/arm/include/kernel/thread_spmc.h
+++ b/core/arch/arm/include/kernel/thread_spmc.h
@@ -5,6 +5,7 @@
#ifndef __KERNEL_THREAD_SPMC_H
#define __KERNEL_THREAD_SPMC_H
+#include <ffa.h>
#include <kernel/thread.h>
/* FF-A endpoint base ID when OP-TEE is used as a S-EL1 endpoint */
@@ -25,4 +26,9 @@ void spmc_handle_version(struct thread_smc_args *args);
void spmc_set_args(struct thread_smc_args *args, uint32_t fid, uint32_t src_dst,
uint32_t w2, uint32_t w3, uint32_t w4, uint32_t w5);
+void spmc_handle_partition_info_get(struct thread_smc_args *args,
+ struct ffa_rxtx *rxtx);
+void spmc_fill_partition_entry(struct ffa_partition_info *fpi,
+ uint16_t endpoint_id,
+ uint16_t execution_context);
#endif /* __KERNEL_THREAD_SPMC_H */
diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c
index b064c27b..977f1e51 100644
--- a/core/arch/arm/kernel/secure_partition.c
+++ b/core/arch/arm/kernel/secure_partition.c
@@ -56,6 +56,23 @@ static void set_sp_ctx_ops(struct ts_ctx *ctx)
ctx->ops = &sp_ops;
}
+TEE_Result sp_find_session_id(const TEE_UUID *uuid, uint32_t *session_id)
+{
+ struct sp_session *s = NULL;
+
+ TAILQ_FOREACH(s, &open_sp_sessions, link) {
+ if (!memcmp(&s->ts_sess.ctx->uuid, uuid, sizeof(*uuid))) {
+ if (s->state == sp_dead)
+ return TEE_ERROR_TARGET_DEAD;
+
+ *session_id = s->endpoint_id;
+ return TEE_SUCCESS;
+ }
+ }
+
+ return TEE_ERROR_ITEM_NOT_FOUND;
+}
+
struct sp_session *sp_get_session(uint32_t session_id)
{
struct sp_session *s = NULL;
@@ -68,6 +85,30 @@ struct sp_session *sp_get_session(uint32_t session_id)
return NULL;
}
+TEE_Result sp_partition_info_get_all(struct ffa_partition_info *fpi,
+ size_t *elem_count)
+{
+ size_t in_count = *elem_count;
+ struct sp_session *s = NULL;
+ size_t count = 0;
+
+ TAILQ_FOREACH(s, &open_sp_sessions, link) {
+ if (s->state == sp_dead)
+ continue;
+ if (count < in_count) {
+ spmc_fill_partition_entry(fpi, s->endpoint_id, 1);
+ fpi++;
+ }
+ count++;
+ }
+
+ *elem_count = count;
+ if (count > in_count)
+ return TEE_ERROR_SHORT_BUFFER;
+
+ return TEE_SUCCESS;
+}
+
static void sp_init_info(struct sp_ctx *ctx, struct thread_smc_args *args)
{
struct sp_ffa_init_info *info = NULL;
diff --git a/core/arch/arm/kernel/spmc_sp_handler.c b/core/arch/arm/kernel/spmc_sp_handler.c
index fcf86509..041e4351 100644
--- a/core/arch/arm/kernel/spmc_sp_handler.c
+++ b/core/arch/arm/kernel/spmc_sp_handler.c
@@ -276,6 +276,12 @@ void spmc_sp_msg_handler(struct thread_smc_args *args,
handle_features(args);
sp_enter(args, caller_sp);
break;
+ case FFA_PARTITION_INFO_GET:
+ ts_push_current_session(&caller_sp->ts_sess);
+ spmc_handle_partition_info_get(args, &caller_sp->rxtx);
+ ts_pop_current_session();
+ sp_enter(args, caller_sp);
+ break;
default:
EMSG("Unhandled FFA function ID %#"PRIx32,
(uint32_t)args->a0);
diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
index 1901a3a7..0cea7380 100644
--- a/core/arch/arm/kernel/thread_spmc.c
+++ b/core/arch/arm/kernel/thread_spmc.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <sys/queue.h>
#include <tee/entry_std.h>
+#include <tee/uuid.h>
#include <util.h>
#include "thread_private.h"
@@ -326,46 +327,116 @@ static bool is_my_uuid(uint32_t w0, uint32_t w1, uint32_t w2, uint32_t w3)
w2 == 0x02005ebc && w3 == 0x1bc5d5a5;
}
-static void handle_partition_info_get(struct thread_smc_args *args,
- struct ffa_rxtx *rxtx)
+void spmc_fill_partition_entry(struct ffa_partition_info *fpi,
+ uint16_t endpoint_id, uint16_t execution_context)
{
- uint32_t ret_fid = 0;
- int rc = 0;
+ fpi->id = endpoint_id;
+ /* Number of execution contexts implemented by this partition */
+ fpi->execution_context = execution_context;
- if (!is_nil_uuid(args->a1, args->a2, args->a3, args->a4) &&
- !is_my_uuid(args->a1, args->a2, args->a3, args->a4)) {
- ret_fid = FFA_ERROR;
- rc = FFA_INVALID_PARAMETERS;
- goto out;
+ fpi->partition_properties = FFA_PARTITION_DIRECT_REQ_RECV_SUPPORT |
+ FFA_PARTITION_DIRECT_REQ_SEND_SUPPORT;
+}
+
+static uint32_t handle_partition_info_get_all(size_t *elem_count,
+ struct ffa_rxtx *rxtx)
+{
+ struct ffa_partition_info *fpi = rxtx->tx;
+
+ /* Add OP-TEE SP */
+ spmc_fill_partition_entry(fpi, my_endpoint_id, CFG_TEE_CORE_NB_CORE);
+ rxtx->tx_is_mine = false;
+ *elem_count = 1;
+ fpi++;
+
+ if (IS_ENABLED(CFG_SECURE_PARTITION)) {
+ size_t count = (rxtx->size / sizeof(*fpi)) - 1;
+
+ if (sp_partition_info_get_all(fpi, &count))
+ return FFA_NO_MEMORY;
+ *elem_count += count;
}
- cpu_spin_lock(&rxtx->spinlock);
- if (rxtx->size && rxtx->tx_is_mine) {
- struct ffa_partition_info *fpi = rxtx->tx;
+ return FFA_OK;
+}
- fpi->id = my_endpoint_id;
- fpi->execution_context = CFG_TEE_CORE_NB_CORE;
- /*
- * Supports receipt of direct requests.
- * Can send direct requests.
- */
- fpi->partition_properties = BIT(0) | BIT(1);
+void spmc_handle_partition_info_get(struct thread_smc_args *args,
+ struct ffa_rxtx *rxtx)
+{
+ uint32_t ret_fid = FFA_ERROR;
+ uint32_t rc = 0;
+ uint32_t endpoint_id = my_endpoint_id;
+ struct ffa_partition_info *fpi = NULL;
- ret_fid = FFA_SUCCESS_32;
- rc = 1;
- rxtx->tx_is_mine = false;
- } else {
- ret_fid = FFA_ERROR;
+ cpu_spin_lock(&rxtx->spinlock);
+
+ if (!rxtx->size || !rxtx->tx_is_mine) {
if (rxtx->size)
rc = FFA_BUSY;
else
rc = FFA_DENIED; /* TX buffer not setup yet */
+ goto out;
}
- cpu_spin_unlock(&rxtx->spinlock);
+
+ fpi = rxtx->tx;
+
+ if (rxtx->size < sizeof(*fpi)) {
+ ret_fid = FFA_ERROR;
+ rc = FFA_NO_MEMORY;
+ goto out;
+ }
+
+ if (is_nil_uuid(args->a1, args->a2, args->a3, args->a4)) {
+ size_t elem_count = 0;
+
+ ret_fid = handle_partition_info_get_all(&elem_count, rxtx);
+
+ if (ret_fid) {
+ rc = ret_fid;
+ ret_fid = FFA_ERROR;
+ } else {
+ ret_fid = FFA_SUCCESS_32;
+ rc = elem_count;
+ }
+
+ goto out;
+ }
+
+ if (is_my_uuid(args->a1, args->a2, args->a3, args->a4)) {
+ spmc_fill_partition_entry(fpi, endpoint_id,
+ CFG_TEE_CORE_NB_CORE);
+ } else if (IS_ENABLED(CFG_SECURE_PARTITION)) {
+ uint32_t uuid_array[4] = { 0 };
+ TEE_UUID uuid = { };
+ TEE_Result res = TEE_SUCCESS;
+
+ uuid_array[0] = args->a1;
+ uuid_array[1] = args->a2;
+ uuid_array[2] = args->a3;
+ uuid_array[3] = args->a4;
+ tee_uuid_from_octets(&uuid, (uint8_t *)uuid_array);
+
+ res = sp_find_session_id(&uuid, &endpoint_id);
+ if (res != TEE_SUCCESS) {
+ ret_fid = FFA_ERROR;
+ rc = FFA_INVALID_PARAMETERS;
+ goto out;
+ }
+ spmc_fill_partition_entry(fpi, endpoint_id, 1);
+ } else {
+ ret_fid = FFA_ERROR;
+ rc = FFA_INVALID_PARAMETERS;
+ goto out;
+ }
+
+ ret_fid = FFA_SUCCESS_32;
+ rxtx->tx_is_mine = false;
+ rc = 1;
out:
spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ,
FFA_PARAM_MBZ, FFA_PARAM_MBZ);
+ cpu_spin_unlock(&rxtx->spinlock);
}
#endif /*CFG_CORE_SEL1_SPMC*/
@@ -871,7 +942,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
spmc_handle_rx_release(args, &nw_rxtx);
break;
case FFA_PARTITION_INFO_GET:
- handle_partition_info_get(args, &nw_rxtx);
+ spmc_handle_partition_info_get(args, &nw_rxtx);
break;
#endif /*CFG_CORE_SEL1_SPMC*/
case FFA_INTERRUPT: