Skip to content

Commit 2b78d79

Browse files
committed
optee: FF-A: dynamic protected memory allocation
Add support in the OP-TEE backend driver dynamic protected memory allocation with FF-A. The protected memory pools for dynamically allocated protected memory are instantiated when requested by user-space. This instantiation can fail if OP-TEE doesn't support the requested use-case of protected memory. Restricted memory pools based on a static carveout or dynamic allocation can coexist for different use-cases. We use only dynamic allocation with FF-A. Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
1 parent 0e32abe commit 2b78d79

4 files changed

Lines changed: 492 additions & 3 deletions

File tree

drivers/tee/optee/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ optee-objs += core.o
44
optee-objs += call.o
55
optee-objs += notif.o
66
optee-objs += rpc.o
7+
optee-objs += protmem.o
78
optee-objs += supp.o
89
optee-objs += device.o
910
optee-objs += smc_abi.o

drivers/tee/optee/ffa_abi.c

Lines changed: 144 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,124 @@ static int optee_ffa_do_call_with_arg(struct tee_context *ctx,
649649
return optee_ffa_yielding_call(ctx, &data, rpc_arg, system_thread);
650650
}
651651

652+
static int do_call_lend_protmem(struct optee *optee, u64 cookie, u32 use_case)
653+
{
654+
struct optee_shm_arg_entry *entry;
655+
struct optee_msg_arg *msg_arg;
656+
struct tee_shm *shm;
657+
u_int offs;
658+
int rc;
659+
660+
msg_arg = optee_get_msg_arg(optee->ctx, 1, &entry, &shm, &offs);
661+
if (IS_ERR(msg_arg))
662+
return PTR_ERR(msg_arg);
663+
664+
msg_arg->cmd = OPTEE_MSG_CMD_ASSIGN_PROTMEM;
665+
msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
666+
msg_arg->params[0].u.value.a = cookie;
667+
msg_arg->params[0].u.value.b = use_case;
668+
669+
rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false);
670+
if (rc)
671+
goto out;
672+
if (msg_arg->ret != TEEC_SUCCESS) {
673+
rc = -EINVAL;
674+
goto out;
675+
}
676+
677+
out:
678+
optee_free_msg_arg(optee->ctx, entry, offs);
679+
return rc;
680+
}
681+
682+
static int optee_ffa_lend_protmem(struct optee *optee, struct tee_shm *protmem,
683+
u32 *mem_attrs, unsigned int ma_count,
684+
u32 use_case)
685+
{
686+
struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
687+
const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
688+
const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
689+
struct ffa_send_direct_data data;
690+
struct ffa_mem_region_attributes *mem_attr;
691+
struct ffa_mem_ops_args args = {
692+
.use_txbuf = true,
693+
.tag = use_case,
694+
};
695+
struct page *page;
696+
struct scatterlist sgl;
697+
unsigned int n;
698+
int rc;
699+
700+
mem_attr = kcalloc(ma_count, sizeof(*mem_attr), GFP_KERNEL);
701+
for (n = 0; n < ma_count; n++) {
702+
mem_attr[n].receiver = mem_attrs[n] & U16_MAX;
703+
mem_attr[n].attrs = mem_attrs[n] >> 16;
704+
}
705+
args.attrs = mem_attr;
706+
args.nattrs = ma_count;
707+
708+
page = phys_to_page(protmem->paddr);
709+
sg_init_table(&sgl, 1);
710+
sg_set_page(&sgl, page, protmem->size, 0);
711+
712+
args.sg = &sgl;
713+
rc = mem_ops->memory_lend(&args);
714+
kfree(mem_attr);
715+
if (rc)
716+
return rc;
717+
718+
rc = do_call_lend_protmem(optee, args.g_handle, use_case);
719+
if (rc)
720+
goto err_reclaim;
721+
722+
rc = optee_shm_add_ffa_handle(optee, protmem, args.g_handle);
723+
if (rc)
724+
goto err_unreg;
725+
726+
protmem->sec_world_id = args.g_handle;
727+
728+
return 0;
729+
730+
err_unreg:
731+
data = (struct ffa_send_direct_data){
732+
.data0 = OPTEE_FFA_RELEASE_PROTMEM,
733+
.data1 = (u32)args.g_handle,
734+
.data2 = (u32)(args.g_handle >> 32),
735+
};
736+
msg_ops->sync_send_receive(ffa_dev, &data);
737+
err_reclaim:
738+
mem_ops->memory_reclaim(args.g_handle, 0);
739+
return rc;
740+
}
741+
742+
static int optee_ffa_reclaim_protmem(struct optee *optee,
743+
struct tee_shm *protmem)
744+
{
745+
struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
746+
const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
747+
const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
748+
u64 global_handle = protmem->sec_world_id;
749+
struct ffa_send_direct_data data = {
750+
.data0 = OPTEE_FFA_RELEASE_PROTMEM,
751+
.data1 = (u32)global_handle,
752+
.data2 = (u32)(global_handle >> 32)
753+
};
754+
int rc;
755+
756+
optee_shm_rem_ffa_handle(optee, global_handle);
757+
protmem->sec_world_id = 0;
758+
759+
rc = msg_ops->sync_send_receive(ffa_dev, &data);
760+
if (rc)
761+
pr_err("Release SHM id 0x%llx rc %d\n", global_handle, rc);
762+
763+
rc = mem_ops->memory_reclaim(global_handle, 0);
764+
if (rc)
765+
pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
766+
767+
return rc;
768+
}
769+
652770
/*
653771
* 6. Driver initialization
654772
*
@@ -819,6 +937,8 @@ static const struct optee_ops optee_ffa_ops = {
819937
.do_call_with_arg = optee_ffa_do_call_with_arg,
820938
.to_msg_param = optee_ffa_to_msg_param,
821939
.from_msg_param = optee_ffa_from_msg_param,
940+
.lend_protmem = optee_ffa_lend_protmem,
941+
.reclaim_protmem = optee_ffa_reclaim_protmem,
822942
};
823943

824944
static void optee_ffa_remove(struct ffa_device *ffa_dev)
@@ -891,6 +1011,25 @@ static int optee_ffa_async_notif_init(struct ffa_device *ffa_dev,
8911011
return rc;
8921012
}
8931013

1014+
static int optee_ffa_protmem_pool_init(struct optee *optee, u32 sec_caps)
1015+
{
1016+
enum tee_dma_heap_id id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY;
1017+
struct tee_protmem_pool *pool;
1018+
int rc = 0;
1019+
1020+
if (sec_caps & OPTEE_FFA_SEC_CAP_PROTMEM) {
1021+
pool = optee_protmem_alloc_dyn_pool(optee, id);
1022+
if (IS_ERR(pool))
1023+
return PTR_ERR(pool);
1024+
1025+
rc = tee_device_register_dma_heap(optee->teedev, id, pool);
1026+
if (rc)
1027+
pool->ops->destroy_pool(pool);
1028+
}
1029+
1030+
return rc;
1031+
}
1032+
8941033
static int optee_ffa_probe(struct ffa_device *ffa_dev)
8951034
{
8961035
const struct ffa_notifier_ops *notif_ops;
@@ -941,7 +1080,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
9411080
optee);
9421081
if (IS_ERR(teedev)) {
9431082
rc = PTR_ERR(teedev);
944-
goto err_free_pool;
1083+
goto err_free_shm_pool;
9451084
}
9461085
optee->teedev = teedev;
9471086

@@ -988,6 +1127,9 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
9881127
rc);
9891128
}
9901129

1130+
if (optee_ffa_protmem_pool_init(optee, sec_caps))
1131+
pr_info("Protected memory service not available\n");
1132+
9911133
rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
9921134
if (rc)
9931135
goto err_unregister_devices;
@@ -1018,7 +1160,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
10181160
tee_device_unregister(optee->supp_teedev);
10191161
err_unreg_teedev:
10201162
tee_device_unregister(optee->teedev);
1021-
err_free_pool:
1163+
err_free_shm_pool:
10221164
tee_shm_pool_free(pool);
10231165
err_free_optee:
10241166
kfree(optee);

drivers/tee/optee/optee_private.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,14 @@ struct optee;
176176
* @do_call_with_arg: enters OP-TEE in secure world
177177
* @to_msg_param: converts from struct tee_param to OPTEE_MSG parameters
178178
* @from_msg_param: converts from OPTEE_MSG parameters to struct tee_param
179+
* @lend_protmem: lends physically contiguous memory as restricted
180+
* memory, inaccessible by the kernel
181+
* @reclaim_protmem: reclaims restricted memory previously lent with
182+
* @lend_protmem() and makes it accessible by the
183+
* kernel again
179184
*
180185
* These OPs are only supposed to be used internally in the OP-TEE driver
181-
* as a way of abstracting the different methogs of entering OP-TEE in
186+
* as a way of abstracting the different methods of entering OP-TEE in
182187
* secure world.
183188
*/
184189
struct optee_ops {
@@ -191,6 +196,10 @@ struct optee_ops {
191196
int (*from_msg_param)(struct optee *optee, struct tee_param *params,
192197
size_t num_params,
193198
const struct optee_msg_param *msg_params);
199+
int (*lend_protmem)(struct optee *optee, struct tee_shm *protmem,
200+
u32 *mem_attr, unsigned int ma_count,
201+
u32 use_case);
202+
int (*reclaim_protmem)(struct optee *optee, struct tee_shm *protmem);
194203
};
195204

196205
/**
@@ -287,6 +296,8 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
287296
void optee_supp_init(struct optee_supp *supp);
288297
void optee_supp_uninit(struct optee_supp *supp);
289298
void optee_supp_release(struct optee_supp *supp);
299+
struct tee_protmem_pool *optee_protmem_alloc_dyn_pool(struct optee *optee,
300+
enum tee_dma_heap_id id);
290301

291302
int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
292303
struct tee_param *param);

0 commit comments

Comments
 (0)