cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

core.c (12135B)


      1// SPDX-License-Identifier: MIT
      2/*
      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_drv.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 "../tee_private.h"
     19#include <linux/psp-tee.h>
     20
     21static struct amdtee_driver_data *drv_data;
     22static DEFINE_MUTEX(session_list_mutex);
     23
     24static void amdtee_get_version(struct tee_device *teedev,
     25			       struct tee_ioctl_version_data *vers)
     26{
     27	struct tee_ioctl_version_data v = {
     28		.impl_id = TEE_IMPL_ID_AMDTEE,
     29		.impl_caps = 0,
     30		.gen_caps = TEE_GEN_CAP_GP,
     31	};
     32	*vers = v;
     33}
     34
     35static int amdtee_open(struct tee_context *ctx)
     36{
     37	struct amdtee_context_data *ctxdata;
     38
     39	ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL);
     40	if (!ctxdata)
     41		return -ENOMEM;
     42
     43	INIT_LIST_HEAD(&ctxdata->sess_list);
     44	INIT_LIST_HEAD(&ctxdata->shm_list);
     45	mutex_init(&ctxdata->shm_mutex);
     46
     47	ctx->data = ctxdata;
     48	return 0;
     49}
     50
     51static void release_session(struct amdtee_session *sess)
     52{
     53	int i;
     54
     55	/* Close any open session */
     56	for (i = 0; i < TEE_NUM_SESSIONS; ++i) {
     57		/* Check if session entry 'i' is valid */
     58		if (!test_bit(i, sess->sess_mask))
     59			continue;
     60
     61		handle_close_session(sess->ta_handle, sess->session_info[i]);
     62		handle_unload_ta(sess->ta_handle);
     63	}
     64
     65	kfree(sess);
     66}
     67
     68static void amdtee_release(struct tee_context *ctx)
     69{
     70	struct amdtee_context_data *ctxdata = ctx->data;
     71
     72	if (!ctxdata)
     73		return;
     74
     75	while (true) {
     76		struct amdtee_session *sess;
     77
     78		sess = list_first_entry_or_null(&ctxdata->sess_list,
     79						struct amdtee_session,
     80						list_node);
     81
     82		if (!sess)
     83			break;
     84
     85		list_del(&sess->list_node);
     86		release_session(sess);
     87	}
     88	mutex_destroy(&ctxdata->shm_mutex);
     89	kfree(ctxdata);
     90
     91	ctx->data = NULL;
     92}
     93
     94/**
     95 * alloc_session() - Allocate a session structure
     96 * @ctxdata:    TEE Context data structure
     97 * @session:    Session ID for which 'struct amdtee_session' structure is to be
     98 *              allocated.
     99 *
    100 * Scans the TEE context's session list to check if TA is already loaded in to
    101 * TEE. If yes, returns the 'session' structure for that TA. Else allocates,
    102 * initializes a new 'session' structure and adds it to context's session list.
    103 *
    104 * The caller must hold a mutex.
    105 *
    106 * Returns:
    107 * 'struct amdtee_session *' on success and NULL on failure.
    108 */
    109static struct amdtee_session *alloc_session(struct amdtee_context_data *ctxdata,
    110					    u32 session)
    111{
    112	struct amdtee_session *sess;
    113	u32 ta_handle = get_ta_handle(session);
    114
    115	/* Scan session list to check if TA is already loaded in to TEE */
    116	list_for_each_entry(sess, &ctxdata->sess_list, list_node)
    117		if (sess->ta_handle == ta_handle) {
    118			kref_get(&sess->refcount);
    119			return sess;
    120		}
    121
    122	/* Allocate a new session and add to list */
    123	sess = kzalloc(sizeof(*sess), GFP_KERNEL);
    124	if (sess) {
    125		sess->ta_handle = ta_handle;
    126		kref_init(&sess->refcount);
    127		spin_lock_init(&sess->lock);
    128		list_add(&sess->list_node, &ctxdata->sess_list);
    129	}
    130
    131	return sess;
    132}
    133
    134/* Requires mutex to be held */
    135static struct amdtee_session *find_session(struct amdtee_context_data *ctxdata,
    136					   u32 session)
    137{
    138	u32 ta_handle = get_ta_handle(session);
    139	u32 index = get_session_index(session);
    140	struct amdtee_session *sess;
    141
    142	if (index >= TEE_NUM_SESSIONS)
    143		return NULL;
    144
    145	list_for_each_entry(sess, &ctxdata->sess_list, list_node)
    146		if (ta_handle == sess->ta_handle &&
    147		    test_bit(index, sess->sess_mask))
    148			return sess;
    149
    150	return NULL;
    151}
    152
    153u32 get_buffer_id(struct tee_shm *shm)
    154{
    155	struct amdtee_context_data *ctxdata = shm->ctx->data;
    156	struct amdtee_shm_data *shmdata;
    157	u32 buf_id = 0;
    158
    159	mutex_lock(&ctxdata->shm_mutex);
    160	list_for_each_entry(shmdata, &ctxdata->shm_list, shm_node)
    161		if (shmdata->kaddr == shm->kaddr) {
    162			buf_id = shmdata->buf_id;
    163			break;
    164		}
    165	mutex_unlock(&ctxdata->shm_mutex);
    166
    167	return buf_id;
    168}
    169
    170static DEFINE_MUTEX(drv_mutex);
    171static int copy_ta_binary(struct tee_context *ctx, void *ptr, void **ta,
    172			  size_t *ta_size)
    173{
    174	const struct firmware *fw;
    175	char fw_name[TA_PATH_MAX];
    176	struct {
    177		u32 lo;
    178		u16 mid;
    179		u16 hi_ver;
    180		u8 seq_n[8];
    181	} *uuid = ptr;
    182	int n, rc = 0;
    183
    184	n = snprintf(fw_name, TA_PATH_MAX,
    185		     "%s/%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x.bin",
    186		     TA_LOAD_PATH, uuid->lo, uuid->mid, uuid->hi_ver,
    187		     uuid->seq_n[0], uuid->seq_n[1],
    188		     uuid->seq_n[2], uuid->seq_n[3],
    189		     uuid->seq_n[4], uuid->seq_n[5],
    190		     uuid->seq_n[6], uuid->seq_n[7]);
    191	if (n < 0 || n >= TA_PATH_MAX) {
    192		pr_err("failed to get firmware name\n");
    193		return -EINVAL;
    194	}
    195
    196	mutex_lock(&drv_mutex);
    197	n = request_firmware(&fw, fw_name, &ctx->teedev->dev);
    198	if (n) {
    199		pr_err("failed to load firmware %s\n", fw_name);
    200		rc = -ENOMEM;
    201		goto unlock;
    202	}
    203
    204	*ta_size = roundup(fw->size, PAGE_SIZE);
    205	*ta = (void *)__get_free_pages(GFP_KERNEL, get_order(*ta_size));
    206	if (!*ta) {
    207		pr_err("%s: get_free_pages failed\n", __func__);
    208		rc = -ENOMEM;
    209		goto rel_fw;
    210	}
    211
    212	memcpy(*ta, fw->data, fw->size);
    213rel_fw:
    214	release_firmware(fw);
    215unlock:
    216	mutex_unlock(&drv_mutex);
    217	return rc;
    218}
    219
    220static void destroy_session(struct kref *ref)
    221{
    222	struct amdtee_session *sess = container_of(ref, struct amdtee_session,
    223						   refcount);
    224
    225	mutex_lock(&session_list_mutex);
    226	list_del(&sess->list_node);
    227	mutex_unlock(&session_list_mutex);
    228	kfree(sess);
    229}
    230
    231int amdtee_open_session(struct tee_context *ctx,
    232			struct tee_ioctl_open_session_arg *arg,
    233			struct tee_param *param)
    234{
    235	struct amdtee_context_data *ctxdata = ctx->data;
    236	struct amdtee_session *sess = NULL;
    237	u32 session_info, ta_handle;
    238	size_t ta_size;
    239	int rc, i;
    240	void *ta;
    241
    242	if (arg->clnt_login != TEE_IOCTL_LOGIN_PUBLIC) {
    243		pr_err("unsupported client login method\n");
    244		return -EINVAL;
    245	}
    246
    247	rc = copy_ta_binary(ctx, &arg->uuid[0], &ta, &ta_size);
    248	if (rc) {
    249		pr_err("failed to copy TA binary\n");
    250		return rc;
    251	}
    252
    253	/* Load the TA binary into TEE environment */
    254	handle_load_ta(ta, ta_size, arg);
    255	if (arg->ret != TEEC_SUCCESS)
    256		goto out;
    257
    258	ta_handle = get_ta_handle(arg->session);
    259
    260	mutex_lock(&session_list_mutex);
    261	sess = alloc_session(ctxdata, arg->session);
    262	mutex_unlock(&session_list_mutex);
    263
    264	if (!sess) {
    265		handle_unload_ta(ta_handle);
    266		rc = -ENOMEM;
    267		goto out;
    268	}
    269
    270	/* Find an empty session index for the given TA */
    271	spin_lock(&sess->lock);
    272	i = find_first_zero_bit(sess->sess_mask, TEE_NUM_SESSIONS);
    273	if (i < TEE_NUM_SESSIONS)
    274		set_bit(i, sess->sess_mask);
    275	spin_unlock(&sess->lock);
    276
    277	if (i >= TEE_NUM_SESSIONS) {
    278		pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
    279		handle_unload_ta(ta_handle);
    280		kref_put(&sess->refcount, destroy_session);
    281		rc = -ENOMEM;
    282		goto out;
    283	}
    284
    285	/* Open session with loaded TA */
    286	handle_open_session(arg, &session_info, param);
    287	if (arg->ret != TEEC_SUCCESS) {
    288		pr_err("open_session failed %d\n", arg->ret);
    289		spin_lock(&sess->lock);
    290		clear_bit(i, sess->sess_mask);
    291		spin_unlock(&sess->lock);
    292		handle_unload_ta(ta_handle);
    293		kref_put(&sess->refcount, destroy_session);
    294		goto out;
    295	}
    296
    297	sess->session_info[i] = session_info;
    298	set_session_id(ta_handle, i, &arg->session);
    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 session
    314	 * usage bit
    315	 */
    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(&sess->refcount, destroy_session);
    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 corresponding
    361	 * buffer Id
    362	 */
    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");