251 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2015-2021, Linaro Limited4 * Copyright (c) 2016, EPAM Systems5 */6 7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt8 9#include <linux/crash_dump.h>10#include <linux/errno.h>11#include <linux/io.h>12#include <linux/module.h>13#include <linux/rpmb.h>14#include <linux/slab.h>15#include <linux/string.h>16#include <linux/tee_core.h>17#include <linux/types.h>18#include "optee_private.h"19 20struct blocking_notifier_head optee_rpmb_intf_added =21 BLOCKING_NOTIFIER_INIT(optee_rpmb_intf_added);22 23static int rpmb_add_dev(struct device *dev)24{25 blocking_notifier_call_chain(&optee_rpmb_intf_added, 0,26 to_rpmb_dev(dev));27 28 return 0;29}30 31static struct class_interface rpmb_class_intf = {32 .add_dev = rpmb_add_dev,33};34 35void optee_bus_scan_rpmb(struct work_struct *work)36{37 struct optee *optee = container_of(work, struct optee,38 rpmb_scan_bus_work);39 int ret;40 41 if (!optee->rpmb_scan_bus_done) {42 ret = optee_enumerate_devices(PTA_CMD_GET_DEVICES_RPMB);43 optee->rpmb_scan_bus_done = !ret;44 if (ret && ret != -ENODEV)45 pr_info("Scanning for RPMB device: ret %d\n", ret);46 }47}48 49int optee_rpmb_intf_rdev(struct notifier_block *intf, unsigned long action,50 void *data)51{52 struct optee *optee = container_of(intf, struct optee, rpmb_intf);53 54 schedule_work(&optee->rpmb_scan_bus_work);55 56 return 0;57}58 59static void optee_bus_scan(struct work_struct *work)60{61 WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP));62}63 64static ssize_t rpmb_routing_model_show(struct device *dev,65 struct device_attribute *attr, char *buf)66{67 struct optee *optee = dev_get_drvdata(dev);68 const char *s;69 70 if (optee->in_kernel_rpmb_routing)71 s = "kernel";72 else73 s = "user";74 75 return scnprintf(buf, PAGE_SIZE, "%s\n", s);76}77static DEVICE_ATTR_RO(rpmb_routing_model);78 79static struct attribute *optee_dev_attrs[] = {80 &dev_attr_rpmb_routing_model.attr,81 NULL82};83 84ATTRIBUTE_GROUPS(optee_dev);85 86void optee_set_dev_group(struct optee *optee)87{88 tee_device_set_dev_groups(optee->teedev, optee_dev_groups);89 tee_device_set_dev_groups(optee->supp_teedev, optee_dev_groups);90}91 92int optee_open(struct tee_context *ctx, bool cap_memref_null)93{94 struct optee_context_data *ctxdata;95 struct tee_device *teedev = ctx->teedev;96 struct optee *optee = tee_get_drvdata(teedev);97 98 ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL);99 if (!ctxdata)100 return -ENOMEM;101 102 if (teedev == optee->supp_teedev) {103 bool busy = true;104 105 mutex_lock(&optee->supp.mutex);106 if (!optee->supp.ctx) {107 busy = false;108 optee->supp.ctx = ctx;109 }110 mutex_unlock(&optee->supp.mutex);111 if (busy) {112 kfree(ctxdata);113 return -EBUSY;114 }115 116 if (!optee->scan_bus_done) {117 INIT_WORK(&optee->scan_bus_work, optee_bus_scan);118 schedule_work(&optee->scan_bus_work);119 optee->scan_bus_done = true;120 }121 }122 mutex_init(&ctxdata->mutex);123 INIT_LIST_HEAD(&ctxdata->sess_list);124 125 ctx->cap_memref_null = cap_memref_null;126 ctx->data = ctxdata;127 return 0;128}129 130static void optee_release_helper(struct tee_context *ctx,131 int (*close_session)(struct tee_context *ctx,132 u32 session,133 bool system_thread))134{135 struct optee_context_data *ctxdata = ctx->data;136 struct optee_session *sess;137 struct optee_session *sess_tmp;138 139 if (!ctxdata)140 return;141 142 list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list,143 list_node) {144 list_del(&sess->list_node);145 close_session(ctx, sess->session_id, sess->use_sys_thread);146 kfree(sess);147 }148 kfree(ctxdata);149 ctx->data = NULL;150}151 152void optee_release(struct tee_context *ctx)153{154 optee_release_helper(ctx, optee_close_session_helper);155}156 157void optee_release_supp(struct tee_context *ctx)158{159 struct optee *optee = tee_get_drvdata(ctx->teedev);160 161 optee_release_helper(ctx, optee_close_session_helper);162 163 optee_supp_release(&optee->supp);164}165 166void optee_remove_common(struct optee *optee)167{168 blocking_notifier_chain_unregister(&optee_rpmb_intf_added,169 &optee->rpmb_intf);170 cancel_work_sync(&optee->rpmb_scan_bus_work);171 /* Unregister OP-TEE specific client devices on TEE bus */172 optee_unregister_devices();173 174 optee_notif_uninit(optee);175 optee_shm_arg_cache_uninit(optee);176 teedev_close_context(optee->ctx);177 /*178 * The two devices have to be unregistered before we can free the179 * other resources.180 */181 tee_device_unregister(optee->supp_teedev);182 tee_device_unregister(optee->teedev);183 184 tee_shm_pool_free(optee->pool);185 optee_supp_uninit(&optee->supp);186 mutex_destroy(&optee->call_queue.mutex);187 rpmb_dev_put(optee->rpmb_dev);188 mutex_destroy(&optee->rpmb_dev_mutex);189}190 191static int smc_abi_rc;192static int ffa_abi_rc;193static bool intf_is_regged;194 195static int __init optee_core_init(void)196{197 int rc;198 199 /*200 * The kernel may have crashed at the same time that all available201 * secure world threads were suspended and we cannot reschedule the202 * suspended threads without access to the crashed kernel's wait_queue.203 * Therefore, we cannot reliably initialize the OP-TEE driver in the204 * kdump kernel.205 */206 if (is_kdump_kernel())207 return -ENODEV;208 209 if (IS_REACHABLE(CONFIG_RPMB)) {210 rc = rpmb_interface_register(&rpmb_class_intf);211 if (rc)212 return rc;213 intf_is_regged = true;214 }215 216 smc_abi_rc = optee_smc_abi_register();217 ffa_abi_rc = optee_ffa_abi_register();218 219 /* If both failed there's no point with this module */220 if (smc_abi_rc && ffa_abi_rc) {221 if (IS_REACHABLE(CONFIG_RPMB)) {222 rpmb_interface_unregister(&rpmb_class_intf);223 intf_is_regged = false;224 }225 return smc_abi_rc;226 }227 228 return 0;229}230module_init(optee_core_init);231 232static void __exit optee_core_exit(void)233{234 if (IS_REACHABLE(CONFIG_RPMB) && intf_is_regged) {235 rpmb_interface_unregister(&rpmb_class_intf);236 intf_is_regged = false;237 }238 239 if (!smc_abi_rc)240 optee_smc_abi_unregister();241 if (!ffa_abi_rc)242 optee_ffa_abi_unregister();243}244module_exit(optee_core_exit);245 246MODULE_AUTHOR("Linaro");247MODULE_DESCRIPTION("OP-TEE driver");248MODULE_VERSION("1.0");249MODULE_LICENSE("GPL v2");250MODULE_ALIAS("platform:optee");251