diff options
Diffstat (limited to 'drivers/tee/optee')
| -rw-r--r-- | drivers/tee/optee/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/tee/optee/core.c | 11 | ||||
| -rw-r--r-- | drivers/tee/optee/ffa_abi.c | 55 | ||||
| -rw-r--r-- | drivers/tee/optee/optee_private.h | 4 | ||||
| -rw-r--r-- | drivers/tee/optee/smc_abi.c | 108 |
5 files changed, 53 insertions, 133 deletions
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig index 3ca71e3812ed..f121c224e682 100644 --- a/drivers/tee/optee/Kconfig +++ b/drivers/tee/optee/Kconfig @@ -7,11 +7,3 @@ config OPTEE help This implements the OP-TEE Trusted Execution Environment (TEE) driver. - -config OPTEE_SHM_NUM_PRIV_PAGES - int "Private Shared Memory Pages" - default 1 - depends on OPTEE - help - This sets the number of private shared memory pages to be - used by OP-TEE TEE driver. diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 17a6f51d3089..f4bccb5f0e93 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -18,8 +18,8 @@ #include <linux/workqueue.h> #include "optee_private.h" -int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, - struct tee_shm *shm, size_t size, +int optee_pool_op_alloc_helper(struct tee_shm_pool *pool, struct tee_shm *shm, + size_t size, size_t align, int (*shm_register)(struct tee_context *ctx, struct tee_shm *shm, struct page **pages, @@ -30,6 +30,10 @@ int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, struct page *page; int rc = 0; + /* + * Ignore alignment since this is already going to be page aligned + * and there's no need for any larger alignment. + */ page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); if (!page) return -ENOMEM; @@ -51,7 +55,6 @@ int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, for (i = 0; i < nr_pages; i++) pages[i] = page + i; - shm->flags |= TEE_SHM_REGISTER; rc = shm_register(shm->ctx, shm, pages, nr_pages, (unsigned long)shm->kaddr); kfree(pages); @@ -62,7 +65,7 @@ int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, return 0; err: - __free_pages(page, order); + free_pages((unsigned long)shm->kaddr, order); return rc; } diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index 545f61af1248..91dd80945bf1 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -369,14 +369,14 @@ static int optee_ffa_shm_unregister_supp(struct tee_context *ctx, * The main function is optee_ffa_shm_pool_alloc_pages(). */ -static int pool_ffa_op_alloc(struct tee_shm_pool_mgr *poolm, - struct tee_shm *shm, size_t size) +static int pool_ffa_op_alloc(struct tee_shm_pool *pool, + struct tee_shm *shm, size_t size, size_t align) { - return optee_pool_op_alloc_helper(poolm, shm, size, + return optee_pool_op_alloc_helper(pool, shm, size, align, optee_ffa_shm_register); } -static void pool_ffa_op_free(struct tee_shm_pool_mgr *poolm, +static void pool_ffa_op_free(struct tee_shm_pool *pool, struct tee_shm *shm) { optee_ffa_shm_unregister(shm->ctx, shm); @@ -384,15 +384,15 @@ static void pool_ffa_op_free(struct tee_shm_pool_mgr *poolm, shm->kaddr = NULL; } -static void pool_ffa_op_destroy_poolmgr(struct tee_shm_pool_mgr *poolm) +static void pool_ffa_op_destroy_pool(struct tee_shm_pool *pool) { - kfree(poolm); + kfree(pool); } -static const struct tee_shm_pool_mgr_ops pool_ffa_ops = { +static const struct tee_shm_pool_ops pool_ffa_ops = { .alloc = pool_ffa_op_alloc, .free = pool_ffa_op_free, - .destroy_poolmgr = pool_ffa_op_destroy_poolmgr, + .destroy_pool = pool_ffa_op_destroy_pool, }; /** @@ -401,16 +401,16 @@ static const struct tee_shm_pool_mgr_ops pool_ffa_ops = { * This pool is used with OP-TEE over FF-A. In this case command buffers * and such are allocated from kernel's own memory. */ -static struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void) +static struct tee_shm_pool *optee_ffa_shm_pool_alloc_pages(void) { - struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); + struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL); - if (!mgr) + if (!pool) return ERR_PTR(-ENOMEM); - mgr->ops = &pool_ffa_ops; + pool->ops = &pool_ffa_ops; - return mgr; + return pool; } /* @@ -691,33 +691,6 @@ static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev, return true; } -static struct tee_shm_pool *optee_ffa_config_dyn_shm(void) -{ - struct tee_shm_pool_mgr *priv_mgr; - struct tee_shm_pool_mgr *dmabuf_mgr; - void *rc; - - rc = optee_ffa_shm_pool_alloc_pages(); - if (IS_ERR(rc)) - return rc; - priv_mgr = rc; - - rc = optee_ffa_shm_pool_alloc_pages(); - if (IS_ERR(rc)) { - tee_shm_pool_mgr_destroy(priv_mgr); - return rc; - } - dmabuf_mgr = rc; - - rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); - if (IS_ERR(rc)) { - tee_shm_pool_mgr_destroy(priv_mgr); - tee_shm_pool_mgr_destroy(dmabuf_mgr); - } - - return rc; -} - static void optee_ffa_get_version(struct tee_device *teedev, struct tee_ioctl_version_data *vers) { @@ -815,7 +788,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) if (!optee) return -ENOMEM; - pool = optee_ffa_config_dyn_shm(); + pool = optee_ffa_shm_pool_alloc_pages(); if (IS_ERR(pool)) { rc = PTR_ERR(pool); goto err_free_optee; diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 92bc47bef95f..df3a483bbf46 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -229,8 +229,8 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session); int optee_enumerate_devices(u32 func); void optee_unregister_devices(void); -int optee_pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, - struct tee_shm *shm, size_t size, +int optee_pool_op_alloc_helper(struct tee_shm_pool *pool, struct tee_shm *shm, + size_t size, size_t align, int (*shm_register)(struct tee_context *ctx, struct tee_shm *shm, struct page **pages, diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index bacd1a1d79ee..3dc8cbea1a24 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -42,7 +42,15 @@ * 6. Driver initialization. */ -#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES +/* + * A typical OP-TEE private shm allocation is 224 bytes (argument struct + * with 6 parameters, needed for open session). So with an alignment of 512 + * we'll waste a bit more than 50%. However, it's only expected that we'll + * have a handful of these structs allocated at a time. Most memory will + * be allocated aligned to the page size, So all in all this should scale + * up and down quite well. + */ +#define OPTEE_MIN_STATIC_POOL_ALIGN 9 /* 512 bytes aligned */ /* * 1. Convert between struct tee_param and struct optee_msg_param @@ -532,20 +540,21 @@ static int optee_shm_unregister_supp(struct tee_context *ctx, * The main function is optee_shm_pool_alloc_pages(). */ -static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, - struct tee_shm *shm, size_t size) +static int pool_op_alloc(struct tee_shm_pool *pool, + struct tee_shm *shm, size_t size, size_t align) { /* * Shared memory private to the OP-TEE driver doesn't need * to be registered with OP-TEE. */ if (shm->flags & TEE_SHM_PRIV) - return optee_pool_op_alloc_helper(poolm, shm, size, NULL); + return optee_pool_op_alloc_helper(pool, shm, size, align, NULL); - return optee_pool_op_alloc_helper(poolm, shm, size, optee_shm_register); + return optee_pool_op_alloc_helper(pool, shm, size, align, + optee_shm_register); } -static void pool_op_free(struct tee_shm_pool_mgr *poolm, +static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm) { if (!(shm->flags & TEE_SHM_PRIV)) @@ -555,15 +564,15 @@ static void pool_op_free(struct tee_shm_pool_mgr *poolm, shm->kaddr = NULL; } -static void pool_op_destroy_poolmgr(struct tee_shm_pool_mgr *poolm) +static void pool_op_destroy_pool(struct tee_shm_pool *pool) { - kfree(poolm); + kfree(pool); } -static const struct tee_shm_pool_mgr_ops pool_ops = { +static const struct tee_shm_pool_ops pool_ops = { .alloc = pool_op_alloc, .free = pool_op_free, - .destroy_poolmgr = pool_op_destroy_poolmgr, + .destroy_pool = pool_op_destroy_pool, }; /** @@ -572,16 +581,16 @@ static const struct tee_shm_pool_mgr_ops pool_ops = { * This pool is used when OP-TEE supports dymanic SHM. In this case * command buffers and such are allocated from kernel's own memory. */ -static struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void) +static struct tee_shm_pool *optee_shm_pool_alloc_pages(void) { - struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); + struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL); - if (!mgr) + if (!pool) return ERR_PTR(-ENOMEM); - mgr->ops = &pool_ops; + pool->ops = &pool_ops; - return mgr; + return pool; } /* @@ -1153,33 +1162,6 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, return true; } -static struct tee_shm_pool *optee_config_dyn_shm(void) -{ - struct tee_shm_pool_mgr *priv_mgr; - struct tee_shm_pool_mgr *dmabuf_mgr; - void *rc; - - rc = optee_shm_pool_alloc_pages(); - if (IS_ERR(rc)) - return rc; - priv_mgr = rc; - - rc = optee_shm_pool_alloc_pages(); - if (IS_ERR(rc)) { - tee_shm_pool_mgr_destroy(priv_mgr); - return rc; - } - dmabuf_mgr = rc; - - rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); - if (IS_ERR(rc)) { - tee_shm_pool_mgr_destroy(priv_mgr); - tee_shm_pool_mgr_destroy(dmabuf_mgr); - } - - return rc; -} - static struct tee_shm_pool * optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) { @@ -1193,10 +1175,7 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) phys_addr_t begin; phys_addr_t end; void *va; - struct tee_shm_pool_mgr *priv_mgr; - struct tee_shm_pool_mgr *dmabuf_mgr; void *rc; - const int sz = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc); if (res.result.status != OPTEE_SMC_RETURN_OK) { @@ -1214,11 +1193,6 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) paddr = begin; size = end - begin; - if (size < 2 * OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE) { - pr_err("too small shared memory area\n"); - return ERR_PTR(-EINVAL); - } - va = memremap(paddr, size, MEMREMAP_WB); if (!va) { pr_err("shared memory ioremap failed\n"); @@ -1226,35 +1200,13 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) } vaddr = (unsigned long)va; - rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, sz, - 3 /* 8 bytes aligned */); - if (IS_ERR(rc)) - goto err_memunmap; - priv_mgr = rc; - - vaddr += sz; - paddr += sz; - size -= sz; - - rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, size, PAGE_SHIFT); - if (IS_ERR(rc)) - goto err_free_priv_mgr; - dmabuf_mgr = rc; - - rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); + rc = tee_shm_pool_alloc_res_mem(vaddr, paddr, size, + OPTEE_MIN_STATIC_POOL_ALIGN); if (IS_ERR(rc)) - goto err_free_dmabuf_mgr; - - *memremaped_shm = va; - - return rc; + memunmap(va); + else + *memremaped_shm = va; -err_free_dmabuf_mgr: - tee_shm_pool_mgr_destroy(dmabuf_mgr); -err_free_priv_mgr: - tee_shm_pool_mgr_destroy(priv_mgr); -err_memunmap: - memunmap(va); return rc; } @@ -1376,7 +1328,7 @@ static int optee_probe(struct platform_device *pdev) * Try to use dynamic shared memory if possible */ if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) - pool = optee_config_dyn_shm(); + pool = optee_shm_pool_alloc_pages(); /* * If dynamic shared memory is not available or failed - try static one |
