Lines Matching +full:op +full:- +full:tee

1 // SPDX-License-Identifier: GPL-2.0-only
22 * This file implement the FF-A ABI used when communicating with secure world
23 * OP-TEE OS via FF-A.
25 * 1. Maintain a hash table for lookup of a global FF-A memory handle
34 * 1. Maintain a hash table for lookup of a global FF-A memory handle
36 * FF-A assigns a global memory handle for each piece shared memory.
65 mutex_lock(&optee->ffa.mutex); in optee_shm_from_ffa_handle()
66 r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id, in optee_shm_from_ffa_handle()
69 shm = r->shm; in optee_shm_from_ffa_handle()
70 mutex_unlock(&optee->ffa.mutex); in optee_shm_from_ffa_handle()
83 return -ENOMEM; in optee_shm_add_ffa_handle()
84 r->shm = shm; in optee_shm_add_ffa_handle()
85 r->global_id = global_id; in optee_shm_add_ffa_handle()
87 mutex_lock(&optee->ffa.mutex); in optee_shm_add_ffa_handle()
88 rc = rhashtable_lookup_insert_fast(&optee->ffa.global_ids, &r->linkage, in optee_shm_add_ffa_handle()
90 mutex_unlock(&optee->ffa.mutex); in optee_shm_add_ffa_handle()
101 int rc = -ENOENT; in optee_shm_rem_ffa_handle()
103 mutex_lock(&optee->ffa.mutex); in optee_shm_rem_ffa_handle()
104 r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id, in optee_shm_rem_ffa_handle()
107 rc = rhashtable_remove_fast(&optee->ffa.global_ids, in optee_shm_rem_ffa_handle()
108 &r->linkage, shm_rhash_params); in optee_shm_rem_ffa_handle()
109 mutex_unlock(&optee->ffa.mutex); in optee_shm_rem_ffa_handle()
131 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT + in from_msg_param_ffa_mem()
132 attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT; in from_msg_param_ffa_mem()
133 p->u.memref.size = mp->u.fmem.size; in from_msg_param_ffa_mem()
135 if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) in from_msg_param_ffa_mem()
136 shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id); in from_msg_param_ffa_mem()
137 p->u.memref.shm = shm; in from_msg_param_ffa_mem()
140 offs_low = mp->u.fmem.offs_low; in from_msg_param_ffa_mem()
141 offs_high = mp->u.fmem.offs_high; in from_msg_param_ffa_mem()
143 p->u.memref.shm_offs = offs_low | offs_high << 32; in from_msg_param_ffa_mem()
147 * optee_ffa_from_msg_param() - convert from OPTEE_MSG parameters to
165 u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK; in optee_ffa_from_msg_param()
169 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE; in optee_ffa_from_msg_param()
170 memset(&p->u, 0, sizeof(p->u)); in optee_ffa_from_msg_param()
183 return -EINVAL; in optee_ffa_from_msg_param()
193 struct tee_shm *shm = p->u.memref.shm; in to_msg_param_ffa_mem()
195 mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr - in to_msg_param_ffa_mem()
199 u64 shm_offs = p->u.memref.shm_offs; in to_msg_param_ffa_mem()
201 mp->u.fmem.internal_offs = shm->offset; in to_msg_param_ffa_mem()
203 mp->u.fmem.offs_low = shm_offs; in to_msg_param_ffa_mem()
204 mp->u.fmem.offs_high = shm_offs >> 32; in to_msg_param_ffa_mem()
206 if (mp->u.fmem.offs_high != shm_offs >> 32) in to_msg_param_ffa_mem()
207 return -EINVAL; in to_msg_param_ffa_mem()
209 mp->u.fmem.global_id = shm->sec_world_id; in to_msg_param_ffa_mem()
211 memset(&mp->u, 0, sizeof(mp->u)); in to_msg_param_ffa_mem()
212 mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; in to_msg_param_ffa_mem()
214 mp->u.fmem.size = p->u.memref.size; in to_msg_param_ffa_mem()
220 * optee_ffa_to_msg_param() - convert from struct tee_params to OPTEE_MSG
239 switch (p->attr) { in optee_ffa_to_msg_param()
241 mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE; in optee_ffa_to_msg_param()
242 memset(&mp->u, 0, sizeof(mp->u)); in optee_ffa_to_msg_param()
253 return -EINVAL; in optee_ffa_to_msg_param()
256 return -EINVAL; in optee_ffa_to_msg_param()
267 * clients and for tee-supplicant.
274 struct optee *optee = tee_get_drvdata(ctx->teedev); in optee_ffa_shm_register()
275 struct ffa_device *ffa_dev = optee->ffa.ffa_dev; in optee_ffa_shm_register()
276 const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops; in optee_ffa_shm_register()
278 .receiver = ffa_dev->vm_id, in optee_ffa_shm_register()
298 rc = mem_ops->memory_share(&args); in optee_ffa_shm_register()
305 mem_ops->memory_reclaim(args.g_handle, 0); in optee_ffa_shm_register()
309 shm->sec_world_id = args.g_handle; in optee_ffa_shm_register()
317 struct optee *optee = tee_get_drvdata(ctx->teedev); in optee_ffa_shm_unregister()
318 struct ffa_device *ffa_dev = optee->ffa.ffa_dev; in optee_ffa_shm_unregister()
319 const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops; in optee_ffa_shm_unregister()
320 const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops; in optee_ffa_shm_unregister()
321 u64 global_handle = shm->sec_world_id; in optee_ffa_shm_unregister()
330 shm->sec_world_id = 0; in optee_ffa_shm_unregister()
332 rc = msg_ops->sync_send_receive(ffa_dev, &data); in optee_ffa_shm_unregister()
336 rc = mem_ops->memory_reclaim(global_handle, 0); in optee_ffa_shm_unregister()
346 struct optee *optee = tee_get_drvdata(ctx->teedev); in optee_ffa_shm_unregister_supp()
348 u64 global_handle = shm->sec_world_id; in optee_ffa_shm_unregister_supp()
353 * since this is OP-TEE freeing via RPC so it has already retired in optee_ffa_shm_unregister_supp()
358 mem_ops = optee->ffa.ffa_dev->ops->mem_ops; in optee_ffa_shm_unregister_supp()
359 rc = mem_ops->memory_reclaim(global_handle, 0); in optee_ffa_shm_unregister_supp()
363 shm->sec_world_id = 0; in optee_ffa_shm_unregister_supp()
371 * Implements an OP-TEE specific shared memory pool.
400 * optee_ffa_shm_pool_alloc_pages() - create page-based allocator pool
402 * This pool is used with OP-TEE over FF-A. In this case command buffers
410 return ERR_PTR(-ENOMEM); in optee_ffa_shm_pool_alloc_pages()
412 pool->ops = &pool_ffa_ops; in optee_ffa_shm_pool_alloc_pages()
423 * delivery of non-secure interrupts to for instance allow rescheduling of
433 if (arg->num_params != 1 || in handle_ffa_rpc_func_cmd_shm_alloc()
434 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { in handle_ffa_rpc_func_cmd_shm_alloc()
435 arg->ret = TEEC_ERROR_BAD_PARAMETERS; in handle_ffa_rpc_func_cmd_shm_alloc()
439 switch (arg->params[0].u.value.a) { in handle_ffa_rpc_func_cmd_shm_alloc()
441 shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b); in handle_ffa_rpc_func_cmd_shm_alloc()
444 shm = tee_shm_alloc_priv_buf(optee->ctx, in handle_ffa_rpc_func_cmd_shm_alloc()
445 arg->params[0].u.value.b); in handle_ffa_rpc_func_cmd_shm_alloc()
448 arg->ret = TEEC_ERROR_BAD_PARAMETERS; in handle_ffa_rpc_func_cmd_shm_alloc()
453 arg->ret = TEEC_ERROR_OUT_OF_MEMORY; in handle_ffa_rpc_func_cmd_shm_alloc()
457 arg->params[0] = (struct optee_msg_param){ in handle_ffa_rpc_func_cmd_shm_alloc()
460 .u.fmem.global_id = shm->sec_world_id, in handle_ffa_rpc_func_cmd_shm_alloc()
461 .u.fmem.internal_offs = shm->offset, in handle_ffa_rpc_func_cmd_shm_alloc()
464 arg->ret = TEEC_SUCCESS; in handle_ffa_rpc_func_cmd_shm_alloc()
473 if (arg->num_params != 1 || in handle_ffa_rpc_func_cmd_shm_free()
474 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) in handle_ffa_rpc_func_cmd_shm_free()
477 shm = optee_shm_from_ffa_handle(optee, arg->params[0].u.value.b); in handle_ffa_rpc_func_cmd_shm_free()
480 switch (arg->params[0].u.value.a) { in handle_ffa_rpc_func_cmd_shm_free()
490 arg->ret = TEEC_SUCCESS; in handle_ffa_rpc_func_cmd_shm_free()
494 arg->ret = TEEC_ERROR_BAD_PARAMETERS; in handle_ffa_rpc_func_cmd_shm_free()
501 arg->ret_origin = TEEC_ORIGIN_COMMS; in handle_ffa_rpc_func_cmd()
502 switch (arg->cmd) { in handle_ffa_rpc_func_cmd()
535 struct optee *optee = tee_get_drvdata(ctx->teedev); in optee_ffa_yielding_call()
536 struct ffa_device *ffa_dev = optee->ffa.ffa_dev; in optee_ffa_yielding_call()
537 const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops; in optee_ffa_yielding_call()
539 u32 cmd = data->data0; in optee_ffa_yielding_call()
540 u32 w4 = data->data1; in optee_ffa_yielding_call()
541 u32 w5 = data->data2; in optee_ffa_yielding_call()
542 u32 w6 = data->data3; in optee_ffa_yielding_call()
546 optee_cq_wait_init(&optee->call_queue, &w, system_thread); in optee_ffa_yielding_call()
548 rc = msg_ops->sync_send_receive(ffa_dev, data); in optee_ffa_yielding_call()
552 switch ((int)data->data0) { in optee_ffa_yielding_call()
557 rc = -EIO; in optee_ffa_yielding_call()
565 optee_cq_wait_for_completion(&optee->call_queue, &w); in optee_ffa_yielding_call()
566 data->data0 = cmd; in optee_ffa_yielding_call()
567 data->data1 = w4; in optee_ffa_yielding_call()
568 data->data2 = w5; in optee_ffa_yielding_call()
569 data->data3 = w6; in optee_ffa_yielding_call()
572 rc = -EIO; in optee_ffa_yielding_call()
576 if (data->data1 == OPTEE_FFA_YIELDING_CALL_RETURN_DONE) in optee_ffa_yielding_call()
580 * OP-TEE has returned with a RPC request. in optee_ffa_yielding_call()
582 * Note that data->data4 (passed in register w7) is already in optee_ffa_yielding_call()
583 * filled in by ffa_mem_ops->sync_send_receive() returning in optee_ffa_yielding_call()
587 optee_handle_ffa_rpc(ctx, optee, data->data1, rpc_arg); in optee_ffa_yielding_call()
589 data->data0 = cmd; in optee_ffa_yielding_call()
590 data->data1 = 0; in optee_ffa_yielding_call()
591 data->data2 = 0; in optee_ffa_yielding_call()
592 data->data3 = 0; in optee_ffa_yielding_call()
599 optee_cq_wait_final(&optee->call_queue, &w); in optee_ffa_yielding_call()
605 * optee_ffa_do_call_with_arg() - Do a FF-A call to enter OP-TEE in secure world
609 * @system_thread: true if caller requests TEE system thread support
611 * Does a FF-A call to OP-TEE in secure world and handles eventual resulting
612 * Remote Procedure Calls (RPC) from OP-TEE.
614 * Returns return code from FF-A, 0 is OK
623 .data1 = (u32)shm->sec_world_id, in optee_ffa_do_call_with_arg()
624 .data2 = (u32)(shm->sec_world_id >> 32), in optee_ffa_do_call_with_arg()
637 if (shm->offset) in optee_ffa_do_call_with_arg()
638 return -EINVAL; in optee_ffa_do_call_with_arg()
644 rpc_arg_offs = OPTEE_MSG_GET_ARG_SIZE(arg->num_params); in optee_ffa_do_call_with_arg()
655 * During driver inititialization is the OP-TEE Secure Partition is probed
663 const struct ffa_msg_ops *msg_ops = ops->msg_ops; in optee_ffa_api_is_compatbile()
669 msg_ops->mode_32bit_set(ffa_dev); in optee_ffa_api_is_compatbile()
671 rc = msg_ops->sync_send_receive(ffa_dev, &data); in optee_ffa_api_is_compatbile()
678 pr_err("Incompatible OP-TEE API version %lu.%lu", in optee_ffa_api_is_compatbile()
686 rc = msg_ops->sync_send_receive(ffa_dev, &data); in optee_ffa_api_is_compatbile()
711 rc = ops->msg_ops->sync_send_receive(ffa_dev, &data); in optee_ffa_exchange_caps()
735 if (notify_id == optee->ffa.bottom_half_value) in notif_callback()
736 optee_do_bottom_half(optee->ctx); in notif_callback()
743 struct ffa_device *ffa_dev = optee->ffa.ffa_dev; in enable_async_notif()
746 .data1 = optee->ffa.bottom_half_value, in enable_async_notif()
750 rc = ffa_dev->ops->msg_ops->sync_send_receive(ffa_dev, &data); in enable_async_notif()
787 .name = DRIVER_NAME "-ffa-clnt",
803 .name = DRIVER_NAME "-ffa-supp",
818 u32 bottom_half_id = optee->ffa.bottom_half_value; in optee_ffa_remove()
821 ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev, in optee_ffa_remove()
825 mutex_destroy(&optee->ffa.mutex); in optee_ffa_remove()
826 rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL); in optee_ffa_remove()
839 rc = ffa_dev->ops->notifier_ops->notify_request(ffa_dev, in optee_ffa_async_notif_init()
847 * -EACCES means that the notification ID was in optee_ffa_async_notif_init()
853 if (rc != -EACCES) in optee_ffa_async_notif_init()
859 optee->ffa.bottom_half_value = notif_id; in optee_ffa_async_notif_init()
863 ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev, in optee_ffa_async_notif_init()
865 optee->ffa.bottom_half_value = U32_MAX; in optee_ffa_async_notif_init()
885 ffa_ops = ffa_dev->ops; in optee_ffa_probe()
886 notif_ops = ffa_ops->notifier_ops; in optee_ffa_probe()
889 return -EINVAL; in optee_ffa_probe()
893 return -EINVAL; in optee_ffa_probe()
899 return -ENOMEM; in optee_ffa_probe()
906 optee->pool = pool; in optee_ffa_probe()
908 optee->ops = &optee_ffa_ops; in optee_ffa_probe()
909 optee->ffa.ffa_dev = ffa_dev; in optee_ffa_probe()
910 optee->ffa.bottom_half_value = U32_MAX; in optee_ffa_probe()
911 optee->rpc_param_count = rpc_param_count; in optee_ffa_probe()
915 optee->in_kernel_rpmb_routing = true; in optee_ffa_probe()
917 teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool, in optee_ffa_probe()
923 optee->teedev = teedev; in optee_ffa_probe()
925 teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool, in optee_ffa_probe()
931 optee->supp_teedev = teedev; in optee_ffa_probe()
935 rc = tee_device_register(optee->teedev); in optee_ffa_probe()
939 rc = tee_device_register(optee->supp_teedev); in optee_ffa_probe()
943 rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params); in optee_ffa_probe()
946 mutex_init(&optee->ffa.mutex); in optee_ffa_probe()
947 optee_cq_init(&optee->call_queue, 0); in optee_ffa_probe()
948 optee_supp_init(&optee->supp); in optee_ffa_probe()
950 mutex_init(&optee->rpmb_dev_mutex); in optee_ffa_probe()
952 ctx = teedev_open(optee->teedev); in optee_ffa_probe()
957 optee->ctx = ctx; in optee_ffa_probe()
972 INIT_WORK(&optee->rpmb_scan_bus_work, optee_bus_scan_rpmb); in optee_ffa_probe()
973 optee->rpmb_intf.notifier_call = optee_rpmb_intf_rdev; in optee_ffa_probe()
975 &optee->rpmb_intf); in optee_ffa_probe()
981 if (optee->ffa.bottom_half_value != U32_MAX) in optee_ffa_probe()
982 notif_ops->notify_relinquish(ffa_dev, in optee_ffa_probe()
983 optee->ffa.bottom_half_value); in optee_ffa_probe()
988 rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL); in optee_ffa_probe()
989 rpmb_dev_put(optee->rpmb_dev); in optee_ffa_probe()
990 mutex_destroy(&optee->rpmb_dev_mutex); in optee_ffa_probe()
991 optee_supp_uninit(&optee->supp); in optee_ffa_probe()
992 mutex_destroy(&optee->call_queue.mutex); in optee_ffa_probe()
993 mutex_destroy(&optee->ffa.mutex); in optee_ffa_probe()
995 tee_device_unregister(optee->supp_teedev); in optee_ffa_probe()
997 tee_device_unregister(optee->teedev); in optee_ffa_probe()
1006 /* 486178e0-e7f8-11e3-bc5e0002a5d5c51b */
1024 return -EOPNOTSUPP; in optee_ffa_abi_register()