brintos

brintos / linux-shallow public Read only

0
0
Text · 11.9 KiB · e487231 Raw
536 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright 2019 Advanced Micro Devices, Inc.4 */5 6#include <linux/errno.h>7#include <linux/io.h>8#include <linux/module.h>9#include <linux/slab.h>10#include <linux/string.h>11#include <linux/device.h>12#include <linux/tee_core.h>13#include <linux/types.h>14#include <linux/mm.h>15#include <linux/uaccess.h>16#include <linux/firmware.h>17#include "amdtee_private.h"18#include <linux/psp-tee.h>19 20static struct amdtee_driver_data *drv_data;21static DEFINE_MUTEX(session_list_mutex);22 23static void amdtee_get_version(struct tee_device *teedev,24			       struct tee_ioctl_version_data *vers)25{26	struct tee_ioctl_version_data v = {27		.impl_id = TEE_IMPL_ID_AMDTEE,28		.impl_caps = 0,29		.gen_caps = TEE_GEN_CAP_GP,30	};31	*vers = v;32}33 34static int amdtee_open(struct tee_context *ctx)35{36	struct amdtee_context_data *ctxdata;37 38	ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL);39	if (!ctxdata)40		return -ENOMEM;41 42	INIT_LIST_HEAD(&ctxdata->sess_list);43	INIT_LIST_HEAD(&ctxdata->shm_list);44	mutex_init(&ctxdata->shm_mutex);45 46	ctx->data = ctxdata;47	return 0;48}49 50static void release_session(struct amdtee_session *sess)51{52	int i;53 54	/* Close any open session */55	for (i = 0; i < TEE_NUM_SESSIONS; ++i) {56		/* Check if session entry 'i' is valid */57		if (!test_bit(i, sess->sess_mask))58			continue;59 60		handle_close_session(sess->ta_handle, sess->session_info[i]);61		handle_unload_ta(sess->ta_handle);62	}63 64	kfree(sess);65}66 67static void amdtee_release(struct tee_context *ctx)68{69	struct amdtee_context_data *ctxdata = ctx->data;70 71	if (!ctxdata)72		return;73 74	while (true) {75		struct amdtee_session *sess;76 77		sess = list_first_entry_or_null(&ctxdata->sess_list,78						struct amdtee_session,79						list_node);80 81		if (!sess)82			break;83 84		list_del(&sess->list_node);85		release_session(sess);86	}87	mutex_destroy(&ctxdata->shm_mutex);88	kfree(ctxdata);89 90	ctx->data = NULL;91}92 93/**94 * alloc_session() - Allocate a session structure95 * @ctxdata:    TEE Context data structure96 * @session:    Session ID for which 'struct amdtee_session' structure is to be97 *              allocated.98 *99 * Scans the TEE context's session list to check if TA is already loaded in to100 * TEE. If yes, returns the 'session' structure for that TA. Else allocates,101 * initializes a new 'session' structure and adds it to context's session list.102 *103 * The caller must hold a mutex.104 *105 * Returns:106 * 'struct amdtee_session *' on success and NULL on failure.107 */108static struct amdtee_session *alloc_session(struct amdtee_context_data *ctxdata,109					    u32 session)110{111	struct amdtee_session *sess;112	u32 ta_handle = get_ta_handle(session);113 114	/* Scan session list to check if TA is already loaded in to TEE */115	list_for_each_entry(sess, &ctxdata->sess_list, list_node)116		if (sess->ta_handle == ta_handle) {117			kref_get(&sess->refcount);118			return sess;119		}120 121	/* Allocate a new session and add to list */122	sess = kzalloc(sizeof(*sess), GFP_KERNEL);123	if (sess) {124		sess->ta_handle = ta_handle;125		kref_init(&sess->refcount);126		spin_lock_init(&sess->lock);127		list_add(&sess->list_node, &ctxdata->sess_list);128	}129 130	return sess;131}132 133/* Requires mutex to be held */134static struct amdtee_session *find_session(struct amdtee_context_data *ctxdata,135					   u32 session)136{137	u32 ta_handle = get_ta_handle(session);138	u32 index = get_session_index(session);139	struct amdtee_session *sess;140 141	if (index >= TEE_NUM_SESSIONS)142		return NULL;143 144	list_for_each_entry(sess, &ctxdata->sess_list, list_node)145		if (ta_handle == sess->ta_handle &&146		    test_bit(index, sess->sess_mask))147			return sess;148 149	return NULL;150}151 152u32 get_buffer_id(struct tee_shm *shm)153{154	struct amdtee_context_data *ctxdata = shm->ctx->data;155	struct amdtee_shm_data *shmdata;156	u32 buf_id = 0;157 158	mutex_lock(&ctxdata->shm_mutex);159	list_for_each_entry(shmdata, &ctxdata->shm_list, shm_node)160		if (shmdata->kaddr == shm->kaddr) {161			buf_id = shmdata->buf_id;162			break;163		}164	mutex_unlock(&ctxdata->shm_mutex);165 166	return buf_id;167}168 169static DEFINE_MUTEX(drv_mutex);170static int copy_ta_binary(struct tee_context *ctx, void *ptr, void **ta,171			  size_t *ta_size)172{173	const struct firmware *fw;174	char fw_name[TA_PATH_MAX];175	struct {176		u32 lo;177		u16 mid;178		u16 hi_ver;179		u8 seq_n[8];180	} *uuid = ptr;181	int n, rc = 0;182 183	n = snprintf(fw_name, TA_PATH_MAX,184		     "%s/%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x.bin",185		     TA_LOAD_PATH, uuid->lo, uuid->mid, uuid->hi_ver,186		     uuid->seq_n[0], uuid->seq_n[1],187		     uuid->seq_n[2], uuid->seq_n[3],188		     uuid->seq_n[4], uuid->seq_n[5],189		     uuid->seq_n[6], uuid->seq_n[7]);190	if (n < 0 || n >= TA_PATH_MAX) {191		pr_err("failed to get firmware name\n");192		return -EINVAL;193	}194 195	mutex_lock(&drv_mutex);196	n = request_firmware(&fw, fw_name, &ctx->teedev->dev);197	if (n) {198		pr_err("failed to load firmware %s\n", fw_name);199		rc = -ENOMEM;200		goto unlock;201	}202 203	*ta_size = roundup(fw->size, PAGE_SIZE);204	*ta = (void *)__get_free_pages(GFP_KERNEL, get_order(*ta_size));205	if (!*ta) {206		pr_err("%s: get_free_pages failed\n", __func__);207		rc = -ENOMEM;208		goto rel_fw;209	}210 211	memcpy(*ta, fw->data, fw->size);212rel_fw:213	release_firmware(fw);214unlock:215	mutex_unlock(&drv_mutex);216	return rc;217}218 219/* mutex must be held by caller */220static void destroy_session(struct kref *ref)221{222	struct amdtee_session *sess = container_of(ref, struct amdtee_session,223						   refcount);224 225	list_del(&sess->list_node);226	mutex_unlock(&session_list_mutex);227	kfree(sess);228}229 230int amdtee_open_session(struct tee_context *ctx,231			struct tee_ioctl_open_session_arg *arg,232			struct tee_param *param)233{234	struct amdtee_context_data *ctxdata = ctx->data;235	struct amdtee_session *sess = NULL;236	u32 session_info, ta_handle;237	size_t ta_size;238	int rc, i;239	void *ta;240 241	if (arg->clnt_login != TEE_IOCTL_LOGIN_PUBLIC) {242		pr_err("unsupported client login method\n");243		return -EINVAL;244	}245 246	rc = copy_ta_binary(ctx, &arg->uuid[0], &ta, &ta_size);247	if (rc) {248		pr_err("failed to copy TA binary\n");249		return rc;250	}251 252	/* Load the TA binary into TEE environment */253	handle_load_ta(ta, ta_size, arg);254	if (arg->ret != TEEC_SUCCESS)255		goto out;256 257	ta_handle = get_ta_handle(arg->session);258 259	mutex_lock(&session_list_mutex);260	sess = alloc_session(ctxdata, arg->session);261	mutex_unlock(&session_list_mutex);262 263	if (!sess) {264		handle_unload_ta(ta_handle);265		rc = -ENOMEM;266		goto out;267	}268 269	/* Open session with loaded TA */270	handle_open_session(arg, &session_info, param);271	if (arg->ret != TEEC_SUCCESS) {272		pr_err("open_session failed %d\n", arg->ret);273		handle_unload_ta(ta_handle);274		kref_put_mutex(&sess->refcount, destroy_session,275			       &session_list_mutex);276		goto out;277	}278 279	/* Find an empty session index for the given TA */280	spin_lock(&sess->lock);281	i = find_first_zero_bit(sess->sess_mask, TEE_NUM_SESSIONS);282	if (i < TEE_NUM_SESSIONS) {283		sess->session_info[i] = session_info;284		set_session_id(ta_handle, i, &arg->session);285		set_bit(i, sess->sess_mask);286	}287	spin_unlock(&sess->lock);288 289	if (i >= TEE_NUM_SESSIONS) {290		pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);291		handle_close_session(ta_handle, session_info);292		handle_unload_ta(ta_handle);293		kref_put_mutex(&sess->refcount, destroy_session,294			       &session_list_mutex);295		rc = -ENOMEM;296		goto out;297	}298 299out:300	free_pages((u64)ta, get_order(ta_size));301	return rc;302}303 304int amdtee_close_session(struct tee_context *ctx, u32 session)305{306	struct amdtee_context_data *ctxdata = ctx->data;307	u32 i, ta_handle, session_info;308	struct amdtee_session *sess;309 310	pr_debug("%s: sid = 0x%x\n", __func__, session);311 312	/*313	 * Check that the session is valid and clear the session314	 * usage bit315	 */316	mutex_lock(&session_list_mutex);317	sess = find_session(ctxdata, session);318	if (sess) {319		ta_handle = get_ta_handle(session);320		i = get_session_index(session);321		session_info = sess->session_info[i];322		spin_lock(&sess->lock);323		clear_bit(i, sess->sess_mask);324		spin_unlock(&sess->lock);325	}326	mutex_unlock(&session_list_mutex);327 328	if (!sess)329		return -EINVAL;330 331	/* Close the session */332	handle_close_session(ta_handle, session_info);333	handle_unload_ta(ta_handle);334 335	kref_put_mutex(&sess->refcount, destroy_session, &session_list_mutex);336 337	return 0;338}339 340int amdtee_map_shmem(struct tee_shm *shm)341{342	struct amdtee_context_data *ctxdata;343	struct amdtee_shm_data *shmnode;344	struct shmem_desc shmem;345	int rc, count;346	u32 buf_id;347 348	if (!shm)349		return -EINVAL;350 351	shmnode = kmalloc(sizeof(*shmnode), GFP_KERNEL);352	if (!shmnode)353		return -ENOMEM;354 355	count = 1;356	shmem.kaddr = shm->kaddr;357	shmem.size = shm->size;358 359	/*360	 * Send a MAP command to TEE and get the corresponding361	 * buffer Id362	 */363	rc = handle_map_shmem(count, &shmem, &buf_id);364	if (rc) {365		pr_err("map_shmem failed: ret = %d\n", rc);366		kfree(shmnode);367		return rc;368	}369 370	shmnode->kaddr = shm->kaddr;371	shmnode->buf_id = buf_id;372	ctxdata = shm->ctx->data;373	mutex_lock(&ctxdata->shm_mutex);374	list_add(&shmnode->shm_node, &ctxdata->shm_list);375	mutex_unlock(&ctxdata->shm_mutex);376 377	pr_debug("buf_id :[%x] kaddr[%p]\n", shmnode->buf_id, shmnode->kaddr);378 379	return 0;380}381 382void amdtee_unmap_shmem(struct tee_shm *shm)383{384	struct amdtee_context_data *ctxdata;385	struct amdtee_shm_data *shmnode;386	u32 buf_id;387 388	if (!shm)389		return;390 391	buf_id = get_buffer_id(shm);392	/* Unmap the shared memory from TEE */393	handle_unmap_shmem(buf_id);394 395	ctxdata = shm->ctx->data;396	mutex_lock(&ctxdata->shm_mutex);397	list_for_each_entry(shmnode, &ctxdata->shm_list, shm_node)398		if (buf_id == shmnode->buf_id) {399			list_del(&shmnode->shm_node);400			kfree(shmnode);401			break;402		}403	mutex_unlock(&ctxdata->shm_mutex);404}405 406int amdtee_invoke_func(struct tee_context *ctx,407		       struct tee_ioctl_invoke_arg *arg,408		       struct tee_param *param)409{410	struct amdtee_context_data *ctxdata = ctx->data;411	struct amdtee_session *sess;412	u32 i, session_info;413 414	/* Check that the session is valid */415	mutex_lock(&session_list_mutex);416	sess = find_session(ctxdata, arg->session);417	if (sess) {418		i = get_session_index(arg->session);419		session_info = sess->session_info[i];420	}421	mutex_unlock(&session_list_mutex);422 423	if (!sess)424		return -EINVAL;425 426	handle_invoke_cmd(arg, session_info, param);427 428	return 0;429}430 431int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)432{433	return -EINVAL;434}435 436static const struct tee_driver_ops amdtee_ops = {437	.get_version = amdtee_get_version,438	.open = amdtee_open,439	.release = amdtee_release,440	.open_session = amdtee_open_session,441	.close_session = amdtee_close_session,442	.invoke_func = amdtee_invoke_func,443	.cancel_req = amdtee_cancel_req,444};445 446static const struct tee_desc amdtee_desc = {447	.name = DRIVER_NAME "-clnt",448	.ops = &amdtee_ops,449	.owner = THIS_MODULE,450};451 452static int __init amdtee_driver_init(void)453{454	struct tee_device *teedev;455	struct tee_shm_pool *pool;456	struct amdtee *amdtee;457	int rc;458 459	rc = psp_check_tee_status();460	if (rc) {461		pr_err("amd-tee driver: tee not present\n");462		return rc;463	}464 465	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);466	if (!drv_data)467		return -ENOMEM;468 469	amdtee = kzalloc(sizeof(*amdtee), GFP_KERNEL);470	if (!amdtee) {471		rc = -ENOMEM;472		goto err_kfree_drv_data;473	}474 475	pool = amdtee_config_shm();476	if (IS_ERR(pool)) {477		pr_err("shared pool configuration error\n");478		rc = PTR_ERR(pool);479		goto err_kfree_amdtee;480	}481 482	teedev = tee_device_alloc(&amdtee_desc, NULL, pool, amdtee);483	if (IS_ERR(teedev)) {484		rc = PTR_ERR(teedev);485		goto err_free_pool;486	}487	amdtee->teedev = teedev;488 489	rc = tee_device_register(amdtee->teedev);490	if (rc)491		goto err_device_unregister;492 493	amdtee->pool = pool;494 495	drv_data->amdtee = amdtee;496 497	pr_info("amd-tee driver initialization successful\n");498	return 0;499 500err_device_unregister:501	tee_device_unregister(amdtee->teedev);502 503err_free_pool:504	tee_shm_pool_free(pool);505 506err_kfree_amdtee:507	kfree(amdtee);508 509err_kfree_drv_data:510	kfree(drv_data);511	drv_data = NULL;512 513	pr_err("amd-tee driver initialization failed\n");514	return rc;515}516module_init(amdtee_driver_init);517 518static void __exit amdtee_driver_exit(void)519{520	struct amdtee *amdtee;521 522	if (!drv_data || !drv_data->amdtee)523		return;524 525	amdtee = drv_data->amdtee;526 527	tee_device_unregister(amdtee->teedev);528	tee_shm_pool_free(amdtee->pool);529}530module_exit(amdtee_driver_exit);531 532MODULE_AUTHOR(DRIVER_AUTHOR);533MODULE_DESCRIPTION("AMD-TEE driver");534MODULE_VERSION("1.0");535MODULE_LICENSE("Dual MIT/GPL");536