hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/tee/tee_shm.c
....@@ -1,15 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2015-2017, 2019-2021 Linaro Limited
3
- *
4
- * This software is licensed under the terms of the GNU General Public
5
- * License version 2, as published by the Free Software Foundation, and
6
- * may be copied, distributed, and modified under those terms.
7
- *
8
- * This program is distributed in the hope that it will be useful,
9
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- * GNU General Public License for more details.
12
- *
134 */
145 #include <linux/anon_inodes.h>
156 #include <linux/device.h>
....@@ -18,7 +9,25 @@
189 #include <linux/sched.h>
1910 #include <linux/slab.h>
2011 #include <linux/tee_drv.h>
12
+#include <linux/uaccess.h>
13
+#include <linux/uio.h>
2114 #include "tee_private.h"
15
+
16
+static void release_registered_pages(struct tee_shm *shm)
17
+{
18
+ if (shm->pages) {
19
+ if (shm->flags & TEE_SHM_USER_MAPPED) {
20
+ unpin_user_pages(shm->pages, shm->num_pages);
21
+ } else {
22
+ size_t n;
23
+
24
+ for (n = 0; n < shm->num_pages; n++)
25
+ put_page(shm->pages[n]);
26
+ }
27
+
28
+ kfree(shm->pages);
29
+ }
30
+}
2231
2332 static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
2433 {
....@@ -32,40 +41,29 @@
3241
3342 poolm->ops->free(poolm, shm);
3443 } else if (shm->flags & TEE_SHM_REGISTER) {
35
- size_t n;
3644 int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);
3745
3846 if (rc)
3947 dev_err(teedev->dev.parent,
4048 "unregister shm %p failed: %d", shm, rc);
4149
42
- for (n = 0; n < shm->num_pages; n++)
43
- put_page(shm->pages[n]);
44
-
45
- kfree(shm->pages);
50
+ release_registered_pages(shm);
4651 }
4752
48
- if (shm->ctx)
49
- teedev_ctx_put(shm->ctx);
53
+ teedev_ctx_put(shm->ctx);
5054
5155 kfree(shm);
5256
5357 tee_device_put(teedev);
5458 }
5559
56
-static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
57
- struct tee_device *teedev,
58
- size_t size, u32 flags)
60
+struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
5961 {
62
+ struct tee_device *teedev = ctx->teedev;
6063 struct tee_shm_pool_mgr *poolm = NULL;
6164 struct tee_shm *shm;
6265 void *ret;
6366 int rc;
64
-
65
- if (ctx && ctx->teedev != teedev) {
66
- dev_err(teedev->dev.parent, "ctx and teedev mismatch\n");
67
- return ERR_PTR(-EINVAL);
68
- }
6967
7068 if (!(flags & TEE_SHM_MAPPED)) {
7169 dev_err(teedev->dev.parent,
....@@ -73,7 +71,7 @@
7371 return ERR_PTR(-EINVAL);
7472 }
7573
76
- if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF))) {
74
+ if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_PRIV))) {
7775 dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags);
7876 return ERR_PTR(-EINVAL);
7977 }
....@@ -95,7 +93,6 @@
9593
9694 refcount_set(&shm->refcount, 1);
9795 shm->flags = flags | TEE_SHM_POOL;
98
- shm->teedev = teedev;
9996 shm->ctx = ctx;
10097 if (flags & TEE_SHM_DMA_BUF)
10198 poolm = teedev->pool->dma_buf_mgr;
....@@ -108,20 +105,17 @@
108105 goto err_kfree;
109106 }
110107
111
- mutex_lock(&teedev->mutex);
112
- shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
113
- mutex_unlock(&teedev->mutex);
114
- if (shm->id < 0) {
115
- ret = ERR_PTR(shm->id);
116
- goto err_pool_free;
108
+ if (flags & TEE_SHM_DMA_BUF) {
109
+ mutex_lock(&teedev->mutex);
110
+ shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
111
+ mutex_unlock(&teedev->mutex);
112
+ if (shm->id < 0) {
113
+ ret = ERR_PTR(shm->id);
114
+ goto err_pool_free;
115
+ }
117116 }
118117
119
- if (ctx) {
120
- teedev_ctx_get(ctx);
121
- mutex_lock(&teedev->mutex);
122
- list_add_tail(&shm->link, &ctx->list_shm);
123
- mutex_unlock(&teedev->mutex);
124
- }
118
+ teedev_ctx_get(ctx);
125119
126120 return shm;
127121 err_pool_free:
....@@ -132,43 +126,39 @@
132126 tee_device_put(teedev);
133127 return ret;
134128 }
135
-
136
-/**
137
- * tee_shm_alloc() - Allocate shared memory
138
- * @ctx: Context that allocates the shared memory
139
- * @size: Requested size of shared memory
140
- * @flags: Flags setting properties for the requested shared memory.
141
- *
142
- * Memory allocated as global shared memory is automatically freed when the
143
- * TEE file pointer is closed. The @flags field uses the bits defined by
144
- * TEE_SHM_* in <linux/tee_drv.h>. TEE_SHM_MAPPED must currently always be
145
- * set. If TEE_SHM_DMA_BUF global shared memory will be allocated and
146
- * associated with a dma-buf handle, else driver private memory.
147
- */
148
-struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
149
-{
150
- return __tee_shm_alloc(ctx, ctx->teedev, size, flags);
151
-}
152129 EXPORT_SYMBOL_GPL(tee_shm_alloc);
153130
154
-struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size)
131
+/**
132
+ * tee_shm_alloc_kernel_buf() - Allocate shared memory for kernel buffer
133
+ * @ctx: Context that allocates the shared memory
134
+ * @size: Requested size of shared memory
135
+ *
136
+ * The returned memory registered in secure world and is suitable to be
137
+ * passed as a memory buffer in parameter argument to
138
+ * tee_client_invoke_func(). The memory allocated is later freed with a
139
+ * call to tee_shm_free().
140
+ *
141
+ * @returns a pointer to 'struct tee_shm'
142
+ */
143
+struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
155144 {
156
- return __tee_shm_alloc(NULL, teedev, size, TEE_SHM_MAPPED);
145
+ return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED);
157146 }
158
-EXPORT_SYMBOL_GPL(tee_shm_priv_alloc);
147
+EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
159148
160149 struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
161150 size_t length, u32 flags)
162151 {
163152 struct tee_device *teedev = ctx->teedev;
164
- const u32 req_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED;
153
+ const u32 req_user_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED;
154
+ const u32 req_kernel_flags = TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED;
165155 struct tee_shm *shm;
166156 void *ret;
167157 int rc;
168158 int num_pages;
169159 unsigned long start;
170160
171
- if (flags != req_flags)
161
+ if (flags != req_user_flags && flags != req_kernel_flags)
172162 return ERR_PTR(-ENOTSUPP);
173163
174164 if (!tee_device_get(teedev))
....@@ -190,7 +180,6 @@
190180
191181 refcount_set(&shm->refcount, 1);
192182 shm->flags = flags | TEE_SHM_REGISTER;
193
- shm->teedev = teedev;
194183 shm->ctx = ctx;
195184 shm->id = -1;
196185 addr = untagged_addr(addr);
....@@ -204,7 +193,27 @@
204193 goto err;
205194 }
206195
207
- rc = get_user_pages_fast(start, num_pages, 1, shm->pages);
196
+ if (flags & TEE_SHM_USER_MAPPED) {
197
+ rc = pin_user_pages_fast(start, num_pages, FOLL_WRITE,
198
+ shm->pages);
199
+ } else {
200
+ struct kvec *kiov;
201
+ int i;
202
+
203
+ kiov = kcalloc(num_pages, sizeof(*kiov), GFP_KERNEL);
204
+ if (!kiov) {
205
+ ret = ERR_PTR(-ENOMEM);
206
+ goto err;
207
+ }
208
+
209
+ for (i = 0; i < num_pages; i++) {
210
+ kiov[i].iov_base = (void *)(start + i * PAGE_SIZE);
211
+ kiov[i].iov_len = PAGE_SIZE;
212
+ }
213
+
214
+ rc = get_kernel_pages(kiov, num_pages, 0, shm->pages);
215
+ kfree(kiov);
216
+ }
208217 if (rc > 0)
209218 shm->num_pages = rc;
210219 if (rc != num_pages) {
....@@ -230,25 +239,15 @@
230239 goto err;
231240 }
232241
233
- mutex_lock(&teedev->mutex);
234
- list_add_tail(&shm->link, &ctx->list_shm);
235
- mutex_unlock(&teedev->mutex);
236
-
237242 return shm;
238243 err:
239244 if (shm) {
240
- size_t n;
241
-
242245 if (shm->id >= 0) {
243246 mutex_lock(&teedev->mutex);
244247 idr_remove(&teedev->idr, shm->id);
245248 mutex_unlock(&teedev->mutex);
246249 }
247
- if (shm->pages) {
248
- for (n = 0; n < shm->num_pages; n++)
249
- put_page(shm->pages[n]);
250
- kfree(shm->pages);
251
- }
250
+ release_registered_pages(shm);
252251 }
253252 kfree(shm);
254253 teedev_ctx_put(ctx);
....@@ -439,7 +438,7 @@
439438 */
440439 void tee_shm_put(struct tee_shm *shm)
441440 {
442
- struct tee_device *teedev = shm->teedev;
441
+ struct tee_device *teedev = shm->ctx->teedev;
443442 bool do_release = false;
444443
445444 mutex_lock(&teedev->mutex);
....@@ -450,9 +449,8 @@
450449 * the refcount_inc() in tee_shm_get_from_id() never starts
451450 * from 0.
452451 */
453
- idr_remove(&teedev->idr, shm->id);
454
- if (shm->ctx)
455
- list_del(&shm->link);
452
+ if (shm->flags & TEE_SHM_DMA_BUF)
453
+ idr_remove(&teedev->idr, shm->id);
456454 do_release = true;
457455 }
458456 mutex_unlock(&teedev->mutex);