aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBalint Dobszay <balint.dobszay@arm.com>2021-04-15 13:52:29 +0200
committerBalint Dobszay <balint.dobszay@arm.com>2022-03-01 17:12:59 +0100
commit28ca1c42976b37a4b7212314af13dc27b46f5d8c (patch)
tree23c51eda45ffad3d362a42c3d20027228b8386fa
parent03df4b3ddda51ffe039b82f8a613741758d788d6 (diff)
downloadoptee_os-28ca1c42976b37a4b7212314af13dc27b46f5d8c.tar.gz
SPM: fix Linux OP-TEE driver compatibility
The OP-TEE driver in Linux can use FF-A as a transport method, in this case the OP-TEE specific messages are encapsulated into FF-A calls. The protocol of this encapsulation has changed over time, currently our code is only compatible with an early WIP version of this protocol. This patch adds compatibility with the first stable version, which was released in Linux v5.16. This patch only consists of backporting changes to our branch, the original modifications were all made by Jens Wiklander <jens.wiklander@linaro.org> in this PR: https://github.com/OP-TEE/optee_os/pull/4509 Change-Id: I4120abf9042c53b739e8ab289b5bfe68e58a30fc Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
-rw-r--r--core/arch/arm/include/mm/mobj.h6
-rw-r--r--core/arch/arm/include/optee_ffa.h110
-rw-r--r--core/arch/arm/kernel/link_dummies_paged.c4
-rw-r--r--core/arch/arm/kernel/sp.c2
-rw-r--r--core/arch/arm/kernel/thread.c5
-rw-r--r--core/arch/arm/kernel/thread_optee_smc.c6
-rw-r--r--core/arch/arm/kernel/thread_private.h9
-rw-r--r--core/arch/arm/kernel/thread_spmc.c298
-rw-r--r--core/arch/arm/mm/mobj_ffa.c10
-rw-r--r--core/arch/arm/tee/entry_std.c3
-rw-r--r--core/include/optee_msg.h3
11 files changed, 218 insertions, 238 deletions
diff --git a/core/arch/arm/include/mm/mobj.h b/core/arch/arm/include/mm/mobj.h
index 2f7322f16..6a0ad6f9d 100644
--- a/core/arch/arm/include/mm/mobj.h
+++ b/core/arch/arm/include/mm/mobj.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2016-2017, Linaro Limited
+ * Copyright (c) 2021-2022, Arm Limited
*/
#ifndef __MM_MOBJ_H
@@ -10,6 +11,7 @@
#include <mm/core_memprot.h>
#include <mm/file.h>
#include <mm/fobj.h>
+#include <optee_msg.h>
#include <string_ext.h>
#include <sys/queue.h>
#include <tee_api_types.h>
@@ -165,7 +167,11 @@ static inline uint64_t mobj_get_cookie(struct mobj *mobj)
if (mobj && mobj->ops && mobj->ops->get_cookie)
return mobj->ops->get_cookie(mobj);
+#if defined(CFG_CORE_SEL1_SPMC) || defined(CFG_CORE_SEL2_SPMC)
+ return OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
+#else
return 0;
+#endif
}
static inline struct fobj *mobj_get_fobj(struct mobj *mobj)
diff --git a/core/arch/arm/include/optee_ffa.h b/core/arch/arm/include/optee_ffa.h
index c08c04667..22c6dd3a5 100644
--- a/core/arch/arm/include/optee_ffa.h
+++ b/core/arch/arm/include/optee_ffa.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2019, Linaro Limited
- * Copyright (c) 2020, Arm Limited
+ * Copyright (c) 2020-2022, Arm Limited
*/
/*
@@ -28,8 +28,8 @@
* w3-w7: Implementation defined, free to be used below
*/
-#define OPTEE_FFA_VERSION_MAJOR UINT32_C(0)
-#define OPTEE_FFA_VERSION_MINOR UINT32_C(9)
+#define OPTEE_FFA_VERSION_MAJOR UINT32_C(1)
+#define OPTEE_FFA_VERSION_MINOR UINT32_C(0)
#define OPTEE_FFA_BLOCKING_CALL(id) UINT32_C(id)
#define OPTEE_FFA_YIELDING_CALL_BIT 31
@@ -79,14 +79,30 @@
*
* Return register usage:
* w3: Error code, 0 on success
- * w4: Bit[1:0]: Number of 4kB pages of shared memory to register with
- * OPTEE_FFA_REGISTER_RPC_SHM to support RPC
- * Bit[31:2]: Reserved (MBZ)
+ * w4: Bit[7:0]: Number of parameters needed for RPC to be supplied
+ * as the second MSG arg struct for
+ * OPTEE_FFA_YIELDING_CALL_WITH_ARG.
+ * Bit[31:8]: Reserved (MBZ)
* w5-w7: Note used (MBZ)
*/
#define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
/*
+ * Unregister shared memory
+ *
+ * Call register usage:
+ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM
+ * w4: Shared memory handle, lower bits
+ * w5: Shared memory handle, higher bits
+ * w6-w7: Not used (MBZ)
+ *
+ * Return register usage:
+ * w3: Error code, 0 on success
+ * w4-w7: Note used (MBZ)
+ */
+#define OPTEE_FFA_UNREGISTER_SHM OPTEE_FFA_BLOCKING_CALL(3)
+
+/*
* Call with struct optee_msg_arg as argument in the supplied shared memory
* with a zero internal offset and normal cached memory attributes.
* Register usage:
@@ -94,35 +110,15 @@
* w4: Lower 32 bits of a 64-bit Shared memory handle
* w5: Upper 32 bits of a 64-bit Shared memory handle
* w6: Offset into shared memory pointing to a struct optee_msg_arg
+ * right after the parameters of this struct (at offset
+ * OPTEE_MSG_GET_ARG_SIZE(num_params) follows a struct optee_msg_arg
+ * for RPC, this struct has reserved space for the number of RPC
+ * parameters as returned by OPTEE_FFA_EXCHANGE_CAPABILITIES.
* w7: Not used (MBZ)
*
- * Call to register shared memory. The data is supplied in shared
- * memory with a zero internal offset and normal cached memory attributes.
- * The data is formatted as described in FF-A 1.0 EAC Table 44
- * "Lend, donate or share memory transaction descriptor".
- * Register usage:
- * w3: Service ID, OPTEE_FFA_YIELDING_CALL_REGISTER_SHM
- * w4: Lower 32 bits of a 64-bit Shared memory handle
- * w5: Upper 32 bits of a 64-bit Shared memory handle
- * w6-w7: Not used (MBZ)
- *
- * Call to unregister shared memory. Register usage:
- * w3: Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM
- * w4: Lower 32 bits of a 64-bit Shared memory handle
- * w5: Upper 32 bits of a 64-bit Shared memory handle
- * w6-w7: Not used (MBZ)
- *
* Resume from RPC. Register usage:
* w3: Service ID, OPTEE_FFA_YIELDING_CALL_RESUME
- * If returning from OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SHM:
- * w4: Lower 32 bits of a 64-bit Shared memory handle
- * w5: Upper 32 bits of a 64-bit Shared memory handle
- * If the allocation failed both w4 and w5 are 0
- * w6: Offset into shared memory pointing the table. If internal
- * offset > 0 then one more 4kB page than requested has been
- * allocated.
- * else if resuming from another RPC:
- * w4-w6: Not used (MBZ)
+ * w4-w6: Not used (MBZ)
* w7: Resume info
*
* Normal return (yielding call is completed). Register usage:
@@ -130,51 +126,18 @@
* w4: OPTEE_FFA_YIELDING_CALL_RETURN_DONE
* w5-w7: Not used (MBZ)
*
- * Alloc SHM return (RPC from secure world). Register usage:
- * w3: Error code == 0
- * w4: OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM or
- * OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM
- * allocate kernel private or supplicant memory respectively.
- * w5: Number of 4kB pages of shared memory
- * w6: Not used (MBZ)
- * w7: Resume info
- *
- * Free SHM return (RPC from secure world). Register usage:
- * w3: Error code == 0
- * w4: OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM or
- * OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM
- * free kernel private or supplicant memory respectively.
- * w5: Lower 32 bits of a 64-bit Shared memory handle
- * w6: Upper 32 bits of a 64-bit Shared memory handle
- * The handle previously allocated with
- * OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM or
- * OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM.
- * w7: Resume info
- *
- * RPC cmd return (RPC from secure world). Register usage:
- * w3: Error code == 0
- * w4: OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD
- * w5: Lower 32 bits of a 64-bit Shared memory handle
- * w6: Upper 32 bits of a 64-bit Shared memory handle
- * The handle contains aed the RPC.
- * w7: Resume info
- *
* RPC interrupt return (RPC from secure world). Register usage:
* w3: Error code == 0
- * w4: OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT
+ * w4: Any defined RPC code but OPTEE_FFA_YIELDING_CALL_RETURN_DONE
* w5-w6: Not used (MBZ)
* w7: Resume info
*
* Possible error codes in register w3:
* 0: Success
* FFA_DENIED: w4 isn't one of OPTEE_FFA_YIELDING_CALL_START
- * OPTEE_FFA_YIELDING_CALL_REGISTER_SHM,
- * OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM or
* OPTEE_FFA_YIELDING_CALL_RESUME
*
* Possible error codes for OPTEE_FFA_YIELDING_CALL_START,
- * OPTEE_FFA_YIELDING_CALL_REGISTER_SHM and
- * OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM
* FFA_BUSY: Number of OP-TEE OS threads exceeded,
* try again later
* FFA_DENIED: RPC shared memory object not found
@@ -184,19 +147,10 @@
* FFA_INVALID_PARAMETER: Bad resume info
*/
#define OPTEE_FFA_YIELDING_CALL_WITH_ARG OPTEE_FFA_YIELDING_CALL(0)
-#define OPTEE_FFA_YIELDING_CALL_REGISTER_SHM OPTEE_FFA_YIELDING_CALL(1)
-#define OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM OPTEE_FFA_YIELDING_CALL(2)
-#define OPTEE_FFA_YIELDING_CALL_RESUME OPTEE_FFA_YIELDING_CALL(3)
+#define OPTEE_FFA_YIELDING_CALL_RESUME OPTEE_FFA_YIELDING_CALL(1)
#define OPTEE_FFA_YIELDING_CALL_RETURN_DONE 0
-#define OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM 1
-#define OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM 2
-#define OPTEE_FFA_YIELDING_CALL_RETURN_RESERVED0 3
-#define OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM 4
-#define OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM 5
-#define OPTEE_FFA_YIELDING_CALL_RETURN_RESERVED1 6
-#define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD 7
-#define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT 8
-#define OPTEE_FFA_SP_INIT 9
+#define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD 1
+#define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT 2
+#define OPTEE_FFA_SP_INIT 3
#endif /*__OPTEE_FFA_H*/
-
diff --git a/core/arch/arm/kernel/link_dummies_paged.c b/core/arch/arm/kernel/link_dummies_paged.c
index a5ae8bd25..c74d3aa85 100644
--- a/core/arch/arm/kernel/link_dummies_paged.c
+++ b/core/arch/arm/kernel/link_dummies_paged.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2017, Linaro Limited
+ * Copyright (c) 2021-2022, Arm Limited
*/
#include <compiler.h>
#include <initcall.h>
@@ -27,7 +28,8 @@ paged_init_primary(unsigned long fdt __unused)
uint32_t __section(".text.dummy.__thread_std_smc_entry")
__thread_std_smc_entry(uint32_t a0 __unused, uint32_t a1 __unused,
- uint32_t a2 __unused, uint32_t a3 __unused)
+ uint32_t a2 __unused, uint32_t a3 __unused,
+ uint32_t a4 __unused, uint32_t a5 __unused)
{
return 0;
}
diff --git a/core/arch/arm/kernel/sp.c b/core/arch/arm/kernel/sp.c
index fe0965b18..bfa177989 100644
--- a/core/arch/arm/kernel/sp.c
+++ b/core/arch/arm/kernel/sp.c
@@ -508,7 +508,7 @@ TEE_Result sp_init_all(void)
TEE_Result sp_start_init_thread(void)
{
- thread_alloc_and_run(0, OPTEE_FFA_SP_INIT, 0, 0);
+ thread_alloc_and_run(0, OPTEE_FFA_SP_INIT, 0, 0, 0, 0);
return TEE_SUCCESS;
}
diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c
index c161e84cb..8cf869132 100644
--- a/core/arch/arm/kernel/thread.c
+++ b/core/arch/arm/kernel/thread.c
@@ -2,7 +2,7 @@
/*
* Copyright (c) 2016, Linaro Limited
* Copyright (c) 2014, STMicroelectronics International N.V.
- * Copyright (c) 2020, Arm Limited
+ * Copyright (c) 2020-2022, Arm Limited
*/
#include <platform_config.h>
@@ -558,7 +558,8 @@ static void __thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2,
panic();
}
-void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3)
+void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3,
+ uint32_t a4 __unused, uint32_t a5 __unused)
{
__thread_alloc_and_run(a0, a1, a2, a3, 0, 0, 0, 0,
(uint64_t)thread_std_smc_entry);
diff --git a/core/arch/arm/kernel/thread_optee_smc.c b/core/arch/arm/kernel/thread_optee_smc.c
index 7fe97b9c2..dc287d8d4 100644
--- a/core/arch/arm/kernel/thread_optee_smc.c
+++ b/core/arch/arm/kernel/thread_optee_smc.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2019, Linaro Limited
+ * Copyright (c) 2021-2022, Arm Limited
*/
#include <assert.h>
@@ -70,7 +71,7 @@ uint32_t thread_handle_std_smc(uint32_t a0, uint32_t a1, uint32_t a2,
thread_resume_from_rpc(a3, a1, a2, a4, a5);
rv = OPTEE_SMC_RETURN_ERESUME;
} else {
- thread_alloc_and_run(a0, a1, a2, a3);
+ thread_alloc_and_run(a0, a1, a2, a3, 0, 0);
rv = OPTEE_SMC_RETURN_ETHREAD_LIMIT;
}
@@ -203,7 +204,8 @@ static uint32_t std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2,
* the unpaged area.
*/
uint32_t __weak __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2,
- uint32_t a3)
+ uint32_t a3, uint32_t a4 __unused,
+ uint32_t a5 __unused)
{
uint32_t rv = 0;
diff --git a/core/arch/arm/kernel/thread_private.h b/core/arch/arm/kernel/thread_private.h
index 416abd7e2..d6dca92dc 100644
--- a/core/arch/arm/kernel/thread_private.h
+++ b/core/arch/arm/kernel/thread_private.h
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2016, Linaro Limited
* Copyright (c) 2014, STMicroelectronics International N.V.
+ * Copyright (c) 2021-2022, Arm Limited
*/
#ifndef THREAD_PRIVATE_H
@@ -125,9 +126,10 @@ void thread_excp_vect_end(void);
* everything is set up and does some post processing once
* __thread_std_smc_entry() returns.
*/
-void thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3);
+void thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3,
+ uint32_t a4, uint32_t a5);
uint32_t __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2,
- uint32_t a3);
+ uint32_t a3, uint32_t a4, uint32_t a5);
void thread_sp_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3);
/*
@@ -184,7 +186,8 @@ void thread_set_fiq_sp(vaddr_t sp);
/* Checks stack canaries */
void thread_check_canaries(void);
-void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3);
+void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3,
+ uint32_t a4, uint32_t a5);
void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1,
uint32_t a2, uint32_t a3);
void thread_lock_global(void);
diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
index 0bd21c5e5..6585e3a73 100644
--- a/core/arch/arm/kernel/thread_spmc.c
+++ b/core/arch/arm/kernel/thread_spmc.c
@@ -567,7 +567,7 @@ out:
static void handle_yielding_call(struct thread_smc_args *args)
{
- uint32_t ret_val = 0;
+ TEE_Result res = TEE_SUCCESS;
thread_check_canaries();
@@ -575,13 +575,33 @@ static void handle_yielding_call(struct thread_smc_args *args)
/* Note connection to struct thread_rpc_arg::ret */
thread_resume_from_rpc(args->a7, args->a4, args->a5, args->a6,
0);
- ret_val = FFA_INVALID_PARAMETERS;
+ res = TEE_ERROR_BAD_PARAMETERS;
} else {
- thread_alloc_and_run(args->a1, args->a3, args->a4, args->a5);
- ret_val = FFA_BUSY;
+ thread_alloc_and_run(args->a1, args->a3, args->a4, args->a5,
+ args->a6, args->a7);
+ res = TEE_ERROR_BUSY;
}
set_args(args, FFA_MSG_SEND_DIRECT_RESP_32,
- swap_src_dst(args->a1), 0, ret_val, 0, 0, FFA_NW_ID);
+ swap_src_dst(args->a1), 0, res, 0, 0, FFA_NW_ID);
+}
+
+static uint32_t handle_unregister_shm(uint32_t a4, uint32_t a5)
+{
+ uint64_t cookie = reg_pair_to_64(a5, a4);
+ uint32_t res = 0;
+
+ res = mobj_ffa_unregister_by_cookie(cookie);
+ switch (res) {
+ case TEE_SUCCESS:
+ case TEE_ERROR_ITEM_NOT_FOUND:
+ return 0;
+ case TEE_ERROR_BUSY:
+ EMSG("res %#"PRIx32, res);
+ return FFA_BUSY;
+ default:
+ EMSG("res %#"PRIx32, res);
+ return FFA_INVALID_PARAMETERS;
+ }
}
static void handle_blocking_call(struct thread_smc_args *args)
@@ -600,7 +620,14 @@ static void handle_blocking_call(struct thread_smc_args *args)
break;
case OPTEE_FFA_EXCHANGE_CAPABILITIES:
set_args(args, FFA_MSG_SEND_DIRECT_RESP_32,
- swap_src_dst(args->a1), 0, 0, 0, 0, FFA_NW_ID);
+ swap_src_dst(args->a1), 0, 0,
+ THREAD_RPC_MAX_NUM_PARAMS, 0, FFA_NW_ID);
+ break;
+ case OPTEE_FFA_UNREGISTER_SHM:
+ set_args(args, FFA_MSG_SEND_DIRECT_RESP_32,
+ swap_src_dst(args->a1), 0,
+ handle_unregister_shm(args->a4, args->a5),
+ 0, 0, FFA_NW_ID);
break;
default:
EMSG("Unhandled blocking service ID %#"PRIx32,
@@ -1141,12 +1168,15 @@ void thread_spmc_msg_recv(struct thread_smc_args *args, uint64_t endpoint_id)
}
/* Only called from assembly */
-static uint32_t yielding_call_with_arg(uint64_t cookie)
+static uint32_t yielding_call_with_arg(uint64_t cookie, uint32_t offset)
{
+ size_t sz_rpc = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS);
+ struct thread_ctx *thr = threads + thread_get_id();
uint32_t rv = TEE_ERROR_BAD_PARAMETERS;
struct optee_msg_arg *arg = NULL;
struct mobj *mobj = NULL;
uint32_t num_params = 0;
+ size_t sz = 0;
mobj = mobj_ffa_get_by_cookie(cookie, 0);
if (!mobj) {
@@ -1159,7 +1189,7 @@ static uint32_t yielding_call_with_arg(uint64_t cookie)
goto out_put_mobj;
rv = TEE_ERROR_BAD_PARAMETERS;
- arg = mobj_get_va(mobj, 0);
+ arg = mobj_get_va(mobj, offset);
if (!arg)
goto out_dec_map;
@@ -1170,12 +1200,15 @@ static uint32_t yielding_call_with_arg(uint64_t cookie)
if (num_params > OPTEE_MSG_MAX_NUM_PARAMS)
goto out_dec_map;
- if (!mobj_get_va(mobj, OPTEE_MSG_GET_ARG_SIZE(num_params)))
+ sz = OPTEE_MSG_GET_ARG_SIZE(num_params);
+ thr->rpc_arg = mobj_get_va(mobj, offset + sz);
+ if (!thr->rpc_arg || !mobj_get_va(mobj, offset + sz + sz_rpc))
goto out_dec_map;
rv = tee_entry_std(arg, num_params);
- thread_rpc_shm_cache_clear(&threads[thread_get_id()].shm_cache);
+ thread_rpc_shm_cache_clear(&thr->shm_cache);
+ thr->rpc_arg = NULL;
out_dec_map:
mobj_dec_map(mobj);
@@ -1184,23 +1217,6 @@ out_put_mobj:
return rv;
}
-static uint32_t yielding_unregister_shm(uint64_t cookie)
-{
- uint32_t res = mobj_ffa_unregister_by_cookie(cookie);
-
- switch (res) {
- case TEE_SUCCESS:
- case TEE_ERROR_ITEM_NOT_FOUND:
- return 0;
- case TEE_ERROR_BUSY:
- EMSG("res %#"PRIx32, res);
- return FFA_BUSY;
- default:
- EMSG("res %#"PRIx32, res);
- return FFA_INVALID_PARAMETERS;
- }
-}
-
/*
* Helper routine for the assembly function thread_std_smc_entry()
*
@@ -1208,7 +1224,8 @@ static uint32_t yielding_unregister_shm(uint64_t cookie)
* the unpaged area.
*/
uint32_t __weak __thread_std_smc_entry(uint32_t a0, uint32_t a1,
- uint32_t a2, uint32_t a3)
+ uint32_t a2, uint32_t a3,
+ uint32_t a4, uint32_t a5 __unused)
{
/*
* Arguments are supplied from handle_yielding_call() as:
@@ -1216,17 +1233,15 @@ uint32_t __weak __thread_std_smc_entry(uint32_t a0, uint32_t a1,
* a1 <- w3
* a2 <- w4
* a3 <- w5
+ * a4 <- w6
+ * a5 <- w7
*/
thread_get_tsd()->rpc_target_info = swap_src_dst(a0);
switch (a1) {
case OPTEE_FFA_SP_INIT:
return sp_init_all();
case OPTEE_FFA_YIELDING_CALL_WITH_ARG:
- return yielding_call_with_arg(reg_pair_to_64(a3, a2));
- case OPTEE_FFA_YIELDING_CALL_REGISTER_SHM:
- return FFA_NOT_SUPPORTED;
- case OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM:
- return yielding_unregister_shm(reg_pair_to_64(a3, a2));
+ return yielding_call_with_arg(reg_pair_to_64(a3, a2), a4);
default:
return FFA_DENIED;
}
@@ -1246,101 +1261,23 @@ static bool set_fmem(struct optee_msg_param *param, struct thread_param *tpm)
param->u.fmem.size = tpm->u.memref.size;
if (tpm->u.memref.mobj) {
- param->u.fmem.global_id = mobj_get_cookie(tpm->u.memref.mobj);
- if (!param->u.fmem.global_id)
+ uint64_t cookie = mobj_get_cookie(tpm->u.memref.mobj);
+
+ /* If a mobj is passed it better be one with a valid cookie. */
+ if (cookie == OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
return false;
+
+ param->u.fmem.global_id = cookie;
} else {
- param->u.fmem.global_id = 0;
+ param->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
}
return true;
}
-static void thread_rpc_free(uint32_t type, uint64_t cookie, struct mobj *mobj)
-{
- TEE_Result res = TEE_SUCCESS;
- struct thread_rpc_arg rpc_arg = { .call = {
- .w1 = thread_get_tsd()->rpc_target_info,
- .w4 = type,
- },
- };
-
- reg_pair_from_64(cookie, &rpc_arg.call.w6, &rpc_arg.call.w5);
- mobj_put(mobj);
- res = mobj_ffa_unregister_by_cookie(cookie);
- if (res)
- DMSG("mobj_ffa_unregister_by_cookie(%#"PRIx64"): res %#"PRIx32,
- cookie, res);
- thread_rpc(&rpc_arg);
-}
-
-static struct mobj *thread_rpc_alloc(size_t size, uint32_t type)
-{
- struct mobj *mobj = NULL;
- unsigned int page_count = ROUNDUP(size, SMALL_PAGE_SIZE) /
- SMALL_PAGE_SIZE;
- struct thread_rpc_arg rpc_arg = { .call = {
- .w1 = thread_get_tsd()->rpc_target_info,
- .w4 = type,
- .w5 = page_count,
- },
- };
- unsigned int internal_offset = 0;
- uint64_t cookie = 0;
-
- thread_rpc(&rpc_arg);
-
- cookie = reg_pair_to_64(rpc_arg.ret.w5, rpc_arg.ret.w4);
- if (!cookie)
- return NULL;
- internal_offset = rpc_arg.ret.w6;
-
- mobj = mobj_ffa_get_by_cookie(cookie, internal_offset);
- if (!mobj) {
- DMSG("mobj_ffa_get_by_cookie(%#"PRIx64", %#x): failed",
- cookie, internal_offset);
- return NULL;
- }
-
- assert(mobj_is_nonsec(mobj));
-
- if (mobj_inc_map(mobj)) {
- DMSG("mobj_inc_map(%#"PRIx64"): failed", cookie);
- mobj_put(mobj);
- return NULL;
- }
-
- return mobj;
-}
-
-struct mobj *thread_rpc_alloc_payload(size_t size)
-{
- return thread_rpc_alloc(size,
- OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM);
-}
-
-void thread_rpc_free_payload(struct mobj *mobj)
-{
- thread_rpc_free(OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM,
- mobj_get_cookie(mobj), mobj);
-}
-
-struct mobj *thread_rpc_alloc_kernel_payload(size_t size)
-{
- return thread_rpc_alloc(size,
- OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM);
-}
-
-void thread_rpc_free_kernel_payload(struct mobj *mobj)
-{
- thread_rpc_free(OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM,
- mobj_get_cookie(mobj), mobj);
-}
-
static uint32_t get_rpc_arg(uint32_t cmd, size_t num_params,
struct thread_param *params,
- struct optee_msg_arg **arg_ret,
- uint64_t *carg_ret)
+ struct optee_msg_arg **arg_ret)
{
size_t sz = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS);
struct thread_ctx *thr = threads + thread_get_id();
@@ -1350,19 +1287,8 @@ static uint32_t get_rpc_arg(uint32_t cmd, size_t num_params,
return TEE_ERROR_BAD_PARAMETERS;
if (!arg) {
- struct mobj *mobj = thread_rpc_alloc_kernel_payload(sz);
-
- if (!mobj)
- return TEE_ERROR_OUT_OF_MEMORY;
-
- arg = mobj_get_va(mobj, 0);
- if (!arg) {
- thread_rpc_free_kernel_payload(mobj);
- return TEE_ERROR_OUT_OF_MEMORY;
- }
-
- thr->rpc_arg = arg;
- thr->rpc_mobj = mobj;
+ EMSG("rpc_arg not set");
+ return TEE_ERROR_GENERIC;
}
memset(arg, 0, sz);
@@ -1396,8 +1322,8 @@ static uint32_t get_rpc_arg(uint32_t cmd, size_t num_params,
}
}
- *arg_ret = arg;
- *carg_ret = mobj_get_cookie(thr->rpc_mobj);
+ if (arg_ret)
+ *arg_ret = arg;
return TEE_SUCCESS;
}
@@ -1433,32 +1359,112 @@ uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params,
.w4 = OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD,
},
};
- uint64_t carg = 0;
struct optee_msg_arg *arg = NULL;
uint32_t ret = 0;
- ret = get_rpc_arg(cmd, num_params, params, &arg, &carg);
+ ret = get_rpc_arg(cmd, num_params, params, &arg);
if (ret)
return ret;
- reg_pair_from_64(carg, &rpc_arg.call.w6, &rpc_arg.call.w5);
thread_rpc(&rpc_arg);
return get_rpc_arg_res(arg, num_params, params);
}
-struct mobj *thread_rpc_alloc_global_payload(size_t size __unused)
+static void thread_rpc_free(unsigned int bt, uint64_t cookie, struct mobj *mobj)
{
- return NULL;
+ struct thread_rpc_arg rpc_arg = { .call = {
+ .w1 = thread_get_tsd()->rpc_target_info,
+ .w4 = OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD,
+ },
+ };
+ struct thread_param param = THREAD_PARAM_VALUE(IN, bt, cookie, 0);
+ uint32_t res2 = 0;
+ uint32_t res = 0;
+
+ DMSG("freeing cookie %#"PRIx64, cookie);
+
+ res = get_rpc_arg(OPTEE_RPC_CMD_SHM_FREE, 1, &param, NULL);
+
+ mobj_put(mobj);
+ res2 = mobj_ffa_unregister_by_cookie(cookie);
+ if (res2)
+ DMSG("mobj_ffa_unregister_by_cookie(%#"PRIx64"): %#"PRIx32,
+ cookie, res2);
+ if (!res)
+ thread_rpc(&rpc_arg);
}
-void thread_rpc_free_global_payload(struct mobj *mobj __unused)
+static struct mobj *thread_rpc_alloc(size_t size, size_t align, unsigned int bt)
{
- /*
- * "can't happen" since thread_rpc_alloc_global_payload() always
- * returns NULL.
- */
- volatile bool cant_happen __maybe_unused = true;
+ struct thread_rpc_arg rpc_arg = { .call = {
+ .w1 = thread_get_tsd()->rpc_target_info,
+ .w4 = OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD,
+ },
+ };
+ struct thread_param param = THREAD_PARAM_VALUE(IN, bt, size, align);
+ struct optee_msg_arg *arg = NULL;
+ unsigned int internal_offset = 0;
+ struct mobj *mobj = NULL;
+ uint64_t cookie = 0;
- assert(!cant_happen);
+ if (get_rpc_arg(OPTEE_RPC_CMD_SHM_ALLOC, 1, &param, &arg))
+ return NULL;
+
+ thread_rpc(&rpc_arg);
+
+ if (arg->num_params != 1 ||
+ arg->params->attr != OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT)
+ return NULL;
+
+ internal_offset = arg->params->u.fmem.internal_offs;
+ cookie = arg->params->u.fmem.global_id;
+ mobj = mobj_ffa_get_by_cookie(cookie, internal_offset);
+ if (!mobj) {
+ DMSG("mobj_ffa_get_by_cookie(%#"PRIx64", %#x): failed",
+ cookie, internal_offset);
+ return NULL;
+ }
+
+ assert(mobj_is_nonsec(mobj));
+
+ if (mobj_inc_map(mobj)) {
+ DMSG("mobj_inc_map(%#"PRIx64"): failed", cookie);
+ mobj_put(mobj);
+ return NULL;
+ }
+
+ return mobj;
+}
+
+struct mobj *thread_rpc_alloc_payload(size_t size)
+{
+ return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_APPL);
+}
+
+struct mobj *thread_rpc_alloc_kernel_payload(size_t size)
+{
+ return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_KERNEL);
+}
+
+void thread_rpc_free_kernel_payload(struct mobj *mobj)
+{
+ thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, mobj_get_cookie(mobj), mobj);
+}
+
+void thread_rpc_free_payload(struct mobj *mobj)
+{
+ thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj),
+ mobj);
+}
+
+struct mobj *thread_rpc_alloc_global_payload(size_t size)
+{
+ return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_GLOBAL);
+}
+
+void thread_rpc_free_global_payload(struct mobj *mobj)
+{
+ thread_rpc_free(OPTEE_RPC_SHM_TYPE_GLOBAL, mobj_get_cookie(mobj),
+ mobj);
}
diff --git a/core/arch/arm/mm/mobj_ffa.c b/core/arch/arm/mm/mobj_ffa.c
index 0443be82c..21b807bc1 100644
--- a/core/arch/arm/mm/mobj_ffa.c
+++ b/core/arch/arm/mm/mobj_ffa.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2016-2020, Linaro Limited
+ * Copyright (c) 2021-2022, Arm Limited
*/
#include <assert.h>
@@ -99,10 +100,10 @@ struct mobj_ffa *mobj_ffa_sel1_spmc_new(unsigned int num_pages,
if (i != -1) {
bit_set(shm_bits, i);
/*
- * + 1 to avoid a cookie value 0, setting bit 44 to use one
- * of the upper 32 bits too for testing.
+ * Setting bit 44 to use one of the upper 32 bits too for
+ * testing.
*/
- mf->cookie = (i + 1) | BIT64(44);
+ mf->cookie = (i) | BIT64(44);
}
cpu_spin_unlock_xrestore(&shm_lock, exceptions);
@@ -177,7 +178,7 @@ static struct mobj_ffa *find_in_list(struct mobj_ffa_head *head,
#ifdef CFG_CORE_SEL1_SPMC
void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mf)
{
- int i = (mf->cookie - 1) & ~BIT64(44);
+ int i = (mf->cookie) & ~BIT64(44);
uint32_t exceptions = 0;
assert(i >= 0 && i < NUM_SHMS);
@@ -285,6 +286,7 @@ TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie)
struct mobj_ffa *mf = NULL;
uint32_t exceptions = 0;
+ assert(cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID);
exceptions = cpu_spin_lock_xsave(&shm_lock);
mf = find_in_list(&shm_head, cmp_cookie, cookie);
/*
diff --git a/core/arch/arm/tee/entry_std.c b/core/arch/arm/tee/entry_std.c
index 424c4c677..5f5123224 100644
--- a/core/arch/arm/tee/entry_std.c
+++ b/core/arch/arm/tee/entry_std.c
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2015-2016, Linaro Limited
* Copyright (c) 2014, STMicroelectronics International N.V.
+ * Copyright (c) 2021-2022, Arm Limited
*/
#include <assert.h>
@@ -67,7 +68,7 @@ static TEE_Result set_fmem_param(const struct optee_msg_param_fmem *fmem,
uint64_t global_id = READ_ONCE(fmem->global_id);
size_t sz = READ_ONCE(fmem->size);
- if (!global_id && !sz) {
+ if (global_id == OPTEE_MSG_FMEM_INVALID_GLOBAL_ID && !sz) {
mem->mobj = NULL;
mem->offs = 0;
mem->size = 0;
diff --git a/core/include/optee_msg.h b/core/include/optee_msg.h
index 57467c773..407f87aeb 100644
--- a/core/include/optee_msg.h
+++ b/core/include/optee_msg.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2015-2020, Linaro Limited
+ * Copyright (c) 2021-2022, Arm Limited
*/
#ifndef _OPTEE_MSG_H
#define _OPTEE_MSG_H
@@ -96,6 +97,8 @@
*/
#define OPTEE_MSG_NONCONTIG_PAGE_SIZE 4096
+#define OPTEE_MSG_FMEM_INVALID_GLOBAL_ID 0xffffffffffffffff
+
#ifndef __ASSEMBLER__
/**
* struct optee_msg_param_tmem - temporary memory reference parameter