Skip to content

Commit

Permalink
ABI change: add shared memory support
Browse files Browse the repository at this point in the history
Normal world now can call OPTEE_MSG_CMD_REGISTER_SHM and
OPTEE_MSG_CMD_UNREGISTER_SHM functions to register/unregister
shared memory.

After that, it can use OPTEE_MSG_ATTR_TYPE_RMEM_* to reference
to that registered shared buffers.

Signed-off-by: Volodymyr Babchuk <vlad.babchuk@gmail.com>
  • Loading branch information
lorc committed Jun 22, 2017
1 parent 6896e91 commit 4e5d00d
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 9 deletions.
6 changes: 6 additions & 0 deletions core/arch/arm/include/sm/optee_smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,12 @@
#define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM (1 << 0)
/* Secure world can communicate via previously unregistered shared memory */
#define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM (1 << 1)
/*
* Secure world supporst commands "register/unregister shared memory",
* secure world accepts command buffers located in any parts of unsecure RAM
*/
#define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM (1 << 2)

#define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9
#define OPTEE_SMC_EXCHANGE_CAPABILITIES \
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES)
Expand Down
20 changes: 16 additions & 4 deletions core/arch/arm/kernel/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,12 @@ struct mobj *thread_rpc_alloc_arg(size_t size, uint64_t *cookie)
if (!ALIGNMENT_IS_OK(pa, struct optee_msg_arg))
goto err;

mobj = mobj_shm_alloc(pa, size);
/* Check if this region is in static shared space */
if (core_pbuf_is(CORE_MEM_NSEC_SHM, pa, size))
mobj = mobj_shm_alloc(pa, size);
else if ((!(pa & SMALL_PAGE_MASK)) && size <= SMALL_PAGE_SIZE)
mobj = mobj_mapped_shm_alloc(&pa, 1, 0, co);

if (!mobj)
goto err;

Expand Down Expand Up @@ -1375,9 +1380,16 @@ static struct mobj *thread_rpc_alloc(size_t size, size_t align, unsigned int bt,
if (arg->num_params != 1)
goto fail;

mobj = mobj_shm_alloc(arg->params[0].u.tmem.buf_ptr,
arg->params[0].u.tmem.size);
*cookie = arg->params[0].u.tmem.shm_ref;
if (arg->params[0].attr == OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT) {
*cookie = arg->params[0].u.tmem.shm_ref;
mobj = mobj_shm_alloc(arg->params[0].u.tmem.buf_ptr,
arg->params[0].u.tmem.size);
} 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);
} else
goto fail;

