From 9bee8f2a5af7ad5219a65d6f12ff25771f3325c0 Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Tue, 21 Jul 2020 11:28:06 +0200 Subject: 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 Signed-off-by: Jens Wiklander --- core/arch/arm/include/kernel/thread.h | 23 +++++++-- core/arch/arm/kernel/thread.c | 85 +++++++++++++++++++++++++++++++++ core/arch/arm/kernel/thread_optee_smc.c | 2 +- core/arch/arm/kernel/thread_private.h | 10 +++- core/include/tee/tee_fs_rpc.h | 19 -------- core/tee/socket.c | 12 +++-- core/tee/sub.mk | 1 - core/tee/tadb.c | 6 ++- core/tee/tee_fs_rpc.c | 27 +++++++---- core/tee/tee_fs_rpc_cache.c | 65 ------------------------- 10 files changed, 144 insertions(+), 106 deletions(-) delete mode 100644 core/tee/tee_fs_rpc_cache.c 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 -#include -#include -#include -#include - -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; -} -- cgit v1.2.3