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);
  23static struct amdtee_shm_context shmctx;
  24
  25static void amdtee_get_version(struct tee_device *teedev,
  26                               struct tee_ioctl_version_data *vers)
  27{
  28        struct tee_ioctl_version_data v = {
  29                .impl_id = TEE_IMPL_ID_AMDTEE,
  30                .impl_caps = 0,
  31                .gen_caps = TEE_GEN_CAP_GP,
  32        };
  33        *vers = v;
  34}
  35
  36static int amdtee_open(struct tee_context *ctx)
  37{
  38        struct amdtee_context_data *ctxdata;
  39
  40        ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL);
  41        if (!ctxdata)
  42                return -ENOMEM;
  43
  44        INIT_LIST_HEAD(&ctxdata->sess_list);
  45        INIT_LIST_HEAD(&shmctx.shmdata_list);
  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        }
  63
  64        /* Unload Trusted Application once all sessions are closed */
  65        handle_unload_ta(sess->ta_handle);
  66        kfree(sess);
  67}
  68
  69static void amdtee_release(struct tee_context *ctx)
  70{
  71        struct amdtee_context_data *ctxdata = ctx->data;
  72
  73        if (!ctxdata)
  74                return;
  75
  76        while (true) {
  77                struct amdtee_session *sess;
  78
  79                sess = list_first_entry_or_null(&ctxdata->sess_list,
  80                                                struct amdtee_session,
  81                                                list_node);
  82
  83                if (!sess)
  84                        break;
  85
  86                list_del(&sess->list_node);
  87                release_session(sess);
  88        }
  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        u32 buf_id = 0;
 156        struct amdtee_shm_data *shmdata;
 157
 158        list_for_each_entry(shmdata, &shmctx.shmdata_list, shm_node)
 159                if (shmdata->kaddr == shm->kaddr) {
 160                        buf_id = shmdata->buf_id;
 161                        break;
 162                }
 163
 164        return buf_id;
 165}
 166
 167static DEFINE_MUTEX(drv_mutex);
 168static int copy_ta_binary(struct tee_context *ctx, void *ptr, void **ta,
 169                          size_t *ta_size)
 170{
 171        const struct firmware *fw;
 172        char fw_name[TA_PATH_MAX];
 173        struct {
 174                u32 lo;
 175                u16 mid;
 176                u16 hi_ver;
 177                u8 seq_n[8];
 178        } *uuid = ptr;
 179        int n, rc = 0;
 180
 181        n = snprintf(fw_name, TA_PATH_MAX,
 182                     "%s/%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x.bin",
 183                     TA_LOAD_PATH, uuid->lo, uuid->mid, uuid->hi_ver,
 184                     uuid->seq_n[0], uuid->seq_n[1],
 185                     uuid->seq_n[2], uuid->seq_n[3],
 186                     uuid->seq_n[4], uuid->seq_n[5],
 187                     uuid->seq_n[6], uuid->seq_n[7]);
 188        if (n < 0 || n >= TA_PATH_MAX) {
 189                pr_err("failed to get firmware name\n");
 190                return -EINVAL;
 191        }
 192
 193        mutex_lock(&drv_mutex);
 194        n = request_firmware(&fw, fw_name, &ctx->teedev->dev);
 195        if (n) {
 196                pr_err("failed to load firmware %s\n", fw_name);
 197                rc = -ENOMEM;
 198                goto unlock;
 199        }
 200
 201        *ta_size = roundup(fw->size, PAGE_SIZE);
 202        *ta = (void *)__get_free_pages(GFP_KERNEL, get_order(*ta_size));
 203        if (IS_ERR(*ta)) {
 204                pr_err("%s: get_free_pages failed 0x%llx\n", __func__,
 205                       (u64)*ta);
 206                rc = -ENOMEM;
 207                goto rel_fw;
 208        }
 209
 210        memcpy(*ta, fw->data, fw->size);
 211rel_fw:
 212        release_firmware(fw);
 213unlock:
 214        mutex_unlock(&drv_mutex);
 215        return rc;
 216}
 217
 218static void destroy_session(struct kref *ref)
 219{
 220        struct amdtee_session *sess = container_of(ref, struct amdtee_session,
 221                                                   refcount);
 222
 223        /* Unload the TA from TEE */
 224        handle_unload_ta(sess->ta_handle);
 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;
 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        mutex_lock(&session_list_mutex);
 259        sess = alloc_session(ctxdata, arg->session);
 260        mutex_unlock(&session_list_mutex);
 261
 262        if (!sess) {
 263                rc = -ENOMEM;
 264                goto out;
 265        }
 266
 267        /* Find an empty session index for the given TA */
 268        spin_lock(&sess->lock);
 269        i = find_first_zero_bit(sess->sess_mask, TEE_NUM_SESSIONS);
 270        if (i < TEE_NUM_SESSIONS)
 271                set_bit(i, sess->sess_mask);
 272        spin_unlock(&sess->lock);
 273
 274        if (i >= TEE_NUM_SESSIONS) {
 275                pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
 276                kref_put(&sess->refcount, destroy_session);
 277                rc = -ENOMEM;
 278                goto out;
 279        }
 280
 281        /* Open session with loaded TA */
 282        handle_open_session(arg, &session_info, param);
 283        if (arg->ret != TEEC_SUCCESS) {
 284                pr_err("open_session failed %d\n", arg->ret);
 285                spin_lock(&sess->lock);
 286                clear_bit(i, sess->sess_mask);
 287                spin_unlock(&sess->lock);
 288                kref_put(&sess->refcount, destroy_session);
 289                goto out;
 290        }
 291
 292        sess->session_info[i] = session_info;
 293        set_session_id(sess->ta_handle, i, &arg->session);
 294out:
 295        free_pages((u64)ta, get_order(ta_size));
 296        return rc;
 297}
 298
 299int amdtee_close_session(struct tee_context *ctx, u32 session)
 300{
 301        struct amdtee_context_data *ctxdata = ctx->data;
 302        u32 i, ta_handle, session_info;
 303        struct amdtee_session *sess;
 304
 305        pr_debug("%s: sid = 0x%x\n", __func__, session);
 306
 307        /*
 308         * Check that the session is valid and clear the session
 309         * usage bit
 310         */
 311        mutex_lock(&session_list_mutex);
 312        sess = find_session(ctxdata, session);
 313        if (sess) {
 314                ta_handle = get_ta_handle(session);
 315                i = get_session_index(session);
 316                session_info = sess->session_info[i];
 317                spin_lock(&sess->lock);
 318                clear_bit(i, sess->sess_mask);
 319                spin_unlock(&sess->lock);
 320        }
 321        mutex_unlock(&session_list_mutex);
 322
 323        if (!sess)
 324                return -EINVAL;
 325
 326        /* Close the session */
 327        handle_close_session(ta_handle, session_info);
 328
 329        kref_put(&sess->refcount, destroy_session);
 330
 331        return 0;
 332}
 333
 334int amdtee_map_shmem(struct tee_shm *shm)
 335{
 336        struct shmem_desc shmem;
 337        struct amdtee_shm_data *shmnode;
 338        int rc, count;
 339        u32 buf_id;
 340
 341        if (!shm)
 342                return -EINVAL;
 343
 344        shmnode = kmalloc(sizeof(*shmnode), GFP_KERNEL);
 345        if (!shmnode)
 346                return -ENOMEM;
 347
 348        count = 1;
 349        shmem.kaddr = shm->kaddr;
 350        shmem.size = shm->size;
 351
 352        /*
 353         * Send a MAP command to TEE and get the corresponding
 354         * buffer Id
 355         */
 356        rc = handle_map_shmem(count, &shmem, &buf_id);
 357        if (rc) {
 358                pr_err("map_shmem failed: ret = %d\n", rc);
 359                kfree(shmnode);
 360                return rc;
 361        }
 362
 363        shmnode->kaddr = shm->kaddr;
 364        shmnode->buf_id = buf_id;
 365        list_add(&shmnode->shm_node, &shmctx.shmdata_list);
 366
 367        pr_debug("buf_id :[%x] kaddr[%p]\n", shmnode->buf_id, shmnode->kaddr);
 368
 369        return 0;
 370}
 371
 372void amdtee_unmap_shmem(struct tee_shm *shm)
 373{
 374        struct amdtee_shm_data *shmnode;
 375        u32 buf_id;
 376
 377        if (!shm)
 378                return;
 379
 380        buf_id = get_buffer_id(shm);
 381        /* Unmap the shared memory from TEE */
 382        handle_unmap_shmem(buf_id);
 383
 384        list_for_each_entry(shmnode, &shmctx.shmdata_list, shm_node)
 385                if (buf_id == shmnode->buf_id) {
 386                        list_del(&shmnode->shm_node);
 387                        kfree(shmnode);
 388                        break;
 389                }
 390}
 391
 392int amdtee_invoke_func(struct tee_context *ctx,
 393                       struct tee_ioctl_invoke_arg *arg,
 394                       struct tee_param *param)
 395{
 396        struct amdtee_context_data *ctxdata = ctx->data;
 397        struct amdtee_session *sess;
 398        u32 i, session_info;
 399
 400        /* Check that the session is valid */
 401        mutex_lock(&session_list_mutex);
 402        sess = find_session(ctxdata, arg->session);
 403        if (sess) {
 404                i = get_session_index(arg->session);
 405                session_info = sess->session_info[i];
 406        }
 407        mutex_unlock(&session_list_mutex);
 408
 409        if (!sess)
 410                return -EINVAL;
 411
 412        handle_invoke_cmd(arg, session_info, param);
 413
 414        return 0;
 415}
 416
 417int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
 418{
 419        return -EINVAL;
 420}
 421
 422static const struct tee_driver_ops amdtee_ops = {
 423        .get_version = amdtee_get_version,
 424        .open = amdtee_open,
 425        .release = amdtee_release,
 426        .open_session = amdtee_open_session,
 427        .close_session = amdtee_close_session,
 428        .invoke_func = amdtee_invoke_func,
 429        .cancel_req = amdtee_cancel_req,
 430};
 431
 432static const struct tee_desc amdtee_desc = {
 433        .name = DRIVER_NAME "-clnt",
 434        .ops = &amdtee_ops,
 435        .owner = THIS_MODULE,
 436};
 437
 438static int __init amdtee_driver_init(void)
 439{
 440        struct tee_device *teedev;
 441        struct tee_shm_pool *pool;
 442        struct amdtee *amdtee;
 443        int rc;
 444
 445        rc = psp_check_tee_status();
 446        if (rc) {
 447                pr_err("amd-tee driver: tee not present\n");
 448                return rc;
 449        }
 450
 451        drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
 452        if (!drv_data)
 453                return -ENOMEM;
 454
 455        amdtee = kzalloc(sizeof(*amdtee), GFP_KERNEL);
 456        if (!amdtee) {
 457                rc = -ENOMEM;
 458                goto err_kfree_drv_data;
 459        }
 460
 461        pool = amdtee_config_shm();
 462        if (IS_ERR(pool)) {
 463                pr_err("shared pool configuration error\n");
 464                rc = PTR_ERR(pool);
 465                goto err_kfree_amdtee;
 466        }
 467
 468        teedev = tee_device_alloc(&amdtee_desc, NULL, pool, amdtee);
 469        if (IS_ERR(teedev)) {
 470                rc = PTR_ERR(teedev);
 471                goto err_free_pool;
 472        }
 473        amdtee->teedev = teedev;
 474
 475        rc = tee_device_register(amdtee->teedev);
 476        if (rc)
 477                goto err_device_unregister;
 478
 479        amdtee->pool = pool;
 480
 481        drv_data->amdtee = amdtee;
 482
 483        pr_info("amd-tee driver initialization successful\n");
 484        return 0;
 485
 486err_device_unregister:
 487        tee_device_unregister(amdtee->teedev);
 488
 489err_free_pool:
 490        tee_shm_pool_free(pool);
 491
 492err_kfree_amdtee:
 493        kfree(amdtee);
 494
 495err_kfree_drv_data:
 496        kfree(drv_data);
 497        drv_data = NULL;
 498
 499        pr_err("amd-tee driver initialization failed\n");
 500        return rc;
 501}
 502module_init(amdtee_driver_init);
 503
 504static void __exit amdtee_driver_exit(void)
 505{
 506        struct amdtee *amdtee;
 507
 508        if (!drv_data || !drv_data->amdtee)
 509                return;
 510
 511        amdtee = drv_data->amdtee;
 512
 513        tee_device_unregister(amdtee->teedev);
 514        tee_shm_pool_free(amdtee->pool);
 515}
 516module_exit(amdtee_driver_exit);
 517
 518MODULE_AUTHOR(DRIVER_AUTHOR);
 519MODULE_DESCRIPTION("AMD-TEE driver");
 520MODULE_VERSION("1.0");
 521MODULE_LICENSE("Dual MIT/GPL");
 522