if (!mobj)
goto free_first;
Expand Down
3 changes: 3 additions & 0 deletions core/arch/arm/mm/core_mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,9 @@ static void set_pg_region(struct core_mmu_table_info *dir_info,

r.size = MIN(CORE_MMU_PGDIR_SIZE - (r.va - pg_info->va_base),
end - r.va);
r.size = MIN(r.size, mobj_get_phys_granule(region->mobj));
r.size = ROUNDUP(r.size, SMALL_PAGE_SIZE);

if (!mobj_is_paged(region->mobj)) {
size_t granule = BIT(pg_info->shift);
size_t offset = r.va - region->va + region->offset;
Expand Down
7 changes: 7 additions & 0 deletions core/arch/arm/tee/entry_fast.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ static void tee_entry_exchange_capabilities(struct thread_smc_args *args)

args->a0 = OPTEE_SMC_RETURN_OK;
args->a1 = OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM;

if (core_mmu_nsec_ddr_is_defined()) {
IMSG("NS DDR configured. Enabling dynamic SHM");
args->a1 |= OPTEE_SMC_SEC_CAP_DYNAMIC_SHM;
} else {
EMSG("No NS DDR configured for the platform. Disabling dynamic SHM");
}
}

static void tee_entry_disable_shm_cache(struct thread_smc_args *args)
Expand Down
137 changes: 132 additions & 5 deletions core/arch/arm/tee/entry_std.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,23 @@ static TEE_Result assign_mobj_to_param_mem(const paddr_t pa, const size_t sz,
return TEE_ERROR_BAD_PARAMETERS;
}

static TEE_Result set_rmem_param(const struct optee_msg_param *param,
struct param_mem *mem)
{
struct mobj *rmem_mobj =
mobj_reg_shm_find_by_cookie(param->u.rmem.shm_ref);
paddr_t b;

if (mobj_get_pa(rmem_mobj, 0, 0, &b) != TEE_SUCCESS)
return TEE_ERROR_BAD_PARAMETERS;

mem->mobj = rmem_mobj;
mem->offs = param->u.rmem.offs + (b & SMALL_PAGE_MASK);
mem->size = param->u.rmem.size;

return TEE_SUCCESS;
}

static TEE_Result copy_in_params(const struct optee_msg_param *params,
uint32_t num_params, struct tee_ta_param *ta_param,
uint64_t *saved_attr)
Expand Down Expand Up @@ -141,6 +158,16 @@ static TEE_Result copy_in_params(const struct optee_msg_param *params,
if (res != TEE_SUCCESS)
return res;
break;
case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;

res = set_rmem_param(params + n, &ta_param->u[n].mem);
if (res != TEE_SUCCESS)
return res;
break;
default:
return TEE_ERROR_BAD_PARAMETERS;
}
Expand All @@ -152,15 +179,26 @@ static TEE_Result copy_in_params(const struct optee_msg_param *params,
}

static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params,
struct optee_msg_param *params)
struct optee_msg_param *params, uint64_t *saved_attr)
{
size_t n;

for (n = 0; n < num_params; n++) {
switch (TEE_PARAM_TYPE_GET(ta_param->types, n)) {
case TEE_PARAM_TYPE_MEMREF_OUTPUT:
case TEE_PARAM_TYPE_MEMREF_INOUT:
params[n].u.tmem.size = ta_param->u[n].mem.size;
switch (saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK) {
case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
params[n].u.tmem.size = ta_param->u[n].mem.size;
break;
case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
params[n].u.rmem.size = ta_param->u[n].mem.size;
break;
default:
break;
}
break;
case TEE_PARAM_TYPE_VALUE_OUTPUT:
case TEE_PARAM_TYPE_VALUE_INOUT:
Expand Down Expand Up @@ -242,7 +280,8 @@ static void entry_open_session(struct thread_smc_args *smc_args,
&clnt_id, TEE_TIMEOUT_INFINITE, &param);
if (res != TEE_SUCCESS)
s = NULL;
copy_out_param(&param, num_params - num_meta, arg->params + num_meta);
copy_out_param(&param, num_params - num_meta, arg->params + num_meta,
saved_attr);

/*
* The occurrence of open/close session command is usually
Expand Down Expand Up @@ -310,7 +349,7 @@ static void entry_invoke_command(struct thread_smc_args *smc_args,

tee_ta_put_session(s);

copy_out_param(&param, num_params, arg->params);
copy_out_param(&param, num_params, arg->params, saved_attr);

out:
arg->ret = res;
Expand Down Expand Up @@ -345,6 +384,77 @@ static void entry_cancel(struct thread_smc_args *smc_args,
smc_args->a0 = OPTEE_SMC_RETURN_OK;
}

static void register_shm(struct thread_smc_args *smc_args,
struct optee_msg_arg *arg, uint32_t num_params)
{
if (num_params != 1 ||
(arg->params[0].attr !=
(OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG))) {
arg->ret = TEE_ERROR_BAD_PARAMETERS;
return;
}

/* We don't need mobj pointer there, we only care if it was created */
if (!msg_param_mobj_from_noncontig(arg->params, false))
arg->ret = TEE_ERROR_BAD_PARAMETERS;
else
arg->ret = TEE_SUCCESS;

smc_args->a0 = OPTEE_SMC_RETURN_OK;
}

static void unregister_shm(struct thread_smc_args *smc_args,
struct optee_msg_arg *arg, uint32_t num_params)
{
if (num_params == 1) {
struct mobj *mobj;
uint64_t cookie = arg->params[0].u.rmem.shm_ref;

mobj = mobj_reg_shm_find_by_cookie(cookie);
if (mobj) {
mobj_free(mobj);
arg->ret = TEE_SUCCESS;
} else {
EMSG("Can't find mapping with given cookie\n");
arg->ret = TEE_ERROR_BAD_PARAMETERS;
}
} else {
arg->ret = TEE_ERROR_BAD_PARAMETERS;
arg->ret_origin = TEE_ORIGIN_TEE;
}

smc_args->a0 = OPTEE_SMC_RETURN_OK;
}

static struct mobj *map_cmd_buffer(paddr_t parg, uint32_t *num_params)
{
struct mobj *mobj;
struct optee_msg_arg *arg;
size_t args_size;

assert(!(parg & SMALL_PAGE_MASK));
/* mobj_mapped_shm_alloc checks if parg resides in nonsec ddr */
mobj = mobj_mapped_shm_alloc(&parg, 1, 0, 0);
if (!mobj)
return NULL;

arg = mobj_get_va(mobj, 0);
if (!arg) {
mobj_free(mobj);
return NULL;
}

*num_params = arg->num_params;
args_size = OPTEE_MSG_GET_ARG_SIZE(*num_params);
if (args_size > SMALL_PAGE_SIZE) {
EMSG("Command buffer spans across page boundary");
mobj_free(mobj);
return NULL;
}

return mobj;
}

static struct mobj *get_cmd_buffer(paddr_t parg, uint32_t *num_params)
{
struct optee_msg_arg *arg;
Expand Down Expand Up @@ -379,7 +489,17 @@ void __weak tee_entry_std(struct thread_smc_args *smc_args)
}
parg = (uint64_t)smc_args->a1 << 32 | smc_args->a2;

mobj = get_cmd_buffer(parg, &num_params);
/* Check if this region is in static shared space */
if (core_pbuf_is(CORE_MEM_NSEC_SHM, parg,
sizeof(struct optee_msg_arg))) {
mobj = get_cmd_buffer(parg, &num_params);
} else {
if (parg & SMALL_PAGE_MASK) {
smc_args->a0 = OPTEE_SMC_RETURN_EBADADDR;
return;
}
mobj = map_cmd_buffer(parg, &num_params);
}

if (!mobj || !ALIGNMENT_IS_OK(parg, struct optee_msg_arg)) {
EMSG("Bad arg address 0x%" PRIxPA, parg);
Expand All @@ -406,6 +526,13 @@ void __weak tee_entry_std(struct thread_smc_args *smc_args)
case OPTEE_MSG_CMD_CANCEL:
entry_cancel(smc_args, arg, num_params);
break;
case OPTEE_MSG_CMD_REGISTER_SHM:
register_shm(smc_args, arg, num_params);
break;
case OPTEE_MSG_CMD_UNREGISTER_SHM:
unregister_shm(smc_args, arg, num_params);
break;

default:
EMSG("Unknown cmd 0x%x\n", arg->cmd);
smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;
Expand Down

0 comments on commit 4e5d00d

Please sign in to comment.