]> Git Repo - linux.git/blob - drivers/tee/amdtee/core.c
Linux 6.14-rc3
[linux.git] / drivers / tee / amdtee / core.c
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_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
20 static struct amdtee_driver_data *drv_data;
21 static DEFINE_MUTEX(session_list_mutex);
22
23 static 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
34 static 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
50 static 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
67 static 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 structure
95  * @ctxdata:    TEE Context data structure
96  * @session:    Session ID for which 'struct amdtee_session' structure is to be
97  *              allocated.
98  *
99  * Scans the TEE context's session list to check if TA is already loaded in to
100  * 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  */
108 static 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 */
134 static 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
152 u32 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
169 static DEFINE_MUTEX(drv_mutex);
170 static 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);
212 rel_fw:
213         release_firmware(fw);
214 unlock:
215         mutex_unlock(&drv_mutex);
216         return rc;
217 }
218
219 /* mutex must be held by caller */
220 static 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
230 int 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
299 out:
300         free_pages((u64)ta, get_order(ta_size));
301         return rc;
302 }
303
304 int 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_mutex(&sess->refcount, destroy_session, &session_list_mutex);
336
337         return 0;
338 }
339
340 int 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
382 void 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
406 int 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
431 int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
432 {
433         return -EINVAL;
434 }
435
436 static 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
446 static const struct tee_desc amdtee_desc = {
447         .name = DRIVER_NAME "-clnt",
448         .ops = &amdtee_ops,
449         .owner = THIS_MODULE,
450 };
451
452 static 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
500 err_device_unregister:
501         tee_device_unregister(amdtee->teedev);
502
503 err_free_pool:
504         tee_shm_pool_free(pool);
505
506 err_kfree_amdtee:
507         kfree(amdtee);
508
509 err_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 }
516 module_init(amdtee_driver_init);
517
518 static 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 }
530 module_exit(amdtee_driver_exit);
531
532 MODULE_AUTHOR(DRIVER_AUTHOR);
533 MODULE_DESCRIPTION("AMD-TEE driver");
534 MODULE_VERSION("1.0");
535 MODULE_LICENSE("Dual MIT/GPL");
This page took 0.065919 seconds and 4 git commands to generate.