Skip to content

Commit

Permalink
ABI change: enable TMEM parameters with non-contiguous shm
Browse files Browse the repository at this point in the history
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 preallocated
shared memory area. By employing OPTEE_MSG_ATTR_NONCONTIG parameter
atribute, REE can provide own buffer as 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>
  • Loading branch information
lorc committed Jun 22, 2017
1 parent 4e5d00d commit 30260ae
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 23 deletions.
6 changes: 5 additions & 1 deletion core/arch/arm/kernel/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,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;

Expand Down
47 changes: 44 additions & 3 deletions core/arch/arm/tee/entry_std.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -130,8 +150,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) {
Expand All @@ -154,6 +172,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;
Expand All @@ -178,6 +198,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)
{
Expand Down Expand Up @@ -291,6 +324,9 @@ static void entry_open_session(struct thread_smc_args *smc_args,
plat_prng_add_jitter_entropy();

out:
cleanup_params(arg->params + num_meta, saved_attr,
num_params - num_meta);

if (s)
arg->session = (vaddr_t)s;
else
Expand Down Expand Up @@ -352,6 +388,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;
Expand Down Expand Up @@ -395,7 +433,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;
Expand Down
16 changes: 9 additions & 7 deletions core/include/kernel/msg_param.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
17 changes: 5 additions & 12 deletions core/kernel/msg_param.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,23 +110,16 @@ static bool msg_param_extract_pages(paddr_t buffer, paddr_t *pages,
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)
Expand All @@ -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;
Expand Down

0 comments on commit 30260ae

Please sign in to comment.