brintos

brintos / linux-shallow public Read only

0
0
Text · 5.8 KiB · c75fddc Raw
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