aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tee/tee_shm_pool.c
diff options
context:
space:
mode:
authorJens Wiklander <jens.wiklander@linaro.org>2022-02-04 10:33:53 +0100
committerJens Wiklander <jens.wiklander@linaro.org>2022-02-16 07:49:41 +0100
commitd88e0493a054c9fe72ade41a42d42e958ee6503d (patch)
treee595be64b33dac3ddbcb27b969e46853f850972c /drivers/tee/tee_shm_pool.c
parenttee: add tee_shm_alloc_user_buf() (diff)
downloadlinux-dev-d88e0493a054c9fe72ade41a42d42e958ee6503d.tar.xz
linux-dev-d88e0493a054c9fe72ade41a42d42e958ee6503d.zip
tee: simplify shm pool handling
Replaces the shared memory pool based on two pools with a single pool. The alloc() function pointer in struct tee_shm_pool_ops gets another parameter, align. This makes it possible to make less than page aligned allocations from the optional reserved shared memory pool while still making user space allocations page aligned. With in practice unchanged behaviour using only a single pool for bookkeeping. The allocation algorithm in the static OP-TEE shared memory pool is changed from best-fit to first-fit since only the latter supports an alignment parameter. The best-fit algorithm was previously the default choice and not a conscious one. The optee and amdtee drivers are updated as needed to work with this changed pool handling. This also removes OPTEE_SHM_NUM_PRIV_PAGES which becomes obsolete with this change as the private pages can be mixed with the payload pages. The OP-TEE driver changes minimum alignment for argument struct from 8 bytes to 512 bytes. 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 well waste a bit more than 50%. Before this we had a single page reserved for this so worst case usage compared to that would be 3 pages instead of 1 page. However, this worst case only occurs if there is a high pressure from multiple threads on secure world. All in all this should scale up and down better than fixed boundaries. Reviewed-by: Sumit Garg <sumit.garg@linaro.org> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'drivers/tee/tee_shm_pool.c')
-rw-r--r--drivers/tee/tee_shm_pool.c106
1 files changed, 34 insertions, 72 deletions
diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
index 54c11aa374a8..71e0f8ae69aa 100644
--- a/drivers/tee/tee_shm_pool.c
+++ b/drivers/tee/tee_shm_pool.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2015 Linaro Limited
+ * Copyright (c) 2015, 2017, 2022 Linaro Limited
*/
#include <linux/device.h>
#include <linux/dma-buf.h>
@@ -9,14 +9,16 @@
#include <linux/tee_drv.h>
#include "tee_private.h"
-static int pool_op_gen_alloc(struct tee_shm_pool_mgr *poolm,
- struct tee_shm *shm, size_t size)
+static int pool_op_gen_alloc(struct tee_shm_pool *pool, struct tee_shm *shm,
+ size_t size, size_t align)
{
unsigned long va;
- struct gen_pool *genpool = poolm->private_data;
- size_t s = roundup(size, 1 << genpool->min_alloc_order);
+ struct gen_pool *genpool = pool->private_data;
+ size_t a = max_t(size_t, align, BIT(genpool->min_alloc_order));
+ struct genpool_data_align data = { .align = a };
+ size_t s = roundup(size, a);
- va = gen_pool_alloc(genpool, s);
+ va = gen_pool_alloc_algo(genpool, s, gen_pool_first_fit_align, &data);
if (!va)
return -ENOMEM;
@@ -24,107 +26,67 @@ static int pool_op_gen_alloc(struct tee_shm_pool_mgr *poolm,
shm->kaddr = (void *)va;
shm->paddr = gen_pool_virt_to_phys(genpool, va);
shm->size = s;
+ /*
+ * This is from a static shared memory pool so no need to register
+ * each chunk, and no need to unregister later either.
+ */
+ shm->flags &= ~TEE_SHM_REGISTER;
return 0;
}
-static void pool_op_gen_free(struct tee_shm_pool_mgr *poolm,
- struct tee_shm *shm)
+static void pool_op_gen_free(struct tee_shm_pool *pool, struct tee_shm *shm)
{
- gen_pool_free(poolm->private_data, (unsigned long)shm->kaddr,
+ gen_pool_free(pool->private_data, (unsigned long)shm->kaddr,
shm->size);
shm->kaddr = NULL;
}
-static void pool_op_gen_destroy_poolmgr(struct tee_shm_pool_mgr *poolm)
+static void pool_op_gen_destroy_pool(struct tee_shm_pool *pool)
{
- gen_pool_destroy(poolm->private_data);
- kfree(poolm);
+ gen_pool_destroy(pool->private_data);
+ kfree(pool);
}
-static const struct tee_shm_pool_mgr_ops pool_ops_generic = {
+static const struct tee_shm_pool_ops pool_ops_generic = {
.alloc = pool_op_gen_alloc,
.free = pool_op_gen_free,
- .destroy_poolmgr = pool_op_gen_destroy_poolmgr,
+ .destroy_pool = pool_op_gen_destroy_pool,
};
-struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr,
- phys_addr_t paddr,
- size_t size,
- int min_alloc_order)
+struct tee_shm_pool *tee_shm_pool_alloc_res_mem(unsigned long vaddr,
+ phys_addr_t paddr, size_t size,
+ int min_alloc_order)
{
const size_t page_mask = PAGE_SIZE - 1;
- struct tee_shm_pool_mgr *mgr;
+ struct tee_shm_pool *pool;
int rc;
/* Start and end must be page aligned */
if (vaddr & page_mask || paddr & page_mask || size & page_mask)
return ERR_PTR(-EINVAL);
- mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
- if (!mgr)
+ pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+ if (!pool)
return ERR_PTR(-ENOMEM);
- mgr->private_data = gen_pool_create(min_alloc_order, -1);
- if (!mgr->private_data) {
+ pool->private_data = gen_pool_create(min_alloc_order, -1);
+ if (!pool->private_data) {
rc = -ENOMEM;
goto err;
}
- gen_pool_set_algo(mgr->private_data, gen_pool_best_fit, NULL);
- rc = gen_pool_add_virt(mgr->private_data, vaddr, paddr, size, -1);
+ rc = gen_pool_add_virt(pool->private_data, vaddr, paddr, size, -1);
if (rc) {
- gen_pool_destroy(mgr->private_data);
+ gen_pool_destroy(pool->private_data);
goto err;
}
- mgr->ops = &pool_ops_generic;
+ pool->ops = &pool_ops_generic;
- return mgr;
+ return pool;
err:
- kfree(mgr);
+ kfree(pool);
return ERR_PTR(rc);
}
-EXPORT_SYMBOL_GPL(tee_shm_pool_mgr_alloc_res_mem);
-
-static bool check_mgr_ops(struct tee_shm_pool_mgr *mgr)
-{
- return mgr && mgr->ops && mgr->ops->alloc && mgr->ops->free &&
- mgr->ops->destroy_poolmgr;
-}
-
-struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr,
- struct tee_shm_pool_mgr *dmabuf_mgr)
-{
- struct tee_shm_pool *pool;
-
- if (!check_mgr_ops(priv_mgr) || !check_mgr_ops(dmabuf_mgr))
- return ERR_PTR(-EINVAL);
-
- pool = kzalloc(sizeof(*pool), GFP_KERNEL);
- if (!pool)
- return ERR_PTR(-ENOMEM);
-
- pool->private_mgr = priv_mgr;
- pool->dma_buf_mgr = dmabuf_mgr;
-
- return pool;
-}
-EXPORT_SYMBOL_GPL(tee_shm_pool_alloc);
-
-/**
- * tee_shm_pool_free() - Free a shared memory pool
- * @pool: The shared memory pool to free
- *
- * There must be no remaining shared memory allocated from this pool when
- * this function is called.
- */
-void tee_shm_pool_free(struct tee_shm_pool *pool)
-{
- if (pool->private_mgr)
- tee_shm_pool_mgr_destroy(pool->private_mgr);
- if (pool->dma_buf_mgr)
- tee_shm_pool_mgr_destroy(pool->dma_buf_mgr);
- kfree(pool);
-}
-EXPORT_SYMBOL_GPL(tee_shm_pool_free);
+EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem);