1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * Copyright 2019 Advanced Micro Devices, Inc. |
4 | */ |
5 | |
6 | #include <linux/slab.h> |
7 | #include <linux/tee_drv.h> |
8 | #include <linux/psp.h> |
9 | #include "amdtee_private.h" |
10 | |
11 | static int pool_op_alloc(struct tee_shm_pool *pool, struct tee_shm *shm, |
12 | size_t size, size_t align) |
13 | { |
14 | unsigned int order = get_order(size); |
15 | unsigned long va; |
16 | int rc; |
17 | |
18 | /* |
19 | * Ignore alignment since this is already going to be page aligned |
20 | * and there's no need for any larger alignment. |
21 | */ |
22 | va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order); |
23 | if (!va) |
24 | return -ENOMEM; |
25 | |
26 | shm->kaddr = (void *)va; |
27 | shm->paddr = __psp_pa((void *)va); |
28 | shm->size = PAGE_SIZE << order; |
29 | |
30 | /* Map the allocated memory in to TEE */ |
31 | rc = amdtee_map_shmem(shm); |
32 | if (rc) { |
33 | free_pages(addr: va, order); |
34 | shm->kaddr = NULL; |
35 | return rc; |
36 | } |
37 | |
38 | return 0; |
39 | } |
40 | |
41 | static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm) |
42 | { |
43 | /* Unmap the shared memory from TEE */ |
44 | amdtee_unmap_shmem(shm); |
45 | free_pages(addr: (unsigned long)shm->kaddr, order: get_order(size: shm->size)); |
46 | shm->kaddr = NULL; |
47 | } |
48 | |
49 | static void pool_op_destroy_pool(struct tee_shm_pool *pool) |
50 | { |
51 | kfree(objp: pool); |
52 | } |
53 | |
54 | static const struct tee_shm_pool_ops pool_ops = { |
55 | .alloc = pool_op_alloc, |
56 | .free = pool_op_free, |
57 | .destroy_pool = pool_op_destroy_pool, |
58 | }; |
59 | |
60 | struct tee_shm_pool *amdtee_config_shm(void) |
61 | { |
62 | struct tee_shm_pool *pool = kzalloc(size: sizeof(*pool), GFP_KERNEL); |
63 | |
64 | if (!pool) |
65 | return ERR_PTR(error: -ENOMEM); |
66 | |
67 | pool->ops = &pool_ops; |
68 | |
69 | return pool; |
70 | } |
71 | |