aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolodymyr Babchuk <vlad.babchuk@gmail.com>2017-06-16 00:38:44 +0300
committerJérôme Forissier <jerome.forissier@linaro.org>2017-10-11 15:50:16 +0200
commitb05cd886e06dce9516b6434d3f1e0bd0029be1ac (patch)
tree12fa3d3d97d05e13f0d7d6b039de0485b8cbd137
parent55d6853cb4682d969705f6e349a96e9f2f4fe9dc (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.c6
-rw-r--r--core/arch/arm/tee/entry_std.c50
-rw-r--r--core/include/kernel/msg_param.h16
-rw-r--r--core/kernel/msg_param.c17
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,
&param, 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, &param);
@@ -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(&param, 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;