Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tee: add tee_shm_alloc_dma_mem()

Add tee_shm_alloc_dma_mem() to allocate DMA memory. The memory is
represented by a tee_shm object using the new flag TEE_SHM_DMA_MEM to
identify it as DMA memory. The allocated memory will later be lent to
the TEE to be used as protected memory.

Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>

+88 -2
+83 -2
drivers/tee/tee_shm.c
··· 5 5 #include <linux/anon_inodes.h> 6 6 #include <linux/device.h> 7 7 #include <linux/dma-buf.h> 8 + #include <linux/dma-mapping.h> 9 + #include <linux/highmem.h> 8 10 #include <linux/idr.h> 9 11 #include <linux/io.h> 10 12 #include <linux/mm.h> ··· 15 13 #include <linux/tee_core.h> 16 14 #include <linux/uaccess.h> 17 15 #include <linux/uio.h> 18 - #include <linux/highmem.h> 19 16 #include "tee_private.h" 17 + 18 + struct tee_shm_dma_mem { 19 + struct tee_shm shm; 20 + dma_addr_t dma_addr; 21 + struct page *page; 22 + }; 20 23 21 24 static void shm_put_kernel_pages(struct page **pages, size_t page_count) 22 25 { ··· 55 48 { 56 49 void *p = shm; 57 50 58 - if (shm->flags & TEE_SHM_DMA_BUF) { 51 + if (shm->flags & TEE_SHM_DMA_MEM) { 52 + #if IS_ENABLED(CONFIG_TEE_DMABUF_HEAPS) 53 + struct tee_shm_dma_mem *dma_mem; 54 + 55 + dma_mem = container_of(shm, struct tee_shm_dma_mem, shm); 56 + p = dma_mem; 57 + dma_free_pages(&teedev->dev, shm->size, dma_mem->page, 58 + dma_mem->dma_addr, DMA_BIDIRECTIONAL); 59 + #endif 60 + } else if (shm->flags & TEE_SHM_DMA_BUF) { 59 61 struct tee_shm_dmabuf_ref *ref; 60 62 61 63 ref = container_of(shm, struct tee_shm_dmabuf_ref, shm); ··· 283 267 return shm_alloc_helper(ctx, size, sizeof(long) * 2, flags, -1); 284 268 } 285 269 EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_buf); 270 + 271 + #if IS_ENABLED(CONFIG_TEE_DMABUF_HEAPS) 272 + /** 273 + * tee_shm_alloc_dma_mem() - Allocate DMA memory as shared memory object 274 + * @ctx: Context that allocates the shared memory 275 + * @page_count: Number of pages 276 + * 277 + * The allocated memory is expected to be lent (made inaccessible to the 278 + * kernel) to the TEE while it's used and returned (accessible to the 279 + * kernel again) before it's freed. 280 + * 281 + * This function should normally only be used internally in the TEE 282 + * drivers. 283 + * 284 + * @returns a pointer to 'struct tee_shm' 285 + */ 286 + struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx, 287 + size_t page_count) 288 + { 289 + struct tee_device *teedev = ctx->teedev; 290 + struct tee_shm_dma_mem *dma_mem; 291 + dma_addr_t dma_addr; 292 + struct page *page; 293 + 294 + if (!tee_device_get(teedev)) 295 + return ERR_PTR(-EINVAL); 296 + 297 + page = dma_alloc_pages(&teedev->dev, page_count * PAGE_SIZE, 298 + &dma_addr, DMA_BIDIRECTIONAL, GFP_KERNEL); 299 + if (!page) 300 + goto err_put_teedev; 301 + 302 + dma_mem = kzalloc(sizeof(*dma_mem), GFP_KERNEL); 303 + if (!dma_mem) 304 + goto err_free_pages; 305 + 306 + refcount_set(&dma_mem->shm.refcount, 1); 307 + dma_mem->shm.ctx = ctx; 308 + dma_mem->shm.paddr = page_to_phys(page); 309 + dma_mem->dma_addr = dma_addr; 310 + dma_mem->page = page; 311 + dma_mem->shm.size = page_count * PAGE_SIZE; 312 + dma_mem->shm.flags = TEE_SHM_DMA_MEM; 313 + 314 + teedev_ctx_get(ctx); 315 + 316 + return &dma_mem->shm; 317 + 318 + err_free_pages: 319 + dma_free_pages(&teedev->dev, page_count * PAGE_SIZE, page, dma_addr, 320 + DMA_BIDIRECTIONAL); 321 + err_put_teedev: 322 + tee_device_put(teedev); 323 + 324 + return ERR_PTR(-ENOMEM); 325 + } 326 + EXPORT_SYMBOL_GPL(tee_shm_alloc_dma_mem); 327 + #else 328 + struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx, 329 + size_t page_count) 330 + { 331 + return ERR_PTR(-EINVAL); 332 + } 333 + EXPORT_SYMBOL_GPL(tee_shm_alloc_dma_mem); 334 + #endif 286 335 287 336 int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t align, 288 337 int (*shm_register)(struct tee_context *ctx,
+5
include/linux/tee_core.h
··· 29 29 #define TEE_SHM_POOL BIT(2) /* Memory allocated from pool */ 30 30 #define TEE_SHM_PRIV BIT(3) /* Memory private to TEE driver */ 31 31 #define TEE_SHM_DMA_BUF BIT(4) /* Memory with dma-buf handle */ 32 + #define TEE_SHM_DMA_MEM BIT(5) /* Memory allocated with */ 33 + /* dma_alloc_pages() */ 32 34 33 35 #define TEE_DEVICE_FLAG_REGISTERED 0x1 34 36 #define TEE_MAX_DEV_NAME_LEN 32 ··· 299 297 * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure 300 298 */ 301 299 struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size); 300 + 301 + struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx, 302 + size_t page_count); 302 303 303 304 int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t align, 304 305 int (*shm_register)(struct tee_context *ctx,