summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolodymyr Babchuk <vlad.babchuk@gmail.com>2017-11-29 07:48:31 -0500
committerJens Wiklander <jens.wiklander@linaro.org>2017-12-15 07:32:32 -0500
commit06ca79179c4e00efe53cfe43456f1586f944f04f (patch)
tree1a2c1887556a988634c5392123c338155e615c7f
parent3bb48ba5cd60f9685aa8f1ccd9b14a72e237c13f (diff)
tee: optee: add shared buffer registration functions
This change adds ops for shm_(un)register functions in tee interface. Client application can use these functions to (un)register an own shared buffer in OP-TEE address space. This allows zero copy data sharing between Normal and Secure Worlds. Please note that while those functions were added to optee code, it does not report to userspace that those functions are available. OP-TEE code does not set TEE_GEN_CAP_REG_MEM flag. This flag will be enabled only after all other features of dynamic shared memory will be implemented in subsequent patches. Of course user can ignore presence of TEE_GEN_CAP_REG_MEM flag and try do call those functions. This is okay, driver will register shared buffer in OP-TEE, but any attempts to use this shared buffer will fail. Signed-off-by: Volodymyr Babchuk <vlad.babchuk@gmail.com> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
-rw-r--r--drivers/tee/optee/call.c69
-rw-r--r--drivers/tee/optee/core.c2
-rw-r--r--drivers/tee/optee/optee_private.h4
3 files changed, 75 insertions, 0 deletions
diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
index e85860f6e057..a05e9e61105f 100644
--- a/drivers/tee/optee/call.c
+++ b/drivers/tee/optee/call.c
@@ -533,3 +533,72 @@ void optee_free_pages_list(void *list, size_t num_entries)
533 free_pages_exact(list, get_pages_list_size(num_entries)); 533 free_pages_exact(list, get_pages_list_size(num_entries));
534} 534}
535 535
536int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
537 struct page **pages, size_t num_pages)
538{
539 struct tee_shm *shm_arg = NULL;
540 struct optee_msg_arg *msg_arg;
541 u64 *pages_list;
542 phys_addr_t msg_parg;
543 int rc = 0;
544
545 if (!num_pages)
546 return -EINVAL;
547
548 pages_list = optee_allocate_pages_list(num_pages);
549 if (!pages_list)
550 return -ENOMEM;
551
552 shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
553 if (IS_ERR(shm_arg)) {
554 rc = PTR_ERR(shm_arg);
555 goto out;
556 }
557
558 optee_fill_pages_list(pages_list, pages, num_pages,
559 tee_shm_get_page_offset(shm));
560
561 msg_arg->cmd = OPTEE_MSG_CMD_REGISTER_SHM;
562 msg_arg->params->attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
563 OPTEE_MSG_ATTR_NONCONTIG;
564 msg_arg->params->u.tmem.shm_ref = (unsigned long)shm;
565 msg_arg->params->u.tmem.size = tee_shm_get_size(shm);
566 /*
567 * In the least bits of msg_arg->params->u.tmem.buf_ptr we
568 * store buffer offset from 4k page, as described in OP-TEE ABI.
569 */
570 msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) |
571 (tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
572
573 if (optee_do_call_with_arg(ctx, msg_parg) ||
574 msg_arg->ret != TEEC_SUCCESS)
575 rc = -EINVAL;
576
577 tee_shm_free(shm_arg);
578out:
579 optee_free_pages_list(pages_list, num_pages);
580 return rc;
581}
582
583int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
584{
585 struct tee_shm *shm_arg;
586 struct optee_msg_arg *msg_arg;
587 phys_addr_t msg_parg;
588 int rc = 0;
589
590 shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
591 if (IS_ERR(shm_arg))
592 return PTR_ERR(shm_arg);
593
594 msg_arg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM;
595
596 msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
597 msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm;
598
599 if (optee_do_call_with_arg(ctx, msg_parg) ||
600 msg_arg->ret != TEEC_SUCCESS)
601 rc = -EINVAL;
602 tee_shm_free(shm_arg);
603 return rc;
604}
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index edb6e4e9ef3a..eb407daaba03 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -267,6 +267,8 @@ static const struct tee_driver_ops optee_ops = {
267 .close_session = optee_close_session, 267 .close_session = optee_close_session,
268 .invoke_func = optee_invoke_func, 268 .invoke_func = optee_invoke_func,
269 .cancel_req = optee_cancel_req, 269 .cancel_req = optee_cancel_req,
270 .shm_register = optee_shm_register,
271 .shm_unregister = optee_shm_unregister,
270}; 272};
271 273
272static const struct tee_desc optee_desc = { 274static const struct tee_desc optee_desc = {
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index b63213d09d68..d7bc77d95022 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -160,6 +160,10 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session);
160void optee_enable_shm_cache(struct optee *optee); 160void optee_enable_shm_cache(struct optee *optee);
161void optee_disable_shm_cache(struct optee *optee); 161void optee_disable_shm_cache(struct optee *optee);
162 162
163int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
164 struct page **pages, size_t num_pages);
165int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm);
166
163int optee_from_msg_param(struct tee_param *params, size_t num_params, 167int optee_from_msg_param(struct tee_param *params, size_t num_params,
164 const struct optee_msg_param *msg_params); 168 const struct optee_msg_param *msg_params);
165int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params, 169int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,