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