Skip to content

Commit

Permalink
core: add registered 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>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
  • Loading branch information
lorc authored and jforissier committed Oct 11, 2017
1 parent 5f4ccb3 commit 55d6853
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 9 deletions.
7 changes: 7 additions & 0 deletions core/arch/arm/include/sm/optee_smc.h
Expand Up @@ -290,6 +290,13 @@
#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 supports commands "register/unregister shared memory",
* secure world accepts command buffers located in any parts of non-secure 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
Expand Up @@ -1249,7 +1249,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 @@ -1406,9 +1411,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
5 changes: 5 additions & 0 deletions core/arch/arm/mm/core_mmu.c
Expand Up @@ -1273,10 +1273,15 @@ 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);

if (!mobj_is_paged(region->mobj)) {
size_t granule = BIT(pg_info->shift);
size_t offset = r.va - region->va + region->offset;

r.size = MIN(r.size,
mobj_get_phys_granule(region->mobj));
r.size = ROUNDUP(r.size, SMALL_PAGE_SIZE);

if (mobj_get_pa(region->mobj, offset, granule,
&r.pa) != TEE_SUCCESS)
panic("Failed to get PA of unpaged mobj");
Expand Down
8 changes: 8 additions & 0 deletions core/arch/arm/tee/entry_fast.c
Expand Up @@ -82,6 +82,8 @@ static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args)

static void tee_entry_exchange_capabilities(struct thread_smc_args *args)
{
bool dyn_shm_en = false;

/*
* Currently we ignore OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
*
Expand All @@ -103,6 +105,12 @@ 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;

dyn_shm_en = core_mmu_nsec_ddr_is_defined();
if (dyn_shm_en)
args->a1 |= OPTEE_SMC_SEC_CAP_DYNAMIC_SHM;

IMSG("Dynamic shared memory is %sabled", dyn_shm_en ? "en" : "dis");
}

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
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,
Expand Down Expand Up @@ -142,6 +159,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 @@ -153,15 +180,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 @@ -243,7 +281,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 @@ -311,7 +350,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 @@ -346,6 +385,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");
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 @@ -380,7 +490,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 @@ -407,6 +527,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

1 comment on commit 55d6853

@leesagacious
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magnitude of the update is large enough.

Please sign in to comment.