aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Wiklander <jens.wiklander@linaro.org>2020-07-21 11:28:06 +0200
committerJérôme Forissier <jerome@forissier.org>2020-07-22 08:36:49 +0200
commit9bee8f2a5af7ad5219a65d6f12ff25771f3325c0 (patch)
treeb549c610222cc185caba33f8f4d50251498c02cb
parenta9d0e06fff51ed6ec026c0c20dae2dd89a882e0f (diff)
core: add generic rpc shared memory buffer caching
Replaces tee_fs_rpc_cache_alloc() with thread_rpc_shm_alloc() which also takes a shared memory type as argument. This allows allocating an kernel private RPC buffer when needed. Acked-by: Jerome Forissier <jerome@forissier.org> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
-rw-r--r--core/arch/arm/include/kernel/thread.h23
-rw-r--r--core/arch/arm/kernel/thread.c85
-rw-r--r--core/arch/arm/kernel/thread_optee_smc.c2
-rw-r--r--core/arch/arm/kernel/thread_private.h10
-rw-r--r--core/include/tee/tee_fs_rpc.h19
-rw-r--r--core/tee/socket.c12
-rw-r--r--core/tee/sub.mk1
-rw-r--r--core/tee/tadb.c6
-rw-r--r--core/tee/tee_fs_rpc.c27
-rw-r--r--core/tee/tee_fs_rpc_cache.c65
10 files changed, 144 insertions, 106 deletions
diff --git a/core/arch/arm/include/kernel/thread.h b/core/arch/arm/include/kernel/thread.h
index 03f2fd08..bb34d783 100644
--- a/core/arch/arm/include/kernel/thread.h
+++ b/core/arch/arm/include/kernel/thread.h
@@ -232,13 +232,9 @@ struct thread_specific_data {
TAILQ_HEAD(, tee_ta_session) sess_stack;
struct tee_ta_ctx *ctx;
struct pgt_cache pgt_cache;
- void *rpc_fs_payload;
- struct mobj *rpc_fs_payload_mobj;
- size_t rpc_fs_payload_size;
#ifdef CFG_CORE_FFA
uint32_t rpc_target_info;
#endif
-
uint32_t abort_type;
uint32_t abort_descr;
vaddr_t abort_va;
@@ -705,6 +701,25 @@ struct mobj *thread_rpc_alloc_global_payload(size_t size);
*/
void thread_rpc_free_global_payload(struct mobj *mobj);
+/*
+ * enum thread_shm_type - type of non-secure shared memory
+ * @THREAD_SHM_TYPE_APPLICATION - user space application shared memory
+ * @THREAD_SHM_TYPE_KERNEL_PRIVATE - kernel private shared memory
+ * @THREAD_SHM_TYPE_GLOBAL - user space and kernel shared memory
+ */
+enum thread_shm_type {
+ THREAD_SHM_TYPE_APPLICATION,
+ THREAD_SHM_TYPE_KERNEL_PRIVATE,
+ THREAD_SHM_TYPE_GLOBAL,
+};
+
+/*
+ * Returns a pointer to the cached FS RPC memory. Each thread has a unique
+ * cache. The pointer is guaranteed to point to a large enough area or to
+ * be NULL.
+ */
+void *thread_rpc_shm_cache_alloc(enum thread_shm_type shm_type,
+ size_t size, struct mobj **mobj);
#endif /*__ASSEMBLER__*/
#endif /*KERNEL_THREAD_H*/
diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c
index 21a00ba3..c03a0774 100644
--- a/core/arch/arm/kernel/thread.c
+++ b/core/arch/arm/kernel/thread.c
@@ -1446,3 +1446,88 @@ void __weak thread_svc_handler(struct thread_svc_regs *regs)
setup_unwind_user_mode(regs);
}
}
+
+static struct mobj *alloc_shm(enum thread_shm_type shm_type, size_t size)
+{
+ switch (shm_type) {
+ case THREAD_SHM_TYPE_APPLICATION:
+ return thread_rpc_alloc_payload(size);
+ case THREAD_SHM_TYPE_KERNEL_PRIVATE:
+ return thread_rpc_alloc_kernel_payload(size);
+ case THREAD_SHM_TYPE_GLOBAL:
+ return thread_rpc_alloc_global_payload(size);
+ default:
+ return NULL;
+ }
+}
+
+void *thread_rpc_shm_cache_alloc(enum thread_shm_type shm_type, size_t size,
+ struct mobj **mobj)
+{
+ struct thread_shm_cache *cache = &threads[thread_get_id()].shm_cache;
+ size_t sz = size;
+ paddr_t p = 0;
+ void *va = NULL;
+
+ if (!size)
+ return NULL;
+
+ /*
+ * Always allocate in page chunks as normal world allocates payload
+ * memory as complete pages.
+ */
+ sz = ROUNDUP(size, SMALL_PAGE_SIZE);
+
+ if (cache->type != shm_type || sz > cache->size) {
+ thread_rpc_shm_cache_clear(cache);
+
+ cache->mobj = alloc_shm(shm_type, sz);
+ if (!cache->mobj)
+ return NULL;
+
+ if (mobj_get_pa(cache->mobj, 0, 0, &p))
+ goto err;
+
+ if (!ALIGNMENT_IS_OK(p, uint64_t))
+ goto err;
+
+ va = mobj_get_va(cache->mobj, 0);
+ if (!va)
+ goto err;
+
+ cache->size = sz;
+ cache->type = shm_type;
+ } else {
+ va = mobj_get_va(cache->mobj, 0);
+ if (!va)
+ goto err;
+ }
+ *mobj = cache->mobj;
+
+ return va;
+err:
+ thread_rpc_shm_cache_clear(cache);
+ return NULL;
+}
+
+void thread_rpc_shm_cache_clear(struct thread_shm_cache *cache)
+{
+ if (cache->mobj) {
+ switch (cache->type) {
+ case THREAD_SHM_TYPE_APPLICATION:
+ thread_rpc_free_payload(cache->mobj);
+ break;
+ case THREAD_SHM_TYPE_KERNEL_PRIVATE:
+ thread_rpc_free_kernel_payload(cache->mobj);
+ break;
+ case THREAD_SHM_TYPE_GLOBAL:
+ thread_rpc_free_global_payload(cache->mobj);
+ break;
+ default:
+ assert(0); /* "can't happen" */
+ break;
+ }
+ cache->mobj = NULL;
+ cache->size = 0;
+ }
+}
diff --git a/core/arch/arm/kernel/thread_optee_smc.c b/core/arch/arm/kernel/thread_optee_smc.c
index 1e326f6f..118d1c57 100644
--- a/core/arch/arm/kernel/thread_optee_smc.c
+++ b/core/arch/arm/kernel/thread_optee_smc.c
@@ -217,7 +217,7 @@ uint32_t __weak __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2,
if (rv == OPTEE_SMC_RETURN_OK) {
struct thread_ctx *thr = threads + thread_get_id();
- tee_fs_rpc_cache_clear(&thr->tsd);
+ thread_rpc_shm_cache_clear(&thr->shm_cache);
if (!thread_prealloc_rpc_cache) {
thread_rpc_free_arg(mobj_get_cookie(thr->rpc_mobj));
mobj_put(thr->rpc_mobj);
diff --git a/core/arch/arm/kernel/thread_private.h b/core/arch/arm/kernel/thread_private.h
index 2933f679..3c6132c2 100644
--- a/core/arch/arm/kernel/thread_private.h
+++ b/core/arch/arm/kernel/thread_private.h
@@ -43,6 +43,12 @@ struct thread_vfp_state {
#endif /*CFG_WITH_VFP*/
+struct thread_shm_cache {
+ struct mobj *mobj;
+ size_t size;
+ enum thread_shm_type type;
+};
+
struct thread_ctx {
struct thread_ctx_regs regs;
enum thread_state state;
@@ -58,6 +64,7 @@ struct thread_ctx {
#endif
void *rpc_arg;
struct mobj *rpc_mobj;
+ struct thread_shm_cache shm_cache;
struct thread_specific_data tsd;
};
#endif /*__ASSEMBLER__*/
@@ -234,6 +241,7 @@ uint32_t thread_handle_std_smc(uint32_t a0, uint32_t a1, uint32_t a2,
/* Called from assembly only. Handles a SVC from user mode. */
void thread_svc_handler(struct thread_svc_regs *regs);
+/* Frees the cache of allocated FS RPC memory */
+void thread_rpc_shm_cache_clear(struct thread_shm_cache *cache);
#endif /*__ASSEMBLER__*/
-
#endif /*THREAD_PRIVATE_H*/
diff --git a/core/include/tee/tee_fs_rpc.h b/core/include/tee/tee_fs_rpc.h
index 0340661f..d1e32535 100644
--- a/core/include/tee/tee_fs_rpc.h
+++ b/core/include/tee/tee_fs_rpc.h
@@ -57,23 +57,4 @@ TEE_Result tee_fs_rpc_opendir(uint32_t id, const TEE_UUID *uuid,
TEE_Result tee_fs_rpc_closedir(uint32_t id, struct tee_fs_dir *d);
TEE_Result tee_fs_rpc_readdir(uint32_t id, struct tee_fs_dir *d,
struct tee_fs_dirent **ent);
-
-struct thread_specific_data;
-#if defined(CFG_WITH_USER_TA) && (defined(CFG_REE_FS) || defined(CFG_RPMB_FS))
-/* Frees the cache of allocated FS RPC memory */
-void tee_fs_rpc_cache_clear(struct thread_specific_data *tsd);
-#else
-static inline void tee_fs_rpc_cache_clear(
- struct thread_specific_data *tsd __unused)
-{
-}
-#endif
-
-/*
- * Returns a pointer to the cached FS RPC memory. Each thread has a unique
- * cache. The pointer is guaranteed to point to a large enough area or to
- * be NULL.
- */
-void *tee_fs_rpc_cache_alloc(size_t size, struct mobj **mobj);
-
#endif /* TEE_FS_RPC_H */
diff --git a/core/tee/socket.c b/core/tee/socket.c
index 5ced5802..40eedb11 100644
--- a/core/tee/socket.c
+++ b/core/tee/socket.c
@@ -33,7 +33,8 @@ static TEE_Result socket_open(uint32_t instance_id, uint32_t param_types,
return TEE_ERROR_BAD_PARAMETERS;
}
- va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ params[1].memref.size, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -95,7 +96,8 @@ static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types,
return TEE_ERROR_BAD_PARAMETERS;
}
- va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ params[1].memref.size, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -132,7 +134,8 @@ static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types,
return TEE_ERROR_BAD_PARAMETERS;
}
- va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ params[1].memref.size, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -172,7 +175,8 @@ static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types,
return TEE_ERROR_BAD_PARAMETERS;
}
- va = tee_fs_rpc_cache_alloc(params[1].memref.size, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ params[1].memref.size, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
diff --git a/core/tee/sub.mk b/core/tee/sub.mk
index 554edfce..39e680b5 100644
--- a/core/tee/sub.mk
+++ b/core/tee/sub.mk
@@ -34,7 +34,6 @@ srcs-$(call cfg-one-enabled,CFG_REE_FS CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += \
fs_htree.c
srcs-$(CFG_REE_FS) += fs_dirfile.c
srcs-$(CFG_REE_FS) += tee_fs_rpc.c
-srcs-$(call cfg-one-enabled,CFG_REE_FS CFG_RPMB_FS) += tee_fs_rpc_cache.c
srcs-y += tee_fs_key_manager.c
srcs-y += tee_obj.c
srcs-y += tee_pobj.c
diff --git a/core/tee/tadb.c b/core/tee/tadb.c
index 01f00234..d78c90b1 100644
--- a/core/tee/tadb.c
+++ b/core/tee/tadb.c
@@ -97,7 +97,8 @@ static TEE_Result ta_operation_open(unsigned int cmd, uint32_t file_number,
TEE_Result res;
void *va;
- va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ TEE_FS_NAME_MAX, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -121,7 +122,8 @@ static TEE_Result ta_operation_remove(uint32_t file_number)
struct mobj *mobj;
void *va;
- va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ TEE_FS_NAME_MAX, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
diff --git a/core/tee/tee_fs_rpc.c b/core/tee/tee_fs_rpc.c
index 8662c43c..22891694 100644
--- a/core/tee/tee_fs_rpc.c
+++ b/core/tee/tee_fs_rpc.c
@@ -35,7 +35,8 @@ static TEE_Result operation_open(uint32_t id, unsigned int cmd,
TEE_Result res;
void *va;
- va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ TEE_FS_NAME_MAX, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -76,7 +77,8 @@ static TEE_Result operation_open_dfh(uint32_t id, unsigned int cmd,
TEE_Result res;
void *va;
- va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ TEE_FS_NAME_MAX, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -134,7 +136,8 @@ TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op,
if (offset < 0)
return TEE_ERROR_BAD_PARAMETERS;
- va = tee_fs_rpc_cache_alloc(data_len, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ data_len, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -171,7 +174,8 @@ TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op,
if (offset < 0)
return TEE_ERROR_BAD_PARAMETERS;
- va = tee_fs_rpc_cache_alloc(data_len, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ data_len, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -211,7 +215,8 @@ TEE_Result tee_fs_rpc_remove(uint32_t id, struct tee_pobj *po)
struct mobj *mobj;
void *va;
- va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ TEE_FS_NAME_MAX, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -237,7 +242,8 @@ TEE_Result tee_fs_rpc_remove_dfh(uint32_t id,
struct mobj *mobj;
void *va;
- va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ TEE_FS_NAME_MAX, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -264,7 +270,8 @@ TEE_Result tee_fs_rpc_rename(uint32_t id, struct tee_pobj *old,
char *va;
bool temp;
- va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX * 2, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ TEE_FS_NAME_MAX * 2, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -314,7 +321,8 @@ TEE_Result tee_fs_rpc_opendir(uint32_t id, const TEE_UUID *uuid,
if (!dir)
return TEE_ERROR_OUT_OF_MEMORY;
- va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ TEE_FS_NAME_MAX, &mobj);
if (!va) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto err_exit;
@@ -373,7 +381,8 @@ TEE_Result tee_fs_rpc_readdir(uint32_t id, struct tee_fs_dir *d,
if (!d)
return TEE_ERROR_ITEM_NOT_FOUND;
- va = tee_fs_rpc_cache_alloc(max_name_len, &mobj);
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_APPLICATION,
+ max_name_len, &mobj);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
diff --git a/core/tee/tee_fs_rpc_cache.c b/core/tee/tee_fs_rpc_cache.c
deleted file mode 100644
index 3148aea2..00000000
--- a/core/tee/tee_fs_rpc_cache.c
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-License-Identifier: BSD-2-Clause
-/*
- * Copyright (c) 2016, Linaro Limited
- */
-
-#include <kernel/thread.h>
-#include <mm/core_memprot.h>
-#include <mm/core_mmu.h>
-#include <mm/mobj.h>
-#include <tee/tee_fs_rpc.h>
-
-void tee_fs_rpc_cache_clear(struct thread_specific_data *tsd)
-{
- if (tsd->rpc_fs_payload) {
- thread_rpc_free_payload(tsd->rpc_fs_payload_mobj);
- tsd->rpc_fs_payload = NULL;
- tsd->rpc_fs_payload_size = 0;
- tsd->rpc_fs_payload_mobj = NULL;
- }
-}
-
-void *tee_fs_rpc_cache_alloc(size_t size, struct mobj **mobj)
-{
- struct thread_specific_data *tsd = thread_get_tsd();
- size_t sz = size;
- paddr_t p;
- void *va;
-
- if (!size)
- return NULL;
-
- /*
- * Always allocate in page chunks as normal world allocates payload
- * memory as complete pages.
- */
- sz = ROUNDUP(size, SMALL_PAGE_SIZE);
-
- if (sz > tsd->rpc_fs_payload_size) {
- tee_fs_rpc_cache_clear(tsd);
-
- *mobj = thread_rpc_alloc_payload(sz);
- if (!*mobj)
- return NULL;
-
- if (mobj_get_pa(*mobj, 0, 0, &p))
- goto err;
-
- if (!ALIGNMENT_IS_OK(p, uint64_t))
- goto err;
-
- va = mobj_get_va(*mobj, 0);
- if (!va)
- goto err;
-
- tsd->rpc_fs_payload = va;
- tsd->rpc_fs_payload_mobj = *mobj;
- tsd->rpc_fs_payload_size = sz;
- } else
- *mobj = tsd->rpc_fs_payload_mobj;
-
- return tsd->rpc_fs_payload;
-err:
- thread_rpc_free_payload(*mobj);
- return NULL;
-}