linux/drivers/tee/amdtee/core.c
<<
>>
Prefs
   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 (IS_ERR(*ta)) {
 207                pr_err("%s: get_free_pages failed 0x%llx\n", __func__,
 208                       (u64)*ta);
 209                rc = -ENOMEM;
 210                goto rel_fw;
 211        }
 212
 213        memcpy(*ta, fw->data, fw->size);
 214rel_fw:
 215        release_firmware(fw);
 216unlock:
 217        mutex_unlock(&drv_mutex);
 218        return rc;
 219}
 220
 221static void destroy_session(struct kref *ref)
 222{
 223        struct amdtee_session *sess = container_of(ref, struct amdtee_session,
 224                                                   refcount);
 225
 226        mutex_lock(&session_list_mutex);
 227        list_del(&sess->list_node);
 228        mutex_unlock(&session_list_mutex);
 229        kfree(sess);
 230}
 231
 232int amdtee_open_session(struct tee_context *ctx,
 233                        struct tee_ioctl_open_session_arg *arg,
 234                        struct tee_param *param)
 235{
 236        struct amdtee_context_data *ctxdata = ctx->data;
 237        struct amdtee_session *sess = NULL;
 238        u32 session_info, ta_handle;
 239        size_t ta_size;
 240        int rc, i;
 241        void *ta;
 242
 243        if (arg->clnt_login != TEE_IOCTL_LOGIN_PUBLIC) {
 244                pr_err("unsupported client login method\n");
 245                return -EINVAL;
 246        }
 247
 248        rc = copy_ta_binary(ctx, &arg->uuid[0], &ta, &ta_size);
 249        if (rc) {
 250                pr_err("failed to copy TA binary\n");
 251                return rc;
 252        }
 253
 254        /* Load the TA binary into TEE environment */
 255        handle_load_ta(ta, ta_size, arg);
 256        if (arg->ret != TEEC_SUCCESS)
 257                goto out;
 258
 259        ta_handle = get_ta_handle(arg->session);
 260
 261        mutex_lock(&session_list_mutex);
 262        sess = alloc_session(ctxdata, arg->session);
 263        mutex_unlock(&session_list_mutex);
 264
 265        if (!sess) {
 266                handle_unload_ta(ta_handle);
 267                rc = -ENOMEM;
 268                goto out;
 269        }
 270
 271        /* Find an empty session index for the given TA */
 272        spin_lock(&sess->lock);
 273        i = find_first_zero_bit(sess->sess_mask, TEE_NUM_SESSIONS);
 274        if (i < TEE_NUM_SESSIONS)
 275                set_bit(i, sess->sess_mask);
 276        spin_unlock(&sess->lock);
 277
 278        if (i >= TEE_NUM_SESSIONS) {
 279                pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
 280                handle_unload_ta(ta_handle);
 281                kref_put(&sess->refcount, destroy_session);
 282                rc = -ENOMEM;
 283                goto out;
 284        }
 285
 286        /* Open session with loaded TA */
 287        handle_open_session(arg, &session_info, param);
 288        if (arg->ret != TEEC_SUCCESS) {
 289                pr_err("open_session failed %d\n", arg->ret);
 290                spin_lock(&sess->lock);
 291                clear_bit(i, sess->sess_mask);
 292                spin_unlock(&sess->lock);
 293                handle_unload_ta(ta_handle);
 294                kref_put(&sess->refcount, destroy_session);
 295                goto out;
 296        }
 297
 298        sess->session_info[i] = session_info;
 299        set_session_id(ta_handle, i, &arg->session);
 300out:
 301        free_pages((u64)ta, get_order(ta_size));
 302        return rc;
 303}
 304
 305int amdtee_close_session(struct tee_context *ctx, u32 session)
 306{
 307        struct amdtee_context_data *ctxdata = ctx->data;
 308        u32 i, ta_handle, session_info;
 309        struct amdtee_session *sess;
 310
 311        pr_debug("%s: sid = 0x%x\n", __func__, session);
 312
 313        /*
 314         * Check that the session is valid and clear the session
 315         * usage bit
 316         */
 317        mutex_lock(&session_list_mutex);
 318        sess = find_session(ctxdata, session);
 319        if (sess) {
 320                ta_handle = get_ta_handle(session);
 321                i = get_session_index(session);
 322                session_info = sess->session_info[i];
 323                spin_lock(&sess->lock);
 324                clear_bit(i, sess->sess_mask);
 325                spin_unlock(&sess->lock);
 326        }
 327        mutex_unlock(&session_list_mutex);
 328
 329        if (!sess)
 330                return -EINVAL;
 331
 332        /* Close the session */
 333        handle_close_session(ta_handle, session_info);
 334        handle_unload_ta(ta_handle);
 335
 336        kref_put(&sess->refcount, destroy_session);
 337
 338        return 0;
 339}
 340
 341int amdtee_map_shmem(struct tee_shm *shm)
 342{
 343        struct amdtee_context_data *ctxdata;
 344        struct amdtee_shm_data *shmnode;
 345        struct shmem_desc shmem;
 346        int rc, count;
 347        u32 buf_id;
 348
 349        if (!shm)
 350                return -EINVAL;
 351
 352        shmnode = kmalloc(sizeof(*shmnode), GFP_KERNEL);
 353        if (!shmnode)
 354                return -ENOMEM;
 355
 356        count = 1;
 357        shmem.kaddr = shm->kaddr;
 358        shmem.size = shm->size;
 359
 360        /*
 361         * Send a MAP command to TEE and get the corresponding
 362         * buffer Id
 363         */
 364        rc = handle_map_shmem(count, &shmem, &buf_id);
 365        if (rc) {
 366                pr_err("map_shmem failed: ret = %d\n", rc);
 367                kfree(shmnode);
 368                return rc;
 369        }
 370
 371        shmnode->kaddr = shm->kaddr;
 372        shmnode->buf_id = buf_id;
 373        ctxdata = shm->ctx->data;
 374        mutex_lock(&ctxdata->shm_mutex);
 375        list_add(&shmnode->shm_node, &ctxdata->shm_list);
 376        mutex_unlock(&ctxdata->shm_mutex);
 377
 378        pr_debug("buf_id :[%x] kaddr[%p]\n", shmnode->buf_id, shmnode->kaddr);
 379
 380        return 0;
 381}
 382
 383void amdtee_unmap_shmem(struct tee_shm *shm)
 384{
 385        struct amdtee_context_data *ctxdata;
 386        struct amdtee_shm_data *shmnode;
 387        u32 buf_id;
 388
 389        if (!shm)
 390                return;
 391
 392        buf_id = get_buffer_id(shm);
 393        /* Unmap the shared memory from TEE */
 394        handle_unmap_shmem(buf_id);
 395
 396        ctxdata = shm->ctx->data;
 397        mutex_lock(&ctxdata->shm_mutex);
 398        list_for_each_entry(shmnode, &ctxdata->shm_list, shm_node)
 399                if (buf_id == shmnode->buf_id) {
 400                        list_del(&shmnode->shm_node);
 401                        kfree(shmnode);
 402                        break;
 403                }
 404        mutex_unlock(&ctxdata->shm_mutex);
 405}
 406
 407int amdtee_invoke_func(struct tee_context *ctx,
 408                       struct tee_ioctl_invoke_arg *arg,
 409                       struct tee_param *param)
 410{
 411        struct amdtee_context_data *ctxdata = ctx->data;
 412        struct amdtee_session *sess;
 413        u32 i, session_info;
 414
 415        /* Check that the session is valid */
 416        mutex_lock(&session_list_mutex);
 417        sess = find_session(ctxdata, arg->session);
 418        if (sess) {
 419                i = get_session_index(arg->session);
 420                session_info = sess->session_info[i];
 421        }
 422        mutex_unlock(&session_list_mutex);
 423
 424        if (!sess)
 425                return -EINVAL;
 426
 427        handle_invoke_cmd(arg, session_info, param);
 428
 429        return 0;
 430}
 431
 432int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
 433{
 434        return -EINVAL;
 435}
 436
 437static const struct tee_driver_ops amdtee_ops = {
 438        .get_version = amdtee_get_version,
 439        .open = amdtee_open,
 440        .release = amdtee_release,
 441        .open_session = amdtee_open_session,
 442        .close_session = amdtee_close_session,
 443        .invoke_func = amdtee_invoke_func,
 444        .cancel_req = amdtee_cancel_req,
 445};
 446
 447static const struct tee_desc amdtee_desc = {
 448        .name = DRIVER_NAME "-clnt",
 449        .ops = &amdtee_ops,
 450        .owner = THIS_MODULE,
 451};
 452
 453static int __init amdtee_driver_init(void)
 454{
 455        struct tee_device *teedev;
 456        struct tee_shm_pool *pool;
 457        struct amdtee *amdtee;
 458        int rc;
 459
 460        rc = psp_check_tee_status();
 461        if (rc) {
 462                pr_err("amd-tee driver: tee not present\n");
 463                return rc;
 464        }
 465
 466        drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
 467        if (!drv_data)
 468                return -ENOMEM;
 469
 470        amdtee = kzalloc(sizeof(*amdtee), GFP_KERNEL);
 471        if (!amdtee) {
 472                rc = -ENOMEM;
 473                goto err_kfree_drv_data;
 474        }
 475
 476        pool = amdtee_config_shm();
 477        if (IS_ERR(pool)) {
 478                pr_err("shared pool configuration error\n");
 479                rc = PTR_ERR(pool);
 480                goto err_kfree_amdtee;
 481        }
 482
 483        teedev = tee_device_alloc(&amdtee_desc, NULL, pool, amdtee);
 484        if (IS_ERR(teedev)) {
 485                rc = PTR_ERR(teedev);
 486                goto err_free_pool;
 487        }
 488        amdtee->teedev = teedev;
 489
 490        rc = tee_device_register(amdtee->teedev);
 491        if (rc)
 492                goto err_device_unregister;
 493
 494        amdtee->pool = pool;
 495
 496        drv_data->amdtee = amdtee;
 497
 498        pr_info("amd-tee driver initialization successful\n");
 499        return 0;
 500
 501err_device_unregister:
 502        tee_device_unregister(amdtee->teedev);
 503
 504err_free_pool:
 505        tee_shm_pool_free(pool);
 506
 507err_kfree_amdtee:
 508        kfree(amdtee);
 509
 510err_kfree_drv_data:
 511        kfree(drv_data);
 512        drv_data = NULL;
 513
 514        pr_err("amd-tee driver initialization failed\n");
 515        return rc;
 516}
 517module_init(amdtee_driver_init);
 518
 519static void __exit amdtee_driver_exit(void)
 520{
 521        struct amdtee *amdtee;
 522
 523        if (!drv_data || !drv_data->amdtee)
 524                return;
 525
 526        amdtee = drv_data->amdtee;
 527
 528        tee_device_unregister(amdtee->teedev);
 529        tee_shm_pool_free(amdtee->pool);
 530}
 531module_exit(amdtee_driver_exit);
 532
 533MODULE_AUTHOR(DRIVER_AUTHOR);
 534MODULE_DESCRIPTION("AMD-TEE driver");
 535MODULE_VERSION("1.0");
 536MODULE_LICENSE("Dual MIT/GPL");
 537