diff options
author | Volodymyr Babchuk <vlad.babchuk@gmail.com> | 2017-06-16 00:38:44 +0300 |
---|---|---|
committer | Jérôme Forissier <jerome.forissier@linaro.org> | 2017-10-11 15:50:16 +0200 |
commit | b05cd886e06dce9516b6434d3f1e0bd0029be1ac (patch) | |
tree | 12fa3d3d97d05e13f0d7d6b039de0485b8cbd137 | |
parent | 55d6853cb4682d969705f6e349a96e9f2f4fe9dc (diff) |
core: enable non-contiguous temporary reference parameters
Now, when we can pass list of pages between REE and TEE it is possible
to use temporary memory references that are not located in a preallocated
shared memory area. By employing OPTEE_MSG_ATTR_NONCONTIG parameter
attribute, REE can provide own buffer as a temporary memory reference.
Actually, such parameters are indistinguishable from registered shared
memory references. So, when OP-TEE spots temporary memory reference with
OPTEE_MSG_ATTR_NONCONTIG attribute, it will create `mobj_reg_shm` for it.
After call was handled, it will free that mobj.
Signed-off-by: Volodymyr Babchuk <vlad.babchuk@gmail.com>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Tested-by: Jerome Forissier <jerome.forissier@linaro.org> (HiKey)
Tested-by: Jens Wiklander <jens.wiklander@linaro.org> (FVP, QEMU v7/v8)
Tested-by: Jens Wiklander <jens.wiklander@linaro.org> (Juno with and without pager)
Tested-by: Volodymyr Babchuk <vlad.babchuk@gmail.com> (Rcar M3)
-rw-r--r-- | core/arch/arm/kernel/thread.c | 6 | ||||
-rw-r--r-- | core/arch/arm/tee/entry_std.c | 50 | ||||
-rw-r--r-- | core/include/kernel/msg_param.h | 16 | ||||
-rw-r--r-- | core/kernel/msg_param.c | 17 |
4 files changed, 65 insertions, 24 deletions
diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c index 013fed36..4c7bbaf3 100644 --- a/core/arch/arm/kernel/thread.c +++ b/core/arch/arm/kernel/thread.c @@ -1418,7 +1418,11 @@ static struct mobj *thread_rpc_alloc(size_t size, size_t align, unsigned int bt, } else if (arg->params[0].attr == (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG)) { *cookie = arg->params[0].u.tmem.shm_ref; - mobj = msg_param_mobj_from_noncontig(arg->params, true); + mobj = msg_param_mobj_from_noncontig( + arg->params[0].u.tmem.buf_ptr, + arg->params[0].u.tmem.size, + *cookie, + true); } else goto fail; diff --git a/core/arch/arm/tee/entry_std.c b/core/arch/arm/tee/entry_std.c index 29db43d1..38be52d8 100644 --- a/core/arch/arm/tee/entry_std.c +++ b/core/arch/arm/tee/entry_std.c @@ -76,10 +76,30 @@ static bool param_mem_from_mobj(struct param_mem *mem, struct mobj *mobj, /* fill 'struct param_mem' structure if buffer matches a valid memory object */ static TEE_Result assign_mobj_to_param_mem(const paddr_t pa, const size_t sz, + uint32_t attr, uint64_t shm_ref, struct param_mem *mem) { struct mobj __maybe_unused **mobj; + /* NULL Memory Rerefence ? */ + if (!pa && !sz) { + mem->mobj = NULL; + mem->offs = 0; + mem->size = 0; + return TEE_SUCCESS; + } + + /* Non-contigous buffer from non sec DDR? */ + if (attr & OPTEE_MSG_ATTR_NONCONTIG) { + mem->mobj = msg_param_mobj_from_noncontig(pa, sz, shm_ref, + false); + if (!mem->mobj) + return TEE_ERROR_BAD_PARAMETERS; + mem->offs = pa & SMALL_PAGE_MASK; + mem->size = sz; + return TEE_SUCCESS; + } + /* belongs to nonsecure shared memory ? */ if (param_mem_from_mobj(mem, shm_mobj, pa, sz)) return TEE_SUCCESS; @@ -131,8 +151,6 @@ static TEE_Result copy_in_params(const struct optee_msg_param *params, if (saved_attr[n] & OPTEE_MSG_ATTR_META) return TEE_ERROR_BAD_PARAMETERS; - if (saved_attr[n] & OPTEE_MSG_ATTR_NONCONTIG) - return TEE_ERROR_BAD_PARAMETERS; attr = saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK; switch (attr) { @@ -155,6 +173,8 @@ static TEE_Result copy_in_params(const struct optee_msg_param *params, OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; res = assign_mobj_to_param_mem(params[n].u.tmem.buf_ptr, params[n].u.tmem.size, + saved_attr[n], + params[n].u.tmem.shm_ref, &ta_param->u[n].mem); if (res != TEE_SUCCESS) return res; @@ -179,6 +199,19 @@ static TEE_Result copy_in_params(const struct optee_msg_param *params, return TEE_SUCCESS; } +static void cleanup_params(const struct optee_msg_param *params, + const uint64_t *saved_attr, + uint32_t num_params) +{ + size_t n; + + for (n = 0; n < num_params; n++) + if (msg_param_attr_is_tmem(saved_attr[n]) && + saved_attr[n] & OPTEE_MSG_ATTR_NONCONTIG) + mobj_free(mobj_reg_shm_find_by_cookie( + params[n].u.tmem.shm_ref)); +} + static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params, struct optee_msg_param *params, uint64_t *saved_attr) { @@ -275,7 +308,7 @@ static void entry_open_session(struct thread_smc_args *smc_args, res = copy_in_params(arg->params + num_meta, num_params - num_meta, ¶m, saved_attr); if (res != TEE_SUCCESS) - goto out; + goto cleanup_params; res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid, &clnt_id, TEE_TIMEOUT_INFINITE, ¶m); @@ -291,6 +324,10 @@ static void entry_open_session(struct thread_smc_args *smc_args, */ plat_prng_add_jitter_entropy(); +cleanup_params: + cleanup_params(arg->params + num_meta, saved_attr, + num_params - num_meta); + out: if (s) arg->session = (vaddr_t)s; @@ -353,6 +390,8 @@ static void entry_invoke_command(struct thread_smc_args *smc_args, copy_out_param(¶m, num_params, arg->params, saved_attr); out: + cleanup_params(arg->params, saved_attr, num_params); + arg->ret = res; arg->ret_origin = err_orig; smc_args->a0 = OPTEE_SMC_RETURN_OK; @@ -396,7 +435,10 @@ static void register_shm(struct thread_smc_args *smc_args, } /* We don't need mobj pointer there, we only care if it was created */ - if (!msg_param_mobj_from_noncontig(arg->params, false)) + if (!msg_param_mobj_from_noncontig(arg->params[0].u.tmem.buf_ptr, + arg->params[0].u.tmem.size, + arg->params[0].u.tmem.shm_ref, + false)) arg->ret = TEE_ERROR_BAD_PARAMETERS; else arg->ret = TEE_SUCCESS; diff --git a/core/include/kernel/msg_param.h b/core/include/kernel/msg_param.h index 99051676..f6dab47b 100644 --- a/core/include/kernel/msg_param.h +++ b/core/include/kernel/msg_param.h @@ -48,14 +48,16 @@ enum msg_param_mem_dir { * msg_param_mobj_from_noncontig() - construct mobj from non-contiguous * list of pages. * - * @param - pointer to msg_param with OPTEE_MSG_ATTR_NONCONTIG flag set + * @buf_ptr - optee_msg_param.u.tmem.buf_ptr value + * @size - optee_msg_param.u.tmem.size value + * @shm_ref - optee_msg_param.u.tmem.shm_ref value * @map_buffer - true if buffer needs to be mapped into OP-TEE address space * * return: * mobj or NULL on error */ -struct mobj *msg_param_mobj_from_noncontig(const struct optee_msg_param *param, - bool map_buffer); +struct mobj *msg_param_mobj_from_noncontig(paddr_t buf_ptr, size_t size, + uint64_t shm_ref, bool map_buffer); /** * msg_param_init_memparam() - fill memory reference parameter for RPC call @@ -105,16 +107,16 @@ static inline size_t msg_param_get_buf_size(const struct optee_msg_param *param) } /** - * msg_param_attr_is_tmem - helper functions that cheks if parameter is tmem + * msg_param_attr_is_tmem - helper functions that cheks if attribute is tmem * - * @param - struct optee_msg_param to check + * @attr - attribute to check * * return: * corresponding size field */ -static inline bool msg_param_attr_is_tmem(const struct optee_msg_param *param) +static inline bool msg_param_attr_is_tmem(uint64_t attr) { - switch (param->attr & OPTEE_MSG_ATTR_TYPE_MASK) { + switch (attr & OPTEE_MSG_ATTR_TYPE_MASK) { case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: diff --git a/core/kernel/msg_param.c b/core/kernel/msg_param.c index bc4683f7..4cbbfbdf 100644 --- a/core/kernel/msg_param.c +++ b/core/kernel/msg_param.c @@ -110,23 +110,16 @@ out: return ret; } -struct mobj *msg_param_mobj_from_noncontig(const struct optee_msg_param *param, - bool map_buffer) +struct mobj *msg_param_mobj_from_noncontig(paddr_t buf_ptr, size_t size, + uint64_t shm_ref, bool map_buffer) { struct mobj *mobj = NULL; paddr_t *pages; paddr_t page_offset; size_t num_pages; - uint64_t buf_ptr; - - assert(param->attr & OPTEE_MSG_ATTR_NONCONTIG); - - /* Make sure that NW will not change value in SHM */ - buf_ptr = param->u.tmem.buf_ptr; page_offset = buf_ptr & SMALL_PAGE_MASK; - num_pages = (param->u.tmem.size + page_offset - 1) / - SMALL_PAGE_SIZE + 1; + num_pages = (size + page_offset - 1) / SMALL_PAGE_SIZE + 1; pages = malloc(num_pages * sizeof(paddr_t)); if (!pages) @@ -138,10 +131,10 @@ struct mobj *msg_param_mobj_from_noncontig(const struct optee_msg_param *param, if (map_buffer) mobj = mobj_mapped_shm_alloc(pages, num_pages, page_offset, - param->u.tmem.shm_ref); + shm_ref); else mobj = mobj_reg_shm_alloc(pages, num_pages, page_offset, - param->u.tmem.shm_ref); + shm_ref); out: free(pages); return mobj; |