Lines Matching +full:op +full:- +full:tee
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015-2021, Linaro Limited
9 #include <linux/arm-smccc.h>
38 * OP-TEE OS via raw SMCs.
49 * A typical OP-TEE private shm allocation is 224 bytes (argument struct
58 /* SMC ABI considers at most a single TEE firmware */
89 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT + in from_msg_param_tmp_mem()
90 attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; in from_msg_param_tmp_mem()
91 p->u.memref.size = mp->u.tmem.size; in from_msg_param_tmp_mem()
92 shm = (struct tee_shm *)(unsigned long)mp->u.tmem.shm_ref; in from_msg_param_tmp_mem()
94 p->u.memref.shm_offs = 0; in from_msg_param_tmp_mem()
95 p->u.memref.shm = NULL; in from_msg_param_tmp_mem()
103 p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa; in from_msg_param_tmp_mem()
104 p->u.memref.shm = shm; in from_msg_param_tmp_mem()
114 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT + in from_msg_param_reg_mem()
115 attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; in from_msg_param_reg_mem()
116 p->u.memref.size = mp->u.rmem.size; in from_msg_param_reg_mem()
117 shm = (struct tee_shm *)(unsigned long)mp->u.rmem.shm_ref; in from_msg_param_reg_mem()
120 p->u.memref.shm_offs = mp->u.rmem.offs; in from_msg_param_reg_mem()
121 p->u.memref.shm = shm; in from_msg_param_reg_mem()
123 p->u.memref.shm_offs = 0; in from_msg_param_reg_mem()
124 p->u.memref.shm = NULL; in from_msg_param_reg_mem()
129 * optee_from_msg_param() - convert from OPTEE_MSG parameters to
147 u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK; in optee_from_msg_param()
151 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE; in optee_from_msg_param()
152 memset(&p->u, 0, sizeof(p->u)); in optee_from_msg_param()
173 return -EINVAL; in optee_from_msg_param()
185 mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr - in to_msg_param_tmp_mem()
188 mp->u.tmem.shm_ref = (unsigned long)p->u.memref.shm; in to_msg_param_tmp_mem()
189 mp->u.tmem.size = p->u.memref.size; in to_msg_param_tmp_mem()
191 if (!p->u.memref.shm) { in to_msg_param_tmp_mem()
192 mp->u.tmem.buf_ptr = 0; in to_msg_param_tmp_mem()
196 rc = tee_shm_get_pa(p->u.memref.shm, p->u.memref.shm_offs, &pa); in to_msg_param_tmp_mem()
200 mp->u.tmem.buf_ptr = pa; in to_msg_param_tmp_mem()
201 mp->attr |= OPTEE_MSG_ATTR_CACHE_PREDEFINED << in to_msg_param_tmp_mem()
210 mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr - in to_msg_param_reg_mem()
213 mp->u.rmem.shm_ref = (unsigned long)p->u.memref.shm; in to_msg_param_reg_mem()
214 mp->u.rmem.size = p->u.memref.size; in to_msg_param_reg_mem()
215 mp->u.rmem.offs = p->u.memref.shm_offs; in to_msg_param_reg_mem()
220 * optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters
238 switch (p->attr) { in optee_to_msg_param()
240 mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE; in optee_to_msg_param()
241 memset(&mp->u, 0, sizeof(mp->u)); in optee_to_msg_param()
251 if (tee_shm_is_dynamic(p->u.memref.shm)) in optee_to_msg_param()
259 return -EINVAL; in optee_to_msg_param()
273 * clients and for tee-supplicant.
277 * optee_enable_shm_cache() - Enables caching of some shared memory allocation
278 * in OP-TEE
286 optee_cq_wait_init(&optee->call_queue, &w); in optee_enable_shm_cache()
290 optee->smc.invoke_fn(OPTEE_SMC_ENABLE_SHM_CACHE, in optee_enable_shm_cache()
294 optee_cq_wait_for_completion(&optee->call_queue, &w); in optee_enable_shm_cache()
296 optee_cq_wait_final(&optee->call_queue, &w); in optee_enable_shm_cache()
300 * __optee_disable_shm_cache() - Disables caching of some shared memory
301 * allocation in OP-TEE
311 optee_cq_wait_init(&optee->call_queue, &w); in __optee_disable_shm_cache()
318 optee->smc.invoke_fn(OPTEE_SMC_DISABLE_SHM_CACHE, in __optee_disable_shm_cache()
336 optee_cq_wait_for_completion(&optee->call_queue, &w); in __optee_disable_shm_cache()
339 optee_cq_wait_final(&optee->call_queue, &w); in __optee_disable_shm_cache()
343 * optee_disable_shm_cache() - Disables caching of mapped shared memory
344 * allocations in OP-TEE
353 * optee_disable_unmapped_shm_cache() - Disables caching of shared memory
354 * allocations in OP-TEE which are not
364 ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(u64)) - 1)
388 * optee_fill_pages_list() - write list of user pages to given shared
391 * @dst: page-aligned buffer where list of pages will be stored
414 * Currently OP-TEE uses 4k page size and it does not looks in optee_fill_pages_list()
427 * because they bear no value data for OP-TEE. in optee_fill_pages_list()
433 pages_data->pages_list[n++] = optee_page; in optee_fill_pages_list()
436 pages_data->next_page_data = in optee_fill_pages_list()
444 if (!--num_pages) in optee_fill_pages_list()
456 struct optee *optee = tee_get_drvdata(ctx->teedev); in optee_shm_register()
464 return -EINVAL; in optee_shm_register()
472 return -ENOMEM; in optee_shm_register()
476 * memory for this request or there's a catch-22. in optee_shm_register()
481 sz = optee_msg_arg_size(optee->rpc_param_count); in optee_shm_register()
497 msg_arg->num_params = 1; in optee_shm_register()
498 msg_arg->cmd = OPTEE_MSG_CMD_REGISTER_SHM; in optee_shm_register()
499 msg_arg->params->attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | in optee_shm_register()
501 msg_arg->params->u.tmem.shm_ref = (unsigned long)shm; in optee_shm_register()
502 msg_arg->params->u.tmem.size = tee_shm_get_size(shm); in optee_shm_register()
504 * In the least bits of msg_arg->params->u.tmem.buf_ptr we in optee_shm_register()
505 * store buffer offset from 4k page, as described in OP-TEE ABI. in optee_shm_register()
507 msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) | in optee_shm_register()
508 (tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1)); in optee_shm_register()
510 if (optee->ops->do_call_with_arg(ctx, shm_arg, 0) || in optee_shm_register()
511 msg_arg->ret != TEEC_SUCCESS) in optee_shm_register()
512 rc = -EINVAL; in optee_shm_register()
522 struct optee *optee = tee_get_drvdata(ctx->teedev); in optee_shm_unregister()
537 sz = optee_msg_arg_size(optee->rpc_param_count); in optee_shm_unregister()
548 msg_arg->num_params = 1; in optee_shm_unregister()
549 msg_arg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM; in optee_shm_unregister()
550 msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; in optee_shm_unregister()
551 msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm; in optee_shm_unregister()
553 if (optee->ops->do_call_with_arg(ctx, shm_arg, 0) || in optee_shm_unregister()
554 msg_arg->ret != TEEC_SUCCESS) in optee_shm_unregister()
555 rc = -EINVAL; in optee_shm_unregister()
566 * We don't want to register supplicant memory in OP-TEE. in optee_shm_register_supp()
581 * Implements an OP-TEE specific shared memory pool which is used
591 * Shared memory private to the OP-TEE driver doesn't need in pool_op_alloc()
592 * to be registered with OP-TEE. in pool_op_alloc()
594 if (shm->flags & TEE_SHM_PRIV) in pool_op_alloc()
604 if (!(shm->flags & TEE_SHM_PRIV)) in pool_op_free()
622 * optee_shm_pool_alloc_pages() - create page-based allocator pool
624 * This pool is used when OP-TEE supports dymanic SHM. In this case
632 return ERR_PTR(-ENOMEM); in optee_shm_pool_alloc_pages()
634 pool->ops = &pool_ops; in optee_shm_pool_alloc_pages()
645 * delivery of non-secure interrupts to for instance allow rescheduling of
654 arg->ret_origin = TEEC_ORIGIN_COMMS; in handle_rpc_func_cmd_shm_free()
656 if (arg->num_params != 1 || in handle_rpc_func_cmd_shm_free()
657 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { in handle_rpc_func_cmd_shm_free()
658 arg->ret = TEEC_ERROR_BAD_PARAMETERS; in handle_rpc_func_cmd_shm_free()
662 shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b; in handle_rpc_func_cmd_shm_free()
663 switch (arg->params[0].u.value.a) { in handle_rpc_func_cmd_shm_free()
671 arg->ret = TEEC_ERROR_BAD_PARAMETERS; in handle_rpc_func_cmd_shm_free()
673 arg->ret = TEEC_SUCCESS; in handle_rpc_func_cmd_shm_free()
686 arg->ret_origin = TEEC_ORIGIN_COMMS; in handle_rpc_func_cmd_shm_alloc()
688 if (!arg->num_params || in handle_rpc_func_cmd_shm_alloc()
689 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { in handle_rpc_func_cmd_shm_alloc()
690 arg->ret = TEEC_ERROR_BAD_PARAMETERS; in handle_rpc_func_cmd_shm_alloc()
694 for (n = 1; n < arg->num_params; n++) { in handle_rpc_func_cmd_shm_alloc()
695 if (arg->params[n].attr != OPTEE_MSG_ATTR_TYPE_NONE) { in handle_rpc_func_cmd_shm_alloc()
696 arg->ret = TEEC_ERROR_BAD_PARAMETERS; in handle_rpc_func_cmd_shm_alloc()
701 sz = arg->params[0].u.value.b; in handle_rpc_func_cmd_shm_alloc()
702 switch (arg->params[0].u.value.a) { in handle_rpc_func_cmd_shm_alloc()
707 shm = tee_shm_alloc_priv_buf(optee->ctx, sz); in handle_rpc_func_cmd_shm_alloc()
710 arg->ret = TEEC_ERROR_BAD_PARAMETERS; in handle_rpc_func_cmd_shm_alloc()
715 arg->ret = TEEC_ERROR_OUT_OF_MEMORY; in handle_rpc_func_cmd_shm_alloc()
720 arg->ret = TEEC_ERROR_BAD_PARAMETERS; in handle_rpc_func_cmd_shm_alloc()
733 arg->ret = TEEC_ERROR_OUT_OF_MEMORY; in handle_rpc_func_cmd_shm_alloc()
739 arg->ret = TEEC_ERROR_OUT_OF_MEMORY; in handle_rpc_func_cmd_shm_alloc()
743 call_ctx->pages_list = pages_list; in handle_rpc_func_cmd_shm_alloc()
744 call_ctx->num_entries = page_num; in handle_rpc_func_cmd_shm_alloc()
746 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | in handle_rpc_func_cmd_shm_alloc()
750 * from 4k page, as described in OP-TEE ABI. in handle_rpc_func_cmd_shm_alloc()
752 arg->params[0].u.tmem.buf_ptr = virt_to_phys(pages_list) | in handle_rpc_func_cmd_shm_alloc()
754 (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1)); in handle_rpc_func_cmd_shm_alloc()
755 arg->params[0].u.tmem.size = tee_shm_get_size(shm); in handle_rpc_func_cmd_shm_alloc()
756 arg->params[0].u.tmem.shm_ref = (unsigned long)shm; in handle_rpc_func_cmd_shm_alloc()
761 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; in handle_rpc_func_cmd_shm_alloc()
762 arg->params[0].u.tmem.buf_ptr = pa; in handle_rpc_func_cmd_shm_alloc()
763 arg->params[0].u.tmem.size = sz; in handle_rpc_func_cmd_shm_alloc()
764 arg->params[0].u.tmem.shm_ref = (unsigned long)shm; in handle_rpc_func_cmd_shm_alloc()
767 arg->ret = TEEC_SUCCESS; in handle_rpc_func_cmd_shm_alloc()
775 if (call_ctx->pages_list) { in free_pages_list()
776 optee_free_pages_list(call_ctx->pages_list, in free_pages_list()
777 call_ctx->num_entries); in free_pages_list()
778 call_ctx->pages_list = NULL; in free_pages_list()
779 call_ctx->num_entries = 0; in free_pages_list()
793 switch (arg->cmd) { in handle_rpc_func_cmd()
807 * optee_handle_rpc() - handle RPC from secure world
810 * @call_ctx: call context. Preserved during one OP-TEE invocation
819 struct tee_device *teedev = ctx->teedev; in optee_handle_rpc()
825 switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) { in optee_handle_rpc()
827 shm = tee_shm_alloc_priv_buf(optee->ctx, param->a1); in optee_handle_rpc()
829 reg_pair_from_64(¶m->a1, ¶m->a2, pa); in optee_handle_rpc()
830 reg_pair_from_64(¶m->a4, ¶m->a5, in optee_handle_rpc()
833 param->a1 = 0; in optee_handle_rpc()
834 param->a2 = 0; in optee_handle_rpc()
835 param->a4 = 0; in optee_handle_rpc()
836 param->a5 = 0; in optee_handle_rpc()
841 shm = reg_pair_to_ptr(param->a1, param->a2); in optee_handle_rpc()
856 shm = reg_pair_to_ptr(param->a1, param->a2); in optee_handle_rpc()
869 (u32)OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)); in optee_handle_rpc()
873 param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC; in optee_handle_rpc()
877 * optee_smc_do_call_with_arg() - Do an SMC to OP-TEE in secure world
882 * Does and SMC to OP-TEE in secure world and handles eventual resulting
883 * Remote Procedure Calls (RPC) from OP-TEE.
890 struct optee *optee = tee_get_drvdata(ctx->teedev); in optee_smc_do_call_with_arg()
897 if (optee->rpc_param_count) { in optee_smc_do_call_with_arg()
905 rpc_arg_offs = OPTEE_MSG_GET_ARG_SIZE(arg->num_params); in optee_smc_do_call_with_arg()
929 optee_cq_wait_init(&optee->call_queue, &w); in optee_smc_do_call_with_arg()
934 optee->smc.invoke_fn(param.a0, param.a1, param.a2, param.a3, in optee_smc_do_call_with_arg()
944 optee_cq_wait_for_completion(&optee->call_queue, &w); in optee_smc_do_call_with_arg()
963 optee_cq_wait_final(&optee->call_queue, &w); in optee_smc_do_call_with_arg()
979 msg_arg->cmd = cmd; in simple_call_with_arg()
1024 value = get_async_notif_value(optee->smc.invoke_fn, in irq_handler()
1051 optee_smc_do_bottom_half(optee->ctx); in notif_irq_thread_fn()
1066 optee->smc.notif_irq = irq; in init_irq()
1074 struct optee *optee = pcpu->optee; in notif_pcpu_irq_handler()
1077 queue_work(optee->smc.notif_pcpu_wq, in notif_pcpu_irq_handler()
1078 &optee->smc.notif_pcpu_work); in notif_pcpu_irq_handler()
1089 optee_smc_do_bottom_half(optee->ctx); in notif_pcpu_irq_work_fn()
1099 return -ENOMEM; in init_pcpu_irq()
1102 per_cpu_ptr(optee_pcpu, cpu)->optee = optee; in init_pcpu_irq()
1109 INIT_WORK(&optee->smc.notif_pcpu_work, notif_pcpu_irq_work_fn); in init_pcpu_irq()
1110 optee->smc.notif_pcpu_wq = create_workqueue("optee_pcpu_notification"); in init_pcpu_irq()
1111 if (!optee->smc.notif_pcpu_wq) { in init_pcpu_irq()
1112 rc = -EINVAL; in init_pcpu_irq()
1116 optee->smc.optee_pcpu = optee_pcpu; in init_pcpu_irq()
1117 optee->smc.notif_irq = irq; in init_pcpu_irq()
1120 rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "optee/pcpu-notif:starting", in init_pcpu_irq()
1124 rc = -EINVAL; in init_pcpu_irq()
1128 optee->smc.notif_cpuhp_state = rc; in init_pcpu_irq()
1150 cpuhp_remove_state(optee->smc.notif_cpuhp_state); in uninit_pcpu_irq()
1152 destroy_workqueue(optee->smc.notif_pcpu_wq); in uninit_pcpu_irq()
1154 free_percpu_irq(optee->smc.notif_irq, optee->smc.optee_pcpu); in uninit_pcpu_irq()
1155 free_percpu(optee->smc.optee_pcpu); in uninit_pcpu_irq()
1160 if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) { in optee_smc_notif_uninit_irq()
1161 optee_smc_stop_async_notif(optee->ctx); in optee_smc_notif_uninit_irq()
1162 if (optee->smc.notif_irq) { in optee_smc_notif_uninit_irq()
1163 if (irq_is_percpu_devid(optee->smc.notif_irq)) in optee_smc_notif_uninit_irq()
1166 free_irq(optee->smc.notif_irq, optee); in optee_smc_notif_uninit_irq()
1168 irq_dispose_mapping(optee->smc.notif_irq); in optee_smc_notif_uninit_irq()
1192 if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) in optee_get_version()
1194 if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL) in optee_get_version()
1201 struct optee *optee = tee_get_drvdata(ctx->teedev); in optee_smc_open()
1202 u32 sec_caps = optee->smc.sec_caps; in optee_smc_open()
1220 .name = DRIVER_NAME "-clnt",
1236 .name = DRIVER_NAME "-supp",
1255 return -EINVAL; in enable_async_notif()
1378 return ERR_PTR(-ENOENT); in optee_config_shm_memremap()
1383 return ERR_PTR(-EINVAL); in optee_config_shm_memremap()
1389 size = end - begin; in optee_config_shm_memremap()
1394 return ERR_PTR(-EINVAL); in optee_config_shm_memremap()
1435 return ERR_PTR(-ENXIO); in get_invoke_func()
1444 return ERR_PTR(-EINVAL); in get_invoke_func()
1447 /* optee_remove - Device Removal Routine
1458 * Ask OP-TEE to free all cached shared memory objects to decrease in optee_smc_remove()
1462 if (!optee->rpc_param_count) in optee_smc_remove()
1469 if (optee->smc.memremaped_shm) in optee_smc_remove()
1470 memunmap(optee->smc.memremaped_shm); in optee_smc_remove()
1477 /* optee_shutdown - Device Removal Routine
1488 if (!optee->rpc_param_count) in optee_shutdown()
1494 #define OPTEE_FW_IMAGE "optee/tee.bin"
1501 * Invoking a call on a CPU will cause OP-TEE to perform the required in optee_cpuhp_probe()
1508 return -EINVAL; in optee_cpuhp_probe()
1527 rc = request_firmware(&fw, OPTEE_FW_IMAGE, &pdev->dev); in optee_load_fw()
1535 return -EPROBE_DEFER; in optee_load_fw()
1539 data_size = fw->size; in optee_load_fw()
1542 * 32-bit space since TF-A cannot map memory beyond the 32-bit boundary. in optee_load_fw()
1544 data_buf = kmemdup(fw->data, fw->size, GFP_KERNEL | GFP_DMA); in optee_load_fw()
1546 rc = -ENOMEM; in optee_load_fw()
1567 pr_warn("OP-TEE image loaded from kernel, this can be insecure"); in optee_load_fw()
1578 * We need to initialize OP-TEE on all other running cores as in optee_load_fw()
1581 * TF-A which are registered by the OP-TEE SPD. Due to that we in optee_load_fw()
1582 * can un-register the callback right after registering it. in optee_load_fw()
1588 pr_warn("Failed with CPU hotplug setup for OP-TEE"); in optee_load_fw()
1589 return -EINVAL; in optee_load_fw()
1608 struct tee_shm_pool *pool = ERR_PTR(-EINVAL); in optee_probe()
1619 invoke_fn = get_invoke_func(&pdev->dev); in optee_probe()
1629 return -EINVAL; in optee_probe()
1636 return -EINVAL; in optee_probe()
1643 return -EINVAL; in optee_probe()
1652 * optee_get_msg_arg() to pre-register (by having in optee_probe()
1656 * With the page is pre-registered we can use a non-zero in optee_probe()
1661 * OPTEE_SMC_CALL_WITH_REGD_ARG for pre-registered pages. in optee_probe()
1672 * If dynamic shared memory is not available or failed - try static one in optee_probe()
1676 * The static memory pool can use non-zero page offsets so in optee_probe()
1679 * optee_get_msg_arg() should not pre-register the in optee_probe()
1697 rc = -ENOMEM; in optee_probe()
1701 optee->ops = &optee_ops; in optee_probe()
1702 optee->smc.invoke_fn = invoke_fn; in optee_probe()
1703 optee->smc.sec_caps = sec_caps; in optee_probe()
1704 optee->rpc_param_count = rpc_param_count; in optee_probe()
1711 optee->teedev = teedev; in optee_probe()
1718 optee->supp_teedev = teedev; in optee_probe()
1720 rc = tee_device_register(optee->teedev); in optee_probe()
1724 rc = tee_device_register(optee->supp_teedev); in optee_probe()
1728 mutex_init(&optee->call_queue.mutex); in optee_probe()
1729 INIT_LIST_HEAD(&optee->call_queue.waiters); in optee_probe()
1730 optee_supp_init(&optee->supp); in optee_probe()
1731 optee->smc.memremaped_shm = memremaped_shm; in optee_probe()
1732 optee->pool = pool; in optee_probe()
1736 ctx = teedev_open(optee->teedev); in optee_probe()
1741 optee->ctx = ctx; in optee_probe()
1761 enable_async_notif(optee->smc.invoke_fn); in optee_probe()
1766 * Ensure that there are no pre-existing shm objects before enabling in optee_probe()
1778 if (!optee->rpc_param_count) in optee_probe()
1781 if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) in optee_probe()
1792 if (!optee->rpc_param_count) in optee_probe()
1802 optee_supp_uninit(&optee->supp); in optee_probe()
1803 mutex_destroy(&optee->call_queue.mutex); in optee_probe()
1805 tee_device_unregister(optee->supp_teedev); in optee_probe()
1807 tee_device_unregister(optee->teedev); in optee_probe()
1818 { .compatible = "linaro,optee-tz" },