^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2015, Linaro Limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2017, EPAM Systems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/dma-buf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/genalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/tee_drv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "optee_private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "optee_smc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "shm_pool.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct tee_shm *shm, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned int order = get_order(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) shm->kaddr = page_address(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) shm->paddr = page_to_phys(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) shm->size = PAGE_SIZE << order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Shared memory private to the OP-TEE driver doesn't need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * to be registered with OP-TEE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (!(shm->flags & TEE_SHM_PRIV)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned int nr_pages = 1 << order, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct page **pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) pages = kcalloc(nr_pages, sizeof(pages), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (!pages) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) for (i = 0; i < nr_pages; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) pages[i] = page + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) shm->flags |= TEE_SHM_REGISTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) rc = optee_shm_register(shm->ctx, shm, pages, nr_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) (unsigned long)shm->kaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) kfree(pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) __free_pages(page, order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static void pool_op_free(struct tee_shm_pool_mgr *poolm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct tee_shm *shm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!(shm->flags & TEE_SHM_PRIV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) optee_shm_unregister(shm->ctx, shm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) free_pages((unsigned long)shm->kaddr, get_order(shm->size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) shm->kaddr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static void pool_op_destroy_poolmgr(struct tee_shm_pool_mgr *poolm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) kfree(poolm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static const struct tee_shm_pool_mgr_ops pool_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .alloc = pool_op_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .free = pool_op_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .destroy_poolmgr = pool_op_destroy_poolmgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * optee_shm_pool_alloc_pages() - create page-based allocator pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * This pool is used when OP-TEE supports dymanic SHM. In this case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * command buffers and such are allocated from kernel's own memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (!mgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) mgr->ops = &pool_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }