Enable support to register kernel memory reference with TEE. This change will allow TEE bus drivers to register memory references.
Unified · Split
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/sched.h> |
| 10 | 10 | #include <linux/slab.h> |
| 11 | 11 | #include <linux/tee_drv.h> |
| 12 | +#include <linux/uio.h> | |
| 12 | 13 | #include "tee_private.h" |
| 13 | 14 | |
| 14 | 15 | static void tee_shm_release(struct tee_shm *shm) |
| @@ -185,14 +186,15 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, · 170 unmodified lines | ||
| 185 | 186 | size_t length, u32 flags) |
| 186 | 187 | { |
| 187 | 188 | struct tee_device *teedev = ctx->teedev; |
| 188 | − const u32 req_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED; | |
| 189 | + const u32 req_user_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED; | |
| 190 | + const u32 req_kernel_flags = TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED; | |
| 189 | 191 | struct tee_shm *shm; |
| 190 | 192 | void *ret; |
| 191 | 193 | int rc; |
| 192 | 194 | int num_pages; |
| 193 | 195 | unsigned long start; |
| 194 | 196 | |
| 195 | − if (flags != req_flags) | |
| 197 | + if (flags != req_user_flags && flags != req_kernel_flags) | |
| 196 | 198 | return ERR_PTR(-ENOTSUPP); |
| 197 | 199 | |
| 198 | 200 | if (!tee_device_get(teedev)) |
| @@ -226,7 +228,27 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, · 27 unmodified lines | ||
| 226 | 228 | goto err; |
| 227 | 229 | } |
| 228 | 230 | |
| 229 | − rc = get_user_pages_fast(start, num_pages, FOLL_WRITE, shm->pages); | |
| 231 | + if (flags & TEE_SHM_USER_MAPPED) { | |
| 232 | + rc = get_user_pages_fast(start, num_pages, FOLL_WRITE, | |
| 233 | + shm->pages); | |
| 234 | + } else { | |
| 235 | + struct kvec *kiov; | |
| 236 | + int i; | |
| 237 | + | |
| 238 | + kiov = kcalloc(num_pages, sizeof(*kiov), GFP_KERNEL); | |
| 239 | + if (!kiov) { | |
| 240 | + ret = ERR_PTR(-ENOMEM); | |
| 241 | + goto err; | |
| 242 | + } | |
| 243 | + | |
| 244 | + for (i = 0; i < num_pages; i++) { | |
| 245 | + kiov[i].iov_base = (void *)(start + i * PAGE_SIZE); | |
| 246 | + kiov[i].iov_len = PAGE_SIZE; | |
| 247 | + } | |
| 248 | + | |
| 249 | + rc = get_kernel_pages(kiov, num_pages, 0, shm->pages); | |
| 250 | + kfree(kiov); | |
| 251 | + } | |
| 230 | 252 | if (rc > 0) |
| 231 | 253 | shm->num_pages = rc; |
| 232 | 254 | if (rc != num_pages) { |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #define TEE_SHM_REGISTER BIT(3) /* Memory registered in secure world */ |
| 27 | 27 | #define TEE_SHM_USER_MAPPED BIT(4) /* Memory mapped in user space */ |
| 28 | 28 | #define TEE_SHM_POOL BIT(5) /* Memory allocated from pool */ |
| 29 | +#define TEE_SHM_KERNEL_MAPPED BIT(6) /* Memory mapped in kernel space */ | |
| 29 | 30 | |
| 30 | 31 | struct device; |
| 31 | 32 | struct tee_device; |