2022-01-14 21:35:27

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 00/12] tee: shared memory updates

Hi all,

This patchset is a general cleanup of shared memory handling in the TEE
subsystem.

Until now has the in-kernel tee clients used tee_shm_alloc() and
tee_shm_register() to share memory with secure world. These two function
exposes via a flags parameter a bit more of the internals of the TEE
subsystem than one would like. So in order to make things easier are those
two functions replaced by few functions which should provide better
abstraction.

Two in-kernel tee clients are updated to use these new functions.

The shared memory pool handling is simplified, an internal matter for the
two TEE drivers OP-TEE and AMDTEE.

An OP-TEE driver internal tee_context is added to handle shared memory
allocations received via RPC, for instance the argument structure needed
to make more complex RPC requests. The tee_context used when doing such a
memory allocation must be kept until the memory is freed. With this we can
avoid keeping a tee_context of a client around for longer than necessary.

In the v1 review it was suggested [1] to allow physically non-contiguous
memory allocations by the drivers. It turned out to be harder than
anticipated so I'll save that for a separate patch.

This patchset is also available at [2] and is based on the asynchronous
notification patches [3] which was just merged during this merge window.

Thanks,
Jens

[1] https://lore.kernel.org/linux-arm-kernel/20210609145811.GJ4910@sequoia/
[2] https://git.linaro.org/people/jens.wiklander/linux-tee.git/log/?h=tee_shm_v2
[3] https://git.linaro.org/people/jens.wiklander/linux-tee.git/log/?h=async_notif

v1->v2:
* The commits three "tee: add tee_shm_alloc_kernel_buf()",
"tpm_ftpm_tee: use tee_shm_alloc_kernel_buf()" and
"firmware: tee_bnxt: use tee_shm_alloc_kernel_buf()" has been merged some
time ago as part of another patchset.
* Another in-kernel tee client is updated with the commit
"KEYS: trusted: tee: use tee_shm_register_kernel_buf()"
* tee_shm_alloc_anon_kernel_buf() is replaced with an easier to use function
tee_shm_alloc_priv_kernel_buf() and tee_shm_free_anon_kernel_buf() has
been dropped.
* A driver internal struct tee_context is used to when doing driver internal
calls to secure world.
* Adds patches to replace tee_shm_register() in a similar way as how
tee_shm_alloc() is replaced.
* A patch is added to clean up the TEE_SHM_* flags
* Fixed a warning reported by kernel test robot <[email protected]>

Jens Wiklander (12):
hwrng: optee-rng: use tee_shm_alloc_kernel_buf()
tee: remove unused tee_shm_pool_alloc_res_mem()
tee: add tee_shm_alloc_user_buf()
tee: simplify shm pool handling
tee: replace tee_shm_alloc()
optee: add driver private tee_context
optee: use driver internal tee_contex for some rpc
optee: add optee_pool_op_free_helper()
tee: add tee_shm_register_{user,kernel}_buf()
KEYS: trusted: tee: use tee_shm_register_kernel_buf()
tee: replace tee_shm_register()
tee: refactor TEE_SHM_* flags

drivers/char/hw_random/optee-rng.c | 6 +-
drivers/tee/amdtee/shm_pool.c | 55 ++--
drivers/tee/optee/Kconfig | 8 -
drivers/tee/optee/call.c | 2 +-
drivers/tee/optee/core.c | 22 +-
drivers/tee/optee/device.c | 5 +-
drivers/tee/optee/ffa_abi.c | 136 ++++------
drivers/tee/optee/optee_private.h | 12 +-
drivers/tee/optee/smc_abi.c | 155 +++--------
drivers/tee/tee_core.c | 5 +-
drivers/tee/tee_private.h | 11 -
drivers/tee/tee_shm.c | 322 +++++++++++++++--------
drivers/tee/tee_shm_pool.c | 162 +++---------
include/linux/tee_drv.h | 133 +++-------
security/keys/trusted-keys/trusted_tee.c | 23 +-
15 files changed, 434 insertions(+), 623 deletions(-)

--
2.31.1


2022-01-14 21:36:13

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 02/12] tee: remove unused tee_shm_pool_alloc_res_mem()

None of the drivers in the TEE subsystem uses
tee_shm_pool_alloc_res_mem() so remove the function.

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/tee/tee_shm_pool.c | 56 --------------------------------------
include/linux/tee_drv.h | 30 --------------------
2 files changed, 86 deletions(-)

diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
index fcbb461fc59c..a9f9d50fd181 100644
--- a/drivers/tee/tee_shm_pool.c
+++ b/drivers/tee/tee_shm_pool.c
@@ -47,62 +47,6 @@ static const struct tee_shm_pool_mgr_ops pool_ops_generic = {
.destroy_poolmgr = pool_op_gen_destroy_poolmgr,
};

-/**
- * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved
- * memory range
- * @priv_info: Information for driver private shared memory pool
- * @dmabuf_info: Information for dma-buf shared memory pool
- *
- * Start and end of pools will must be page aligned.
- *
- * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
- * in @dmabuf, others will use the range provided by @priv.
- *
- * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
- */
-struct tee_shm_pool *
-tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info,
- struct tee_shm_pool_mem_info *dmabuf_info)
-{
- struct tee_shm_pool_mgr *priv_mgr;
- struct tee_shm_pool_mgr *dmabuf_mgr;
- void *rc;
-
- /*
- * Create the pool for driver private shared memory
- */
- rc = tee_shm_pool_mgr_alloc_res_mem(priv_info->vaddr, priv_info->paddr,
- priv_info->size,
- 3 /* 8 byte aligned */);
- if (IS_ERR(rc))
- return rc;
- priv_mgr = rc;
-
- /*
- * Create the pool for dma_buf shared memory
- */
- rc = tee_shm_pool_mgr_alloc_res_mem(dmabuf_info->vaddr,
- dmabuf_info->paddr,
- dmabuf_info->size, PAGE_SHIFT);
- if (IS_ERR(rc))
- goto err_free_priv_mgr;
- dmabuf_mgr = rc;
-
- rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
- if (IS_ERR(rc))
- goto err_free_dmabuf_mgr;
-
- return rc;
-
-err_free_dmabuf_mgr:
- tee_shm_pool_mgr_destroy(dmabuf_mgr);
-err_free_priv_mgr:
- tee_shm_pool_mgr_destroy(priv_mgr);
-
- return rc;
-}
-EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem);
-
struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr,
phys_addr_t paddr,
size_t size,
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index 5e1533ee3785..6b0f0d01ebdf 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -278,36 +278,6 @@ static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
poolm->ops->destroy_poolmgr(poolm);
}

-/**
- * struct tee_shm_pool_mem_info - holds information needed to create a shared
- * memory pool
- * @vaddr: Virtual address of start of pool
- * @paddr: Physical address of start of pool
- * @size: Size in bytes of the pool
- */
-struct tee_shm_pool_mem_info {
- unsigned long vaddr;
- phys_addr_t paddr;
- size_t size;
-};
-
-/**
- * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved
- * memory range
- * @priv_info: Information for driver private shared memory pool
- * @dmabuf_info: Information for dma-buf shared memory pool
- *
- * Start and end of pools will must be page aligned.
- *
- * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
- * in @dmabuf, others will use the range provided by @priv.
- *
- * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
- */
-struct tee_shm_pool *
-tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info,
- struct tee_shm_pool_mem_info *dmabuf_info);
-
/**
* tee_shm_pool_free() - Free a shared memory pool
* @pool: The shared memory pool to free
--
2.31.1

2022-01-14 21:36:32

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 03/12] tee: add tee_shm_alloc_user_buf()

Adds a new function tee_shm_alloc_user_buf() or user mode allocations,
replacing passing the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF to
tee_shm_alloc().

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/tee/tee_core.c | 2 +-
drivers/tee/tee_shm.c | 18 ++++++++++++++++++
drivers/tee/tee_shm_pool.c | 2 +-
include/linux/tee_drv.h | 3 ++-
4 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index 3fc426dad2df..a15812baaeb1 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -297,7 +297,7 @@ static int tee_ioctl_shm_alloc(struct tee_context *ctx,
if (data.flags)
return -EINVAL;

- shm = tee_shm_alloc(ctx, data.size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+ shm = tee_shm_alloc_user_buf(ctx, data.size);
if (IS_ERR(shm))
return PTR_ERR(shm);

diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index 499fccba3d74..b43178986985 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -127,6 +127,24 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
}
EXPORT_SYMBOL_GPL(tee_shm_alloc);

+/**
+ * tee_shm_alloc_user_buf() - Allocate shared memory for user space
+ * @ctx: Context that allocates the shared memory
+ * @size: Requested size of shared memory
+ *
+ * Memory allocated as user space shared memory is automatically freed when
+ * the TEE file pointer is closed. The primary usage of this function is
+ * when the TEE driver doesn't support registering ordinary user space
+ * memory.
+ *
+ * @returns a pointer to 'struct tee_shm'
+ */
+struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
+{
+ return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+}
+EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
+
/**
* tee_shm_alloc_kernel_buf() - Allocate shared memory for kernel buffer
* @ctx: Context that allocates the shared memory
diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
index a9f9d50fd181..0e460347138a 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>
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index 6b0f0d01ebdf..26b450484ac1 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2015-2016, Linaro Limited
+ * Copyright (c) 2015-2022 Linaro Limited
*/

#ifndef __TEE_DRV_H
@@ -308,6 +308,7 @@ void *tee_get_drvdata(struct tee_device *teedev);
* @returns a pointer to 'struct tee_shm'
*/
struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
+struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);

/**
--
2.31.1

2022-01-14 21:36:35

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 05/12] tee: replace tee_shm_alloc()

tee_shm_alloc() is replaced by three new functions,

tee_shm_alloc_user_buf() - for user mode allocations, replacing passing
the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF

tee_shm_alloc_kernel_buf() - for kernel mode allocations, slightly
optimized compared to using the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF.

tee_shm_alloc_priv_kernel_buf() - primarily for TEE driver internal use.

This also makes the interface easier to use as we can get rid of the
somewhat hard to use flags parameter.

The TEE subsystem and the TEE drivers are updated to use the new
functions instead.

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/tee/optee/call.c | 2 +-
drivers/tee/optee/device.c | 5 +-
drivers/tee/optee/ffa_abi.c | 4 +-
drivers/tee/optee/smc_abi.c | 5 +-
drivers/tee/tee_shm.c | 109 +++++++++++++++++++++++-------------
include/linux/tee_drv.h | 17 +-----
6 files changed, 78 insertions(+), 64 deletions(-)

diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
index b25cc1fac945..fd6ad7d6fbee 100644
--- a/drivers/tee/optee/call.c
+++ b/drivers/tee/optee/call.c
@@ -120,7 +120,7 @@ struct tee_shm *optee_get_msg_arg(struct tee_context *ctx, size_t num_params,
if (optee->rpc_arg_count)
sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count);

- shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
+ shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
if (IS_ERR(shm))
return shm;

diff --git a/drivers/tee/optee/device.c b/drivers/tee/optee/device.c
index 128a2d2a50a1..f3947be13e2e 100644
--- a/drivers/tee/optee/device.c
+++ b/drivers/tee/optee/device.c
@@ -121,10 +121,9 @@ static int __optee_enumerate_devices(u32 func)
if (rc < 0 || !shm_size)
goto out_sess;

- device_shm = tee_shm_alloc(ctx, shm_size,
- TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+ device_shm = tee_shm_alloc_kernel_buf(ctx, shm_size);
if (IS_ERR(device_shm)) {
- pr_err("tee_shm_alloc failed\n");
+ pr_err("tee_shm_alloc_kernel_buf failed\n");
rc = PTR_ERR(device_shm);
goto out_sess;
}
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index e690d9420966..18963f7e4d48 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -439,8 +439,8 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
break;
case OPTEE_RPC_SHM_TYPE_KERNEL:
- shm = tee_shm_alloc(ctx, arg->params[0].u.value.b,
- TEE_SHM_MAPPED | TEE_SHM_PRIV);
+ shm = tee_shm_alloc_priv_kernel_buf(ctx,
+ arg->params[0].u.value.b);
break;
default:
arg->ret = TEEC_ERROR_BAD_PARAMETERS;
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index b679037ea794..196cd4316d7d 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -650,7 +650,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
break;
case OPTEE_RPC_SHM_TYPE_KERNEL:
- shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
+ shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
break;
default:
arg->ret = TEEC_ERROR_BAD_PARAMETERS;
@@ -775,8 +775,7 @@ static void optee_handle_rpc(struct tee_context *ctx,

switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
case OPTEE_SMC_RPC_FUNC_ALLOC:
- shm = tee_shm_alloc(ctx, param->a1,
- TEE_SHM_MAPPED | TEE_SHM_PRIV);
+ shm = tee_shm_alloc_priv_kernel_buf(ctx, param->a1);
if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
reg_pair_from_64(&param->a1, &param->a2, pa);
reg_pair_from_64(&param->a4, &param->a5,
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index 2c8ce0c6801a..d51bf97ce7e5 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -49,25 +49,14 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
tee_device_put(teedev);
}

-struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
+static struct tee_shm *shm_alloc_helper(struct tee_context *ctx, size_t size,
+ size_t align, u32 flags, int id)
{
struct tee_device *teedev = ctx->teedev;
struct tee_shm *shm;
- size_t align;
void *ret;
int rc;

- if (!(flags & TEE_SHM_MAPPED)) {
- dev_err(teedev->dev.parent,
- "only mapped allocations supported\n");
- return ERR_PTR(-EINVAL);
- }
-
- if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_PRIV))) {
- dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags);
- return ERR_PTR(-EINVAL);
- }
-
if (!tee_device_get(teedev))
return ERR_PTR(-EINVAL);

@@ -84,18 +73,16 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
}

refcount_set(&shm->refcount, 1);
- shm->flags = flags | TEE_SHM_POOL;
+ shm->flags = flags;
+ shm->id = id;
+
+ /*
+ * We're assigning this as it is needed if the shm is to be
+ * registered. If this function returns OK then the caller expected
+ * to call teedev_ctx_get() or clear shm->ctx in case it's not
+ * needed any longer.
+ */
shm->ctx = ctx;
- if (flags & TEE_SHM_DMA_BUF) {
- align = PAGE_SIZE;
- /*
- * Request to register the shm in the pool allocator below
- * if supported.
- */
- shm->flags |= TEE_SHM_REGISTER;
- } else {
- align = 2 * sizeof(long);
- }

rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
if (rc) {
@@ -103,28 +90,14 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
goto err_kfree;
}

- if (flags & TEE_SHM_DMA_BUF) {
- mutex_lock(&teedev->mutex);
- shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
- mutex_unlock(&teedev->mutex);
- if (shm->id < 0) {
- ret = ERR_PTR(shm->id);
- goto err_pool_free;
- }
- }
-
teedev_ctx_get(ctx);
-
return shm;
-err_pool_free:
- teedev->pool->ops->free(teedev->pool, shm);
err_kfree:
kfree(shm);
err_dev_put:
tee_device_put(teedev);
return ret;
}
-EXPORT_SYMBOL_GPL(tee_shm_alloc);

/**
* tee_shm_alloc_user_buf() - Allocate shared memory for user space
@@ -140,7 +113,36 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc);
*/
struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
{
- return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+ u32 flags = TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_REGISTER |
+ TEE_SHM_POOL;
+ struct tee_device *teedev = ctx->teedev;
+ struct tee_shm *shm;
+ void *ret;
+ int id;
+
+ mutex_lock(&teedev->mutex);
+ id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL);
+ mutex_unlock(&teedev->mutex);
+ if (id < 0)
+ return ERR_PTR(id);
+
+ shm = shm_alloc_helper(ctx, size, PAGE_SIZE, flags, id);
+ if (IS_ERR(shm)) {
+ mutex_lock(&teedev->mutex);
+ idr_remove(&teedev->idr, id);
+ mutex_unlock(&teedev->mutex);
+ return shm;
+ }
+
+ mutex_lock(&teedev->mutex);
+ ret = idr_replace(&teedev->idr, shm, id);
+ mutex_unlock(&teedev->mutex);
+ if (IS_ERR(ret)) {
+ tee_shm_free(shm);
+ return ret;
+ }
+
+ return shm;
}
EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);

@@ -158,10 +160,37 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
*/
struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
{
- return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED);
+ u32 flags = TEE_SHM_MAPPED | TEE_SHM_REGISTER | TEE_SHM_POOL;
+
+ return shm_alloc_helper(ctx, size, PAGE_SIZE, flags, -1);
}
EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);

+/**
+ * tee_shm_alloc_priv_kernel_buf() - Allocate shared memory for a privatly
+ * shared kernel buffer
+ * @ctx: Context that allocates the shared memory
+ * @size: Requested size of shared memory
+ *
+ * This function returns similar shared memory as
+ * tee_shm_alloc_kernel_buf(), but with the difference that the memory
+ * might not be registered in secure world in case the driver supports
+ * passing memory not registered in advance.
+ *
+ * This function should normally only be used internally in the TEE
+ * drivers.
+ *
+ * @returns a pointer to 'struct tee_shm'
+ */
+struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
+ size_t size)
+{
+ u32 flags = TEE_SHM_MAPPED | TEE_SHM_PRIV | TEE_SHM_POOL;
+
+ return shm_alloc_helper(ctx, size, sizeof(long) * 2, flags, -1);
+}
+EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_kernel_buf);
+
struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
size_t length, u32 flags)
{
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index 808aa23308c2..e71cb0411e9c 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -273,22 +273,9 @@ static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
*/
void *tee_get_drvdata(struct tee_device *teedev);

-/**
- * tee_shm_alloc() - Allocate shared memory
- * @ctx: Context that allocates the shared memory
- * @size: Requested size of shared memory
- * @flags: Flags setting properties for the requested shared memory.
- *
- * Memory allocated as global shared memory is automatically freed when the
- * TEE file pointer is closed. The @flags field uses the bits defined by
- * TEE_SHM_* above. TEE_SHM_MAPPED must currently always be set. If
- * TEE_SHM_DMA_BUF global shared memory will be allocated and associated
- * with a dma-buf handle, else driver private memory.
- *
- * @returns a pointer to 'struct tee_shm'
- */
-struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
+struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
+ size_t size);
struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);

/**
--
2.31.1

2022-01-14 21:36:50

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 04/12] 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 concious 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.

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/tee/amdtee/shm_pool.c | 55 +++++-----------
drivers/tee/optee/Kconfig | 8 ---
drivers/tee/optee/core.c | 11 ++--
drivers/tee/optee/ffa_abi.c | 55 ++++------------
drivers/tee/optee/optee_private.h | 4 +-
drivers/tee/optee/smc_abi.c | 100 ++++++----------------------
drivers/tee/tee_private.h | 11 ----
drivers/tee/tee_shm.c | 29 ++++-----
drivers/tee/tee_shm_pool.c | 104 ++++++++++--------------------
include/linux/tee_drv.h | 58 ++++++-----------
10 files changed, 126 insertions(+), 309 deletions(-)

diff --git a/drivers/tee/amdtee/shm_pool.c b/drivers/tee/amdtee/shm_pool.c
index 065854e2db18..f87f96a291c9 100644
--- a/drivers/tee/amdtee/shm_pool.c
+++ b/drivers/tee/amdtee/shm_pool.c
@@ -8,13 +8,17 @@
#include <linux/psp-sev.h>
#include "amdtee_private.h"

-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)
{
unsigned int order = get_order(size);
unsigned long va;
int rc;

+ /*
+ * Ignore alignment since this is already going to be page aligned
+ * and there's no need for any larger alignment.
+ */
va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
if (!va)
return -ENOMEM;
@@ -34,7 +38,7 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm,
return 0;
}

-static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
+static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm)
{
/* Unmap the shared memory from TEE */
amdtee_unmap_shmem(shm);
@@ -42,52 +46,25 @@ static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
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,
};

-static struct tee_shm_pool_mgr *pool_mem_mgr_alloc(void)
-{
- struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
-
- if (!mgr)
- return ERR_PTR(-ENOMEM);
-
- mgr->ops = &pool_ops;
-
- return mgr;
-}
-
struct tee_shm_pool *amdtee_config_shm(void)
{
- struct tee_shm_pool_mgr *priv_mgr;
- struct tee_shm_pool_mgr *dmabuf_mgr;
- void *rc;
+ struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL);

- rc = pool_mem_mgr_alloc();
- if (IS_ERR(rc))
- return rc;
- priv_mgr = rc;
-
- rc = pool_mem_mgr_alloc();
- if (IS_ERR(rc)) {
- tee_shm_pool_mgr_destroy(priv_mgr);
- return rc;
- }
- dmabuf_mgr = rc;
+ if (!pool)
+ return ERR_PTR(-ENOMEM);

- 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);
- }
+ pool->ops = &pool_ops;

- return rc;
+ return pool;
}
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 1ca320885fad..2a369e346b85 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 20a1b1a3d965..e690d9420966 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)
{
@@ -813,7 +786,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
if (!optee)
return -ENOMEM;

- optee->pool = optee_ffa_config_dyn_shm();
+ optee->pool = optee_ffa_shm_pool_alloc_pages();
if (IS_ERR(optee->pool)) {
rc = PTR_ERR(optee->pool);
optee->pool = NULL;
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index 46f74ab07c7e..df2450921464 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -228,8 +228,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 449d6a72d289..b679037ea794 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -42,8 +42,6 @@
* 6. Driver initialization.
*/

-#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
-
/*
* 1. Convert between struct tee_param and struct optee_msg_param
*
@@ -532,20 +530,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 +554,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 +571,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;
}

/*
@@ -1174,33 +1173,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)
{
@@ -1214,10 +1186,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) {
@@ -1235,11 +1204,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");
@@ -1247,35 +1211,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);
+ rc = tee_shm_pool_alloc_res_mem(vaddr, paddr, size,
+ 9 /* 512 bytes aligned */);
if (IS_ERR(rc))
- goto err_free_priv_mgr;
- dmabuf_mgr = rc;
-
- rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
- 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;
}

@@ -1396,7 +1338,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
diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
index e55204df31ce..72376cf38bc0 100644
--- a/drivers/tee/tee_private.h
+++ b/drivers/tee/tee_private.h
@@ -12,17 +12,6 @@
#include <linux/mutex.h>
#include <linux/types.h>

-/**
- * struct tee_shm_pool - shared memory pool
- * @private_mgr: pool manager for shared memory only between kernel
- * and secure world
- * @dma_buf_mgr: pool manager for shared memory exported to user space
- */
-struct tee_shm_pool {
- struct tee_shm_pool_mgr *private_mgr;
- struct tee_shm_pool_mgr *dma_buf_mgr;
-};
-
#define TEE_DEVICE_FLAG_REGISTERED 0x1
#define TEE_MAX_DEV_NAME_LEN 32

diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index b43178986985..2c8ce0c6801a 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -31,14 +31,7 @@ static void release_registered_pages(struct tee_shm *shm)
static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
{
if (shm->flags & TEE_SHM_POOL) {
- struct tee_shm_pool_mgr *poolm;
-
- if (shm->flags & TEE_SHM_DMA_BUF)
- poolm = teedev->pool->dma_buf_mgr;
- else
- poolm = teedev->pool->private_mgr;
-
- poolm->ops->free(poolm, shm);
+ teedev->pool->ops->free(teedev->pool, shm);
} else if (shm->flags & TEE_SHM_REGISTER) {
int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);

@@ -59,8 +52,8 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
{
struct tee_device *teedev = ctx->teedev;
- struct tee_shm_pool_mgr *poolm = NULL;
struct tee_shm *shm;
+ size_t align;
void *ret;
int rc;

@@ -93,12 +86,18 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
refcount_set(&shm->refcount, 1);
shm->flags = flags | TEE_SHM_POOL;
shm->ctx = ctx;
- if (flags & TEE_SHM_DMA_BUF)
- poolm = teedev->pool->dma_buf_mgr;
- else
- poolm = teedev->pool->private_mgr;
+ if (flags & TEE_SHM_DMA_BUF) {
+ align = PAGE_SIZE;
+ /*
+ * Request to register the shm in the pool allocator below
+ * if supported.
+ */
+ shm->flags |= TEE_SHM_REGISTER;
+ } else {
+ align = 2 * sizeof(long);
+ }

- rc = poolm->ops->alloc(poolm, shm, size);
+ rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
if (rc) {
ret = ERR_PTR(rc);
goto err_kfree;
@@ -118,7 +117,7 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)

return shm;
err_pool_free:
- poolm->ops->free(poolm, shm);
+ teedev->pool->ops->free(teedev->pool, shm);
err_kfree:
kfree(shm);
err_dev_put:
diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
index 0e460347138a..71e0f8ae69aa 100644
--- a/drivers/tee/tee_shm_pool.c
+++ b/drivers/tee/tee_shm_pool.c
@@ -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);
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index 26b450484ac1..808aa23308c2 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -221,62 +221,39 @@ struct tee_shm {
};

/**
- * struct tee_shm_pool_mgr - shared memory manager
+ * struct tee_shm_pool - shared memory pool
* @ops: operations
* @private_data: private data for the shared memory manager
*/
-struct tee_shm_pool_mgr {
- const struct tee_shm_pool_mgr_ops *ops;
+struct tee_shm_pool {
+ const struct tee_shm_pool_ops *ops;
void *private_data;
};

/**
- * struct tee_shm_pool_mgr_ops - shared memory pool manager operations
+ * struct tee_shm_pool_ops - shared memory pool operations
* @alloc: called when allocating shared memory
* @free: called when freeing shared memory
- * @destroy_poolmgr: called when destroying the pool manager
+ * @destroy_pool: called when destroying the pool
*/
-struct tee_shm_pool_mgr_ops {
- int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm,
- size_t size);
- void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm);
- void (*destroy_poolmgr)(struct tee_shm_pool_mgr *poolmgr);
+struct tee_shm_pool_ops {
+ int (*alloc)(struct tee_shm_pool *pool, struct tee_shm *shm,
+ size_t size, size_t align);
+ void (*free)(struct tee_shm_pool *pool, struct tee_shm *shm);
+ void (*destroy_pool)(struct tee_shm_pool *pool);
};

-/**
- * tee_shm_pool_alloc() - Create a shared memory pool from shm managers
- * @priv_mgr: manager for driver private shared memory allocations
- * @dmabuf_mgr: manager for dma-buf shared memory allocations
- *
- * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
- * in @dmabuf, others will use the range provided by @priv.
- *
- * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
- */
-struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr,
- struct tee_shm_pool_mgr *dmabuf_mgr);
-
/*
- * tee_shm_pool_mgr_alloc_res_mem() - Create a shm manager for reserved
- * memory
+ * tee_shm_pool_alloc_res_mem() - Create a shm manager for reserved memory
* @vaddr: Virtual address of start of pool
* @paddr: Physical address of start of pool
* @size: Size in bytes of the pool
*
- * @returns pointer to a 'struct tee_shm_pool_mgr' or an ERR_PTR on failure.
- */
-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);
-
-/**
- * tee_shm_pool_mgr_destroy() - Free a shared memory manager
+ * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
*/
-static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
-{
- poolm->ops->destroy_poolmgr(poolm);
-}
+struct tee_shm_pool *tee_shm_pool_alloc_res_mem(unsigned long vaddr,
+ phys_addr_t paddr, size_t size,
+ int min_alloc_order);

/**
* tee_shm_pool_free() - Free a shared memory pool
@@ -285,7 +262,10 @@ static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
* The 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);
+static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
+{
+ pool->ops->destroy_pool(pool);
+}

/**
* tee_get_drvdata() - Return driver_data pointer
--
2.31.1

2022-01-14 21:36:52

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 01/12] hwrng: optee-rng: use tee_shm_alloc_kernel_buf()

Uses the new simplified tee_shm_alloc_kernel_buf() function instead of
the old deprecated tee_shm_alloc() function which required specific
TEE_SHM-flags.

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/char/hw_random/optee-rng.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/char/hw_random/optee-rng.c b/drivers/char/hw_random/optee-rng.c
index 135a82590923..a948c0727b2b 100644
--- a/drivers/char/hw_random/optee-rng.c
+++ b/drivers/char/hw_random/optee-rng.c
@@ -145,10 +145,10 @@ static int optee_rng_init(struct hwrng *rng)
struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
struct tee_shm *entropy_shm_pool = NULL;

- entropy_shm_pool = tee_shm_alloc(pvt_data->ctx, MAX_ENTROPY_REQ_SZ,
- TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+ entropy_shm_pool = tee_shm_alloc_kernel_buf(pvt_data->ctx,
+ MAX_ENTROPY_REQ_SZ);
if (IS_ERR(entropy_shm_pool)) {
- dev_err(pvt_data->dev, "tee_shm_alloc failed\n");
+ dev_err(pvt_data->dev, "tee_shm_alloc_kernel_buf failed\n");
return PTR_ERR(entropy_shm_pool);
}

--
2.31.1

2022-01-14 21:37:05

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 06/12] optee: add driver private tee_context

Adds a driver private tee_context by moving the tee_context in struct
optee_notif to struct optee. This tee_context is used when doing
internal calls to secure world to deliver notification and later also
when sharing driver private memory with secure world.

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/tee/optee/core.c | 1 +
drivers/tee/optee/ffa_abi.c | 61 ++++++++++++++++++-------------
drivers/tee/optee/optee_private.h | 5 ++-
drivers/tee/optee/smc_abi.c | 40 ++++++--------------
4 files changed, 51 insertions(+), 56 deletions(-)

diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index 2a369e346b85..f4bccb5f0e93 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -161,6 +161,7 @@ void optee_remove_common(struct optee *optee)
optee_unregister_devices();

optee_notif_uninit(optee);
+ teedev_close_context(optee->ctx);
/*
* The two devices have to be unregistered before we can free the
* other resources.
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 18963f7e4d48..88a028d4fb7b 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -766,7 +766,9 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
{
const struct ffa_dev_ops *ffa_ops;
unsigned int rpc_arg_count;
+ struct tee_shm_pool *pool;
struct tee_device *teedev;
+ struct tee_context *ctx;
struct optee *optee;
int rc;

@@ -786,12 +788,12 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
if (!optee)
return -ENOMEM;

- optee->pool = optee_ffa_shm_pool_alloc_pages();
- if (IS_ERR(optee->pool)) {
- rc = PTR_ERR(optee->pool);
- optee->pool = NULL;
- goto err;
+ pool = optee_ffa_shm_pool_alloc_pages();
+ if (IS_ERR(pool)) {
+ rc = PTR_ERR(pool);
+ goto err_free_optee;
}
+ optee->pool = pool;

optee->ops = &optee_ffa_ops;
optee->ffa.ffa_dev = ffa_dev;
@@ -802,7 +804,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
optee);
if (IS_ERR(teedev)) {
rc = PTR_ERR(teedev);
- goto err;
+ goto err_free_pool;
}
optee->teedev = teedev;

@@ -810,50 +812,57 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
optee);
if (IS_ERR(teedev)) {
rc = PTR_ERR(teedev);
- goto err;
+ goto err_unreg_teedev;
}
optee->supp_teedev = teedev;

rc = tee_device_register(optee->teedev);
if (rc)
- goto err;
+ goto err_unreg_supp_teedev;

rc = tee_device_register(optee->supp_teedev);
if (rc)
- goto err;
+ goto err_unreg_supp_teedev;

rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
if (rc)
- goto err;
+ goto err_unreg_supp_teedev;
mutex_init(&optee->ffa.mutex);
mutex_init(&optee->call_queue.mutex);
INIT_LIST_HEAD(&optee->call_queue.waiters);
optee_supp_init(&optee->supp);
ffa_dev_set_drvdata(ffa_dev, optee);
+ ctx = teedev_open(optee->teedev);
+ if (IS_ERR(ctx))
+ goto err_rhashtable_free;
+ optee->ctx = ctx;
rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE);
- if (rc) {
- optee_ffa_remove(ffa_dev);
- return rc;
- }
+ if (rc)
+ goto err_close_ctx;

rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
- if (rc) {
- optee_ffa_remove(ffa_dev);
- return rc;
- }
+ if (rc)
+ goto err_unregister_devices;

pr_info("initialized driver\n");
return 0;
-err:
- /*
- * tee_device_unregister() is safe to call even if the
- * devices hasn't been registered with
- * tee_device_register() yet.
- */
+
+err_unregister_devices:
+ optee_unregister_devices();
+ optee_notif_uninit(optee);
+err_close_ctx:
+ teedev_close_context(ctx);
+err_rhashtable_free:
+ rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL);
+ optee_supp_uninit(&optee->supp);
+ mutex_destroy(&optee->call_queue.mutex);
+err_unreg_supp_teedev:
tee_device_unregister(optee->supp_teedev);
+err_unreg_teedev:
tee_device_unregister(optee->teedev);
- if (optee->pool)
- tee_shm_pool_free(optee->pool);
+err_free_pool:
+ tee_shm_pool_free(pool);
+err_free_optee:
kfree(optee);
return rc;
}
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index df2450921464..df3a483bbf46 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -53,7 +53,6 @@ struct optee_call_queue {

struct optee_notif {
u_int max_key;
- struct tee_context *ctx;
/* Serializes access to the elements below in this struct */
spinlock_t lock;
struct list_head db;
@@ -134,9 +133,10 @@ struct optee_ops {
/**
* struct optee - main service struct
* @supp_teedev: supplicant device
+ * @teedev: client device
* @ops: internal callbacks for different ways to reach secure
* world
- * @teedev: client device
+ * @ctx: driver internal TEE context
* @smc: specific to SMC ABI
* @ffa: specific to FF-A ABI
* @call_queue: queue of threads waiting to call @invoke_fn
@@ -152,6 +152,7 @@ struct optee {
struct tee_device *supp_teedev;
struct tee_device *teedev;
const struct optee_ops *ops;
+ struct tee_context *ctx;
union {
struct optee_smc smc;
struct optee_ffa ffa;
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index 196cd4316d7d..1dbb13b08381 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -952,57 +952,34 @@ static irqreturn_t notif_irq_thread_fn(int irq, void *dev_id)
{
struct optee *optee = dev_id;

- optee_smc_do_bottom_half(optee->notif.ctx);
+ optee_smc_do_bottom_half(optee->ctx);

return IRQ_HANDLED;
}

static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
{
- struct tee_context *ctx;
int rc;

- ctx = teedev_open(optee->teedev);
- if (IS_ERR(ctx))
- return PTR_ERR(ctx);
-
- optee->notif.ctx = ctx;
rc = request_threaded_irq(irq, notif_irq_handler,
notif_irq_thread_fn,
0, "optee_notification", optee);
if (rc)
- goto err_close_ctx;
+ return rc;

optee->smc.notif_irq = irq;

return 0;
-
-err_close_ctx:
- teedev_close_context(optee->notif.ctx);
- optee->notif.ctx = NULL;
-
- return rc;
}

static void optee_smc_notif_uninit_irq(struct optee *optee)
{
- if (optee->notif.ctx) {
- optee_smc_stop_async_notif(optee->notif.ctx);
+ if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
+ optee_smc_stop_async_notif(optee->ctx);
if (optee->smc.notif_irq) {
free_irq(optee->smc.notif_irq, optee);
irq_dispose_mapping(optee->smc.notif_irq);
}
-
- /*
- * The thread normally working with optee->notif.ctx was
- * stopped with free_irq() above.
- *
- * Note we're not using teedev_close_context() or
- * tee_client_close_context() since we have already called
- * tee_device_put() while initializing to avoid a circular
- * reference counting.
- */
- teedev_close_context(optee->notif.ctx);
}
}

@@ -1307,6 +1284,7 @@ static int optee_probe(struct platform_device *pdev)
struct optee *optee = NULL;
void *memremaped_shm = NULL;
struct tee_device *teedev;
+ struct tee_context *ctx;
u32 max_notif_value;
u32 sec_caps;
int rc;
@@ -1387,9 +1365,13 @@ static int optee_probe(struct platform_device *pdev)
optee->pool = pool;

platform_set_drvdata(pdev, optee);
+ ctx = teedev_open(optee->teedev);
+ if (IS_ERR(ctx))
+ goto err_supp_uninit;
+ optee->ctx = ctx;
rc = optee_notif_init(optee, max_notif_value);
if (rc)
- goto err_supp_uninit;
+ goto err_close_ctx;

if (sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
unsigned int irq;
@@ -1437,6 +1419,8 @@ static int optee_probe(struct platform_device *pdev)
optee_unregister_devices();
err_notif_uninit:
optee_notif_uninit(optee);
+err_close_ctx:
+ teedev_close_context(ctx);
err_supp_uninit:
optee_supp_uninit(&optee->supp);
mutex_destroy(&optee->call_queue.mutex);
--
2.31.1

2022-01-14 21:37:28

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 07/12] optee: use driver internal tee_contex for some rpc

Uses the new driver internal tee_context when allocating driver private
shared memory. This decouples the shared memory object from its original
tee_context. This is needed when the life time of such a memory
allocation outlives the client tee_context.

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/tee/optee/ffa_abi.c | 16 ++++++++--------
drivers/tee/optee/smc_abi.c | 7 ++++---
2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 88a028d4fb7b..5ec484b42432 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -424,6 +424,7 @@ static struct tee_shm_pool *optee_ffa_shm_pool_alloc_pages(void)
*/

static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
+ struct optee *optee,
struct optee_msg_arg *arg)
{
struct tee_shm *shm;
@@ -439,7 +440,7 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
break;
case OPTEE_RPC_SHM_TYPE_KERNEL:
- shm = tee_shm_alloc_priv_kernel_buf(ctx,
+ shm = tee_shm_alloc_priv_kernel_buf(optee->ctx,
arg->params[0].u.value.b);
break;
default:
@@ -493,14 +494,13 @@ static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx,
}

static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
+ struct optee *optee,
struct optee_msg_arg *arg)
{
- struct optee *optee = tee_get_drvdata(ctx->teedev);
-
arg->ret_origin = TEEC_ORIGIN_COMMS;
switch (arg->cmd) {
case OPTEE_RPC_CMD_SHM_ALLOC:
- handle_ffa_rpc_func_cmd_shm_alloc(ctx, arg);
+ handle_ffa_rpc_func_cmd_shm_alloc(ctx, optee, arg);
break;
case OPTEE_RPC_CMD_SHM_FREE:
handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg);
@@ -510,12 +510,12 @@ static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
}
}

-static void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd,
- struct optee_msg_arg *arg)
+static void optee_handle_ffa_rpc(struct tee_context *ctx, struct optee *optee,
+ u32 cmd, struct optee_msg_arg *arg)
{
switch (cmd) {
case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
- handle_ffa_rpc_func_cmd(ctx, arg);
+ handle_ffa_rpc_func_cmd(ctx, optee, arg);
break;
case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
/* Interrupt delivered by now */
@@ -582,7 +582,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx,
* above.
*/
cond_resched();
- optee_handle_ffa_rpc(ctx, data->data1, rpc_arg);
+ optee_handle_ffa_rpc(ctx, optee, data->data1, rpc_arg);
cmd = OPTEE_FFA_YIELDING_CALL_RESUME;
data->data0 = cmd;
data->data1 = 0;
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index 1dbb13b08381..f2ef76451443 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -621,6 +621,7 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
}

static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
+ struct optee *optee,
struct optee_msg_arg *arg,
struct optee_call_ctx *call_ctx)
{
@@ -650,7 +651,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
break;
case OPTEE_RPC_SHM_TYPE_KERNEL:
- shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
+ shm = tee_shm_alloc_priv_kernel_buf(optee->ctx, sz);
break;
default:
arg->ret = TEEC_ERROR_BAD_PARAMETERS;
@@ -746,7 +747,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
switch (arg->cmd) {
case OPTEE_RPC_CMD_SHM_ALLOC:
free_pages_list(call_ctx);
- handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
+ handle_rpc_func_cmd_shm_alloc(ctx, optee, arg, call_ctx);
break;
case OPTEE_RPC_CMD_SHM_FREE:
handle_rpc_func_cmd_shm_free(ctx, arg);
@@ -775,7 +776,7 @@ static void optee_handle_rpc(struct tee_context *ctx,

switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
case OPTEE_SMC_RPC_FUNC_ALLOC:
- shm = tee_shm_alloc_priv_kernel_buf(ctx, param->a1);
+ shm = tee_shm_alloc_priv_kernel_buf(optee->ctx, param->a1);
if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
reg_pair_from_64(&param->a1, &param->a2, pa);
reg_pair_from_64(&param->a4, &param->a5,
--
2.31.1

2022-01-14 21:38:13

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 08/12] optee: add optee_pool_op_free_helper()

Adds a common helper function to free a tee_shm allocated using the
helper function optee_pool_op_alloc_helper().

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/tee/optee/core.c | 10 ++++++++++
drivers/tee/optee/ffa_abi.c | 4 +---
drivers/tee/optee/optee_private.h | 3 +++
drivers/tee/optee/smc_abi.c | 7 +++----
4 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index f4bccb5f0e93..daf947e98d14 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -69,6 +69,16 @@ int optee_pool_op_alloc_helper(struct tee_shm_pool *pool, struct tee_shm *shm,
return rc;
}

+void optee_pool_op_free_helper(struct tee_shm_pool *pool, struct tee_shm *shm,
+ int (*shm_unregister)(struct tee_context *ctx,
+ struct tee_shm *shm))
+{
+ if (shm_unregister)
+ shm_unregister(shm->ctx, shm);
+ free_pages((unsigned long)shm->kaddr, get_order(shm->size));
+ shm->kaddr = NULL;
+}
+
static void optee_bus_scan(struct work_struct *work)
{
WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP));
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 5ec484b42432..4cbc45035f92 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -379,9 +379,7 @@ static int pool_ffa_op_alloc(struct tee_shm_pool *pool,
static void pool_ffa_op_free(struct tee_shm_pool *pool,
struct tee_shm *shm)
{
- optee_ffa_shm_unregister(shm->ctx, shm);
- free_pages((unsigned long)shm->kaddr, get_order(shm->size));
- shm->kaddr = NULL;
+ optee_pool_op_free_helper(pool, shm, optee_ffa_shm_unregister);
}

static void pool_ffa_op_destroy_pool(struct tee_shm_pool *pool)
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index df3a483bbf46..e77765c78878 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -236,6 +236,9 @@ int optee_pool_op_alloc_helper(struct tee_shm_pool *pool, struct tee_shm *shm,
struct page **pages,
size_t num_pages,
unsigned long start));
+void optee_pool_op_free_helper(struct tee_shm_pool *pool, struct tee_shm *shm,
+ int (*shm_unregister)(struct tee_context *ctx,
+ struct tee_shm *shm));


void optee_remove_common(struct optee *optee);
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index f2ef76451443..0b27688d1e97 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -548,10 +548,9 @@ static void pool_op_free(struct tee_shm_pool *pool,
struct tee_shm *shm)
{
if (!(shm->flags & TEE_SHM_PRIV))
- optee_shm_unregister(shm->ctx, shm);
-
- free_pages((unsigned long)shm->kaddr, get_order(shm->size));
- shm->kaddr = NULL;
+ optee_pool_op_free_helper(pool, shm, optee_shm_unregister);
+ else
+ optee_pool_op_free_helper(pool, shm, NULL);
}

static void pool_op_destroy_pool(struct tee_shm_pool *pool)
--
2.31.1

2022-01-14 21:38:52

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 12/12] tee: refactor TEE_SHM_* flags

Removes the redundant TEE_SHM_DMA_BUF, TEE_SHM_EXT_DMA_BUF,
TEE_SHM_MAPPED and TEE_SHM_KERNEL_MAPPED flags.

Assigns new values to the remaining flags to void gaps.

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/tee/tee_shm.c | 21 ++++++++++-----------
include/linux/tee_drv.h | 12 ++++--------
2 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index fe3e5977dd7c..9945bdec086b 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -139,8 +139,7 @@ static struct tee_shm *shm_alloc_helper(struct tee_context *ctx, size_t size,
*/
struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
{
- u32 flags = TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_REGISTER |
- TEE_SHM_POOL;
+ u32 flags = TEE_SHM_REGISTER | TEE_SHM_POOL;
struct tee_device *teedev = ctx->teedev;
struct tee_shm *shm;
void *ret;
@@ -186,7 +185,7 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
*/
struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
{
- u32 flags = TEE_SHM_MAPPED | TEE_SHM_REGISTER | TEE_SHM_POOL;
+ u32 flags = TEE_SHM_REGISTER | TEE_SHM_POOL;

return shm_alloc_helper(ctx, size, PAGE_SIZE, flags, -1);
}
@@ -211,7 +210,7 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
size_t size)
{
- u32 flags = TEE_SHM_MAPPED | TEE_SHM_PRIV | TEE_SHM_POOL;
+ u32 flags = TEE_SHM_PRIV | TEE_SHM_POOL;

return shm_alloc_helper(ctx, size, sizeof(long) * 2, flags, -1);
}
@@ -308,7 +307,7 @@ register_shm_helper(struct tee_context *ctx, unsigned long addr,
struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
unsigned long addr, size_t length)
{
- u32 f = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED | TEE_SHM_REGISTER;
+ u32 f = TEE_SHM_USER_MAPPED | TEE_SHM_REGISTER;
struct tee_device *teedev = ctx->teedev;
struct tee_shm *shm;
void *ret;
@@ -354,7 +353,7 @@ EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
void *addr, size_t length)
{
- u32 f = TEE_SHM_REGISTER | TEE_SHM_KERNEL_MAPPED;
+ u32 f = TEE_SHM_REGISTER;

return register_shm_helper(ctx, (unsigned long)addr, length, f, -1);
}
@@ -398,7 +397,7 @@ int tee_shm_get_fd(struct tee_shm *shm)
{
int fd;

- if (!(shm->flags & TEE_SHM_DMA_BUF))
+ if (shm->id < 0)
return -EINVAL;

/* matched by tee_shm_put() in tee_shm_op_release() */
@@ -428,7 +427,7 @@ EXPORT_SYMBOL_GPL(tee_shm_free);
*/
int tee_shm_va2pa(struct tee_shm *shm, void *va, phys_addr_t *pa)
{
- if (!(shm->flags & TEE_SHM_MAPPED))
+ if (!shm->kaddr)
return -EINVAL;
/* Check that we're in the range of the shm */
if ((char *)va < (char *)shm->kaddr)
@@ -450,7 +449,7 @@ EXPORT_SYMBOL_GPL(tee_shm_va2pa);
*/
int tee_shm_pa2va(struct tee_shm *shm, phys_addr_t pa, void **va)
{
- if (!(shm->flags & TEE_SHM_MAPPED))
+ if (!shm->kaddr)
return -EINVAL;
/* Check that we're in the range of the shm */
if (pa < shm->paddr)
@@ -478,7 +477,7 @@ EXPORT_SYMBOL_GPL(tee_shm_pa2va);
*/
void *tee_shm_get_va(struct tee_shm *shm, size_t offs)
{
- if (!(shm->flags & TEE_SHM_MAPPED))
+ if (!shm->kaddr)
return ERR_PTR(-EINVAL);
if (offs >= shm->size)
return ERR_PTR(-EINVAL);
@@ -553,7 +552,7 @@ void tee_shm_put(struct tee_shm *shm)
* the refcount_inc() in tee_shm_get_from_id() never starts
* from 0.
*/
- if (shm->flags & TEE_SHM_DMA_BUF)
+ if (shm->id >= 0)
idr_remove(&teedev->idr, shm->id);
do_release = true;
}
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index e4f32885e273..dcc7a55e1128 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -20,14 +20,10 @@
* specific TEE driver.
*/

-#define TEE_SHM_MAPPED BIT(0) /* Memory mapped by the kernel */
-#define TEE_SHM_DMA_BUF BIT(1) /* Memory with dma-buf handle */
-#define TEE_SHM_EXT_DMA_BUF BIT(2) /* Memory with dma-buf handle */
-#define TEE_SHM_REGISTER BIT(3) /* Memory registered in secure world */
-#define TEE_SHM_USER_MAPPED BIT(4) /* Memory mapped in user space */
-#define TEE_SHM_POOL BIT(5) /* Memory allocated from pool */
-#define TEE_SHM_KERNEL_MAPPED BIT(6) /* Memory mapped in kernel space */
-#define TEE_SHM_PRIV BIT(7) /* Memory private to TEE driver */
+#define TEE_SHM_REGISTER BIT(0) /* Memory registered in secure world */
+#define TEE_SHM_USER_MAPPED BIT(1) /* Memory mapped in user space */
+#define TEE_SHM_POOL BIT(2) /* Memory allocated from pool */
+#define TEE_SHM_PRIV BIT(3) /* Memory private to TEE driver */

struct device;
struct tee_device;
--
2.31.1

2022-01-14 21:38:56

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 10/12] KEYS: trusted: tee: use tee_shm_register_kernel_buf()

Uses the new simplified tee_shm_register_kernel_buf() function instead
of the old tee_shm_alloc() function which required specific
TEE_SHM-flags

Signed-off-by: Jens Wiklander <[email protected]>
---
security/keys/trusted-keys/trusted_tee.c | 23 +++++++++--------------
1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/security/keys/trusted-keys/trusted_tee.c b/security/keys/trusted-keys/trusted_tee.c
index 2ce66c199e1d..c8626686ee1b 100644
--- a/security/keys/trusted-keys/trusted_tee.c
+++ b/security/keys/trusted-keys/trusted_tee.c
@@ -70,17 +70,15 @@ static int trusted_tee_seal(struct trusted_key_payload *p, char *datablob)
memset(&inv_arg, 0, sizeof(inv_arg));
memset(&param, 0, sizeof(param));

- reg_shm_in = tee_shm_register(pvt_data.ctx, (unsigned long)p->key,
- p->key_len, TEE_SHM_DMA_BUF |
- TEE_SHM_KERNEL_MAPPED);
+ reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
+ p->key_len);
if (IS_ERR(reg_shm_in)) {
dev_err(pvt_data.dev, "key shm register failed\n");
return PTR_ERR(reg_shm_in);
}

- reg_shm_out = tee_shm_register(pvt_data.ctx, (unsigned long)p->blob,
- sizeof(p->blob), TEE_SHM_DMA_BUF |
- TEE_SHM_KERNEL_MAPPED);
+ reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob,
+ sizeof(p->blob));
if (IS_ERR(reg_shm_out)) {
dev_err(pvt_data.dev, "blob shm register failed\n");
ret = PTR_ERR(reg_shm_out);
@@ -131,17 +129,15 @@ static int trusted_tee_unseal(struct trusted_key_payload *p, char *datablob)
memset(&inv_arg, 0, sizeof(inv_arg));
memset(&param, 0, sizeof(param));

- reg_shm_in = tee_shm_register(pvt_data.ctx, (unsigned long)p->blob,
- p->blob_len, TEE_SHM_DMA_BUF |
- TEE_SHM_KERNEL_MAPPED);
+ reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob,
+ p->blob_len);
if (IS_ERR(reg_shm_in)) {
dev_err(pvt_data.dev, "blob shm register failed\n");
return PTR_ERR(reg_shm_in);
}

- reg_shm_out = tee_shm_register(pvt_data.ctx, (unsigned long)p->key,
- sizeof(p->key), TEE_SHM_DMA_BUF |
- TEE_SHM_KERNEL_MAPPED);
+ reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
+ sizeof(p->key));
if (IS_ERR(reg_shm_out)) {
dev_err(pvt_data.dev, "key shm register failed\n");
ret = PTR_ERR(reg_shm_out);
@@ -192,8 +188,7 @@ static int trusted_tee_get_random(unsigned char *key, size_t key_len)
memset(&inv_arg, 0, sizeof(inv_arg));
memset(&param, 0, sizeof(param));

- reg_shm = tee_shm_register(pvt_data.ctx, (unsigned long)key, key_len,
- TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED);
+ reg_shm = tee_shm_register_kernel_buf(pvt_data.ctx, key, key_len);
if (IS_ERR(reg_shm)) {
dev_err(pvt_data.dev, "key shm register failed\n");
return PTR_ERR(reg_shm);
--
2.31.1

2022-01-14 21:40:04

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 11/12] tee: replace tee_shm_register()

tee_shm_register() is replaced by the previously introduced functions
tee_shm_register_user_buf() and tee_shm_register_kernel_buf().

Since there are not external callers left we can remove tee_shm_register()
and refactor the remains.

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/tee/tee_shm.c | 157 +++++++++++++++++++++++-----------------
include/linux/tee_drv.h | 11 ---
2 files changed, 91 insertions(+), 77 deletions(-)

diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index 6a1dbce75616..fe3e5977dd7c 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -12,17 +12,43 @@
#include <linux/uio.h>
#include "tee_private.h"

+static void shm_put_kernel_pages(struct page **pages, unsigned long npages)
+{
+ unsigned long n;
+
+ for (n = 0; n < npages; n++)
+ put_page(pages[n]);
+}
+
+static int shm_get_kernel_pages(unsigned long start, int page_count,
+ struct page **pages)
+{
+ struct kvec *kiov;
+ unsigned int n;
+ int rc;
+
+ kiov = kcalloc(page_count, sizeof(*kiov), GFP_KERNEL);
+ if (!kiov)
+ return -ENOMEM;
+
+ for (n = 0; n < page_count; n++) {
+ kiov[n].iov_base = (void *)(start + n * PAGE_SIZE);
+ kiov[n].iov_len = PAGE_SIZE;
+ }
+
+ rc = get_kernel_pages(kiov, page_count, 0, pages);
+ kfree(kiov);
+
+ return rc;
+}
+
static void release_registered_pages(struct tee_shm *shm)
{
if (shm->pages) {
- if (shm->flags & TEE_SHM_USER_MAPPED) {
+ if (shm->flags & TEE_SHM_USER_MAPPED)
unpin_user_pages(shm->pages, shm->num_pages);
- } else {
- size_t n;
-
- for (n = 0; n < shm->num_pages; n++)
- put_page(shm->pages[n]);
- }
+ else
+ shm_put_kernel_pages(shm->pages, shm->num_pages);

kfree(shm->pages);
}
@@ -191,28 +217,24 @@ struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
}
EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_kernel_buf);

-struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
- size_t length, u32 flags)
+static struct tee_shm *
+register_shm_helper(struct tee_context *ctx, unsigned long addr,
+ size_t length, u32 flags, int id)
{
struct tee_device *teedev = ctx->teedev;
- const u32 req_user_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED;
- const u32 req_kernel_flags = TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED;
struct tee_shm *shm;
+ unsigned long start;
+ int num_pages;
void *ret;
int rc;
- int num_pages;
- unsigned long start;
-
- if (flags != req_user_flags && flags != req_kernel_flags)
- return ERR_PTR(-ENOTSUPP);

if (!tee_device_get(teedev))
return ERR_PTR(-EINVAL);

if (!teedev->desc->ops->shm_register ||
!teedev->desc->ops->shm_unregister) {
- tee_device_put(teedev);
- return ERR_PTR(-ENOTSUPP);
+ ret = ERR_PTR(-ENOTSUPP);
+ goto err_dev_put;
}

teedev_ctx_get(ctx);
@@ -220,13 +242,13 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
shm = kzalloc(sizeof(*shm), GFP_KERNEL);
if (!shm) {
ret = ERR_PTR(-ENOMEM);
- goto err;
+ goto err_ctx_put;
}

refcount_set(&shm->refcount, 1);
- shm->flags = flags | TEE_SHM_REGISTER;
+ shm->flags = flags;
shm->ctx = ctx;
- shm->id = -1;
+ shm->id = id;
addr = untagged_addr(addr);
start = rounddown(addr, PAGE_SIZE);
shm->offset = addr - start;
@@ -235,71 +257,45 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
shm->pages = kcalloc(num_pages, sizeof(*shm->pages), GFP_KERNEL);
if (!shm->pages) {
ret = ERR_PTR(-ENOMEM);
- goto err;
+ goto err_free_shm;
}

- if (flags & TEE_SHM_USER_MAPPED) {
+ if (flags & TEE_SHM_USER_MAPPED)
rc = pin_user_pages_fast(start, num_pages, FOLL_WRITE,
shm->pages);
- } else {
- struct kvec *kiov;
- int i;
-
- kiov = kcalloc(num_pages, sizeof(*kiov), GFP_KERNEL);
- if (!kiov) {
- ret = ERR_PTR(-ENOMEM);
- goto err;
- }
-
- for (i = 0; i < num_pages; i++) {
- kiov[i].iov_base = (void *)(start + i * PAGE_SIZE);
- kiov[i].iov_len = PAGE_SIZE;
- }
-
- rc = get_kernel_pages(kiov, num_pages, 0, shm->pages);
- kfree(kiov);
- }
+ else
+ rc = shm_get_kernel_pages(start, num_pages, shm->pages);
if (rc > 0)
shm->num_pages = rc;
if (rc != num_pages) {
if (rc >= 0)
rc = -ENOMEM;
ret = ERR_PTR(rc);
- goto err;
- }
-
- mutex_lock(&teedev->mutex);
- shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
- mutex_unlock(&teedev->mutex);
-
- if (shm->id < 0) {
- ret = ERR_PTR(shm->id);
- goto err;
+ goto err_put_shm_pages;
}

rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages,
shm->num_pages, start);
if (rc) {
ret = ERR_PTR(rc);
- goto err;
+ goto err_put_shm_pages;
}

return shm;
-err:
- if (shm) {
- if (shm->id >= 0) {
- mutex_lock(&teedev->mutex);
- idr_remove(&teedev->idr, shm->id);
- mutex_unlock(&teedev->mutex);
- }
- release_registered_pages(shm);
- }
+err_put_shm_pages:
+ if (flags & TEE_SHM_USER_MAPPED)
+ unpin_user_pages(shm->pages, shm->num_pages);
+ else
+ shm_put_kernel_pages(shm->pages, shm->num_pages);
+ kfree(shm->pages);
+err_free_shm:
kfree(shm);
+err_ctx_put:
teedev_ctx_put(ctx);
+err_dev_put:
tee_device_put(teedev);
return ret;
}
-EXPORT_SYMBOL_GPL(tee_shm_register);

/**
* tee_shm_register_user_buf() - Register a userspace shared memory buffer
@@ -312,8 +308,36 @@ EXPORT_SYMBOL_GPL(tee_shm_register);
struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
unsigned long addr, size_t length)
{
- return tee_shm_register(ctx, addr, length,
- TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
+ u32 f = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED | TEE_SHM_REGISTER;
+ struct tee_device *teedev = ctx->teedev;
+ struct tee_shm *shm;
+ void *ret;
+ int id;
+
+ mutex_lock(&teedev->mutex);
+ id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL);
+ mutex_unlock(&teedev->mutex);
+
+ if (id < 0)
+ return ERR_PTR(id);
+
+ shm = register_shm_helper(ctx, addr, length, f, id);
+ if (IS_ERR(shm)) {
+ mutex_lock(&teedev->mutex);
+ idr_remove(&teedev->idr, id);
+ mutex_unlock(&teedev->mutex);
+ return shm;
+ }
+
+ mutex_lock(&teedev->mutex);
+ ret = idr_replace(&teedev->idr, shm, id);
+ mutex_unlock(&teedev->mutex);
+ if (IS_ERR(ret)) {
+ tee_shm_free(shm);
+ return ret;
+ }
+
+ return shm;
}
EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);

@@ -330,8 +354,9 @@ EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
void *addr, size_t length)
{
- return tee_shm_register(ctx, (unsigned long)addr, length,
- TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED);
+ u32 f = TEE_SHM_REGISTER | TEE_SHM_KERNEL_MAPPED;
+
+ return register_shm_helper(ctx, (unsigned long)addr, length, f, -1);
}
EXPORT_SYMBOL_GPL(tee_shm_register_kernel_buf);

diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index 029c9a0590cc..e4f32885e273 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -278,17 +278,6 @@ struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
size_t size);
struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);

-/**
- * tee_shm_register() - Register shared memory buffer
- * @ctx: Context that registers the shared memory
- * @addr: Address is userspace of the shared buffer
- * @length: Length of the shared buffer
- * @flags: Flags setting properties for the requested shared memory.
- *
- * @returns a pointer to 'struct tee_shm'
- */
-struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
- size_t length, u32 flags);
struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
unsigned long addr, size_t length);
struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
--
2.31.1

2022-01-14 21:40:16

by Jens Wiklander

[permalink] [raw]
Subject: [PATCH v2 09/12] tee: add tee_shm_register_{user,kernel}_buf()

Adds the two new functions tee_shm_register_user_buf() and
tee_shm_register_kernel_buf() which should be used instead of the old
tee_shm_register().

This avoids having the caller supplying the flags parameter which
exposes a bit more than desired of the internals of the TEE subsystem.

Signed-off-by: Jens Wiklander <[email protected]>
---
drivers/tee/tee_core.c | 3 +--
drivers/tee/tee_shm.c | 34 ++++++++++++++++++++++++++++++++++
include/linux/tee_drv.h | 4 ++++
3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index a15812baaeb1..8aa1a4836b92 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -334,8 +334,7 @@ tee_ioctl_shm_register(struct tee_context *ctx,
if (data.flags)
return -EINVAL;

- shm = tee_shm_register(ctx, data.addr, data.length,
- TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
+ shm = tee_shm_register_user_buf(ctx, data.addr, data.length);
if (IS_ERR(shm))
return PTR_ERR(shm);

diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index d51bf97ce7e5..6a1dbce75616 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -301,6 +301,40 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
}
EXPORT_SYMBOL_GPL(tee_shm_register);

+/**
+ * tee_shm_register_user_buf() - Register a userspace shared memory buffer
+ * @ctx: Context that registers the shared memory
+ * @addr: The userspace address of the shared buffer
+ * @length: Length of the shared buffer
+ *
+ * @returns a pointer to 'struct tee_shm'
+ */
+struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
+ unsigned long addr, size_t length)
+{
+ return tee_shm_register(ctx, addr, length,
+ TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
+}
+EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
+
+/**
+ * tee_shm_register_kernel_buf() - Register kernel memory to be shared with
+ * secure world
+ * @ctx: Context that registers the shared memory
+ * @addr: The buffer
+ * @length: Length of the buffer
+ *
+ * @returns a pointer to 'struct tee_shm'
+ */
+
+struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
+ void *addr, size_t length)
+{
+ return tee_shm_register(ctx, (unsigned long)addr, length,
+ TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED);
+}
+EXPORT_SYMBOL_GPL(tee_shm_register_kernel_buf);
+
static int tee_shm_fop_release(struct inode *inode, struct file *filp)
{
tee_shm_put(filp->private_data);
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index e71cb0411e9c..029c9a0590cc 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -289,6 +289,10 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
*/
struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
size_t length, u32 flags);
+struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
+ unsigned long addr, size_t length);
+struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
+ void *addr, size_t length);

/**
* tee_shm_is_registered() - Check if shared memory object in registered in TEE
--
2.31.1

2022-01-20 09:08:58

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 01/12] hwrng: optee-rng: use tee_shm_alloc_kernel_buf()

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> Uses the new simplified tee_shm_alloc_kernel_buf() function instead of
> the old deprecated tee_shm_alloc() function which required specific
> TEE_SHM-flags.
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/char/hw_random/optee-rng.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>

Reviewed-by: Sumit Garg <[email protected]>

-Sumit

> diff --git a/drivers/char/hw_random/optee-rng.c b/drivers/char/hw_random/optee-rng.c
> index 135a82590923..a948c0727b2b 100644
> --- a/drivers/char/hw_random/optee-rng.c
> +++ b/drivers/char/hw_random/optee-rng.c
> @@ -145,10 +145,10 @@ static int optee_rng_init(struct hwrng *rng)
> struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
> struct tee_shm *entropy_shm_pool = NULL;
>
> - entropy_shm_pool = tee_shm_alloc(pvt_data->ctx, MAX_ENTROPY_REQ_SZ,
> - TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
> + entropy_shm_pool = tee_shm_alloc_kernel_buf(pvt_data->ctx,
> + MAX_ENTROPY_REQ_SZ);
> if (IS_ERR(entropy_shm_pool)) {
> - dev_err(pvt_data->dev, "tee_shm_alloc failed\n");
> + dev_err(pvt_data->dev, "tee_shm_alloc_kernel_buf failed\n");
> return PTR_ERR(entropy_shm_pool);
> }
>
> --
> 2.31.1
>

2022-01-20 09:10:58

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 02/12] tee: remove unused tee_shm_pool_alloc_res_mem()

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> None of the drivers in the TEE subsystem uses
> tee_shm_pool_alloc_res_mem() so remove the function.
>

It looks like originally it was used by the OP-TEE driver that
switched directly to use tee_shm_pool_mgr_alloc_res_mem() after commit
f58e236c9d665 ("tee: optee: enable dynamic SHM support").

> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/tee/tee_shm_pool.c | 56 --------------------------------------
> include/linux/tee_drv.h | 30 --------------------
> 2 files changed, 86 deletions(-)
>

FWIW,

Reviewed-by: Sumit Garg <[email protected]>

-Sumit

> diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
> index fcbb461fc59c..a9f9d50fd181 100644
> --- a/drivers/tee/tee_shm_pool.c
> +++ b/drivers/tee/tee_shm_pool.c
> @@ -47,62 +47,6 @@ static const struct tee_shm_pool_mgr_ops pool_ops_generic = {
> .destroy_poolmgr = pool_op_gen_destroy_poolmgr,
> };
>
> -/**
> - * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved
> - * memory range
> - * @priv_info: Information for driver private shared memory pool
> - * @dmabuf_info: Information for dma-buf shared memory pool
> - *
> - * Start and end of pools will must be page aligned.
> - *
> - * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
> - * in @dmabuf, others will use the range provided by @priv.
> - *
> - * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> - */
> -struct tee_shm_pool *
> -tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info,
> - struct tee_shm_pool_mem_info *dmabuf_info)
> -{
> - struct tee_shm_pool_mgr *priv_mgr;
> - struct tee_shm_pool_mgr *dmabuf_mgr;
> - void *rc;
> -
> - /*
> - * Create the pool for driver private shared memory
> - */
> - rc = tee_shm_pool_mgr_alloc_res_mem(priv_info->vaddr, priv_info->paddr,
> - priv_info->size,
> - 3 /* 8 byte aligned */);
> - if (IS_ERR(rc))
> - return rc;
> - priv_mgr = rc;
> -
> - /*
> - * Create the pool for dma_buf shared memory
> - */
> - rc = tee_shm_pool_mgr_alloc_res_mem(dmabuf_info->vaddr,
> - dmabuf_info->paddr,
> - dmabuf_info->size, PAGE_SHIFT);
> - if (IS_ERR(rc))
> - goto err_free_priv_mgr;
> - dmabuf_mgr = rc;
> -
> - rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
> - if (IS_ERR(rc))
> - goto err_free_dmabuf_mgr;
> -
> - return rc;
> -
> -err_free_dmabuf_mgr:
> - tee_shm_pool_mgr_destroy(dmabuf_mgr);
> -err_free_priv_mgr:
> - tee_shm_pool_mgr_destroy(priv_mgr);
> -
> - return rc;
> -}
> -EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem);
> -
> struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr,
> phys_addr_t paddr,
> size_t size,
> diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> index 5e1533ee3785..6b0f0d01ebdf 100644
> --- a/include/linux/tee_drv.h
> +++ b/include/linux/tee_drv.h
> @@ -278,36 +278,6 @@ static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
> poolm->ops->destroy_poolmgr(poolm);
> }
>
> -/**
> - * struct tee_shm_pool_mem_info - holds information needed to create a shared
> - * memory pool
> - * @vaddr: Virtual address of start of pool
> - * @paddr: Physical address of start of pool
> - * @size: Size in bytes of the pool
> - */
> -struct tee_shm_pool_mem_info {
> - unsigned long vaddr;
> - phys_addr_t paddr;
> - size_t size;
> -};
> -
> -/**
> - * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved
> - * memory range
> - * @priv_info: Information for driver private shared memory pool
> - * @dmabuf_info: Information for dma-buf shared memory pool
> - *
> - * Start and end of pools will must be page aligned.
> - *
> - * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
> - * in @dmabuf, others will use the range provided by @priv.
> - *
> - * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> - */
> -struct tee_shm_pool *
> -tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info,
> - struct tee_shm_pool_mem_info *dmabuf_info);
> -
> /**
> * tee_shm_pool_free() - Free a shared memory pool
> * @pool: The shared memory pool to free
> --
> 2.31.1
>

2022-01-20 09:13:19

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 03/12] tee: add tee_shm_alloc_user_buf()

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> Adds a new function tee_shm_alloc_user_buf() or user mode allocations,
> replacing passing the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF to
> tee_shm_alloc().
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/tee/tee_core.c | 2 +-
> drivers/tee/tee_shm.c | 18 ++++++++++++++++++
> drivers/tee/tee_shm_pool.c | 2 +-
> include/linux/tee_drv.h | 3 ++-
> 4 files changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> index 3fc426dad2df..a15812baaeb1 100644
> --- a/drivers/tee/tee_core.c
> +++ b/drivers/tee/tee_core.c
> @@ -297,7 +297,7 @@ static int tee_ioctl_shm_alloc(struct tee_context *ctx,
> if (data.flags)
> return -EINVAL;
>
> - shm = tee_shm_alloc(ctx, data.size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
> + shm = tee_shm_alloc_user_buf(ctx, data.size);

Since it's the only place this API would be used within the driver
itself and I can't see any future usage from other kernel drivers..

> if (IS_ERR(shm))
> return PTR_ERR(shm);
>
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index 499fccba3d74..b43178986985 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -127,6 +127,24 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> }
> EXPORT_SYMBOL_GPL(tee_shm_alloc);
>
> +/**
> + * tee_shm_alloc_user_buf() - Allocate shared memory for user space
> + * @ctx: Context that allocates the shared memory
> + * @size: Requested size of shared memory
> + *
> + * Memory allocated as user space shared memory is automatically freed when
> + * the TEE file pointer is closed. The primary usage of this function is
> + * when the TEE driver doesn't support registering ordinary user space
> + * memory.
> + *
> + * @returns a pointer to 'struct tee_shm'
> + */
> +struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
> +{
> + return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
> +}
> +EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
> +

..so I don't see any value-add for this export..

> /**
> * tee_shm_alloc_kernel_buf() - Allocate shared memory for kernel buffer
> * @ctx: Context that allocates the shared memory
> diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
> index a9f9d50fd181..0e460347138a 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>
> diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> index 6b0f0d01ebdf..26b450484ac1 100644
> --- a/include/linux/tee_drv.h
> +++ b/include/linux/tee_drv.h
> @@ -1,6 +1,6 @@
> /* SPDX-License-Identifier: GPL-2.0-only */
> /*
> - * Copyright (c) 2015-2016, Linaro Limited
> + * Copyright (c) 2015-2022 Linaro Limited
> */
>
> #ifndef __TEE_DRV_H
> @@ -308,6 +308,7 @@ void *tee_get_drvdata(struct tee_device *teedev);
> * @returns a pointer to 'struct tee_shm'
> */
> struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
> +struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);

..and it should rather belong to drivers/tee/tee_private.h.

-Sumit

> struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
>
> /**
> --
> 2.31.1
>

2022-01-21 18:36:10

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH v2 03/12] tee: add tee_shm_alloc_user_buf()

On Tue, Jan 18, 2022 at 2:11 PM Sumit Garg <[email protected]> wrote:
>
> On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> >
> > Adds a new function tee_shm_alloc_user_buf() or user mode allocations,
> > replacing passing the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF to
> > tee_shm_alloc().
> >
> > Signed-off-by: Jens Wiklander <[email protected]>
> > ---
> > drivers/tee/tee_core.c | 2 +-
> > drivers/tee/tee_shm.c | 18 ++++++++++++++++++
> > drivers/tee/tee_shm_pool.c | 2 +-
> > include/linux/tee_drv.h | 3 ++-
> > 4 files changed, 22 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> > index 3fc426dad2df..a15812baaeb1 100644
> > --- a/drivers/tee/tee_core.c
> > +++ b/drivers/tee/tee_core.c
> > @@ -297,7 +297,7 @@ static int tee_ioctl_shm_alloc(struct tee_context *ctx,
> > if (data.flags)
> > return -EINVAL;
> >
> > - shm = tee_shm_alloc(ctx, data.size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
> > + shm = tee_shm_alloc_user_buf(ctx, data.size);
>
> Since it's the only place this API would be used within the driver
> itself and I can't see any future usage from other kernel drivers..
>
> > if (IS_ERR(shm))
> > return PTR_ERR(shm);
> >
> > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > index 499fccba3d74..b43178986985 100644
> > --- a/drivers/tee/tee_shm.c
> > +++ b/drivers/tee/tee_shm.c
> > @@ -127,6 +127,24 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > }
> > EXPORT_SYMBOL_GPL(tee_shm_alloc);
> >
> > +/**
> > + * tee_shm_alloc_user_buf() - Allocate shared memory for user space
> > + * @ctx: Context that allocates the shared memory
> > + * @size: Requested size of shared memory
> > + *
> > + * Memory allocated as user space shared memory is automatically freed when
> > + * the TEE file pointer is closed. The primary usage of this function is
> > + * when the TEE driver doesn't support registering ordinary user space
> > + * memory.
> > + *
> > + * @returns a pointer to 'struct tee_shm'
> > + */
> > +struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
> > +{
> > + return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
> > +}
> > +EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
> > +
>
> ..so I don't see any value-add for this export..
>
> > /**
> > * tee_shm_alloc_kernel_buf() - Allocate shared memory for kernel buffer
> > * @ctx: Context that allocates the shared memory
> > diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
> > index a9f9d50fd181..0e460347138a 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>
> > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> > index 6b0f0d01ebdf..26b450484ac1 100644
> > --- a/include/linux/tee_drv.h
> > +++ b/include/linux/tee_drv.h
> > @@ -1,6 +1,6 @@
> > /* SPDX-License-Identifier: GPL-2.0-only */
> > /*
> > - * Copyright (c) 2015-2016, Linaro Limited
> > + * Copyright (c) 2015-2022 Linaro Limited
> > */
> >
> > #ifndef __TEE_DRV_H
> > @@ -308,6 +308,7 @@ void *tee_get_drvdata(struct tee_device *teedev);
> > * @returns a pointer to 'struct tee_shm'
> > */
> > struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
> > +struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
>
> ..and it should rather belong to drivers/tee/tee_private.h.

Makes sense, I'll fix this in the next version.

Thanks,
Jens

>
> -Sumit
>
> > struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
> >
> > /**
> > --
> > 2.31.1
> >

2022-01-21 21:16:17

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 04/12] tee: simplify shm pool handling

Hi Jens,

Thanks for this cleanup.

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> 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 concious one.

typo: s/concious/conscious/

AFAIU, the earlier design was to keep separate pools for differently
aligned memory allocation (one for 8 bytes aligned, other for
PAGE_SIZE aligned). But after this patch we would be mixing these
allocations using a first-fit algorithm. Don't you think that it would
lead to inefficient memory allocation (fragmentation) as compared to
existing one?

I think we need to be careful about allocation strategy for static
shared memory as it's a constrained resource and if a particular
device is using this approach then a kernel upgrade shouldn't cause
any regressions for that device.

>
> 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.
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/tee/amdtee/shm_pool.c | 55 +++++-----------
> drivers/tee/optee/Kconfig | 8 ---
> drivers/tee/optee/core.c | 11 ++--
> drivers/tee/optee/ffa_abi.c | 55 ++++------------
> drivers/tee/optee/optee_private.h | 4 +-
> drivers/tee/optee/smc_abi.c | 100 ++++++----------------------
> drivers/tee/tee_private.h | 11 ----
> drivers/tee/tee_shm.c | 29 ++++-----
> drivers/tee/tee_shm_pool.c | 104 ++++++++++--------------------
> include/linux/tee_drv.h | 58 ++++++-----------
> 10 files changed, 126 insertions(+), 309 deletions(-)
>
> diff --git a/drivers/tee/amdtee/shm_pool.c b/drivers/tee/amdtee/shm_pool.c
> index 065854e2db18..f87f96a291c9 100644
> --- a/drivers/tee/amdtee/shm_pool.c
> +++ b/drivers/tee/amdtee/shm_pool.c
> @@ -8,13 +8,17 @@
> #include <linux/psp-sev.h>
> #include "amdtee_private.h"
>
> -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)
> {
> unsigned int order = get_order(size);
> unsigned long va;
> int rc;
>
> + /*
> + * Ignore alignment since this is already going to be page aligned
> + * and there's no need for any larger alignment.
> + */
> va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
> if (!va)
> return -ENOMEM;
> @@ -34,7 +38,7 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm,
> return 0;
> }
>
> -static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
> +static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm)
> {
> /* Unmap the shared memory from TEE */
> amdtee_unmap_shmem(shm);
> @@ -42,52 +46,25 @@ static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
> 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,
> };
>
> -static struct tee_shm_pool_mgr *pool_mem_mgr_alloc(void)
> -{
> - struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
> -
> - if (!mgr)
> - return ERR_PTR(-ENOMEM);
> -
> - mgr->ops = &pool_ops;
> -
> - return mgr;
> -}
> -
> struct tee_shm_pool *amdtee_config_shm(void)
> {
> - struct tee_shm_pool_mgr *priv_mgr;
> - struct tee_shm_pool_mgr *dmabuf_mgr;
> - void *rc;
> + struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL);
>
> - rc = pool_mem_mgr_alloc();
> - if (IS_ERR(rc))
> - return rc;
> - priv_mgr = rc;
> -
> - rc = pool_mem_mgr_alloc();
> - if (IS_ERR(rc)) {
> - tee_shm_pool_mgr_destroy(priv_mgr);
> - return rc;
> - }
> - dmabuf_mgr = rc;
> + if (!pool)
> + return ERR_PTR(-ENOMEM);
>
> - 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);
> - }
> + pool->ops = &pool_ops;
>
> - return rc;
> + return pool;
> }
> 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 1ca320885fad..2a369e346b85 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 20a1b1a3d965..e690d9420966 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)
> {
> @@ -813,7 +786,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> if (!optee)
> return -ENOMEM;
>
> - optee->pool = optee_ffa_config_dyn_shm();
> + optee->pool = optee_ffa_shm_pool_alloc_pages();
> if (IS_ERR(optee->pool)) {
> rc = PTR_ERR(optee->pool);
> optee->pool = NULL;
> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> index 46f74ab07c7e..df2450921464 100644
> --- a/drivers/tee/optee/optee_private.h
> +++ b/drivers/tee/optee/optee_private.h
> @@ -228,8 +228,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 449d6a72d289..b679037ea794 100644
> --- a/drivers/tee/optee/smc_abi.c
> +++ b/drivers/tee/optee/smc_abi.c
> @@ -42,8 +42,6 @@
> * 6. Driver initialization.
> */
>
> -#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
> -
> /*
> * 1. Convert between struct tee_param and struct optee_msg_param
> *
> @@ -532,20 +530,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 +554,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 +571,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;
> }
>
> /*
> @@ -1174,33 +1173,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)
> {
> @@ -1214,10 +1186,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) {
> @@ -1235,11 +1204,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");
> @@ -1247,35 +1211,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);
> + rc = tee_shm_pool_alloc_res_mem(vaddr, paddr, size,
> + 9 /* 512 bytes aligned */);

Here you are specifying minimal allocation alignment to be 512 bytes?
Wouldn't it be inefficient corresponding to 8 bytes aligned OP-TEE
private memory allocation earlier?

-Sumit

> if (IS_ERR(rc))
> - goto err_free_priv_mgr;
> - dmabuf_mgr = rc;
> -
> - rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
> - 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;
> }
>
> @@ -1396,7 +1338,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
> diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
> index e55204df31ce..72376cf38bc0 100644
> --- a/drivers/tee/tee_private.h
> +++ b/drivers/tee/tee_private.h
> @@ -12,17 +12,6 @@
> #include <linux/mutex.h>
> #include <linux/types.h>
>
> -/**
> - * struct tee_shm_pool - shared memory pool
> - * @private_mgr: pool manager for shared memory only between kernel
> - * and secure world
> - * @dma_buf_mgr: pool manager for shared memory exported to user space
> - */
> -struct tee_shm_pool {
> - struct tee_shm_pool_mgr *private_mgr;
> - struct tee_shm_pool_mgr *dma_buf_mgr;
> -};
> -
> #define TEE_DEVICE_FLAG_REGISTERED 0x1
> #define TEE_MAX_DEV_NAME_LEN 32
>
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index b43178986985..2c8ce0c6801a 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -31,14 +31,7 @@ static void release_registered_pages(struct tee_shm *shm)
> static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> {
> if (shm->flags & TEE_SHM_POOL) {
> - struct tee_shm_pool_mgr *poolm;
> -
> - if (shm->flags & TEE_SHM_DMA_BUF)
> - poolm = teedev->pool->dma_buf_mgr;
> - else
> - poolm = teedev->pool->private_mgr;
> -
> - poolm->ops->free(poolm, shm);
> + teedev->pool->ops->free(teedev->pool, shm);
> } else if (shm->flags & TEE_SHM_REGISTER) {
> int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);
>
> @@ -59,8 +52,8 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> {
> struct tee_device *teedev = ctx->teedev;
> - struct tee_shm_pool_mgr *poolm = NULL;
> struct tee_shm *shm;
> + size_t align;
> void *ret;
> int rc;
>
> @@ -93,12 +86,18 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> refcount_set(&shm->refcount, 1);
> shm->flags = flags | TEE_SHM_POOL;
> shm->ctx = ctx;
> - if (flags & TEE_SHM_DMA_BUF)
> - poolm = teedev->pool->dma_buf_mgr;
> - else
> - poolm = teedev->pool->private_mgr;
> + if (flags & TEE_SHM_DMA_BUF) {
> + align = PAGE_SIZE;
> + /*
> + * Request to register the shm in the pool allocator below
> + * if supported.
> + */
> + shm->flags |= TEE_SHM_REGISTER;
> + } else {
> + align = 2 * sizeof(long);
> + }
>
> - rc = poolm->ops->alloc(poolm, shm, size);
> + rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
> if (rc) {
> ret = ERR_PTR(rc);
> goto err_kfree;
> @@ -118,7 +117,7 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
>
> return shm;
> err_pool_free:
> - poolm->ops->free(poolm, shm);
> + teedev->pool->ops->free(teedev->pool, shm);
> err_kfree:
> kfree(shm);
> err_dev_put:
> diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
> index 0e460347138a..71e0f8ae69aa 100644
> --- a/drivers/tee/tee_shm_pool.c
> +++ b/drivers/tee/tee_shm_pool.c
> @@ -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);
> diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> index 26b450484ac1..808aa23308c2 100644
> --- a/include/linux/tee_drv.h
> +++ b/include/linux/tee_drv.h
> @@ -221,62 +221,39 @@ struct tee_shm {
> };
>
> /**
> - * struct tee_shm_pool_mgr - shared memory manager
> + * struct tee_shm_pool - shared memory pool
> * @ops: operations
> * @private_data: private data for the shared memory manager
> */
> -struct tee_shm_pool_mgr {
> - const struct tee_shm_pool_mgr_ops *ops;
> +struct tee_shm_pool {
> + const struct tee_shm_pool_ops *ops;
> void *private_data;
> };
>
> /**
> - * struct tee_shm_pool_mgr_ops - shared memory pool manager operations
> + * struct tee_shm_pool_ops - shared memory pool operations
> * @alloc: called when allocating shared memory
> * @free: called when freeing shared memory
> - * @destroy_poolmgr: called when destroying the pool manager
> + * @destroy_pool: called when destroying the pool
> */
> -struct tee_shm_pool_mgr_ops {
> - int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm,
> - size_t size);
> - void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm);
> - void (*destroy_poolmgr)(struct tee_shm_pool_mgr *poolmgr);
> +struct tee_shm_pool_ops {
> + int (*alloc)(struct tee_shm_pool *pool, struct tee_shm *shm,
> + size_t size, size_t align);
> + void (*free)(struct tee_shm_pool *pool, struct tee_shm *shm);
> + void (*destroy_pool)(struct tee_shm_pool *pool);
> };
>
> -/**
> - * tee_shm_pool_alloc() - Create a shared memory pool from shm managers
> - * @priv_mgr: manager for driver private shared memory allocations
> - * @dmabuf_mgr: manager for dma-buf shared memory allocations
> - *
> - * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
> - * in @dmabuf, others will use the range provided by @priv.
> - *
> - * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> - */
> -struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr,
> - struct tee_shm_pool_mgr *dmabuf_mgr);
> -
> /*
> - * tee_shm_pool_mgr_alloc_res_mem() - Create a shm manager for reserved
> - * memory
> + * tee_shm_pool_alloc_res_mem() - Create a shm manager for reserved memory
> * @vaddr: Virtual address of start of pool
> * @paddr: Physical address of start of pool
> * @size: Size in bytes of the pool
> *
> - * @returns pointer to a 'struct tee_shm_pool_mgr' or an ERR_PTR on failure.
> - */
> -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);
> -
> -/**
> - * tee_shm_pool_mgr_destroy() - Free a shared memory manager
> + * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> */
> -static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
> -{
> - poolm->ops->destroy_poolmgr(poolm);
> -}
> +struct tee_shm_pool *tee_shm_pool_alloc_res_mem(unsigned long vaddr,
> + phys_addr_t paddr, size_t size,
> + int min_alloc_order);
>
> /**
> * tee_shm_pool_free() - Free a shared memory pool
> @@ -285,7 +262,10 @@ static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
> * The 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);
> +static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
> +{
> + pool->ops->destroy_pool(pool);
> +}
>
> /**
> * tee_get_drvdata() - Return driver_data pointer
> --
> 2.31.1
>

2022-01-21 21:17:48

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 05/12] tee: replace tee_shm_alloc()

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> tee_shm_alloc() is replaced by three new functions,
>
> tee_shm_alloc_user_buf() - for user mode allocations, replacing passing
> the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF
>
> tee_shm_alloc_kernel_buf() - for kernel mode allocations, slightly
> optimized compared to using the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF.
>
> tee_shm_alloc_priv_kernel_buf() - primarily for TEE driver internal use.
>

This name seems ambiguous to me and I would rather prefer it named as
tee_shm_alloc_priv_buf().

I noticed that you have done flags refactoring as part of patch #12.
So rest looks fine to me.

-Sumit

> This also makes the interface easier to use as we can get rid of the
> somewhat hard to use flags parameter.
>
> The TEE subsystem and the TEE drivers are updated to use the new
> functions instead.
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/tee/optee/call.c | 2 +-
> drivers/tee/optee/device.c | 5 +-
> drivers/tee/optee/ffa_abi.c | 4 +-
> drivers/tee/optee/smc_abi.c | 5 +-
> drivers/tee/tee_shm.c | 109 +++++++++++++++++++++++-------------
> include/linux/tee_drv.h | 17 +-----
> 6 files changed, 78 insertions(+), 64 deletions(-)
>
> diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
> index b25cc1fac945..fd6ad7d6fbee 100644
> --- a/drivers/tee/optee/call.c
> +++ b/drivers/tee/optee/call.c
> @@ -120,7 +120,7 @@ struct tee_shm *optee_get_msg_arg(struct tee_context *ctx, size_t num_params,
> if (optee->rpc_arg_count)
> sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count);
>
> - shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
> + shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
> if (IS_ERR(shm))
> return shm;
>
> diff --git a/drivers/tee/optee/device.c b/drivers/tee/optee/device.c
> index 128a2d2a50a1..f3947be13e2e 100644
> --- a/drivers/tee/optee/device.c
> +++ b/drivers/tee/optee/device.c
> @@ -121,10 +121,9 @@ static int __optee_enumerate_devices(u32 func)
> if (rc < 0 || !shm_size)
> goto out_sess;
>
> - device_shm = tee_shm_alloc(ctx, shm_size,
> - TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
> + device_shm = tee_shm_alloc_kernel_buf(ctx, shm_size);
> if (IS_ERR(device_shm)) {
> - pr_err("tee_shm_alloc failed\n");
> + pr_err("tee_shm_alloc_kernel_buf failed\n");
> rc = PTR_ERR(device_shm);
> goto out_sess;
> }
> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> index e690d9420966..18963f7e4d48 100644
> --- a/drivers/tee/optee/ffa_abi.c
> +++ b/drivers/tee/optee/ffa_abi.c
> @@ -439,8 +439,8 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
> break;
> case OPTEE_RPC_SHM_TYPE_KERNEL:
> - shm = tee_shm_alloc(ctx, arg->params[0].u.value.b,
> - TEE_SHM_MAPPED | TEE_SHM_PRIV);
> + shm = tee_shm_alloc_priv_kernel_buf(ctx,
> + arg->params[0].u.value.b);
> break;
> default:
> arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> index b679037ea794..196cd4316d7d 100644
> --- a/drivers/tee/optee/smc_abi.c
> +++ b/drivers/tee/optee/smc_abi.c
> @@ -650,7 +650,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
> break;
> case OPTEE_RPC_SHM_TYPE_KERNEL:
> - shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
> + shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
> break;
> default:
> arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> @@ -775,8 +775,7 @@ static void optee_handle_rpc(struct tee_context *ctx,
>
> switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
> case OPTEE_SMC_RPC_FUNC_ALLOC:
> - shm = tee_shm_alloc(ctx, param->a1,
> - TEE_SHM_MAPPED | TEE_SHM_PRIV);
> + shm = tee_shm_alloc_priv_kernel_buf(ctx, param->a1);
> if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
> reg_pair_from_64(&param->a1, &param->a2, pa);
> reg_pair_from_64(&param->a4, &param->a5,
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index 2c8ce0c6801a..d51bf97ce7e5 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -49,25 +49,14 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> tee_device_put(teedev);
> }
>
> -struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> +static struct tee_shm *shm_alloc_helper(struct tee_context *ctx, size_t size,
> + size_t align, u32 flags, int id)
> {
> struct tee_device *teedev = ctx->teedev;
> struct tee_shm *shm;
> - size_t align;
> void *ret;
> int rc;
>
> - if (!(flags & TEE_SHM_MAPPED)) {
> - dev_err(teedev->dev.parent,
> - "only mapped allocations supported\n");
> - return ERR_PTR(-EINVAL);
> - }
> -
> - if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_PRIV))) {
> - dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags);
> - return ERR_PTR(-EINVAL);
> - }
> -
> if (!tee_device_get(teedev))
> return ERR_PTR(-EINVAL);
>
> @@ -84,18 +73,16 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> }
>
> refcount_set(&shm->refcount, 1);
> - shm->flags = flags | TEE_SHM_POOL;
> + shm->flags = flags;
> + shm->id = id;
> +
> + /*
> + * We're assigning this as it is needed if the shm is to be
> + * registered. If this function returns OK then the caller expected
> + * to call teedev_ctx_get() or clear shm->ctx in case it's not
> + * needed any longer.
> + */
> shm->ctx = ctx;
> - if (flags & TEE_SHM_DMA_BUF) {
> - align = PAGE_SIZE;
> - /*
> - * Request to register the shm in the pool allocator below
> - * if supported.
> - */
> - shm->flags |= TEE_SHM_REGISTER;
> - } else {
> - align = 2 * sizeof(long);
> - }
>
> rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
> if (rc) {
> @@ -103,28 +90,14 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> goto err_kfree;
> }
>
> - if (flags & TEE_SHM_DMA_BUF) {
> - mutex_lock(&teedev->mutex);
> - shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
> - mutex_unlock(&teedev->mutex);
> - if (shm->id < 0) {
> - ret = ERR_PTR(shm->id);
> - goto err_pool_free;
> - }
> - }
> -
> teedev_ctx_get(ctx);
> -
> return shm;
> -err_pool_free:
> - teedev->pool->ops->free(teedev->pool, shm);
> err_kfree:
> kfree(shm);
> err_dev_put:
> tee_device_put(teedev);
> return ret;
> }
> -EXPORT_SYMBOL_GPL(tee_shm_alloc);
>
> /**
> * tee_shm_alloc_user_buf() - Allocate shared memory for user space
> @@ -140,7 +113,36 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc);
> */
> struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
> {
> - return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
> + u32 flags = TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_REGISTER |
> + TEE_SHM_POOL;
> + struct tee_device *teedev = ctx->teedev;
> + struct tee_shm *shm;
> + void *ret;
> + int id;
> +
> + mutex_lock(&teedev->mutex);
> + id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL);
> + mutex_unlock(&teedev->mutex);
> + if (id < 0)
> + return ERR_PTR(id);
> +
> + shm = shm_alloc_helper(ctx, size, PAGE_SIZE, flags, id);
> + if (IS_ERR(shm)) {
> + mutex_lock(&teedev->mutex);
> + idr_remove(&teedev->idr, id);
> + mutex_unlock(&teedev->mutex);
> + return shm;
> + }
> +
> + mutex_lock(&teedev->mutex);
> + ret = idr_replace(&teedev->idr, shm, id);
> + mutex_unlock(&teedev->mutex);
> + if (IS_ERR(ret)) {
> + tee_shm_free(shm);
> + return ret;
> + }
> +
> + return shm;
> }
> EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
>
> @@ -158,10 +160,37 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
> */
> struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
> {
> - return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED);
> + u32 flags = TEE_SHM_MAPPED | TEE_SHM_REGISTER | TEE_SHM_POOL;
> +
> + return shm_alloc_helper(ctx, size, PAGE_SIZE, flags, -1);
> }
> EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
>
> +/**
> + * tee_shm_alloc_priv_kernel_buf() - Allocate shared memory for a privatly
> + * shared kernel buffer
> + * @ctx: Context that allocates the shared memory
> + * @size: Requested size of shared memory
> + *
> + * This function returns similar shared memory as
> + * tee_shm_alloc_kernel_buf(), but with the difference that the memory
> + * might not be registered in secure world in case the driver supports
> + * passing memory not registered in advance.
> + *
> + * This function should normally only be used internally in the TEE
> + * drivers.
> + *
> + * @returns a pointer to 'struct tee_shm'
> + */
> +struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> + size_t size)
> +{
> + u32 flags = TEE_SHM_MAPPED | TEE_SHM_PRIV | TEE_SHM_POOL;
> +
> + return shm_alloc_helper(ctx, size, sizeof(long) * 2, flags, -1);
> +}
> +EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_kernel_buf);
> +
> struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> size_t length, u32 flags)
> {
> diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> index 808aa23308c2..e71cb0411e9c 100644
> --- a/include/linux/tee_drv.h
> +++ b/include/linux/tee_drv.h
> @@ -273,22 +273,9 @@ static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
> */
> void *tee_get_drvdata(struct tee_device *teedev);
>
> -/**
> - * tee_shm_alloc() - Allocate shared memory
> - * @ctx: Context that allocates the shared memory
> - * @size: Requested size of shared memory
> - * @flags: Flags setting properties for the requested shared memory.
> - *
> - * Memory allocated as global shared memory is automatically freed when the
> - * TEE file pointer is closed. The @flags field uses the bits defined by
> - * TEE_SHM_* above. TEE_SHM_MAPPED must currently always be set. If
> - * TEE_SHM_DMA_BUF global shared memory will be allocated and associated
> - * with a dma-buf handle, else driver private memory.
> - *
> - * @returns a pointer to 'struct tee_shm'
> - */
> -struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
> struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
> +struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> + size_t size);
> struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
>
> /**
> --
> 2.31.1
>

2022-01-21 21:21:58

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 08/12] optee: add optee_pool_op_free_helper()

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> Adds a common helper function to free a tee_shm allocated using the
> helper function optee_pool_op_alloc_helper().
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/tee/optee/core.c | 10 ++++++++++
> drivers/tee/optee/ffa_abi.c | 4 +---
> drivers/tee/optee/optee_private.h | 3 +++
> drivers/tee/optee/smc_abi.c | 7 +++----
> 4 files changed, 17 insertions(+), 7 deletions(-)
>

Reviewed-by: Sumit Garg <[email protected]>

-Sumit

> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> index f4bccb5f0e93..daf947e98d14 100644
> --- a/drivers/tee/optee/core.c
> +++ b/drivers/tee/optee/core.c
> @@ -69,6 +69,16 @@ int optee_pool_op_alloc_helper(struct tee_shm_pool *pool, struct tee_shm *shm,
> return rc;
> }
>
> +void optee_pool_op_free_helper(struct tee_shm_pool *pool, struct tee_shm *shm,
> + int (*shm_unregister)(struct tee_context *ctx,
> + struct tee_shm *shm))
> +{
> + if (shm_unregister)
> + shm_unregister(shm->ctx, shm);
> + free_pages((unsigned long)shm->kaddr, get_order(shm->size));
> + shm->kaddr = NULL;
> +}
> +
> static void optee_bus_scan(struct work_struct *work)
> {
> WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP));
> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> index 5ec484b42432..4cbc45035f92 100644
> --- a/drivers/tee/optee/ffa_abi.c
> +++ b/drivers/tee/optee/ffa_abi.c
> @@ -379,9 +379,7 @@ static int pool_ffa_op_alloc(struct tee_shm_pool *pool,
> static void pool_ffa_op_free(struct tee_shm_pool *pool,
> struct tee_shm *shm)
> {
> - optee_ffa_shm_unregister(shm->ctx, shm);
> - free_pages((unsigned long)shm->kaddr, get_order(shm->size));
> - shm->kaddr = NULL;
> + optee_pool_op_free_helper(pool, shm, optee_ffa_shm_unregister);
> }
>
> static void pool_ffa_op_destroy_pool(struct tee_shm_pool *pool)
> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> index df3a483bbf46..e77765c78878 100644
> --- a/drivers/tee/optee/optee_private.h
> +++ b/drivers/tee/optee/optee_private.h
> @@ -236,6 +236,9 @@ int optee_pool_op_alloc_helper(struct tee_shm_pool *pool, struct tee_shm *shm,
> struct page **pages,
> size_t num_pages,
> unsigned long start));
> +void optee_pool_op_free_helper(struct tee_shm_pool *pool, struct tee_shm *shm,
> + int (*shm_unregister)(struct tee_context *ctx,
> + struct tee_shm *shm));
>
>
> void optee_remove_common(struct optee *optee);
> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> index f2ef76451443..0b27688d1e97 100644
> --- a/drivers/tee/optee/smc_abi.c
> +++ b/drivers/tee/optee/smc_abi.c
> @@ -548,10 +548,9 @@ static void pool_op_free(struct tee_shm_pool *pool,
> struct tee_shm *shm)
> {
> if (!(shm->flags & TEE_SHM_PRIV))
> - optee_shm_unregister(shm->ctx, shm);
> -
> - free_pages((unsigned long)shm->kaddr, get_order(shm->size));
> - shm->kaddr = NULL;
> + optee_pool_op_free_helper(pool, shm, optee_shm_unregister);
> + else
> + optee_pool_op_free_helper(pool, shm, NULL);
> }
>
> static void pool_op_destroy_pool(struct tee_shm_pool *pool)
> --
> 2.31.1
>

2022-01-21 21:22:14

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 09/12] tee: add tee_shm_register_{user,kernel}_buf()

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> Adds the two new functions tee_shm_register_user_buf() and
> tee_shm_register_kernel_buf() which should be used instead of the old
> tee_shm_register().
>
> This avoids having the caller supplying the flags parameter which
> exposes a bit more than desired of the internals of the TEE subsystem.
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/tee/tee_core.c | 3 +--
> drivers/tee/tee_shm.c | 34 ++++++++++++++++++++++++++++++++++
> include/linux/tee_drv.h | 4 ++++
> 3 files changed, 39 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> index a15812baaeb1..8aa1a4836b92 100644
> --- a/drivers/tee/tee_core.c
> +++ b/drivers/tee/tee_core.c
> @@ -334,8 +334,7 @@ tee_ioctl_shm_register(struct tee_context *ctx,
> if (data.flags)
> return -EINVAL;
>
> - shm = tee_shm_register(ctx, data.addr, data.length,
> - TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
> + shm = tee_shm_register_user_buf(ctx, data.addr, data.length);
> if (IS_ERR(shm))
> return PTR_ERR(shm);
>
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index d51bf97ce7e5..6a1dbce75616 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -301,6 +301,40 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> }
> EXPORT_SYMBOL_GPL(tee_shm_register);
>
> +/**
> + * tee_shm_register_user_buf() - Register a userspace shared memory buffer
> + * @ctx: Context that registers the shared memory
> + * @addr: The userspace address of the shared buffer
> + * @length: Length of the shared buffer
> + *
> + * @returns a pointer to 'struct tee_shm'
> + */
> +struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> + unsigned long addr, size_t length)
> +{
> + return tee_shm_register(ctx, addr, length,
> + TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
> +}
> +EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
> +

Similar comment as for tee_shm_alloc_user_buf() in patch #3. This
isn't required to be exported but rather a private function to TEE
core.

-Sumit

> +/**
> + * tee_shm_register_kernel_buf() - Register kernel memory to be shared with
> + * secure world
> + * @ctx: Context that registers the shared memory
> + * @addr: The buffer
> + * @length: Length of the buffer
> + *
> + * @returns a pointer to 'struct tee_shm'
> + */
> +
> +struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> + void *addr, size_t length)
> +{
> + return tee_shm_register(ctx, (unsigned long)addr, length,
> + TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED);
> +}
> +EXPORT_SYMBOL_GPL(tee_shm_register_kernel_buf);
> +
> static int tee_shm_fop_release(struct inode *inode, struct file *filp)
> {
> tee_shm_put(filp->private_data);
> diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> index e71cb0411e9c..029c9a0590cc 100644
> --- a/include/linux/tee_drv.h
> +++ b/include/linux/tee_drv.h
> @@ -289,6 +289,10 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
> */
> struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> size_t length, u32 flags);
> +struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> + unsigned long addr, size_t length);
> +struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> + void *addr, size_t length);
>
> /**
> * tee_shm_is_registered() - Check if shared memory object in registered in TEE
> --
> 2.31.1
>

2022-01-21 21:23:30

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 10/12] KEYS: trusted: tee: use tee_shm_register_kernel_buf()

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> Uses the new simplified tee_shm_register_kernel_buf() function instead
> of the old tee_shm_alloc() function which required specific
> TEE_SHM-flags
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> security/keys/trusted-keys/trusted_tee.c | 23 +++++++++--------------
> 1 file changed, 9 insertions(+), 14 deletions(-)
>

Reviewed-by: Sumit Garg <[email protected]>

-Sumit

> diff --git a/security/keys/trusted-keys/trusted_tee.c b/security/keys/trusted-keys/trusted_tee.c
> index 2ce66c199e1d..c8626686ee1b 100644
> --- a/security/keys/trusted-keys/trusted_tee.c
> +++ b/security/keys/trusted-keys/trusted_tee.c
> @@ -70,17 +70,15 @@ static int trusted_tee_seal(struct trusted_key_payload *p, char *datablob)
> memset(&inv_arg, 0, sizeof(inv_arg));
> memset(&param, 0, sizeof(param));
>
> - reg_shm_in = tee_shm_register(pvt_data.ctx, (unsigned long)p->key,
> - p->key_len, TEE_SHM_DMA_BUF |
> - TEE_SHM_KERNEL_MAPPED);
> + reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
> + p->key_len);
> if (IS_ERR(reg_shm_in)) {
> dev_err(pvt_data.dev, "key shm register failed\n");
> return PTR_ERR(reg_shm_in);
> }
>
> - reg_shm_out = tee_shm_register(pvt_data.ctx, (unsigned long)p->blob,
> - sizeof(p->blob), TEE_SHM_DMA_BUF |
> - TEE_SHM_KERNEL_MAPPED);
> + reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob,
> + sizeof(p->blob));
> if (IS_ERR(reg_shm_out)) {
> dev_err(pvt_data.dev, "blob shm register failed\n");
> ret = PTR_ERR(reg_shm_out);
> @@ -131,17 +129,15 @@ static int trusted_tee_unseal(struct trusted_key_payload *p, char *datablob)
> memset(&inv_arg, 0, sizeof(inv_arg));
> memset(&param, 0, sizeof(param));
>
> - reg_shm_in = tee_shm_register(pvt_data.ctx, (unsigned long)p->blob,
> - p->blob_len, TEE_SHM_DMA_BUF |
> - TEE_SHM_KERNEL_MAPPED);
> + reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob,
> + p->blob_len);
> if (IS_ERR(reg_shm_in)) {
> dev_err(pvt_data.dev, "blob shm register failed\n");
> return PTR_ERR(reg_shm_in);
> }
>
> - reg_shm_out = tee_shm_register(pvt_data.ctx, (unsigned long)p->key,
> - sizeof(p->key), TEE_SHM_DMA_BUF |
> - TEE_SHM_KERNEL_MAPPED);
> + reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
> + sizeof(p->key));
> if (IS_ERR(reg_shm_out)) {
> dev_err(pvt_data.dev, "key shm register failed\n");
> ret = PTR_ERR(reg_shm_out);
> @@ -192,8 +188,7 @@ static int trusted_tee_get_random(unsigned char *key, size_t key_len)
> memset(&inv_arg, 0, sizeof(inv_arg));
> memset(&param, 0, sizeof(param));
>
> - reg_shm = tee_shm_register(pvt_data.ctx, (unsigned long)key, key_len,
> - TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED);
> + reg_shm = tee_shm_register_kernel_buf(pvt_data.ctx, key, key_len);
> if (IS_ERR(reg_shm)) {
> dev_err(pvt_data.dev, "key shm register failed\n");
> return PTR_ERR(reg_shm);
> --
> 2.31.1
>

2022-01-21 21:51:16

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 11/12] tee: replace tee_shm_register()

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> tee_shm_register() is replaced by the previously introduced functions
> tee_shm_register_user_buf() and tee_shm_register_kernel_buf().
>
> Since there are not external callers left we can remove tee_shm_register()
> and refactor the remains.
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/tee/tee_shm.c | 157 +++++++++++++++++++++++-----------------
> include/linux/tee_drv.h | 11 ---
> 2 files changed, 91 insertions(+), 77 deletions(-)
>
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index 6a1dbce75616..fe3e5977dd7c 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -12,17 +12,43 @@
> #include <linux/uio.h>
> #include "tee_private.h"
>
> +static void shm_put_kernel_pages(struct page **pages, unsigned long npages)
> +{
> + unsigned long n;

nit: Can we have a consistent prototype for the number of pages?
size_t as used by struct tee_shm or unsigned long? Same holds true for
variables below as well: npages, page_count, num_pages, n.

> +
> + for (n = 0; n < npages; n++)
> + put_page(pages[n]);
> +}
> +
> +static int shm_get_kernel_pages(unsigned long start, int page_count,
> + struct page **pages)
> +{
> + struct kvec *kiov;
> + unsigned int n;
> + int rc;
> +
> + kiov = kcalloc(page_count, sizeof(*kiov), GFP_KERNEL);
> + if (!kiov)
> + return -ENOMEM;
> +
> + for (n = 0; n < page_count; n++) {
> + kiov[n].iov_base = (void *)(start + n * PAGE_SIZE);
> + kiov[n].iov_len = PAGE_SIZE;
> + }
> +
> + rc = get_kernel_pages(kiov, page_count, 0, pages);
> + kfree(kiov);
> +
> + return rc;
> +}
> +
> static void release_registered_pages(struct tee_shm *shm)
> {
> if (shm->pages) {
> - if (shm->flags & TEE_SHM_USER_MAPPED) {
> + if (shm->flags & TEE_SHM_USER_MAPPED)
> unpin_user_pages(shm->pages, shm->num_pages);
> - } else {
> - size_t n;
> -
> - for (n = 0; n < shm->num_pages; n++)
> - put_page(shm->pages[n]);
> - }
> + else
> + shm_put_kernel_pages(shm->pages, shm->num_pages);
>
> kfree(shm->pages);
> }
> @@ -191,28 +217,24 @@ struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> }
> EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_kernel_buf);
>
> -struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> - size_t length, u32 flags)
> +static struct tee_shm *
> +register_shm_helper(struct tee_context *ctx, unsigned long addr,
> + size_t length, u32 flags, int id)
> {
> struct tee_device *teedev = ctx->teedev;
> - const u32 req_user_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED;
> - const u32 req_kernel_flags = TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED;
> struct tee_shm *shm;
> + unsigned long start;
> + int num_pages;
> void *ret;
> int rc;
> - int num_pages;
> - unsigned long start;
> -
> - if (flags != req_user_flags && flags != req_kernel_flags)
> - return ERR_PTR(-ENOTSUPP);
>
> if (!tee_device_get(teedev))
> return ERR_PTR(-EINVAL);
>
> if (!teedev->desc->ops->shm_register ||
> !teedev->desc->ops->shm_unregister) {
> - tee_device_put(teedev);
> - return ERR_PTR(-ENOTSUPP);
> + ret = ERR_PTR(-ENOTSUPP);

Checkpatch warns about this error code:

WARNING: ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP
#104: FILE: drivers/tee/tee_shm.c:236:
+ ret = ERR_PTR(-ENOTSUPP);

> + goto err_dev_put;
> }
>
> teedev_ctx_get(ctx);
> @@ -220,13 +242,13 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> shm = kzalloc(sizeof(*shm), GFP_KERNEL);
> if (!shm) {
> ret = ERR_PTR(-ENOMEM);
> - goto err;
> + goto err_ctx_put;
> }
>
> refcount_set(&shm->refcount, 1);
> - shm->flags = flags | TEE_SHM_REGISTER;
> + shm->flags = flags;
> shm->ctx = ctx;
> - shm->id = -1;
> + shm->id = id;
> addr = untagged_addr(addr);
> start = rounddown(addr, PAGE_SIZE);
> shm->offset = addr - start;
> @@ -235,71 +257,45 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> shm->pages = kcalloc(num_pages, sizeof(*shm->pages), GFP_KERNEL);
> if (!shm->pages) {
> ret = ERR_PTR(-ENOMEM);
> - goto err;
> + goto err_free_shm;
> }
>
> - if (flags & TEE_SHM_USER_MAPPED) {
> + if (flags & TEE_SHM_USER_MAPPED)
> rc = pin_user_pages_fast(start, num_pages, FOLL_WRITE,
> shm->pages);
> - } else {
> - struct kvec *kiov;
> - int i;
> -
> - kiov = kcalloc(num_pages, sizeof(*kiov), GFP_KERNEL);
> - if (!kiov) {
> - ret = ERR_PTR(-ENOMEM);
> - goto err;
> - }
> -
> - for (i = 0; i < num_pages; i++) {
> - kiov[i].iov_base = (void *)(start + i * PAGE_SIZE);
> - kiov[i].iov_len = PAGE_SIZE;
> - }
> -
> - rc = get_kernel_pages(kiov, num_pages, 0, shm->pages);
> - kfree(kiov);
> - }
> + else
> + rc = shm_get_kernel_pages(start, num_pages, shm->pages);
> if (rc > 0)
> shm->num_pages = rc;
> if (rc != num_pages) {
> if (rc >= 0)
> rc = -ENOMEM;
> ret = ERR_PTR(rc);
> - goto err;
> - }
> -
> - mutex_lock(&teedev->mutex);
> - shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
> - mutex_unlock(&teedev->mutex);
> -
> - if (shm->id < 0) {
> - ret = ERR_PTR(shm->id);
> - goto err;
> + goto err_put_shm_pages;
> }
>
> rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages,
> shm->num_pages, start);
> if (rc) {
> ret = ERR_PTR(rc);
> - goto err;
> + goto err_put_shm_pages;
> }
>
> return shm;
> -err:
> - if (shm) {
> - if (shm->id >= 0) {
> - mutex_lock(&teedev->mutex);
> - idr_remove(&teedev->idr, shm->id);
> - mutex_unlock(&teedev->mutex);
> - }
> - release_registered_pages(shm);
> - }
> +err_put_shm_pages:
> + if (flags & TEE_SHM_USER_MAPPED)
> + unpin_user_pages(shm->pages, shm->num_pages);
> + else
> + shm_put_kernel_pages(shm->pages, shm->num_pages);
> + kfree(shm->pages);
> +err_free_shm:
> kfree(shm);
> +err_ctx_put:
> teedev_ctx_put(ctx);
> +err_dev_put:
> tee_device_put(teedev);
> return ret;
> }
> -EXPORT_SYMBOL_GPL(tee_shm_register);
>
> /**
> * tee_shm_register_user_buf() - Register a userspace shared memory buffer
> @@ -312,8 +308,36 @@ EXPORT_SYMBOL_GPL(tee_shm_register);
> struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> unsigned long addr, size_t length)
> {
> - return tee_shm_register(ctx, addr, length,
> - TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
> + u32 f = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED | TEE_SHM_REGISTER;

nit: I would prefer to write variable name as "flags" for clarity.

> + struct tee_device *teedev = ctx->teedev;
> + struct tee_shm *shm;
> + void *ret;
> + int id;
> +
> + mutex_lock(&teedev->mutex);
> + id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL);
> + mutex_unlock(&teedev->mutex);
> +

nit: redundant extra line.

> + if (id < 0)
> + return ERR_PTR(id);
> +
> + shm = register_shm_helper(ctx, addr, length, f, id);
> + if (IS_ERR(shm)) {
> + mutex_lock(&teedev->mutex);
> + idr_remove(&teedev->idr, id);
> + mutex_unlock(&teedev->mutex);
> + return shm;
> + }
> +
> + mutex_lock(&teedev->mutex);
> + ret = idr_replace(&teedev->idr, shm, id);
> + mutex_unlock(&teedev->mutex);
> + if (IS_ERR(ret)) {
> + tee_shm_free(shm);
> + return ret;
> + }
> +
> + return shm;
> }
> EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
>
> @@ -330,8 +354,9 @@ EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
> struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> void *addr, size_t length)
> {
> - return tee_shm_register(ctx, (unsigned long)addr, length,
> - TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED);
> + u32 f = TEE_SHM_REGISTER | TEE_SHM_KERNEL_MAPPED;

Ditto.

-Sumit

> +
> + return register_shm_helper(ctx, (unsigned long)addr, length, f, -1);
> }
> EXPORT_SYMBOL_GPL(tee_shm_register_kernel_buf);
>
> diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> index 029c9a0590cc..e4f32885e273 100644
> --- a/include/linux/tee_drv.h
> +++ b/include/linux/tee_drv.h
> @@ -278,17 +278,6 @@ struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> size_t size);
> struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
>
> -/**
> - * tee_shm_register() - Register shared memory buffer
> - * @ctx: Context that registers the shared memory
> - * @addr: Address is userspace of the shared buffer
> - * @length: Length of the shared buffer
> - * @flags: Flags setting properties for the requested shared memory.
> - *
> - * @returns a pointer to 'struct tee_shm'
> - */
> -struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> - size_t length, u32 flags);
> struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> unsigned long addr, size_t length);
> struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> --
> 2.31.1
>

2022-01-21 22:02:51

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH v2 04/12] tee: simplify shm pool handling

On Thu, Jan 20, 2022 at 03:36:45PM +0530, Sumit Garg wrote:
> Hi Jens,
>
> Thanks for this cleanup.
>
> On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> >
> > 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 concious one.
>
> typo: s/concious/conscious/

Thanks

>
> AFAIU, the earlier design was to keep separate pools for differently
> aligned memory allocation (one for 8 bytes aligned, other for
> PAGE_SIZE aligned). But after this patch we would be mixing these
> allocations using a first-fit algorithm. Don't you think that it would
> lead to inefficient memory allocation (fragmentation) as compared to
> existing one?

These small private allocation are expected to be rather short lived
so if there is fragmentation it will typically we restricted to the first
pages.

>
> I think we need to be careful about allocation strategy for static
> shared memory as it's a constrained resource and if a particular
> device is using this approach then a kernel upgrade shouldn't cause
> any regressions for that device.

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 preassure from multiple threads on secure world. All in all I
believe this scales up and down better than fixed boundaries.

I was chosing somewhat large alignment to avoid increasing it again. I
have some patches in the pipe which will grow the typicall private shm
allocation to a page at a time which then will be used for multiple
argument structs at a time.


>
> >
> > 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.
> >
> > Signed-off-by: Jens Wiklander <[email protected]>
> > ---
> > drivers/tee/amdtee/shm_pool.c | 55 +++++-----------
> > drivers/tee/optee/Kconfig | 8 ---
> > drivers/tee/optee/core.c | 11 ++--
> > drivers/tee/optee/ffa_abi.c | 55 ++++------------
> > drivers/tee/optee/optee_private.h | 4 +-
> > drivers/tee/optee/smc_abi.c | 100 ++++++----------------------
> > drivers/tee/tee_private.h | 11 ----
> > drivers/tee/tee_shm.c | 29 ++++-----
> > drivers/tee/tee_shm_pool.c | 104 ++++++++++--------------------
> > include/linux/tee_drv.h | 58 ++++++-----------
> > 10 files changed, 126 insertions(+), 309 deletions(-)
> >
> > diff --git a/drivers/tee/amdtee/shm_pool.c b/drivers/tee/amdtee/shm_pool.c
> > index 065854e2db18..f87f96a291c9 100644
> > --- a/drivers/tee/amdtee/shm_pool.c
> > +++ b/drivers/tee/amdtee/shm_pool.c
> > @@ -8,13 +8,17 @@
> > #include <linux/psp-sev.h>
> > #include "amdtee_private.h"
> >
> > -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)
> > {
> > unsigned int order = get_order(size);
> > unsigned long va;
> > int rc;
> >
> > + /*
> > + * Ignore alignment since this is already going to be page aligned
> > + * and there's no need for any larger alignment.
> > + */
> > va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
> > if (!va)
> > return -ENOMEM;
> > @@ -34,7 +38,7 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm,
> > return 0;
> > }
> >
> > -static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
> > +static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm)
> > {
> > /* Unmap the shared memory from TEE */
> > amdtee_unmap_shmem(shm);
> > @@ -42,52 +46,25 @@ static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
> > 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,
> > };
> >
> > -static struct tee_shm_pool_mgr *pool_mem_mgr_alloc(void)
> > -{
> > - struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
> > -
> > - if (!mgr)
> > - return ERR_PTR(-ENOMEM);
> > -
> > - mgr->ops = &pool_ops;
> > -
> > - return mgr;
> > -}
> > -
> > struct tee_shm_pool *amdtee_config_shm(void)
> > {
> > - struct tee_shm_pool_mgr *priv_mgr;
> > - struct tee_shm_pool_mgr *dmabuf_mgr;
> > - void *rc;
> > + struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL);
> >
> > - rc = pool_mem_mgr_alloc();
> > - if (IS_ERR(rc))
> > - return rc;
> > - priv_mgr = rc;
> > -
> > - rc = pool_mem_mgr_alloc();
> > - if (IS_ERR(rc)) {
> > - tee_shm_pool_mgr_destroy(priv_mgr);
> > - return rc;
> > - }
> > - dmabuf_mgr = rc;
> > + if (!pool)
> > + return ERR_PTR(-ENOMEM);
> >
> > - 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);
> > - }
> > + pool->ops = &pool_ops;
> >
> > - return rc;
> > + return pool;
> > }
> > 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 1ca320885fad..2a369e346b85 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 20a1b1a3d965..e690d9420966 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)
> > {
> > @@ -813,7 +786,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> > if (!optee)
> > return -ENOMEM;
> >
> > - optee->pool = optee_ffa_config_dyn_shm();
> > + optee->pool = optee_ffa_shm_pool_alloc_pages();
> > if (IS_ERR(optee->pool)) {
> > rc = PTR_ERR(optee->pool);
> > optee->pool = NULL;
> > diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> > index 46f74ab07c7e..df2450921464 100644
> > --- a/drivers/tee/optee/optee_private.h
> > +++ b/drivers/tee/optee/optee_private.h
> > @@ -228,8 +228,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 449d6a72d289..b679037ea794 100644
> > --- a/drivers/tee/optee/smc_abi.c
> > +++ b/drivers/tee/optee/smc_abi.c
> > @@ -42,8 +42,6 @@
> > * 6. Driver initialization.
> > */
> >
> > -#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
> > -
> > /*
> > * 1. Convert between struct tee_param and struct optee_msg_param
> > *
> > @@ -532,20 +530,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 +554,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 +571,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;
> > }
> >
> > /*
> > @@ -1174,33 +1173,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)
> > {
> > @@ -1214,10 +1186,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) {
> > @@ -1235,11 +1204,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");
> > @@ -1247,35 +1211,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);
> > + rc = tee_shm_pool_alloc_res_mem(vaddr, paddr, size,
> > + 9 /* 512 bytes aligned */);
>
> Here you are specifying minimal allocation alignment to be 512 bytes?
> Wouldn't it be inefficient corresponding to 8 bytes aligned OP-TEE
> private memory allocation earlier?

I hope I've been able to address this above.

Thanks,
Jens

>
> -Sumit
>
> > if (IS_ERR(rc))
> > - goto err_free_priv_mgr;
> > - dmabuf_mgr = rc;
> > -
> > - rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
> > - 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;
> > }
> >
> > @@ -1396,7 +1338,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
> > diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
> > index e55204df31ce..72376cf38bc0 100644
> > --- a/drivers/tee/tee_private.h
> > +++ b/drivers/tee/tee_private.h
> > @@ -12,17 +12,6 @@
> > #include <linux/mutex.h>
> > #include <linux/types.h>
> >
> > -/**
> > - * struct tee_shm_pool - shared memory pool
> > - * @private_mgr: pool manager for shared memory only between kernel
> > - * and secure world
> > - * @dma_buf_mgr: pool manager for shared memory exported to user space
> > - */
> > -struct tee_shm_pool {
> > - struct tee_shm_pool_mgr *private_mgr;
> > - struct tee_shm_pool_mgr *dma_buf_mgr;
> > -};
> > -
> > #define TEE_DEVICE_FLAG_REGISTERED 0x1
> > #define TEE_MAX_DEV_NAME_LEN 32
> >
> > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > index b43178986985..2c8ce0c6801a 100644
> > --- a/drivers/tee/tee_shm.c
> > +++ b/drivers/tee/tee_shm.c
> > @@ -31,14 +31,7 @@ static void release_registered_pages(struct tee_shm *shm)
> > static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> > {
> > if (shm->flags & TEE_SHM_POOL) {
> > - struct tee_shm_pool_mgr *poolm;
> > -
> > - if (shm->flags & TEE_SHM_DMA_BUF)
> > - poolm = teedev->pool->dma_buf_mgr;
> > - else
> > - poolm = teedev->pool->private_mgr;
> > -
> > - poolm->ops->free(poolm, shm);
> > + teedev->pool->ops->free(teedev->pool, shm);
> > } else if (shm->flags & TEE_SHM_REGISTER) {
> > int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);
> >
> > @@ -59,8 +52,8 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> > struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > {
> > struct tee_device *teedev = ctx->teedev;
> > - struct tee_shm_pool_mgr *poolm = NULL;
> > struct tee_shm *shm;
> > + size_t align;
> > void *ret;
> > int rc;
> >
> > @@ -93,12 +86,18 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > refcount_set(&shm->refcount, 1);
> > shm->flags = flags | TEE_SHM_POOL;
> > shm->ctx = ctx;
> > - if (flags & TEE_SHM_DMA_BUF)
> > - poolm = teedev->pool->dma_buf_mgr;
> > - else
> > - poolm = teedev->pool->private_mgr;
> > + if (flags & TEE_SHM_DMA_BUF) {
> > + align = PAGE_SIZE;
> > + /*
> > + * Request to register the shm in the pool allocator below
> > + * if supported.
> > + */
> > + shm->flags |= TEE_SHM_REGISTER;
> > + } else {
> > + align = 2 * sizeof(long);
> > + }
> >
> > - rc = poolm->ops->alloc(poolm, shm, size);
> > + rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
> > if (rc) {
> > ret = ERR_PTR(rc);
> > goto err_kfree;
> > @@ -118,7 +117,7 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> >
> > return shm;
> > err_pool_free:
> > - poolm->ops->free(poolm, shm);
> > + teedev->pool->ops->free(teedev->pool, shm);
> > err_kfree:
> > kfree(shm);
> > err_dev_put:
> > diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
> > index 0e460347138a..71e0f8ae69aa 100644
> > --- a/drivers/tee/tee_shm_pool.c
> > +++ b/drivers/tee/tee_shm_pool.c
> > @@ -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);
> > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> > index 26b450484ac1..808aa23308c2 100644
> > --- a/include/linux/tee_drv.h
> > +++ b/include/linux/tee_drv.h
> > @@ -221,62 +221,39 @@ struct tee_shm {
> > };
> >
> > /**
> > - * struct tee_shm_pool_mgr - shared memory manager
> > + * struct tee_shm_pool - shared memory pool
> > * @ops: operations
> > * @private_data: private data for the shared memory manager
> > */
> > -struct tee_shm_pool_mgr {
> > - const struct tee_shm_pool_mgr_ops *ops;
> > +struct tee_shm_pool {
> > + const struct tee_shm_pool_ops *ops;
> > void *private_data;
> > };
> >
> > /**
> > - * struct tee_shm_pool_mgr_ops - shared memory pool manager operations
> > + * struct tee_shm_pool_ops - shared memory pool operations
> > * @alloc: called when allocating shared memory
> > * @free: called when freeing shared memory
> > - * @destroy_poolmgr: called when destroying the pool manager
> > + * @destroy_pool: called when destroying the pool
> > */
> > -struct tee_shm_pool_mgr_ops {
> > - int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm,
> > - size_t size);
> > - void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm);
> > - void (*destroy_poolmgr)(struct tee_shm_pool_mgr *poolmgr);
> > +struct tee_shm_pool_ops {
> > + int (*alloc)(struct tee_shm_pool *pool, struct tee_shm *shm,
> > + size_t size, size_t align);
> > + void (*free)(struct tee_shm_pool *pool, struct tee_shm *shm);
> > + void (*destroy_pool)(struct tee_shm_pool *pool);
> > };
> >
> > -/**
> > - * tee_shm_pool_alloc() - Create a shared memory pool from shm managers
> > - * @priv_mgr: manager for driver private shared memory allocations
> > - * @dmabuf_mgr: manager for dma-buf shared memory allocations
> > - *
> > - * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
> > - * in @dmabuf, others will use the range provided by @priv.
> > - *
> > - * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> > - */
> > -struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr,
> > - struct tee_shm_pool_mgr *dmabuf_mgr);
> > -
> > /*
> > - * tee_shm_pool_mgr_alloc_res_mem() - Create a shm manager for reserved
> > - * memory
> > + * tee_shm_pool_alloc_res_mem() - Create a shm manager for reserved memory
> > * @vaddr: Virtual address of start of pool
> > * @paddr: Physical address of start of pool
> > * @size: Size in bytes of the pool
> > *
> > - * @returns pointer to a 'struct tee_shm_pool_mgr' or an ERR_PTR on failure.
> > - */
> > -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);
> > -
> > -/**
> > - * tee_shm_pool_mgr_destroy() - Free a shared memory manager
> > + * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> > */
> > -static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
> > -{
> > - poolm->ops->destroy_poolmgr(poolm);
> > -}
> > +struct tee_shm_pool *tee_shm_pool_alloc_res_mem(unsigned long vaddr,
> > + phys_addr_t paddr, size_t size,
> > + int min_alloc_order);
> >
> > /**
> > * tee_shm_pool_free() - Free a shared memory pool
> > @@ -285,7 +262,10 @@ static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
> > * The 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);
> > +static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
> > +{
> > + pool->ops->destroy_pool(pool);
> > +}
> >
> > /**
> > * tee_get_drvdata() - Return driver_data pointer
> > --
> > 2.31.1
> >

2022-01-21 22:05:11

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH v2 05/12] tee: replace tee_shm_alloc()

On Thu, Jan 20, 2022 at 11:41 AM Sumit Garg <[email protected]> wrote:
>
> On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> >
> > tee_shm_alloc() is replaced by three new functions,
> >
> > tee_shm_alloc_user_buf() - for user mode allocations, replacing passing
> > the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF
> >
> > tee_shm_alloc_kernel_buf() - for kernel mode allocations, slightly
> > optimized compared to using the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF.
> >
> > tee_shm_alloc_priv_kernel_buf() - primarily for TEE driver internal use.
> >
>
> This name seems ambiguous to me and I would rather prefer it named as
> tee_shm_alloc_priv_buf().

OK, I'll rename it in the v3.

>
> I noticed that you have done flags refactoring as part of patch #12.
> So rest looks fine to me.

Thanks,
Jens

>
> -Sumit
>
> > This also makes the interface easier to use as we can get rid of the
> > somewhat hard to use flags parameter.
> >
> > The TEE subsystem and the TEE drivers are updated to use the new
> > functions instead.
> >
> > Signed-off-by: Jens Wiklander <[email protected]>
> > ---
> > drivers/tee/optee/call.c | 2 +-
> > drivers/tee/optee/device.c | 5 +-
> > drivers/tee/optee/ffa_abi.c | 4 +-
> > drivers/tee/optee/smc_abi.c | 5 +-
> > drivers/tee/tee_shm.c | 109 +++++++++++++++++++++++-------------
> > include/linux/tee_drv.h | 17 +-----
> > 6 files changed, 78 insertions(+), 64 deletions(-)
> >
> > diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
> > index b25cc1fac945..fd6ad7d6fbee 100644
> > --- a/drivers/tee/optee/call.c
> > +++ b/drivers/tee/optee/call.c
> > @@ -120,7 +120,7 @@ struct tee_shm *optee_get_msg_arg(struct tee_context *ctx, size_t num_params,
> > if (optee->rpc_arg_count)
> > sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count);
> >
> > - shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
> > + shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
> > if (IS_ERR(shm))
> > return shm;
> >
> > diff --git a/drivers/tee/optee/device.c b/drivers/tee/optee/device.c
> > index 128a2d2a50a1..f3947be13e2e 100644
> > --- a/drivers/tee/optee/device.c
> > +++ b/drivers/tee/optee/device.c
> > @@ -121,10 +121,9 @@ static int __optee_enumerate_devices(u32 func)
> > if (rc < 0 || !shm_size)
> > goto out_sess;
> >
> > - device_shm = tee_shm_alloc(ctx, shm_size,
> > - TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
> > + device_shm = tee_shm_alloc_kernel_buf(ctx, shm_size);
> > if (IS_ERR(device_shm)) {
> > - pr_err("tee_shm_alloc failed\n");
> > + pr_err("tee_shm_alloc_kernel_buf failed\n");
> > rc = PTR_ERR(device_shm);
> > goto out_sess;
> > }
> > diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> > index e690d9420966..18963f7e4d48 100644
> > --- a/drivers/tee/optee/ffa_abi.c
> > +++ b/drivers/tee/optee/ffa_abi.c
> > @@ -439,8 +439,8 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> > shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
> > break;
> > case OPTEE_RPC_SHM_TYPE_KERNEL:
> > - shm = tee_shm_alloc(ctx, arg->params[0].u.value.b,
> > - TEE_SHM_MAPPED | TEE_SHM_PRIV);
> > + shm = tee_shm_alloc_priv_kernel_buf(ctx,
> > + arg->params[0].u.value.b);
> > break;
> > default:
> > arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> > diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> > index b679037ea794..196cd4316d7d 100644
> > --- a/drivers/tee/optee/smc_abi.c
> > +++ b/drivers/tee/optee/smc_abi.c
> > @@ -650,7 +650,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> > shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
> > break;
> > case OPTEE_RPC_SHM_TYPE_KERNEL:
> > - shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
> > + shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
> > break;
> > default:
> > arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> > @@ -775,8 +775,7 @@ static void optee_handle_rpc(struct tee_context *ctx,
> >
> > switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
> > case OPTEE_SMC_RPC_FUNC_ALLOC:
> > - shm = tee_shm_alloc(ctx, param->a1,
> > - TEE_SHM_MAPPED | TEE_SHM_PRIV);
> > + shm = tee_shm_alloc_priv_kernel_buf(ctx, param->a1);
> > if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
> > reg_pair_from_64(&param->a1, &param->a2, pa);
> > reg_pair_from_64(&param->a4, &param->a5,
> > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > index 2c8ce0c6801a..d51bf97ce7e5 100644
> > --- a/drivers/tee/tee_shm.c
> > +++ b/drivers/tee/tee_shm.c
> > @@ -49,25 +49,14 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> > tee_device_put(teedev);
> > }
> >
> > -struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > +static struct tee_shm *shm_alloc_helper(struct tee_context *ctx, size_t size,
> > + size_t align, u32 flags, int id)
> > {
> > struct tee_device *teedev = ctx->teedev;
> > struct tee_shm *shm;
> > - size_t align;
> > void *ret;
> > int rc;
> >
> > - if (!(flags & TEE_SHM_MAPPED)) {
> > - dev_err(teedev->dev.parent,
> > - "only mapped allocations supported\n");
> > - return ERR_PTR(-EINVAL);
> > - }
> > -
> > - if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_PRIV))) {
> > - dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags);
> > - return ERR_PTR(-EINVAL);
> > - }
> > -
> > if (!tee_device_get(teedev))
> > return ERR_PTR(-EINVAL);
> >
> > @@ -84,18 +73,16 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > }
> >
> > refcount_set(&shm->refcount, 1);
> > - shm->flags = flags | TEE_SHM_POOL;
> > + shm->flags = flags;
> > + shm->id = id;
> > +
> > + /*
> > + * We're assigning this as it is needed if the shm is to be
> > + * registered. If this function returns OK then the caller expected
> > + * to call teedev_ctx_get() or clear shm->ctx in case it's not
> > + * needed any longer.
> > + */
> > shm->ctx = ctx;
> > - if (flags & TEE_SHM_DMA_BUF) {
> > - align = PAGE_SIZE;
> > - /*
> > - * Request to register the shm in the pool allocator below
> > - * if supported.
> > - */
> > - shm->flags |= TEE_SHM_REGISTER;
> > - } else {
> > - align = 2 * sizeof(long);
> > - }
> >
> > rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
> > if (rc) {
> > @@ -103,28 +90,14 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > goto err_kfree;
> > }
> >
> > - if (flags & TEE_SHM_DMA_BUF) {
> > - mutex_lock(&teedev->mutex);
> > - shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
> > - mutex_unlock(&teedev->mutex);
> > - if (shm->id < 0) {
> > - ret = ERR_PTR(shm->id);
> > - goto err_pool_free;
> > - }
> > - }
> > -
> > teedev_ctx_get(ctx);
> > -
> > return shm;
> > -err_pool_free:
> > - teedev->pool->ops->free(teedev->pool, shm);
> > err_kfree:
> > kfree(shm);
> > err_dev_put:
> > tee_device_put(teedev);
> > return ret;
> > }
> > -EXPORT_SYMBOL_GPL(tee_shm_alloc);
> >
> > /**
> > * tee_shm_alloc_user_buf() - Allocate shared memory for user space
> > @@ -140,7 +113,36 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc);
> > */
> > struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
> > {
> > - return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
> > + u32 flags = TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_REGISTER |
> > + TEE_SHM_POOL;
> > + struct tee_device *teedev = ctx->teedev;
> > + struct tee_shm *shm;
> > + void *ret;
> > + int id;
> > +
> > + mutex_lock(&teedev->mutex);
> > + id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL);
> > + mutex_unlock(&teedev->mutex);
> > + if (id < 0)
> > + return ERR_PTR(id);
> > +
> > + shm = shm_alloc_helper(ctx, size, PAGE_SIZE, flags, id);
> > + if (IS_ERR(shm)) {
> > + mutex_lock(&teedev->mutex);
> > + idr_remove(&teedev->idr, id);
> > + mutex_unlock(&teedev->mutex);
> > + return shm;
> > + }
> > +
> > + mutex_lock(&teedev->mutex);
> > + ret = idr_replace(&teedev->idr, shm, id);
> > + mutex_unlock(&teedev->mutex);
> > + if (IS_ERR(ret)) {
> > + tee_shm_free(shm);
> > + return ret;
> > + }
> > +
> > + return shm;
> > }
> > EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
> >
> > @@ -158,10 +160,37 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
> > */
> > struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
> > {
> > - return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED);
> > + u32 flags = TEE_SHM_MAPPED | TEE_SHM_REGISTER | TEE_SHM_POOL;
> > +
> > + return shm_alloc_helper(ctx, size, PAGE_SIZE, flags, -1);
> > }
> > EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
> >
> > +/**
> > + * tee_shm_alloc_priv_kernel_buf() - Allocate shared memory for a privatly
> > + * shared kernel buffer
> > + * @ctx: Context that allocates the shared memory
> > + * @size: Requested size of shared memory
> > + *
> > + * This function returns similar shared memory as
> > + * tee_shm_alloc_kernel_buf(), but with the difference that the memory
> > + * might not be registered in secure world in case the driver supports
> > + * passing memory not registered in advance.
> > + *
> > + * This function should normally only be used internally in the TEE
> > + * drivers.
> > + *
> > + * @returns a pointer to 'struct tee_shm'
> > + */
> > +struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> > + size_t size)
> > +{
> > + u32 flags = TEE_SHM_MAPPED | TEE_SHM_PRIV | TEE_SHM_POOL;
> > +
> > + return shm_alloc_helper(ctx, size, sizeof(long) * 2, flags, -1);
> > +}
> > +EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_kernel_buf);
> > +
> > struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > size_t length, u32 flags)
> > {
> > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> > index 808aa23308c2..e71cb0411e9c 100644
> > --- a/include/linux/tee_drv.h
> > +++ b/include/linux/tee_drv.h
> > @@ -273,22 +273,9 @@ static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
> > */
> > void *tee_get_drvdata(struct tee_device *teedev);
> >
> > -/**
> > - * tee_shm_alloc() - Allocate shared memory
> > - * @ctx: Context that allocates the shared memory
> > - * @size: Requested size of shared memory
> > - * @flags: Flags setting properties for the requested shared memory.
> > - *
> > - * Memory allocated as global shared memory is automatically freed when the
> > - * TEE file pointer is closed. The @flags field uses the bits defined by
> > - * TEE_SHM_* above. TEE_SHM_MAPPED must currently always be set. If
> > - * TEE_SHM_DMA_BUF global shared memory will be allocated and associated
> > - * with a dma-buf handle, else driver private memory.
> > - *
> > - * @returns a pointer to 'struct tee_shm'
> > - */
> > -struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
> > struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size);
> > +struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> > + size_t size);
> > struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
> >
> > /**
> > --
> > 2.31.1
> >

2022-01-21 22:05:25

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 12/12] tee: refactor TEE_SHM_* flags

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> Removes the redundant TEE_SHM_DMA_BUF, TEE_SHM_EXT_DMA_BUF,
> TEE_SHM_MAPPED and TEE_SHM_KERNEL_MAPPED flags.
>
> Assigns new values to the remaining flags to void gaps.
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/tee/tee_shm.c | 21 ++++++++++-----------
> include/linux/tee_drv.h | 12 ++++--------
> 2 files changed, 14 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index fe3e5977dd7c..9945bdec086b 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -139,8 +139,7 @@ static struct tee_shm *shm_alloc_helper(struct tee_context *ctx, size_t size,
> */
> struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
> {
> - u32 flags = TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_REGISTER |
> - TEE_SHM_POOL;
> + u32 flags = TEE_SHM_REGISTER | TEE_SHM_POOL;
> struct tee_device *teedev = ctx->teedev;
> struct tee_shm *shm;
> void *ret;
> @@ -186,7 +185,7 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
> */
> struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
> {
> - u32 flags = TEE_SHM_MAPPED | TEE_SHM_REGISTER | TEE_SHM_POOL;
> + u32 flags = TEE_SHM_REGISTER | TEE_SHM_POOL;
>
> return shm_alloc_helper(ctx, size, PAGE_SIZE, flags, -1);
> }
> @@ -211,7 +210,7 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
> struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> size_t size)
> {
> - u32 flags = TEE_SHM_MAPPED | TEE_SHM_PRIV | TEE_SHM_POOL;
> + u32 flags = TEE_SHM_PRIV | TEE_SHM_POOL;
>
> return shm_alloc_helper(ctx, size, sizeof(long) * 2, flags, -1);
> }
> @@ -308,7 +307,7 @@ register_shm_helper(struct tee_context *ctx, unsigned long addr,
> struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> unsigned long addr, size_t length)
> {
> - u32 f = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED | TEE_SHM_REGISTER;
> + u32 f = TEE_SHM_USER_MAPPED | TEE_SHM_REGISTER;
> struct tee_device *teedev = ctx->teedev;
> struct tee_shm *shm;
> void *ret;
> @@ -354,7 +353,7 @@ EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
> struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> void *addr, size_t length)
> {
> - u32 f = TEE_SHM_REGISTER | TEE_SHM_KERNEL_MAPPED;
> + u32 f = TEE_SHM_REGISTER;
>
> return register_shm_helper(ctx, (unsigned long)addr, length, f, -1);
> }
> @@ -398,7 +397,7 @@ int tee_shm_get_fd(struct tee_shm *shm)
> {
> int fd;
>
> - if (!(shm->flags & TEE_SHM_DMA_BUF))
> + if (shm->id < 0)
> return -EINVAL;
>
> /* matched by tee_shm_put() in tee_shm_op_release() */
> @@ -428,7 +427,7 @@ EXPORT_SYMBOL_GPL(tee_shm_free);
> */
> int tee_shm_va2pa(struct tee_shm *shm, void *va, phys_addr_t *pa)
> {
> - if (!(shm->flags & TEE_SHM_MAPPED))
> + if (!shm->kaddr)
> return -EINVAL;
> /* Check that we're in the range of the shm */
> if ((char *)va < (char *)shm->kaddr)
> @@ -450,7 +449,7 @@ EXPORT_SYMBOL_GPL(tee_shm_va2pa);
> */
> int tee_shm_pa2va(struct tee_shm *shm, phys_addr_t pa, void **va)
> {
> - if (!(shm->flags & TEE_SHM_MAPPED))
> + if (!shm->kaddr)
> return -EINVAL;
> /* Check that we're in the range of the shm */
> if (pa < shm->paddr)
> @@ -478,7 +477,7 @@ EXPORT_SYMBOL_GPL(tee_shm_pa2va);
> */
> void *tee_shm_get_va(struct tee_shm *shm, size_t offs)
> {
> - if (!(shm->flags & TEE_SHM_MAPPED))
> + if (!shm->kaddr)
> return ERR_PTR(-EINVAL);
> if (offs >= shm->size)
> return ERR_PTR(-EINVAL);
> @@ -553,7 +552,7 @@ void tee_shm_put(struct tee_shm *shm)
> * the refcount_inc() in tee_shm_get_from_id() never starts
> * from 0.
> */
> - if (shm->flags & TEE_SHM_DMA_BUF)
> + if (shm->id >= 0)
> idr_remove(&teedev->idr, shm->id);
> do_release = true;
> }
> diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> index e4f32885e273..dcc7a55e1128 100644
> --- a/include/linux/tee_drv.h
> +++ b/include/linux/tee_drv.h
> @@ -20,14 +20,10 @@
> * specific TEE driver.
> */
>
> -#define TEE_SHM_MAPPED BIT(0) /* Memory mapped by the kernel */
> -#define TEE_SHM_DMA_BUF BIT(1) /* Memory with dma-buf handle */
> -#define TEE_SHM_EXT_DMA_BUF BIT(2) /* Memory with dma-buf handle */
> -#define TEE_SHM_REGISTER BIT(3) /* Memory registered in secure world */
> -#define TEE_SHM_USER_MAPPED BIT(4) /* Memory mapped in user space */
> -#define TEE_SHM_POOL BIT(5) /* Memory allocated from pool */
> -#define TEE_SHM_KERNEL_MAPPED BIT(6) /* Memory mapped in kernel space */
> -#define TEE_SHM_PRIV BIT(7) /* Memory private to TEE driver */
> +#define TEE_SHM_REGISTER BIT(0) /* Memory registered in secure world */

TEE_SHM_REGISTER as a flag name seems ambiguous to me when it is being
used by both types of APIs tee_shm_alloc_* and tee_shm_register_*. Can
we rename it to TEE_SHM_DYNAMIC instead?

-Sumit

> +#define TEE_SHM_USER_MAPPED BIT(1) /* Memory mapped in user space */
> +#define TEE_SHM_POOL BIT(2) /* Memory allocated from pool */
> +#define TEE_SHM_PRIV BIT(3) /* Memory private to TEE driver */
>
> struct device;
> struct tee_device;
> --
> 2.31.1
>

2022-01-21 22:05:51

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH v2 09/12] tee: add tee_shm_register_{user,kernel}_buf()

On Thu, Jan 20, 2022 at 12:00 PM Sumit Garg <[email protected]> wrote:
>
> On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> >
> > Adds the two new functions tee_shm_register_user_buf() and
> > tee_shm_register_kernel_buf() which should be used instead of the old
> > tee_shm_register().
> >
> > This avoids having the caller supplying the flags parameter which
> > exposes a bit more than desired of the internals of the TEE subsystem.
> >
> > Signed-off-by: Jens Wiklander <[email protected]>
> > ---
> > drivers/tee/tee_core.c | 3 +--
> > drivers/tee/tee_shm.c | 34 ++++++++++++++++++++++++++++++++++
> > include/linux/tee_drv.h | 4 ++++
> > 3 files changed, 39 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> > index a15812baaeb1..8aa1a4836b92 100644
> > --- a/drivers/tee/tee_core.c
> > +++ b/drivers/tee/tee_core.c
> > @@ -334,8 +334,7 @@ tee_ioctl_shm_register(struct tee_context *ctx,
> > if (data.flags)
> > return -EINVAL;
> >
> > - shm = tee_shm_register(ctx, data.addr, data.length,
> > - TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
> > + shm = tee_shm_register_user_buf(ctx, data.addr, data.length);
> > if (IS_ERR(shm))
> > return PTR_ERR(shm);
> >
> > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > index d51bf97ce7e5..6a1dbce75616 100644
> > --- a/drivers/tee/tee_shm.c
> > +++ b/drivers/tee/tee_shm.c
> > @@ -301,6 +301,40 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > }
> > EXPORT_SYMBOL_GPL(tee_shm_register);
> >
> > +/**
> > + * tee_shm_register_user_buf() - Register a userspace shared memory buffer
> > + * @ctx: Context that registers the shared memory
> > + * @addr: The userspace address of the shared buffer
> > + * @length: Length of the shared buffer
> > + *
> > + * @returns a pointer to 'struct tee_shm'
> > + */
> > +struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> > + unsigned long addr, size_t length)
> > +{
> > + return tee_shm_register(ctx, addr, length,
> > + TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
> > +}
> > +EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
> > +
>
> Similar comment as for tee_shm_alloc_user_buf() in patch #3. This
> isn't required to be exported but rather a private function to TEE
> core.

OK, I'll fix it in v3.

Thanks,
Jens

>
> -Sumit
>
> > +/**
> > + * tee_shm_register_kernel_buf() - Register kernel memory to be shared with
> > + * secure world
> > + * @ctx: Context that registers the shared memory
> > + * @addr: The buffer
> > + * @length: Length of the buffer
> > + *
> > + * @returns a pointer to 'struct tee_shm'
> > + */
> > +
> > +struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> > + void *addr, size_t length)
> > +{
> > + return tee_shm_register(ctx, (unsigned long)addr, length,
> > + TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED);
> > +}
> > +EXPORT_SYMBOL_GPL(tee_shm_register_kernel_buf);
> > +
> > static int tee_shm_fop_release(struct inode *inode, struct file *filp)
> > {
> > tee_shm_put(filp->private_data);
> > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> > index e71cb0411e9c..029c9a0590cc 100644
> > --- a/include/linux/tee_drv.h
> > +++ b/include/linux/tee_drv.h
> > @@ -289,6 +289,10 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
> > */
> > struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > size_t length, u32 flags);
> > +struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> > + unsigned long addr, size_t length);
> > +struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> > + void *addr, size_t length);
> >
> > /**
> > * tee_shm_is_registered() - Check if shared memory object in registered in TEE
> > --
> > 2.31.1
> >

2022-01-21 22:14:00

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH v2 11/12] tee: replace tee_shm_register()

On Thu, Jan 20, 2022 at 12:51 PM Sumit Garg <[email protected]> wrote:
>
> On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> >
> > tee_shm_register() is replaced by the previously introduced functions
> > tee_shm_register_user_buf() and tee_shm_register_kernel_buf().
> >
> > Since there are not external callers left we can remove tee_shm_register()
> > and refactor the remains.
> >
> > Signed-off-by: Jens Wiklander <[email protected]>
> > ---
> > drivers/tee/tee_shm.c | 157 +++++++++++++++++++++++-----------------
> > include/linux/tee_drv.h | 11 ---
> > 2 files changed, 91 insertions(+), 77 deletions(-)
> >
> > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > index 6a1dbce75616..fe3e5977dd7c 100644
> > --- a/drivers/tee/tee_shm.c
> > +++ b/drivers/tee/tee_shm.c
> > @@ -12,17 +12,43 @@
> > #include <linux/uio.h>
> > #include "tee_private.h"
> >
> > +static void shm_put_kernel_pages(struct page **pages, unsigned long npages)
> > +{
> > + unsigned long n;
>
> nit: Can we have a consistent prototype for the number of pages?
> size_t as used by struct tee_shm or unsigned long? Same holds true for
> variables below as well: npages, page_count, num_pages, n.

Fair point, I'll fix what's changed here.

>
> > +
> > + for (n = 0; n < npages; n++)
> > + put_page(pages[n]);
> > +}
> > +
> > +static int shm_get_kernel_pages(unsigned long start, int page_count,
> > + struct page **pages)
> > +{
> > + struct kvec *kiov;
> > + unsigned int n;
> > + int rc;
> > +
> > + kiov = kcalloc(page_count, sizeof(*kiov), GFP_KERNEL);
> > + if (!kiov)
> > + return -ENOMEM;
> > +
> > + for (n = 0; n < page_count; n++) {
> > + kiov[n].iov_base = (void *)(start + n * PAGE_SIZE);
> > + kiov[n].iov_len = PAGE_SIZE;
> > + }
> > +
> > + rc = get_kernel_pages(kiov, page_count, 0, pages);
> > + kfree(kiov);
> > +
> > + return rc;
> > +}
> > +
> > static void release_registered_pages(struct tee_shm *shm)
> > {
> > if (shm->pages) {
> > - if (shm->flags & TEE_SHM_USER_MAPPED) {
> > + if (shm->flags & TEE_SHM_USER_MAPPED)
> > unpin_user_pages(shm->pages, shm->num_pages);
> > - } else {
> > - size_t n;
> > -
> > - for (n = 0; n < shm->num_pages; n++)
> > - put_page(shm->pages[n]);
> > - }
> > + else
> > + shm_put_kernel_pages(shm->pages, shm->num_pages);
> >
> > kfree(shm->pages);
> > }
> > @@ -191,28 +217,24 @@ struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> > }
> > EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_kernel_buf);
> >
> > -struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > - size_t length, u32 flags)
> > +static struct tee_shm *
> > +register_shm_helper(struct tee_context *ctx, unsigned long addr,
> > + size_t length, u32 flags, int id)
> > {
> > struct tee_device *teedev = ctx->teedev;
> > - const u32 req_user_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED;
> > - const u32 req_kernel_flags = TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED;
> > struct tee_shm *shm;
> > + unsigned long start;
> > + int num_pages;
> > void *ret;
> > int rc;
> > - int num_pages;
> > - unsigned long start;
> > -
> > - if (flags != req_user_flags && flags != req_kernel_flags)
> > - return ERR_PTR(-ENOTSUPP);
> >
> > if (!tee_device_get(teedev))
> > return ERR_PTR(-EINVAL);
> >
> > if (!teedev->desc->ops->shm_register ||
> > !teedev->desc->ops->shm_unregister) {
> > - tee_device_put(teedev);
> > - return ERR_PTR(-ENOTSUPP);
> > + ret = ERR_PTR(-ENOTSUPP);
>
> Checkpatch warns about this error code:
>
> WARNING: ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP
> #104: FILE: drivers/tee/tee_shm.c:236:
> + ret = ERR_PTR(-ENOTSUPP);

I noticed that too. I'd rather keep it as it is for now as changing
would a bit of a ABI change even if I doubt that anyone is depending
on this particular errno value.

>
> > + goto err_dev_put;
> > }
> >
> > teedev_ctx_get(ctx);
> > @@ -220,13 +242,13 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > shm = kzalloc(sizeof(*shm), GFP_KERNEL);
> > if (!shm) {
> > ret = ERR_PTR(-ENOMEM);
> > - goto err;
> > + goto err_ctx_put;
> > }
> >
> > refcount_set(&shm->refcount, 1);
> > - shm->flags = flags | TEE_SHM_REGISTER;
> > + shm->flags = flags;
> > shm->ctx = ctx;
> > - shm->id = -1;
> > + shm->id = id;
> > addr = untagged_addr(addr);
> > start = rounddown(addr, PAGE_SIZE);
> > shm->offset = addr - start;
> > @@ -235,71 +257,45 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > shm->pages = kcalloc(num_pages, sizeof(*shm->pages), GFP_KERNEL);
> > if (!shm->pages) {
> > ret = ERR_PTR(-ENOMEM);
> > - goto err;
> > + goto err_free_shm;
> > }
> >
> > - if (flags & TEE_SHM_USER_MAPPED) {
> > + if (flags & TEE_SHM_USER_MAPPED)
> > rc = pin_user_pages_fast(start, num_pages, FOLL_WRITE,
> > shm->pages);
> > - } else {
> > - struct kvec *kiov;
> > - int i;
> > -
> > - kiov = kcalloc(num_pages, sizeof(*kiov), GFP_KERNEL);
> > - if (!kiov) {
> > - ret = ERR_PTR(-ENOMEM);
> > - goto err;
> > - }
> > -
> > - for (i = 0; i < num_pages; i++) {
> > - kiov[i].iov_base = (void *)(start + i * PAGE_SIZE);
> > - kiov[i].iov_len = PAGE_SIZE;
> > - }
> > -
> > - rc = get_kernel_pages(kiov, num_pages, 0, shm->pages);
> > - kfree(kiov);
> > - }
> > + else
> > + rc = shm_get_kernel_pages(start, num_pages, shm->pages);
> > if (rc > 0)
> > shm->num_pages = rc;
> > if (rc != num_pages) {
> > if (rc >= 0)
> > rc = -ENOMEM;
> > ret = ERR_PTR(rc);
> > - goto err;
> > - }
> > -
> > - mutex_lock(&teedev->mutex);
> > - shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
> > - mutex_unlock(&teedev->mutex);
> > -
> > - if (shm->id < 0) {
> > - ret = ERR_PTR(shm->id);
> > - goto err;
> > + goto err_put_shm_pages;
> > }
> >
> > rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages,
> > shm->num_pages, start);
> > if (rc) {
> > ret = ERR_PTR(rc);
> > - goto err;
> > + goto err_put_shm_pages;
> > }
> >
> > return shm;
> > -err:
> > - if (shm) {
> > - if (shm->id >= 0) {
> > - mutex_lock(&teedev->mutex);
> > - idr_remove(&teedev->idr, shm->id);
> > - mutex_unlock(&teedev->mutex);
> > - }
> > - release_registered_pages(shm);
> > - }
> > +err_put_shm_pages:
> > + if (flags & TEE_SHM_USER_MAPPED)
> > + unpin_user_pages(shm->pages, shm->num_pages);
> > + else
> > + shm_put_kernel_pages(shm->pages, shm->num_pages);
> > + kfree(shm->pages);
> > +err_free_shm:
> > kfree(shm);
> > +err_ctx_put:
> > teedev_ctx_put(ctx);
> > +err_dev_put:
> > tee_device_put(teedev);
> > return ret;
> > }
> > -EXPORT_SYMBOL_GPL(tee_shm_register);
> >
> > /**
> > * tee_shm_register_user_buf() - Register a userspace shared memory buffer
> > @@ -312,8 +308,36 @@ EXPORT_SYMBOL_GPL(tee_shm_register);
> > struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> > unsigned long addr, size_t length)
> > {
> > - return tee_shm_register(ctx, addr, length,
> > - TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
> > + u32 f = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED | TEE_SHM_REGISTER;
>
> nit: I would prefer to write variable name as "flags" for clarity.
>
> > + struct tee_device *teedev = ctx->teedev;
> > + struct tee_shm *shm;
> > + void *ret;
> > + int id;
> > +
> > + mutex_lock(&teedev->mutex);
> > + id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL);
> > + mutex_unlock(&teedev->mutex);
> > +
>
> nit: redundant extra line.
>
> > + if (id < 0)
> > + return ERR_PTR(id);
> > +
> > + shm = register_shm_helper(ctx, addr, length, f, id);
> > + if (IS_ERR(shm)) {
> > + mutex_lock(&teedev->mutex);
> > + idr_remove(&teedev->idr, id);
> > + mutex_unlock(&teedev->mutex);
> > + return shm;
> > + }
> > +
> > + mutex_lock(&teedev->mutex);
> > + ret = idr_replace(&teedev->idr, shm, id);
> > + mutex_unlock(&teedev->mutex);
> > + if (IS_ERR(ret)) {
> > + tee_shm_free(shm);
> > + return ret;
> > + }
> > +
> > + return shm;
> > }
> > EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
> >
> > @@ -330,8 +354,9 @@ EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
> > struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> > void *addr, size_t length)
> > {
> > - return tee_shm_register(ctx, (unsigned long)addr, length,
> > - TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED);
> > + u32 f = TEE_SHM_REGISTER | TEE_SHM_KERNEL_MAPPED;
>
> Ditto.

Thanks,
Jens

>
> -Sumit
>
> > +
> > + return register_shm_helper(ctx, (unsigned long)addr, length, f, -1);
> > }
> > EXPORT_SYMBOL_GPL(tee_shm_register_kernel_buf);
> >
> > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> > index 029c9a0590cc..e4f32885e273 100644
> > --- a/include/linux/tee_drv.h
> > +++ b/include/linux/tee_drv.h
> > @@ -278,17 +278,6 @@ struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> > size_t size);
> > struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
> >
> > -/**
> > - * tee_shm_register() - Register shared memory buffer
> > - * @ctx: Context that registers the shared memory
> > - * @addr: Address is userspace of the shared buffer
> > - * @length: Length of the shared buffer
> > - * @flags: Flags setting properties for the requested shared memory.
> > - *
> > - * @returns a pointer to 'struct tee_shm'
> > - */
> > -struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > - size_t length, u32 flags);
> > struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> > unsigned long addr, size_t length);
> > struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> > --
> > 2.31.1
> >

2022-01-22 00:36:49

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH v2 12/12] tee: refactor TEE_SHM_* flags

On Thu, Jan 20, 2022 at 2:04 PM Sumit Garg <[email protected]> wrote:
>
> On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> >
> > Removes the redundant TEE_SHM_DMA_BUF, TEE_SHM_EXT_DMA_BUF,
> > TEE_SHM_MAPPED and TEE_SHM_KERNEL_MAPPED flags.
> >
> > Assigns new values to the remaining flags to void gaps.
> >
> > Signed-off-by: Jens Wiklander <[email protected]>
> > ---
> > drivers/tee/tee_shm.c | 21 ++++++++++-----------
> > include/linux/tee_drv.h | 12 ++++--------
> > 2 files changed, 14 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > index fe3e5977dd7c..9945bdec086b 100644
> > --- a/drivers/tee/tee_shm.c
> > +++ b/drivers/tee/tee_shm.c
> > @@ -139,8 +139,7 @@ static struct tee_shm *shm_alloc_helper(struct tee_context *ctx, size_t size,
> > */
> > struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
> > {
> > - u32 flags = TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_REGISTER |
> > - TEE_SHM_POOL;
> > + u32 flags = TEE_SHM_REGISTER | TEE_SHM_POOL;
> > struct tee_device *teedev = ctx->teedev;
> > struct tee_shm *shm;
> > void *ret;
> > @@ -186,7 +185,7 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc_user_buf);
> > */
> > struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
> > {
> > - u32 flags = TEE_SHM_MAPPED | TEE_SHM_REGISTER | TEE_SHM_POOL;
> > + u32 flags = TEE_SHM_REGISTER | TEE_SHM_POOL;
> >
> > return shm_alloc_helper(ctx, size, PAGE_SIZE, flags, -1);
> > }
> > @@ -211,7 +210,7 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
> > struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> > size_t size)
> > {
> > - u32 flags = TEE_SHM_MAPPED | TEE_SHM_PRIV | TEE_SHM_POOL;
> > + u32 flags = TEE_SHM_PRIV | TEE_SHM_POOL;
> >
> > return shm_alloc_helper(ctx, size, sizeof(long) * 2, flags, -1);
> > }
> > @@ -308,7 +307,7 @@ register_shm_helper(struct tee_context *ctx, unsigned long addr,
> > struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> > unsigned long addr, size_t length)
> > {
> > - u32 f = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED | TEE_SHM_REGISTER;
> > + u32 f = TEE_SHM_USER_MAPPED | TEE_SHM_REGISTER;
> > struct tee_device *teedev = ctx->teedev;
> > struct tee_shm *shm;
> > void *ret;
> > @@ -354,7 +353,7 @@ EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
> > struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> > void *addr, size_t length)
> > {
> > - u32 f = TEE_SHM_REGISTER | TEE_SHM_KERNEL_MAPPED;
> > + u32 f = TEE_SHM_REGISTER;
> >
> > return register_shm_helper(ctx, (unsigned long)addr, length, f, -1);
> > }
> > @@ -398,7 +397,7 @@ int tee_shm_get_fd(struct tee_shm *shm)
> > {
> > int fd;
> >
> > - if (!(shm->flags & TEE_SHM_DMA_BUF))
> > + if (shm->id < 0)
> > return -EINVAL;
> >
> > /* matched by tee_shm_put() in tee_shm_op_release() */
> > @@ -428,7 +427,7 @@ EXPORT_SYMBOL_GPL(tee_shm_free);
> > */
> > int tee_shm_va2pa(struct tee_shm *shm, void *va, phys_addr_t *pa)
> > {
> > - if (!(shm->flags & TEE_SHM_MAPPED))
> > + if (!shm->kaddr)
> > return -EINVAL;
> > /* Check that we're in the range of the shm */
> > if ((char *)va < (char *)shm->kaddr)
> > @@ -450,7 +449,7 @@ EXPORT_SYMBOL_GPL(tee_shm_va2pa);
> > */
> > int tee_shm_pa2va(struct tee_shm *shm, phys_addr_t pa, void **va)
> > {
> > - if (!(shm->flags & TEE_SHM_MAPPED))
> > + if (!shm->kaddr)
> > return -EINVAL;
> > /* Check that we're in the range of the shm */
> > if (pa < shm->paddr)
> > @@ -478,7 +477,7 @@ EXPORT_SYMBOL_GPL(tee_shm_pa2va);
> > */
> > void *tee_shm_get_va(struct tee_shm *shm, size_t offs)
> > {
> > - if (!(shm->flags & TEE_SHM_MAPPED))
> > + if (!shm->kaddr)
> > return ERR_PTR(-EINVAL);
> > if (offs >= shm->size)
> > return ERR_PTR(-EINVAL);
> > @@ -553,7 +552,7 @@ void tee_shm_put(struct tee_shm *shm)
> > * the refcount_inc() in tee_shm_get_from_id() never starts
> > * from 0.
> > */
> > - if (shm->flags & TEE_SHM_DMA_BUF)
> > + if (shm->id >= 0)
> > idr_remove(&teedev->idr, shm->id);
> > do_release = true;
> > }
> > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> > index e4f32885e273..dcc7a55e1128 100644
> > --- a/include/linux/tee_drv.h
> > +++ b/include/linux/tee_drv.h
> > @@ -20,14 +20,10 @@
> > * specific TEE driver.
> > */
> >
> > -#define TEE_SHM_MAPPED BIT(0) /* Memory mapped by the kernel */
> > -#define TEE_SHM_DMA_BUF BIT(1) /* Memory with dma-buf handle */
> > -#define TEE_SHM_EXT_DMA_BUF BIT(2) /* Memory with dma-buf handle */
> > -#define TEE_SHM_REGISTER BIT(3) /* Memory registered in secure world */
> > -#define TEE_SHM_USER_MAPPED BIT(4) /* Memory mapped in user space */
> > -#define TEE_SHM_POOL BIT(5) /* Memory allocated from pool */
> > -#define TEE_SHM_KERNEL_MAPPED BIT(6) /* Memory mapped in kernel space */
> > -#define TEE_SHM_PRIV BIT(7) /* Memory private to TEE driver */
> > +#define TEE_SHM_REGISTER BIT(0) /* Memory registered in secure world */
>
> TEE_SHM_REGISTER as a flag name seems ambiguous to me when it is being
> used by both types of APIs tee_shm_alloc_* and tee_shm_register_*. Can
> we rename it to TEE_SHM_DYNAMIC instead?

Sure, I'll fix that in v3.

Thanks,
Jens

>
> -Sumit
>
> > +#define TEE_SHM_USER_MAPPED BIT(1) /* Memory mapped in user space */
> > +#define TEE_SHM_POOL BIT(2) /* Memory allocated from pool */
> > +#define TEE_SHM_PRIV BIT(3) /* Memory private to TEE driver */
> >
> > struct device;
> > struct tee_device;
> > --
> > 2.31.1
> >

2022-01-22 01:15:04

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 06/12] optee: add driver private tee_context

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> Adds a driver private tee_context by moving the tee_context in struct
> optee_notif to struct optee. This tee_context is used when doing
> internal calls to secure world to deliver notification and later also
> when sharing driver private memory with secure world.
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/tee/optee/core.c | 1 +
> drivers/tee/optee/ffa_abi.c | 61 ++++++++++++++++++-------------
> drivers/tee/optee/optee_private.h | 5 ++-
> drivers/tee/optee/smc_abi.c | 40 ++++++--------------
> 4 files changed, 51 insertions(+), 56 deletions(-)
>

After looking at this patch, it looks like there is a need for some
more refactoring to pick out common probe functionality from both ABIs
and add optee_probe_common(). If it was there earlier, this patch
would mostly be modifying the OP-TEE core file apart from
notifications stuff.

I would leave it upto you to have a refactoring patch before and then
changes in this patch or vice-versa.

-Sumit

> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> index 2a369e346b85..f4bccb5f0e93 100644
> --- a/drivers/tee/optee/core.c
> +++ b/drivers/tee/optee/core.c
> @@ -161,6 +161,7 @@ void optee_remove_common(struct optee *optee)
> optee_unregister_devices();
>
> optee_notif_uninit(optee);
> + teedev_close_context(optee->ctx);
> /*
> * The two devices have to be unregistered before we can free the
> * other resources.
> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> index 18963f7e4d48..88a028d4fb7b 100644
> --- a/drivers/tee/optee/ffa_abi.c
> +++ b/drivers/tee/optee/ffa_abi.c
> @@ -766,7 +766,9 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> {
> const struct ffa_dev_ops *ffa_ops;
> unsigned int rpc_arg_count;
> + struct tee_shm_pool *pool;
> struct tee_device *teedev;
> + struct tee_context *ctx;
> struct optee *optee;
> int rc;
>
> @@ -786,12 +788,12 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> if (!optee)
> return -ENOMEM;
>
> - optee->pool = optee_ffa_shm_pool_alloc_pages();
> - if (IS_ERR(optee->pool)) {
> - rc = PTR_ERR(optee->pool);
> - optee->pool = NULL;
> - goto err;
> + pool = optee_ffa_shm_pool_alloc_pages();
> + if (IS_ERR(pool)) {
> + rc = PTR_ERR(pool);
> + goto err_free_optee;
> }
> + optee->pool = pool;
>
> optee->ops = &optee_ffa_ops;
> optee->ffa.ffa_dev = ffa_dev;
> @@ -802,7 +804,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> optee);
> if (IS_ERR(teedev)) {
> rc = PTR_ERR(teedev);
> - goto err;
> + goto err_free_pool;
> }
> optee->teedev = teedev;
>
> @@ -810,50 +812,57 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> optee);
> if (IS_ERR(teedev)) {
> rc = PTR_ERR(teedev);
> - goto err;
> + goto err_unreg_teedev;
> }
> optee->supp_teedev = teedev;
>
> rc = tee_device_register(optee->teedev);
> if (rc)
> - goto err;
> + goto err_unreg_supp_teedev;
>
> rc = tee_device_register(optee->supp_teedev);
> if (rc)
> - goto err;
> + goto err_unreg_supp_teedev;
>
> rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
> if (rc)
> - goto err;
> + goto err_unreg_supp_teedev;
> mutex_init(&optee->ffa.mutex);
> mutex_init(&optee->call_queue.mutex);
> INIT_LIST_HEAD(&optee->call_queue.waiters);
> optee_supp_init(&optee->supp);
> ffa_dev_set_drvdata(ffa_dev, optee);
> + ctx = teedev_open(optee->teedev);
> + if (IS_ERR(ctx))
> + goto err_rhashtable_free;
> + optee->ctx = ctx;
> rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE);
> - if (rc) {
> - optee_ffa_remove(ffa_dev);
> - return rc;
> - }
> + if (rc)
> + goto err_close_ctx;
>
> rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
> - if (rc) {
> - optee_ffa_remove(ffa_dev);
> - return rc;
> - }
> + if (rc)
> + goto err_unregister_devices;
>
> pr_info("initialized driver\n");
> return 0;
> -err:
> - /*
> - * tee_device_unregister() is safe to call even if the
> - * devices hasn't been registered with
> - * tee_device_register() yet.
> - */
> +
> +err_unregister_devices:
> + optee_unregister_devices();
> + optee_notif_uninit(optee);
> +err_close_ctx:
> + teedev_close_context(ctx);
> +err_rhashtable_free:
> + rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL);
> + optee_supp_uninit(&optee->supp);
> + mutex_destroy(&optee->call_queue.mutex);
> +err_unreg_supp_teedev:
> tee_device_unregister(optee->supp_teedev);
> +err_unreg_teedev:
> tee_device_unregister(optee->teedev);
> - if (optee->pool)
> - tee_shm_pool_free(optee->pool);
> +err_free_pool:
> + tee_shm_pool_free(pool);
> +err_free_optee:
> kfree(optee);
> return rc;
> }
> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> index df2450921464..df3a483bbf46 100644
> --- a/drivers/tee/optee/optee_private.h
> +++ b/drivers/tee/optee/optee_private.h
> @@ -53,7 +53,6 @@ struct optee_call_queue {
>
> struct optee_notif {
> u_int max_key;
> - struct tee_context *ctx;
> /* Serializes access to the elements below in this struct */
> spinlock_t lock;
> struct list_head db;
> @@ -134,9 +133,10 @@ struct optee_ops {
> /**
> * struct optee - main service struct
> * @supp_teedev: supplicant device
> + * @teedev: client device
> * @ops: internal callbacks for different ways to reach secure
> * world
> - * @teedev: client device
> + * @ctx: driver internal TEE context
> * @smc: specific to SMC ABI
> * @ffa: specific to FF-A ABI
> * @call_queue: queue of threads waiting to call @invoke_fn
> @@ -152,6 +152,7 @@ struct optee {
> struct tee_device *supp_teedev;
> struct tee_device *teedev;
> const struct optee_ops *ops;
> + struct tee_context *ctx;
> union {
> struct optee_smc smc;
> struct optee_ffa ffa;
> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> index 196cd4316d7d..1dbb13b08381 100644
> --- a/drivers/tee/optee/smc_abi.c
> +++ b/drivers/tee/optee/smc_abi.c
> @@ -952,57 +952,34 @@ static irqreturn_t notif_irq_thread_fn(int irq, void *dev_id)
> {
> struct optee *optee = dev_id;
>
> - optee_smc_do_bottom_half(optee->notif.ctx);
> + optee_smc_do_bottom_half(optee->ctx);
>
> return IRQ_HANDLED;
> }
>
> static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
> {
> - struct tee_context *ctx;
> int rc;
>
> - ctx = teedev_open(optee->teedev);
> - if (IS_ERR(ctx))
> - return PTR_ERR(ctx);
> -
> - optee->notif.ctx = ctx;
> rc = request_threaded_irq(irq, notif_irq_handler,
> notif_irq_thread_fn,
> 0, "optee_notification", optee);
> if (rc)
> - goto err_close_ctx;
> + return rc;
>
> optee->smc.notif_irq = irq;
>
> return 0;
> -
> -err_close_ctx:
> - teedev_close_context(optee->notif.ctx);
> - optee->notif.ctx = NULL;
> -
> - return rc;
> }
>
> static void optee_smc_notif_uninit_irq(struct optee *optee)
> {
> - if (optee->notif.ctx) {
> - optee_smc_stop_async_notif(optee->notif.ctx);
> + if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
> + optee_smc_stop_async_notif(optee->ctx);
> if (optee->smc.notif_irq) {
> free_irq(optee->smc.notif_irq, optee);
> irq_dispose_mapping(optee->smc.notif_irq);
> }
> -
> - /*
> - * The thread normally working with optee->notif.ctx was
> - * stopped with free_irq() above.
> - *
> - * Note we're not using teedev_close_context() or
> - * tee_client_close_context() since we have already called
> - * tee_device_put() while initializing to avoid a circular
> - * reference counting.
> - */
> - teedev_close_context(optee->notif.ctx);
> }
> }
>
> @@ -1307,6 +1284,7 @@ static int optee_probe(struct platform_device *pdev)
> struct optee *optee = NULL;
> void *memremaped_shm = NULL;
> struct tee_device *teedev;
> + struct tee_context *ctx;
> u32 max_notif_value;
> u32 sec_caps;
> int rc;
> @@ -1387,9 +1365,13 @@ static int optee_probe(struct platform_device *pdev)
> optee->pool = pool;
>
> platform_set_drvdata(pdev, optee);
> + ctx = teedev_open(optee->teedev);
> + if (IS_ERR(ctx))
> + goto err_supp_uninit;
> + optee->ctx = ctx;
> rc = optee_notif_init(optee, max_notif_value);
> if (rc)
> - goto err_supp_uninit;
> + goto err_close_ctx;
>
> if (sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
> unsigned int irq;
> @@ -1437,6 +1419,8 @@ static int optee_probe(struct platform_device *pdev)
> optee_unregister_devices();
> err_notif_uninit:
> optee_notif_uninit(optee);
> +err_close_ctx:
> + teedev_close_context(ctx);
> err_supp_uninit:
> optee_supp_uninit(&optee->supp);
> mutex_destroy(&optee->call_queue.mutex);
> --
> 2.31.1
>

2022-01-22 01:19:34

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 07/12] optee: use driver internal tee_contex for some rpc

+ Jerome, Etienne

On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>
> Uses the new driver internal tee_context when allocating driver private
> shared memory. This decouples the shared memory object from its original
> tee_context. This is needed when the life time of such a memory
> allocation outlives the client tee_context.
>
> Signed-off-by: Jens Wiklander <[email protected]>
> ---
> drivers/tee/optee/ffa_abi.c | 16 ++++++++--------
> drivers/tee/optee/smc_abi.c | 7 ++++---
> 2 files changed, 12 insertions(+), 11 deletions(-)
>

I guess with this patch we should no longer see issues [1] reported earlier.

FWIW,

Reviewed-by: Sumit Garg <[email protected]>

[1] https://github.com/OP-TEE/optee_os/issues/1918

-Sumit

> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> index 88a028d4fb7b..5ec484b42432 100644
> --- a/drivers/tee/optee/ffa_abi.c
> +++ b/drivers/tee/optee/ffa_abi.c
> @@ -424,6 +424,7 @@ static struct tee_shm_pool *optee_ffa_shm_pool_alloc_pages(void)
> */
>
> static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> + struct optee *optee,
> struct optee_msg_arg *arg)
> {
> struct tee_shm *shm;
> @@ -439,7 +440,7 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
> break;
> case OPTEE_RPC_SHM_TYPE_KERNEL:
> - shm = tee_shm_alloc_priv_kernel_buf(ctx,
> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx,
> arg->params[0].u.value.b);
> break;
> default:
> @@ -493,14 +494,13 @@ static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx,
> }
>
> static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
> + struct optee *optee,
> struct optee_msg_arg *arg)
> {
> - struct optee *optee = tee_get_drvdata(ctx->teedev);
> -
> arg->ret_origin = TEEC_ORIGIN_COMMS;
> switch (arg->cmd) {
> case OPTEE_RPC_CMD_SHM_ALLOC:
> - handle_ffa_rpc_func_cmd_shm_alloc(ctx, arg);
> + handle_ffa_rpc_func_cmd_shm_alloc(ctx, optee, arg);
> break;
> case OPTEE_RPC_CMD_SHM_FREE:
> handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg);
> @@ -510,12 +510,12 @@ static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
> }
> }
>
> -static void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd,
> - struct optee_msg_arg *arg)
> +static void optee_handle_ffa_rpc(struct tee_context *ctx, struct optee *optee,
> + u32 cmd, struct optee_msg_arg *arg)
> {
> switch (cmd) {
> case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
> - handle_ffa_rpc_func_cmd(ctx, arg);
> + handle_ffa_rpc_func_cmd(ctx, optee, arg);
> break;
> case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
> /* Interrupt delivered by now */
> @@ -582,7 +582,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx,
> * above.
> */
> cond_resched();
> - optee_handle_ffa_rpc(ctx, data->data1, rpc_arg);
> + optee_handle_ffa_rpc(ctx, optee, data->data1, rpc_arg);
> cmd = OPTEE_FFA_YIELDING_CALL_RESUME;
> data->data0 = cmd;
> data->data1 = 0;
> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> index 1dbb13b08381..f2ef76451443 100644
> --- a/drivers/tee/optee/smc_abi.c
> +++ b/drivers/tee/optee/smc_abi.c
> @@ -621,6 +621,7 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
> }
>
> static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> + struct optee *optee,
> struct optee_msg_arg *arg,
> struct optee_call_ctx *call_ctx)
> {
> @@ -650,7 +651,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
> break;
> case OPTEE_RPC_SHM_TYPE_KERNEL:
> - shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx, sz);
> break;
> default:
> arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> @@ -746,7 +747,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
> switch (arg->cmd) {
> case OPTEE_RPC_CMD_SHM_ALLOC:
> free_pages_list(call_ctx);
> - handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
> + handle_rpc_func_cmd_shm_alloc(ctx, optee, arg, call_ctx);
> break;
> case OPTEE_RPC_CMD_SHM_FREE:
> handle_rpc_func_cmd_shm_free(ctx, arg);
> @@ -775,7 +776,7 @@ static void optee_handle_rpc(struct tee_context *ctx,
>
> switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
> case OPTEE_SMC_RPC_FUNC_ALLOC:
> - shm = tee_shm_alloc_priv_kernel_buf(ctx, param->a1);
> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx, param->a1);
> if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
> reg_pair_from_64(&param->a1, &param->a2, pa);
> reg_pair_from_64(&param->a4, &param->a5,
> --
> 2.31.1
>

2022-01-22 01:20:33

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 11/12] tee: replace tee_shm_register()

On Thu, 20 Jan 2022 at 19:42, Jens Wiklander <[email protected]> wrote:
>
> On Thu, Jan 20, 2022 at 12:51 PM Sumit Garg <[email protected]> wrote:
> >
> > On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> > >
> > > tee_shm_register() is replaced by the previously introduced functions
> > > tee_shm_register_user_buf() and tee_shm_register_kernel_buf().
> > >
> > > Since there are not external callers left we can remove tee_shm_register()
> > > and refactor the remains.
> > >
> > > Signed-off-by: Jens Wiklander <[email protected]>
> > > ---
> > > drivers/tee/tee_shm.c | 157 +++++++++++++++++++++++-----------------
> > > include/linux/tee_drv.h | 11 ---
> > > 2 files changed, 91 insertions(+), 77 deletions(-)
> > >
> > > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > > index 6a1dbce75616..fe3e5977dd7c 100644
> > > --- a/drivers/tee/tee_shm.c
> > > +++ b/drivers/tee/tee_shm.c
> > > @@ -12,17 +12,43 @@
> > > #include <linux/uio.h>
> > > #include "tee_private.h"
> > >
> > > +static void shm_put_kernel_pages(struct page **pages, unsigned long npages)
> > > +{
> > > + unsigned long n;
> >
> > nit: Can we have a consistent prototype for the number of pages?
> > size_t as used by struct tee_shm or unsigned long? Same holds true for
> > variables below as well: npages, page_count, num_pages, n.
>
> Fair point, I'll fix what's changed here.
>
> >
> > > +
> > > + for (n = 0; n < npages; n++)
> > > + put_page(pages[n]);
> > > +}
> > > +
> > > +static int shm_get_kernel_pages(unsigned long start, int page_count,
> > > + struct page **pages)
> > > +{
> > > + struct kvec *kiov;
> > > + unsigned int n;
> > > + int rc;
> > > +
> > > + kiov = kcalloc(page_count, sizeof(*kiov), GFP_KERNEL);
> > > + if (!kiov)
> > > + return -ENOMEM;
> > > +
> > > + for (n = 0; n < page_count; n++) {
> > > + kiov[n].iov_base = (void *)(start + n * PAGE_SIZE);
> > > + kiov[n].iov_len = PAGE_SIZE;
> > > + }
> > > +
> > > + rc = get_kernel_pages(kiov, page_count, 0, pages);
> > > + kfree(kiov);
> > > +
> > > + return rc;
> > > +}
> > > +
> > > static void release_registered_pages(struct tee_shm *shm)
> > > {
> > > if (shm->pages) {
> > > - if (shm->flags & TEE_SHM_USER_MAPPED) {
> > > + if (shm->flags & TEE_SHM_USER_MAPPED)
> > > unpin_user_pages(shm->pages, shm->num_pages);
> > > - } else {
> > > - size_t n;
> > > -
> > > - for (n = 0; n < shm->num_pages; n++)
> > > - put_page(shm->pages[n]);
> > > - }
> > > + else
> > > + shm_put_kernel_pages(shm->pages, shm->num_pages);
> > >
> > > kfree(shm->pages);
> > > }
> > > @@ -191,28 +217,24 @@ struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> > > }
> > > EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_kernel_buf);
> > >
> > > -struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > > - size_t length, u32 flags)
> > > +static struct tee_shm *
> > > +register_shm_helper(struct tee_context *ctx, unsigned long addr,
> > > + size_t length, u32 flags, int id)
> > > {
> > > struct tee_device *teedev = ctx->teedev;
> > > - const u32 req_user_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED;
> > > - const u32 req_kernel_flags = TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED;
> > > struct tee_shm *shm;
> > > + unsigned long start;
> > > + int num_pages;
> > > void *ret;
> > > int rc;
> > > - int num_pages;
> > > - unsigned long start;
> > > -
> > > - if (flags != req_user_flags && flags != req_kernel_flags)
> > > - return ERR_PTR(-ENOTSUPP);
> > >
> > > if (!tee_device_get(teedev))
> > > return ERR_PTR(-EINVAL);
> > >
> > > if (!teedev->desc->ops->shm_register ||
> > > !teedev->desc->ops->shm_unregister) {
> > > - tee_device_put(teedev);
> > > - return ERR_PTR(-ENOTSUPP);
> > > + ret = ERR_PTR(-ENOTSUPP);
> >
> > Checkpatch warns about this error code:
> >
> > WARNING: ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP
> > #104: FILE: drivers/tee/tee_shm.c:236:
> > + ret = ERR_PTR(-ENOTSUPP);
>
> I noticed that too. I'd rather keep it as it is for now as changing
> would a bit of a ABI change even if I doubt that anyone is depending
> on this particular errno value.
>

Okay, I am fine with this.

-Sumit

> >
> > > + goto err_dev_put;
> > > }
> > >
> > > teedev_ctx_get(ctx);
> > > @@ -220,13 +242,13 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > > shm = kzalloc(sizeof(*shm), GFP_KERNEL);
> > > if (!shm) {
> > > ret = ERR_PTR(-ENOMEM);
> > > - goto err;
> > > + goto err_ctx_put;
> > > }
> > >
> > > refcount_set(&shm->refcount, 1);
> > > - shm->flags = flags | TEE_SHM_REGISTER;
> > > + shm->flags = flags;
> > > shm->ctx = ctx;
> > > - shm->id = -1;
> > > + shm->id = id;
> > > addr = untagged_addr(addr);
> > > start = rounddown(addr, PAGE_SIZE);
> > > shm->offset = addr - start;
> > > @@ -235,71 +257,45 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > > shm->pages = kcalloc(num_pages, sizeof(*shm->pages), GFP_KERNEL);
> > > if (!shm->pages) {
> > > ret = ERR_PTR(-ENOMEM);
> > > - goto err;
> > > + goto err_free_shm;
> > > }
> > >
> > > - if (flags & TEE_SHM_USER_MAPPED) {
> > > + if (flags & TEE_SHM_USER_MAPPED)
> > > rc = pin_user_pages_fast(start, num_pages, FOLL_WRITE,
> > > shm->pages);
> > > - } else {
> > > - struct kvec *kiov;
> > > - int i;
> > > -
> > > - kiov = kcalloc(num_pages, sizeof(*kiov), GFP_KERNEL);
> > > - if (!kiov) {
> > > - ret = ERR_PTR(-ENOMEM);
> > > - goto err;
> > > - }
> > > -
> > > - for (i = 0; i < num_pages; i++) {
> > > - kiov[i].iov_base = (void *)(start + i * PAGE_SIZE);
> > > - kiov[i].iov_len = PAGE_SIZE;
> > > - }
> > > -
> > > - rc = get_kernel_pages(kiov, num_pages, 0, shm->pages);
> > > - kfree(kiov);
> > > - }
> > > + else
> > > + rc = shm_get_kernel_pages(start, num_pages, shm->pages);
> > > if (rc > 0)
> > > shm->num_pages = rc;
> > > if (rc != num_pages) {
> > > if (rc >= 0)
> > > rc = -ENOMEM;
> > > ret = ERR_PTR(rc);
> > > - goto err;
> > > - }
> > > -
> > > - mutex_lock(&teedev->mutex);
> > > - shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
> > > - mutex_unlock(&teedev->mutex);
> > > -
> > > - if (shm->id < 0) {
> > > - ret = ERR_PTR(shm->id);
> > > - goto err;
> > > + goto err_put_shm_pages;
> > > }
> > >
> > > rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages,
> > > shm->num_pages, start);
> > > if (rc) {
> > > ret = ERR_PTR(rc);
> > > - goto err;
> > > + goto err_put_shm_pages;
> > > }
> > >
> > > return shm;
> > > -err:
> > > - if (shm) {
> > > - if (shm->id >= 0) {
> > > - mutex_lock(&teedev->mutex);
> > > - idr_remove(&teedev->idr, shm->id);
> > > - mutex_unlock(&teedev->mutex);
> > > - }
> > > - release_registered_pages(shm);
> > > - }
> > > +err_put_shm_pages:
> > > + if (flags & TEE_SHM_USER_MAPPED)
> > > + unpin_user_pages(shm->pages, shm->num_pages);
> > > + else
> > > + shm_put_kernel_pages(shm->pages, shm->num_pages);
> > > + kfree(shm->pages);
> > > +err_free_shm:
> > > kfree(shm);
> > > +err_ctx_put:
> > > teedev_ctx_put(ctx);
> > > +err_dev_put:
> > > tee_device_put(teedev);
> > > return ret;
> > > }
> > > -EXPORT_SYMBOL_GPL(tee_shm_register);
> > >
> > > /**
> > > * tee_shm_register_user_buf() - Register a userspace shared memory buffer
> > > @@ -312,8 +308,36 @@ EXPORT_SYMBOL_GPL(tee_shm_register);
> > > struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> > > unsigned long addr, size_t length)
> > > {
> > > - return tee_shm_register(ctx, addr, length,
> > > - TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
> > > + u32 f = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED | TEE_SHM_REGISTER;
> >
> > nit: I would prefer to write variable name as "flags" for clarity.
> >
> > > + struct tee_device *teedev = ctx->teedev;
> > > + struct tee_shm *shm;
> > > + void *ret;
> > > + int id;
> > > +
> > > + mutex_lock(&teedev->mutex);
> > > + id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL);
> > > + mutex_unlock(&teedev->mutex);
> > > +
> >
> > nit: redundant extra line.
> >
> > > + if (id < 0)
> > > + return ERR_PTR(id);
> > > +
> > > + shm = register_shm_helper(ctx, addr, length, f, id);
> > > + if (IS_ERR(shm)) {
> > > + mutex_lock(&teedev->mutex);
> > > + idr_remove(&teedev->idr, id);
> > > + mutex_unlock(&teedev->mutex);
> > > + return shm;
> > > + }
> > > +
> > > + mutex_lock(&teedev->mutex);
> > > + ret = idr_replace(&teedev->idr, shm, id);
> > > + mutex_unlock(&teedev->mutex);
> > > + if (IS_ERR(ret)) {
> > > + tee_shm_free(shm);
> > > + return ret;
> > > + }
> > > +
> > > + return shm;
> > > }
> > > EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
> > >
> > > @@ -330,8 +354,9 @@ EXPORT_SYMBOL_GPL(tee_shm_register_user_buf);
> > > struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> > > void *addr, size_t length)
> > > {
> > > - return tee_shm_register(ctx, (unsigned long)addr, length,
> > > - TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED);
> > > + u32 f = TEE_SHM_REGISTER | TEE_SHM_KERNEL_MAPPED;
> >
> > Ditto.
>
> Thanks,
> Jens
>
> >
> > -Sumit
> >
> > > +
> > > + return register_shm_helper(ctx, (unsigned long)addr, length, f, -1);
> > > }
> > > EXPORT_SYMBOL_GPL(tee_shm_register_kernel_buf);
> > >
> > > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> > > index 029c9a0590cc..e4f32885e273 100644
> > > --- a/include/linux/tee_drv.h
> > > +++ b/include/linux/tee_drv.h
> > > @@ -278,17 +278,6 @@ struct tee_shm *tee_shm_alloc_priv_kernel_buf(struct tee_context *ctx,
> > > size_t size);
> > > struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
> > >
> > > -/**
> > > - * tee_shm_register() - Register shared memory buffer
> > > - * @ctx: Context that registers the shared memory
> > > - * @addr: Address is userspace of the shared buffer
> > > - * @length: Length of the shared buffer
> > > - * @flags: Flags setting properties for the requested shared memory.
> > > - *
> > > - * @returns a pointer to 'struct tee_shm'
> > > - */
> > > -struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > > - size_t length, u32 flags);
> > > struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
> > > unsigned long addr, size_t length);
> > > struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
> > > --
> > > 2.31.1
> > >

2022-01-22 01:24:13

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 04/12] tee: simplify shm pool handling

On Thu, 20 Jan 2022 at 18:26, Jens Wiklander <[email protected]> wrote:
>
> On Thu, Jan 20, 2022 at 03:36:45PM +0530, Sumit Garg wrote:
> > Hi Jens,
> >
> > Thanks for this cleanup.
> >
> > On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> > >
> > > 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 concious one.
> >
> > typo: s/concious/conscious/
>
> Thanks
>
> >
> > AFAIU, the earlier design was to keep separate pools for differently
> > aligned memory allocation (one for 8 bytes aligned, other for
> > PAGE_SIZE aligned). But after this patch we would be mixing these
> > allocations using a first-fit algorithm. Don't you think that it would
> > lead to inefficient memory allocation (fragmentation) as compared to
> > existing one?
>
> These small private allocation are expected to be rather short lived
> so if there is fragmentation it will typically we restricted to the first
> pages.
>
> >
> > I think we need to be careful about allocation strategy for static
> > shared memory as it's a constrained resource and if a particular
> > device is using this approach then a kernel upgrade shouldn't cause
> > any regressions for that device.
>
> 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 preassure from multiple threads on secure world. All in all I
> believe this scales up and down better than fixed boundaries.
>
> I was chosing somewhat large alignment to avoid increasing it again. I
> have some patches in the pipe which will grow the typicall private shm
> allocation to a page at a time which then will be used for multiple
> argument structs at a time.
>

Thanks for the details. Can we have this included in the commit
message as well as in the code itself as comment for minimum alignment
as 512 bytes for future reference?

/*
* <above description>
*/
OPTEE_MIN_STATIC_POOL_ALIGN 9 /* 512 bytes aligned */

-Sumit

>
> >
> > >
> > > 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.
> > >
> > > Signed-off-by: Jens Wiklander <[email protected]>
> > > ---
> > > drivers/tee/amdtee/shm_pool.c | 55 +++++-----------
> > > drivers/tee/optee/Kconfig | 8 ---
> > > drivers/tee/optee/core.c | 11 ++--
> > > drivers/tee/optee/ffa_abi.c | 55 ++++------------
> > > drivers/tee/optee/optee_private.h | 4 +-
> > > drivers/tee/optee/smc_abi.c | 100 ++++++----------------------
> > > drivers/tee/tee_private.h | 11 ----
> > > drivers/tee/tee_shm.c | 29 ++++-----
> > > drivers/tee/tee_shm_pool.c | 104 ++++++++++--------------------
> > > include/linux/tee_drv.h | 58 ++++++-----------
> > > 10 files changed, 126 insertions(+), 309 deletions(-)
> > >
> > > diff --git a/drivers/tee/amdtee/shm_pool.c b/drivers/tee/amdtee/shm_pool.c
> > > index 065854e2db18..f87f96a291c9 100644
> > > --- a/drivers/tee/amdtee/shm_pool.c
> > > +++ b/drivers/tee/amdtee/shm_pool.c
> > > @@ -8,13 +8,17 @@
> > > #include <linux/psp-sev.h>
> > > #include "amdtee_private.h"
> > >
> > > -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)
> > > {
> > > unsigned int order = get_order(size);
> > > unsigned long va;
> > > int rc;
> > >
> > > + /*
> > > + * Ignore alignment since this is already going to be page aligned
> > > + * and there's no need for any larger alignment.
> > > + */
> > > va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
> > > if (!va)
> > > return -ENOMEM;
> > > @@ -34,7 +38,7 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm,
> > > return 0;
> > > }
> > >
> > > -static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
> > > +static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm)
> > > {
> > > /* Unmap the shared memory from TEE */
> > > amdtee_unmap_shmem(shm);
> > > @@ -42,52 +46,25 @@ static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
> > > 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,
> > > };
> > >
> > > -static struct tee_shm_pool_mgr *pool_mem_mgr_alloc(void)
> > > -{
> > > - struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
> > > -
> > > - if (!mgr)
> > > - return ERR_PTR(-ENOMEM);
> > > -
> > > - mgr->ops = &pool_ops;
> > > -
> > > - return mgr;
> > > -}
> > > -
> > > struct tee_shm_pool *amdtee_config_shm(void)
> > > {
> > > - struct tee_shm_pool_mgr *priv_mgr;
> > > - struct tee_shm_pool_mgr *dmabuf_mgr;
> > > - void *rc;
> > > + struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL);
> > >
> > > - rc = pool_mem_mgr_alloc();
> > > - if (IS_ERR(rc))
> > > - return rc;
> > > - priv_mgr = rc;
> > > -
> > > - rc = pool_mem_mgr_alloc();
> > > - if (IS_ERR(rc)) {
> > > - tee_shm_pool_mgr_destroy(priv_mgr);
> > > - return rc;
> > > - }
> > > - dmabuf_mgr = rc;
> > > + if (!pool)
> > > + return ERR_PTR(-ENOMEM);
> > >
> > > - 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);
> > > - }
> > > + pool->ops = &pool_ops;
> > >
> > > - return rc;
> > > + return pool;
> > > }
> > > 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 1ca320885fad..2a369e346b85 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 20a1b1a3d965..e690d9420966 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)
> > > {
> > > @@ -813,7 +786,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> > > if (!optee)
> > > return -ENOMEM;
> > >
> > > - optee->pool = optee_ffa_config_dyn_shm();
> > > + optee->pool = optee_ffa_shm_pool_alloc_pages();
> > > if (IS_ERR(optee->pool)) {
> > > rc = PTR_ERR(optee->pool);
> > > optee->pool = NULL;
> > > diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> > > index 46f74ab07c7e..df2450921464 100644
> > > --- a/drivers/tee/optee/optee_private.h
> > > +++ b/drivers/tee/optee/optee_private.h
> > > @@ -228,8 +228,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 449d6a72d289..b679037ea794 100644
> > > --- a/drivers/tee/optee/smc_abi.c
> > > +++ b/drivers/tee/optee/smc_abi.c
> > > @@ -42,8 +42,6 @@
> > > * 6. Driver initialization.
> > > */
> > >
> > > -#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
> > > -
> > > /*
> > > * 1. Convert between struct tee_param and struct optee_msg_param
> > > *
> > > @@ -532,20 +530,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 +554,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 +571,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;
> > > }
> > >
> > > /*
> > > @@ -1174,33 +1173,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)
> > > {
> > > @@ -1214,10 +1186,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) {
> > > @@ -1235,11 +1204,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");
> > > @@ -1247,35 +1211,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);
> > > + rc = tee_shm_pool_alloc_res_mem(vaddr, paddr, size,
> > > + 9 /* 512 bytes aligned */);
> >
> > Here you are specifying minimal allocation alignment to be 512 bytes?
> > Wouldn't it be inefficient corresponding to 8 bytes aligned OP-TEE
> > private memory allocation earlier?
>
> I hope I've been able to address this above.
>
> Thanks,
> Jens
>
> >
> > -Sumit
> >
> > > if (IS_ERR(rc))
> > > - goto err_free_priv_mgr;
> > > - dmabuf_mgr = rc;
> > > -
> > > - rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
> > > - 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;
> > > }
> > >
> > > @@ -1396,7 +1338,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
> > > diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
> > > index e55204df31ce..72376cf38bc0 100644
> > > --- a/drivers/tee/tee_private.h
> > > +++ b/drivers/tee/tee_private.h
> > > @@ -12,17 +12,6 @@
> > > #include <linux/mutex.h>
> > > #include <linux/types.h>
> > >
> > > -/**
> > > - * struct tee_shm_pool - shared memory pool
> > > - * @private_mgr: pool manager for shared memory only between kernel
> > > - * and secure world
> > > - * @dma_buf_mgr: pool manager for shared memory exported to user space
> > > - */
> > > -struct tee_shm_pool {
> > > - struct tee_shm_pool_mgr *private_mgr;
> > > - struct tee_shm_pool_mgr *dma_buf_mgr;
> > > -};
> > > -
> > > #define TEE_DEVICE_FLAG_REGISTERED 0x1
> > > #define TEE_MAX_DEV_NAME_LEN 32
> > >
> > > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > > index b43178986985..2c8ce0c6801a 100644
> > > --- a/drivers/tee/tee_shm.c
> > > +++ b/drivers/tee/tee_shm.c
> > > @@ -31,14 +31,7 @@ static void release_registered_pages(struct tee_shm *shm)
> > > static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> > > {
> > > if (shm->flags & TEE_SHM_POOL) {
> > > - struct tee_shm_pool_mgr *poolm;
> > > -
> > > - if (shm->flags & TEE_SHM_DMA_BUF)
> > > - poolm = teedev->pool->dma_buf_mgr;
> > > - else
> > > - poolm = teedev->pool->private_mgr;
> > > -
> > > - poolm->ops->free(poolm, shm);
> > > + teedev->pool->ops->free(teedev->pool, shm);
> > > } else if (shm->flags & TEE_SHM_REGISTER) {
> > > int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);
> > >
> > > @@ -59,8 +52,8 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> > > struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > > {
> > > struct tee_device *teedev = ctx->teedev;
> > > - struct tee_shm_pool_mgr *poolm = NULL;
> > > struct tee_shm *shm;
> > > + size_t align;
> > > void *ret;
> > > int rc;
> > >
> > > @@ -93,12 +86,18 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > > refcount_set(&shm->refcount, 1);
> > > shm->flags = flags | TEE_SHM_POOL;
> > > shm->ctx = ctx;
> > > - if (flags & TEE_SHM_DMA_BUF)
> > > - poolm = teedev->pool->dma_buf_mgr;
> > > - else
> > > - poolm = teedev->pool->private_mgr;
> > > + if (flags & TEE_SHM_DMA_BUF) {
> > > + align = PAGE_SIZE;
> > > + /*
> > > + * Request to register the shm in the pool allocator below
> > > + * if supported.
> > > + */
> > > + shm->flags |= TEE_SHM_REGISTER;
> > > + } else {
> > > + align = 2 * sizeof(long);
> > > + }
> > >
> > > - rc = poolm->ops->alloc(poolm, shm, size);
> > > + rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
> > > if (rc) {
> > > ret = ERR_PTR(rc);
> > > goto err_kfree;
> > > @@ -118,7 +117,7 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > >
> > > return shm;
> > > err_pool_free:
> > > - poolm->ops->free(poolm, shm);
> > > + teedev->pool->ops->free(teedev->pool, shm);
> > > err_kfree:
> > > kfree(shm);
> > > err_dev_put:
> > > diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
> > > index 0e460347138a..71e0f8ae69aa 100644
> > > --- a/drivers/tee/tee_shm_pool.c
> > > +++ b/drivers/tee/tee_shm_pool.c
> > > @@ -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);
> > > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> > > index 26b450484ac1..808aa23308c2 100644
> > > --- a/include/linux/tee_drv.h
> > > +++ b/include/linux/tee_drv.h
> > > @@ -221,62 +221,39 @@ struct tee_shm {
> > > };
> > >
> > > /**
> > > - * struct tee_shm_pool_mgr - shared memory manager
> > > + * struct tee_shm_pool - shared memory pool
> > > * @ops: operations
> > > * @private_data: private data for the shared memory manager
> > > */
> > > -struct tee_shm_pool_mgr {
> > > - const struct tee_shm_pool_mgr_ops *ops;
> > > +struct tee_shm_pool {
> > > + const struct tee_shm_pool_ops *ops;
> > > void *private_data;
> > > };
> > >
> > > /**
> > > - * struct tee_shm_pool_mgr_ops - shared memory pool manager operations
> > > + * struct tee_shm_pool_ops - shared memory pool operations
> > > * @alloc: called when allocating shared memory
> > > * @free: called when freeing shared memory
> > > - * @destroy_poolmgr: called when destroying the pool manager
> > > + * @destroy_pool: called when destroying the pool
> > > */
> > > -struct tee_shm_pool_mgr_ops {
> > > - int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm,
> > > - size_t size);
> > > - void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm);
> > > - void (*destroy_poolmgr)(struct tee_shm_pool_mgr *poolmgr);
> > > +struct tee_shm_pool_ops {
> > > + int (*alloc)(struct tee_shm_pool *pool, struct tee_shm *shm,
> > > + size_t size, size_t align);
> > > + void (*free)(struct tee_shm_pool *pool, struct tee_shm *shm);
> > > + void (*destroy_pool)(struct tee_shm_pool *pool);
> > > };
> > >
> > > -/**
> > > - * tee_shm_pool_alloc() - Create a shared memory pool from shm managers
> > > - * @priv_mgr: manager for driver private shared memory allocations
> > > - * @dmabuf_mgr: manager for dma-buf shared memory allocations
> > > - *
> > > - * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
> > > - * in @dmabuf, others will use the range provided by @priv.
> > > - *
> > > - * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> > > - */
> > > -struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr,
> > > - struct tee_shm_pool_mgr *dmabuf_mgr);
> > > -
> > > /*
> > > - * tee_shm_pool_mgr_alloc_res_mem() - Create a shm manager for reserved
> > > - * memory
> > > + * tee_shm_pool_alloc_res_mem() - Create a shm manager for reserved memory
> > > * @vaddr: Virtual address of start of pool
> > > * @paddr: Physical address of start of pool
> > > * @size: Size in bytes of the pool
> > > *
> > > - * @returns pointer to a 'struct tee_shm_pool_mgr' or an ERR_PTR on failure.
> > > - */
> > > -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);
> > > -
> > > -/**
> > > - * tee_shm_pool_mgr_destroy() - Free a shared memory manager
> > > + * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> > > */
> > > -static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
> > > -{
> > > - poolm->ops->destroy_poolmgr(poolm);
> > > -}
> > > +struct tee_shm_pool *tee_shm_pool_alloc_res_mem(unsigned long vaddr,
> > > + phys_addr_t paddr, size_t size,
> > > + int min_alloc_order);
> > >
> > > /**
> > > * tee_shm_pool_free() - Free a shared memory pool
> > > @@ -285,7 +262,10 @@ static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
> > > * The 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);
> > > +static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
> > > +{
> > > + pool->ops->destroy_pool(pool);
> > > +}
> > >
> > > /**
> > > * tee_get_drvdata() - Return driver_data pointer
> > > --
> > > 2.31.1
> > >

2022-01-22 01:33:03

by Jerome Forissier

[permalink] [raw]
Subject: Re: [PATCH v2 07/12] optee: use driver internal tee_contex for some rpc



On 1/21/22 13:54, Sumit Garg wrote:
> + Jerome, Etienne
>
> On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
>>
>> Uses the new driver internal tee_context when allocating driver private
>> shared memory. This decouples the shared memory object from its original
>> tee_context. This is needed when the life time of such a memory
>> allocation outlives the client tee_context.
>>
>> Signed-off-by: Jens Wiklander <[email protected]>
>> ---
>> drivers/tee/optee/ffa_abi.c | 16 ++++++++--------
>> drivers/tee/optee/smc_abi.c | 7 ++++---
>> 2 files changed, 12 insertions(+), 11 deletions(-)
>>
>
> I guess with this patch we should no longer see issues [1] reported earlier.

Correct. I have tested [1] again in QEMU with this whole series applied
and the issue is gone.

--
Jerome

>
> FWIW,
>
> Reviewed-by: Sumit Garg <[email protected]>
>
> [1] https://github.com/OP-TEE/optee_os/issues/1918
>
> -Sumit
>
>> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
>> index 88a028d4fb7b..5ec484b42432 100644
>> --- a/drivers/tee/optee/ffa_abi.c
>> +++ b/drivers/tee/optee/ffa_abi.c
>> @@ -424,6 +424,7 @@ static struct tee_shm_pool *optee_ffa_shm_pool_alloc_pages(void)
>> */
>>
>> static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
>> + struct optee *optee,
>> struct optee_msg_arg *arg)
>> {
>> struct tee_shm *shm;
>> @@ -439,7 +440,7 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
>> shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
>> break;
>> case OPTEE_RPC_SHM_TYPE_KERNEL:
>> - shm = tee_shm_alloc_priv_kernel_buf(ctx,
>> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx,
>> arg->params[0].u.value.b);
>> break;
>> default:
>> @@ -493,14 +494,13 @@ static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx,
>> }
>>
>> static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
>> + struct optee *optee,
>> struct optee_msg_arg *arg)
>> {
>> - struct optee *optee = tee_get_drvdata(ctx->teedev);
>> -
>> arg->ret_origin = TEEC_ORIGIN_COMMS;
>> switch (arg->cmd) {
>> case OPTEE_RPC_CMD_SHM_ALLOC:
>> - handle_ffa_rpc_func_cmd_shm_alloc(ctx, arg);
>> + handle_ffa_rpc_func_cmd_shm_alloc(ctx, optee, arg);
>> break;
>> case OPTEE_RPC_CMD_SHM_FREE:
>> handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg);
>> @@ -510,12 +510,12 @@ static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
>> }
>> }
>>
>> -static void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd,
>> - struct optee_msg_arg *arg)
>> +static void optee_handle_ffa_rpc(struct tee_context *ctx, struct optee *optee,
>> + u32 cmd, struct optee_msg_arg *arg)
>> {
>> switch (cmd) {
>> case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
>> - handle_ffa_rpc_func_cmd(ctx, arg);
>> + handle_ffa_rpc_func_cmd(ctx, optee, arg);
>> break;
>> case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
>> /* Interrupt delivered by now */
>> @@ -582,7 +582,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx,
>> * above.
>> */
>> cond_resched();
>> - optee_handle_ffa_rpc(ctx, data->data1, rpc_arg);
>> + optee_handle_ffa_rpc(ctx, optee, data->data1, rpc_arg);
>> cmd = OPTEE_FFA_YIELDING_CALL_RESUME;
>> data->data0 = cmd;
>> data->data1 = 0;
>> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
>> index 1dbb13b08381..f2ef76451443 100644
>> --- a/drivers/tee/optee/smc_abi.c
>> +++ b/drivers/tee/optee/smc_abi.c
>> @@ -621,6 +621,7 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
>> }
>>
>> static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
>> + struct optee *optee,
>> struct optee_msg_arg *arg,
>> struct optee_call_ctx *call_ctx)
>> {
>> @@ -650,7 +651,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
>> shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
>> break;
>> case OPTEE_RPC_SHM_TYPE_KERNEL:
>> - shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
>> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx, sz);
>> break;
>> default:
>> arg->ret = TEEC_ERROR_BAD_PARAMETERS;
>> @@ -746,7 +747,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
>> switch (arg->cmd) {
>> case OPTEE_RPC_CMD_SHM_ALLOC:
>> free_pages_list(call_ctx);
>> - handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
>> + handle_rpc_func_cmd_shm_alloc(ctx, optee, arg, call_ctx);
>> break;
>> case OPTEE_RPC_CMD_SHM_FREE:
>> handle_rpc_func_cmd_shm_free(ctx, arg);
>> @@ -775,7 +776,7 @@ static void optee_handle_rpc(struct tee_context *ctx,
>>
>> switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
>> case OPTEE_SMC_RPC_FUNC_ALLOC:
>> - shm = tee_shm_alloc_priv_kernel_buf(ctx, param->a1);
>> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx, param->a1);
>> if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
>> reg_pair_from_64(&param->a1, &param->a2, pa);
>> reg_pair_from_64(&param->a4, &param->a5,
>> --
>> 2.31.1
>>

2022-01-22 01:34:14

by Sumit Garg

[permalink] [raw]
Subject: Re: [PATCH v2 07/12] optee: use driver internal tee_contex for some rpc

On Fri, 21 Jan 2022 at 18:58, Jerome Forissier <[email protected]> wrote:
>
> On 1/21/22 13:54, Sumit Garg wrote:
> > + Jerome, Etienne
> >
> > On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> >>
> >> Uses the new driver internal tee_context when allocating driver private
> >> shared memory. This decouples the shared memory object from its original
> >> tee_context. This is needed when the life time of such a memory
> >> allocation outlives the client tee_context.
> >>
> >> Signed-off-by: Jens Wiklander <[email protected]>
> >> ---
> >> drivers/tee/optee/ffa_abi.c | 16 ++++++++--------
> >> drivers/tee/optee/smc_abi.c | 7 ++++---
> >> 2 files changed, 12 insertions(+), 11 deletions(-)
> >>
> >
> > I guess with this patch we should no longer see issues [1] reported earlier.
>
> Correct. I have tested [1] again in QEMU with this whole series applied
> and the issue is gone.
>

Thanks for the confirmation.

Jens,

Can we have a Fixes tag for this and CC stable? I know it won't be
directly applicable to stable kernels but we can help with a backport.

-Sumit

> --
> Jerome
>
> >
> > FWIW,
> >
> > Reviewed-by: Sumit Garg <[email protected]>
> >
> > [1] https://github.com/OP-TEE/optee_os/issues/1918
> >
> > -Sumit
> >
> >> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> >> index 88a028d4fb7b..5ec484b42432 100644
> >> --- a/drivers/tee/optee/ffa_abi.c
> >> +++ b/drivers/tee/optee/ffa_abi.c
> >> @@ -424,6 +424,7 @@ static struct tee_shm_pool *optee_ffa_shm_pool_alloc_pages(void)
> >> */
> >>
> >> static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> >> + struct optee *optee,
> >> struct optee_msg_arg *arg)
> >> {
> >> struct tee_shm *shm;
> >> @@ -439,7 +440,7 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> >> shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
> >> break;
> >> case OPTEE_RPC_SHM_TYPE_KERNEL:
> >> - shm = tee_shm_alloc_priv_kernel_buf(ctx,
> >> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx,
> >> arg->params[0].u.value.b);
> >> break;
> >> default:
> >> @@ -493,14 +494,13 @@ static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx,
> >> }
> >>
> >> static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
> >> + struct optee *optee,
> >> struct optee_msg_arg *arg)
> >> {
> >> - struct optee *optee = tee_get_drvdata(ctx->teedev);
> >> -
> >> arg->ret_origin = TEEC_ORIGIN_COMMS;
> >> switch (arg->cmd) {
> >> case OPTEE_RPC_CMD_SHM_ALLOC:
> >> - handle_ffa_rpc_func_cmd_shm_alloc(ctx, arg);
> >> + handle_ffa_rpc_func_cmd_shm_alloc(ctx, optee, arg);
> >> break;
> >> case OPTEE_RPC_CMD_SHM_FREE:
> >> handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg);
> >> @@ -510,12 +510,12 @@ static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
> >> }
> >> }
> >>
> >> -static void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd,
> >> - struct optee_msg_arg *arg)
> >> +static void optee_handle_ffa_rpc(struct tee_context *ctx, struct optee *optee,
> >> + u32 cmd, struct optee_msg_arg *arg)
> >> {
> >> switch (cmd) {
> >> case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
> >> - handle_ffa_rpc_func_cmd(ctx, arg);
> >> + handle_ffa_rpc_func_cmd(ctx, optee, arg);
> >> break;
> >> case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
> >> /* Interrupt delivered by now */
> >> @@ -582,7 +582,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx,
> >> * above.
> >> */
> >> cond_resched();
> >> - optee_handle_ffa_rpc(ctx, data->data1, rpc_arg);
> >> + optee_handle_ffa_rpc(ctx, optee, data->data1, rpc_arg);
> >> cmd = OPTEE_FFA_YIELDING_CALL_RESUME;
> >> data->data0 = cmd;
> >> data->data1 = 0;
> >> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> >> index 1dbb13b08381..f2ef76451443 100644
> >> --- a/drivers/tee/optee/smc_abi.c
> >> +++ b/drivers/tee/optee/smc_abi.c
> >> @@ -621,6 +621,7 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
> >> }
> >>
> >> static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> >> + struct optee *optee,
> >> struct optee_msg_arg *arg,
> >> struct optee_call_ctx *call_ctx)
> >> {
> >> @@ -650,7 +651,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> >> shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
> >> break;
> >> case OPTEE_RPC_SHM_TYPE_KERNEL:
> >> - shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
> >> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx, sz);
> >> break;
> >> default:
> >> arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> >> @@ -746,7 +747,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
> >> switch (arg->cmd) {
> >> case OPTEE_RPC_CMD_SHM_ALLOC:
> >> free_pages_list(call_ctx);
> >> - handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
> >> + handle_rpc_func_cmd_shm_alloc(ctx, optee, arg, call_ctx);
> >> break;
> >> case OPTEE_RPC_CMD_SHM_FREE:
> >> handle_rpc_func_cmd_shm_free(ctx, arg);
> >> @@ -775,7 +776,7 @@ static void optee_handle_rpc(struct tee_context *ctx,
> >>
> >> switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
> >> case OPTEE_SMC_RPC_FUNC_ALLOC:
> >> - shm = tee_shm_alloc_priv_kernel_buf(ctx, param->a1);
> >> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx, param->a1);
> >> if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
> >> reg_pair_from_64(&param->a1, &param->a2, pa);
> >> reg_pair_from_64(&param->a4, &param->a5,
> >> --
> >> 2.31.1
> >>

2022-01-22 01:36:46

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH v2 04/12] tee: simplify shm pool handling

On Fri, Jan 21, 2022 at 2:06 PM Sumit Garg <[email protected]> wrote:
>
> On Thu, 20 Jan 2022 at 18:26, Jens Wiklander <[email protected]> wrote:
> >
> > On Thu, Jan 20, 2022 at 03:36:45PM +0530, Sumit Garg wrote:
> > > Hi Jens,
> > >
> > > Thanks for this cleanup.
> > >
> > > On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> > > >
> > > > 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 concious one.
> > >
> > > typo: s/concious/conscious/
> >
> > Thanks
> >
> > >
> > > AFAIU, the earlier design was to keep separate pools for differently
> > > aligned memory allocation (one for 8 bytes aligned, other for
> > > PAGE_SIZE aligned). But after this patch we would be mixing these
> > > allocations using a first-fit algorithm. Don't you think that it would
> > > lead to inefficient memory allocation (fragmentation) as compared to
> > > existing one?
> >
> > These small private allocation are expected to be rather short lived
> > so if there is fragmentation it will typically we restricted to the first
> > pages.
> >
> > >
> > > I think we need to be careful about allocation strategy for static
> > > shared memory as it's a constrained resource and if a particular
> > > device is using this approach then a kernel upgrade shouldn't cause
> > > any regressions for that device.
> >
> > 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 preassure from multiple threads on secure world. All in all I
> > believe this scales up and down better than fixed boundaries.
> >
> > I was chosing somewhat large alignment to avoid increasing it again. I
> > have some patches in the pipe which will grow the typicall private shm
> > allocation to a page at a time which then will be used for multiple
> > argument structs at a time.
> >
>
> Thanks for the details. Can we have this included in the commit
> message as well as in the code itself as comment for minimum alignment
> as 512 bytes for future reference?
>
> /*
> * <above description>
> */
> OPTEE_MIN_STATIC_POOL_ALIGN 9 /* 512 bytes aligned */

I'll add something.

Thanks,
Jens

>
> -Sumit
>
> >
> > >
> > > >
> > > > 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.
> > > >
> > > > Signed-off-by: Jens Wiklander <[email protected]>
> > > > ---
> > > > drivers/tee/amdtee/shm_pool.c | 55 +++++-----------
> > > > drivers/tee/optee/Kconfig | 8 ---
> > > > drivers/tee/optee/core.c | 11 ++--
> > > > drivers/tee/optee/ffa_abi.c | 55 ++++------------
> > > > drivers/tee/optee/optee_private.h | 4 +-
> > > > drivers/tee/optee/smc_abi.c | 100 ++++++----------------------
> > > > drivers/tee/tee_private.h | 11 ----
> > > > drivers/tee/tee_shm.c | 29 ++++-----
> > > > drivers/tee/tee_shm_pool.c | 104 ++++++++++--------------------
> > > > include/linux/tee_drv.h | 58 ++++++-----------
> > > > 10 files changed, 126 insertions(+), 309 deletions(-)
> > > >
> > > > diff --git a/drivers/tee/amdtee/shm_pool.c b/drivers/tee/amdtee/shm_pool.c
> > > > index 065854e2db18..f87f96a291c9 100644
> > > > --- a/drivers/tee/amdtee/shm_pool.c
> > > > +++ b/drivers/tee/amdtee/shm_pool.c
> > > > @@ -8,13 +8,17 @@
> > > > #include <linux/psp-sev.h>
> > > > #include "amdtee_private.h"
> > > >
> > > > -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)
> > > > {
> > > > unsigned int order = get_order(size);
> > > > unsigned long va;
> > > > int rc;
> > > >
> > > > + /*
> > > > + * Ignore alignment since this is already going to be page aligned
> > > > + * and there's no need for any larger alignment.
> > > > + */
> > > > va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
> > > > if (!va)
> > > > return -ENOMEM;
> > > > @@ -34,7 +38,7 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm,
> > > > return 0;
> > > > }
> > > >
> > > > -static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
> > > > +static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm)
> > > > {
> > > > /* Unmap the shared memory from TEE */
> > > > amdtee_unmap_shmem(shm);
> > > > @@ -42,52 +46,25 @@ static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
> > > > 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,
> > > > };
> > > >
> > > > -static struct tee_shm_pool_mgr *pool_mem_mgr_alloc(void)
> > > > -{
> > > > - struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
> > > > -
> > > > - if (!mgr)
> > > > - return ERR_PTR(-ENOMEM);
> > > > -
> > > > - mgr->ops = &pool_ops;
> > > > -
> > > > - return mgr;
> > > > -}
> > > > -
> > > > struct tee_shm_pool *amdtee_config_shm(void)
> > > > {
> > > > - struct tee_shm_pool_mgr *priv_mgr;
> > > > - struct tee_shm_pool_mgr *dmabuf_mgr;
> > > > - void *rc;
> > > > + struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL);
> > > >
> > > > - rc = pool_mem_mgr_alloc();
> > > > - if (IS_ERR(rc))
> > > > - return rc;
> > > > - priv_mgr = rc;
> > > > -
> > > > - rc = pool_mem_mgr_alloc();
> > > > - if (IS_ERR(rc)) {
> > > > - tee_shm_pool_mgr_destroy(priv_mgr);
> > > > - return rc;
> > > > - }
> > > > - dmabuf_mgr = rc;
> > > > + if (!pool)
> > > > + return ERR_PTR(-ENOMEM);
> > > >
> > > > - 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);
> > > > - }
> > > > + pool->ops = &pool_ops;
> > > >
> > > > - return rc;
> > > > + return pool;
> > > > }
> > > > 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 1ca320885fad..2a369e346b85 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 20a1b1a3d965..e690d9420966 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)
> > > > {
> > > > @@ -813,7 +786,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> > > > if (!optee)
> > > > return -ENOMEM;
> > > >
> > > > - optee->pool = optee_ffa_config_dyn_shm();
> > > > + optee->pool = optee_ffa_shm_pool_alloc_pages();
> > > > if (IS_ERR(optee->pool)) {
> > > > rc = PTR_ERR(optee->pool);
> > > > optee->pool = NULL;
> > > > diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> > > > index 46f74ab07c7e..df2450921464 100644
> > > > --- a/drivers/tee/optee/optee_private.h
> > > > +++ b/drivers/tee/optee/optee_private.h
> > > > @@ -228,8 +228,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 449d6a72d289..b679037ea794 100644
> > > > --- a/drivers/tee/optee/smc_abi.c
> > > > +++ b/drivers/tee/optee/smc_abi.c
> > > > @@ -42,8 +42,6 @@
> > > > * 6. Driver initialization.
> > > > */
> > > >
> > > > -#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
> > > > -
> > > > /*
> > > > * 1. Convert between struct tee_param and struct optee_msg_param
> > > > *
> > > > @@ -532,20 +530,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 +554,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 +571,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;
> > > > }
> > > >
> > > > /*
> > > > @@ -1174,33 +1173,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)
> > > > {
> > > > @@ -1214,10 +1186,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) {
> > > > @@ -1235,11 +1204,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");
> > > > @@ -1247,35 +1211,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);
> > > > + rc = tee_shm_pool_alloc_res_mem(vaddr, paddr, size,
> > > > + 9 /* 512 bytes aligned */);
> > >
> > > Here you are specifying minimal allocation alignment to be 512 bytes?
> > > Wouldn't it be inefficient corresponding to 8 bytes aligned OP-TEE
> > > private memory allocation earlier?
> >
> > I hope I've been able to address this above.
> >
> > Thanks,
> > Jens
> >
> > >
> > > -Sumit
> > >
> > > > if (IS_ERR(rc))
> > > > - goto err_free_priv_mgr;
> > > > - dmabuf_mgr = rc;
> > > > -
> > > > - rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
> > > > - 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;
> > > > }
> > > >
> > > > @@ -1396,7 +1338,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
> > > > diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
> > > > index e55204df31ce..72376cf38bc0 100644
> > > > --- a/drivers/tee/tee_private.h
> > > > +++ b/drivers/tee/tee_private.h
> > > > @@ -12,17 +12,6 @@
> > > > #include <linux/mutex.h>
> > > > #include <linux/types.h>
> > > >
> > > > -/**
> > > > - * struct tee_shm_pool - shared memory pool
> > > > - * @private_mgr: pool manager for shared memory only between kernel
> > > > - * and secure world
> > > > - * @dma_buf_mgr: pool manager for shared memory exported to user space
> > > > - */
> > > > -struct tee_shm_pool {
> > > > - struct tee_shm_pool_mgr *private_mgr;
> > > > - struct tee_shm_pool_mgr *dma_buf_mgr;
> > > > -};
> > > > -
> > > > #define TEE_DEVICE_FLAG_REGISTERED 0x1
> > > > #define TEE_MAX_DEV_NAME_LEN 32
> > > >
> > > > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > > > index b43178986985..2c8ce0c6801a 100644
> > > > --- a/drivers/tee/tee_shm.c
> > > > +++ b/drivers/tee/tee_shm.c
> > > > @@ -31,14 +31,7 @@ static void release_registered_pages(struct tee_shm *shm)
> > > > static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> > > > {
> > > > if (shm->flags & TEE_SHM_POOL) {
> > > > - struct tee_shm_pool_mgr *poolm;
> > > > -
> > > > - if (shm->flags & TEE_SHM_DMA_BUF)
> > > > - poolm = teedev->pool->dma_buf_mgr;
> > > > - else
> > > > - poolm = teedev->pool->private_mgr;
> > > > -
> > > > - poolm->ops->free(poolm, shm);
> > > > + teedev->pool->ops->free(teedev->pool, shm);
> > > > } else if (shm->flags & TEE_SHM_REGISTER) {
> > > > int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);
> > > >
> > > > @@ -59,8 +52,8 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
> > > > struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > > > {
> > > > struct tee_device *teedev = ctx->teedev;
> > > > - struct tee_shm_pool_mgr *poolm = NULL;
> > > > struct tee_shm *shm;
> > > > + size_t align;
> > > > void *ret;
> > > > int rc;
> > > >
> > > > @@ -93,12 +86,18 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > > > refcount_set(&shm->refcount, 1);
> > > > shm->flags = flags | TEE_SHM_POOL;
> > > > shm->ctx = ctx;
> > > > - if (flags & TEE_SHM_DMA_BUF)
> > > > - poolm = teedev->pool->dma_buf_mgr;
> > > > - else
> > > > - poolm = teedev->pool->private_mgr;
> > > > + if (flags & TEE_SHM_DMA_BUF) {
> > > > + align = PAGE_SIZE;
> > > > + /*
> > > > + * Request to register the shm in the pool allocator below
> > > > + * if supported.
> > > > + */
> > > > + shm->flags |= TEE_SHM_REGISTER;
> > > > + } else {
> > > > + align = 2 * sizeof(long);
> > > > + }
> > > >
> > > > - rc = poolm->ops->alloc(poolm, shm, size);
> > > > + rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
> > > > if (rc) {
> > > > ret = ERR_PTR(rc);
> > > > goto err_kfree;
> > > > @@ -118,7 +117,7 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
> > > >
> > > > return shm;
> > > > err_pool_free:
> > > > - poolm->ops->free(poolm, shm);
> > > > + teedev->pool->ops->free(teedev->pool, shm);
> > > > err_kfree:
> > > > kfree(shm);
> > > > err_dev_put:
> > > > diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
> > > > index 0e460347138a..71e0f8ae69aa 100644
> > > > --- a/drivers/tee/tee_shm_pool.c
> > > > +++ b/drivers/tee/tee_shm_pool.c
> > > > @@ -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);
> > > > diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
> > > > index 26b450484ac1..808aa23308c2 100644
> > > > --- a/include/linux/tee_drv.h
> > > > +++ b/include/linux/tee_drv.h
> > > > @@ -221,62 +221,39 @@ struct tee_shm {
> > > > };
> > > >
> > > > /**
> > > > - * struct tee_shm_pool_mgr - shared memory manager
> > > > + * struct tee_shm_pool - shared memory pool
> > > > * @ops: operations
> > > > * @private_data: private data for the shared memory manager
> > > > */
> > > > -struct tee_shm_pool_mgr {
> > > > - const struct tee_shm_pool_mgr_ops *ops;
> > > > +struct tee_shm_pool {
> > > > + const struct tee_shm_pool_ops *ops;
> > > > void *private_data;
> > > > };
> > > >
> > > > /**
> > > > - * struct tee_shm_pool_mgr_ops - shared memory pool manager operations
> > > > + * struct tee_shm_pool_ops - shared memory pool operations
> > > > * @alloc: called when allocating shared memory
> > > > * @free: called when freeing shared memory
> > > > - * @destroy_poolmgr: called when destroying the pool manager
> > > > + * @destroy_pool: called when destroying the pool
> > > > */
> > > > -struct tee_shm_pool_mgr_ops {
> > > > - int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm,
> > > > - size_t size);
> > > > - void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm);
> > > > - void (*destroy_poolmgr)(struct tee_shm_pool_mgr *poolmgr);
> > > > +struct tee_shm_pool_ops {
> > > > + int (*alloc)(struct tee_shm_pool *pool, struct tee_shm *shm,
> > > > + size_t size, size_t align);
> > > > + void (*free)(struct tee_shm_pool *pool, struct tee_shm *shm);
> > > > + void (*destroy_pool)(struct tee_shm_pool *pool);
> > > > };
> > > >
> > > > -/**
> > > > - * tee_shm_pool_alloc() - Create a shared memory pool from shm managers
> > > > - * @priv_mgr: manager for driver private shared memory allocations
> > > > - * @dmabuf_mgr: manager for dma-buf shared memory allocations
> > > > - *
> > > > - * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
> > > > - * in @dmabuf, others will use the range provided by @priv.
> > > > - *
> > > > - * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> > > > - */
> > > > -struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr,
> > > > - struct tee_shm_pool_mgr *dmabuf_mgr);
> > > > -
> > > > /*
> > > > - * tee_shm_pool_mgr_alloc_res_mem() - Create a shm manager for reserved
> > > > - * memory
> > > > + * tee_shm_pool_alloc_res_mem() - Create a shm manager for reserved memory
> > > > * @vaddr: Virtual address of start of pool
> > > > * @paddr: Physical address of start of pool
> > > > * @size: Size in bytes of the pool
> > > > *
> > > > - * @returns pointer to a 'struct tee_shm_pool_mgr' or an ERR_PTR on failure.
> > > > - */
> > > > -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);
> > > > -
> > > > -/**
> > > > - * tee_shm_pool_mgr_destroy() - Free a shared memory manager
> > > > + * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
> > > > */
> > > > -static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
> > > > -{
> > > > - poolm->ops->destroy_poolmgr(poolm);
> > > > -}
> > > > +struct tee_shm_pool *tee_shm_pool_alloc_res_mem(unsigned long vaddr,
> > > > + phys_addr_t paddr, size_t size,
> > > > + int min_alloc_order);
> > > >
> > > > /**
> > > > * tee_shm_pool_free() - Free a shared memory pool
> > > > @@ -285,7 +262,10 @@ static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
> > > > * The 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);
> > > > +static inline void tee_shm_pool_free(struct tee_shm_pool *pool)
> > > > +{
> > > > + pool->ops->destroy_pool(pool);
> > > > +}
> > > >
> > > > /**
> > > > * tee_get_drvdata() - Return driver_data pointer
> > > > --
> > > > 2.31.1
> > > >

2022-01-22 01:39:03

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH v2 07/12] optee: use driver internal tee_contex for some rpc

On Fri, Jan 21, 2022 at 2:37 PM Sumit Garg <[email protected]> wrote:
>
> On Fri, 21 Jan 2022 at 18:58, Jerome Forissier <[email protected]> wrote:
> >
> > On 1/21/22 13:54, Sumit Garg wrote:
> > > + Jerome, Etienne
> > >
> > > On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> > >>
> > >> Uses the new driver internal tee_context when allocating driver private
> > >> shared memory. This decouples the shared memory object from its original
> > >> tee_context. This is needed when the life time of such a memory
> > >> allocation outlives the client tee_context.
> > >>
> > >> Signed-off-by: Jens Wiklander <[email protected]>
> > >> ---
> > >> drivers/tee/optee/ffa_abi.c | 16 ++++++++--------
> > >> drivers/tee/optee/smc_abi.c | 7 ++++---
> > >> 2 files changed, 12 insertions(+), 11 deletions(-)
> > >>
> > >
> > > I guess with this patch we should no longer see issues [1] reported earlier.
> >
> > Correct. I have tested [1] again in QEMU with this whole series applied
> > and the issue is gone.
> >
>
> Thanks for the confirmation.
>
> Jens,
>
> Can we have a Fixes tag for this and CC stable? I know it won't be
> directly applicable to stable kernels but we can help with a backport.
>

OK, I'll add that.

Thanks,
Jens

> -Sumit
>
> > --
> > Jerome
> >
> > >
> > > FWIW,
> > >
> > > Reviewed-by: Sumit Garg <[email protected]>
> > >
> > > [1] https://github.com/OP-TEE/optee_os/issues/1918
> > >
> > > -Sumit
> > >
> > >> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> > >> index 88a028d4fb7b..5ec484b42432 100644
> > >> --- a/drivers/tee/optee/ffa_abi.c
> > >> +++ b/drivers/tee/optee/ffa_abi.c
> > >> @@ -424,6 +424,7 @@ static struct tee_shm_pool *optee_ffa_shm_pool_alloc_pages(void)
> > >> */
> > >>
> > >> static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> > >> + struct optee *optee,
> > >> struct optee_msg_arg *arg)
> > >> {
> > >> struct tee_shm *shm;
> > >> @@ -439,7 +440,7 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> > >> shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
> > >> break;
> > >> case OPTEE_RPC_SHM_TYPE_KERNEL:
> > >> - shm = tee_shm_alloc_priv_kernel_buf(ctx,
> > >> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx,
> > >> arg->params[0].u.value.b);
> > >> break;
> > >> default:
> > >> @@ -493,14 +494,13 @@ static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx,
> > >> }
> > >>
> > >> static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
> > >> + struct optee *optee,
> > >> struct optee_msg_arg *arg)
> > >> {
> > >> - struct optee *optee = tee_get_drvdata(ctx->teedev);
> > >> -
> > >> arg->ret_origin = TEEC_ORIGIN_COMMS;
> > >> switch (arg->cmd) {
> > >> case OPTEE_RPC_CMD_SHM_ALLOC:
> > >> - handle_ffa_rpc_func_cmd_shm_alloc(ctx, arg);
> > >> + handle_ffa_rpc_func_cmd_shm_alloc(ctx, optee, arg);
> > >> break;
> > >> case OPTEE_RPC_CMD_SHM_FREE:
> > >> handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg);
> > >> @@ -510,12 +510,12 @@ static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
> > >> }
> > >> }
> > >>
> > >> -static void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd,
> > >> - struct optee_msg_arg *arg)
> > >> +static void optee_handle_ffa_rpc(struct tee_context *ctx, struct optee *optee,
> > >> + u32 cmd, struct optee_msg_arg *arg)
> > >> {
> > >> switch (cmd) {
> > >> case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
> > >> - handle_ffa_rpc_func_cmd(ctx, arg);
> > >> + handle_ffa_rpc_func_cmd(ctx, optee, arg);
> > >> break;
> > >> case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
> > >> /* Interrupt delivered by now */
> > >> @@ -582,7 +582,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx,
> > >> * above.
> > >> */
> > >> cond_resched();
> > >> - optee_handle_ffa_rpc(ctx, data->data1, rpc_arg);
> > >> + optee_handle_ffa_rpc(ctx, optee, data->data1, rpc_arg);
> > >> cmd = OPTEE_FFA_YIELDING_CALL_RESUME;
> > >> data->data0 = cmd;
> > >> data->data1 = 0;
> > >> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> > >> index 1dbb13b08381..f2ef76451443 100644
> > >> --- a/drivers/tee/optee/smc_abi.c
> > >> +++ b/drivers/tee/optee/smc_abi.c
> > >> @@ -621,6 +621,7 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
> > >> }
> > >>
> > >> static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> > >> + struct optee *optee,
> > >> struct optee_msg_arg *arg,
> > >> struct optee_call_ctx *call_ctx)
> > >> {
> > >> @@ -650,7 +651,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
> > >> shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
> > >> break;
> > >> case OPTEE_RPC_SHM_TYPE_KERNEL:
> > >> - shm = tee_shm_alloc_priv_kernel_buf(ctx, sz);
> > >> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx, sz);
> > >> break;
> > >> default:
> > >> arg->ret = TEEC_ERROR_BAD_PARAMETERS;
> > >> @@ -746,7 +747,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
> > >> switch (arg->cmd) {
> > >> case OPTEE_RPC_CMD_SHM_ALLOC:
> > >> free_pages_list(call_ctx);
> > >> - handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
> > >> + handle_rpc_func_cmd_shm_alloc(ctx, optee, arg, call_ctx);
> > >> break;
> > >> case OPTEE_RPC_CMD_SHM_FREE:
> > >> handle_rpc_func_cmd_shm_free(ctx, arg);
> > >> @@ -775,7 +776,7 @@ static void optee_handle_rpc(struct tee_context *ctx,
> > >>
> > >> switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
> > >> case OPTEE_SMC_RPC_FUNC_ALLOC:
> > >> - shm = tee_shm_alloc_priv_kernel_buf(ctx, param->a1);
> > >> + shm = tee_shm_alloc_priv_kernel_buf(optee->ctx, param->a1);
> > >> if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
> > >> reg_pair_from_64(&param->a1, &param->a2, pa);
> > >> reg_pair_from_64(&param->a4, &param->a5,
> > >> --
> > >> 2.31.1
> > >>

2022-01-24 19:21:43

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH v2 06/12] optee: add driver private tee_context

On Fri, Jan 21, 2022 at 1:48 PM Sumit Garg <[email protected]> wrote:
>
> On Fri, 14 Jan 2022 at 20:38, Jens Wiklander <[email protected]> wrote:
> >
> > Adds a driver private tee_context by moving the tee_context in struct
> > optee_notif to struct optee. This tee_context is used when doing
> > internal calls to secure world to deliver notification and later also
> > when sharing driver private memory with secure world.
> >
> > Signed-off-by: Jens Wiklander <[email protected]>
> > ---
> > drivers/tee/optee/core.c | 1 +
> > drivers/tee/optee/ffa_abi.c | 61 ++++++++++++++++++-------------
> > drivers/tee/optee/optee_private.h | 5 ++-
> > drivers/tee/optee/smc_abi.c | 40 ++++++--------------
> > 4 files changed, 51 insertions(+), 56 deletions(-)
> >
>
> After looking at this patch, it looks like there is a need for some
> more refactoring to pick out common probe functionality from both ABIs
> and add optee_probe_common(). If it was there earlier, this patch
> would mostly be modifying the OP-TEE core file apart from
> notifications stuff.
>
> I would leave it upto you to have a refactoring patch before and then
> changes in this patch or vice-versa.

I'll do the refactoring after this patch set.

Thanks,
Jens

>
> -Sumit
>
> > diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> > index 2a369e346b85..f4bccb5f0e93 100644
> > --- a/drivers/tee/optee/core.c
> > +++ b/drivers/tee/optee/core.c
> > @@ -161,6 +161,7 @@ void optee_remove_common(struct optee *optee)
> > optee_unregister_devices();
> >
> > optee_notif_uninit(optee);
> > + teedev_close_context(optee->ctx);
> > /*
> > * The two devices have to be unregistered before we can free the
> > * other resources.
> > diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> > index 18963f7e4d48..88a028d4fb7b 100644
> > --- a/drivers/tee/optee/ffa_abi.c
> > +++ b/drivers/tee/optee/ffa_abi.c
> > @@ -766,7 +766,9 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> > {
> > const struct ffa_dev_ops *ffa_ops;
> > unsigned int rpc_arg_count;
> > + struct tee_shm_pool *pool;
> > struct tee_device *teedev;
> > + struct tee_context *ctx;
> > struct optee *optee;
> > int rc;
> >
> > @@ -786,12 +788,12 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> > if (!optee)
> > return -ENOMEM;
> >
> > - optee->pool = optee_ffa_shm_pool_alloc_pages();
> > - if (IS_ERR(optee->pool)) {
> > - rc = PTR_ERR(optee->pool);
> > - optee->pool = NULL;
> > - goto err;
> > + pool = optee_ffa_shm_pool_alloc_pages();
> > + if (IS_ERR(pool)) {
> > + rc = PTR_ERR(pool);
> > + goto err_free_optee;
> > }
> > + optee->pool = pool;
> >
> > optee->ops = &optee_ffa_ops;
> > optee->ffa.ffa_dev = ffa_dev;
> > @@ -802,7 +804,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> > optee);
> > if (IS_ERR(teedev)) {
> > rc = PTR_ERR(teedev);
> > - goto err;
> > + goto err_free_pool;
> > }
> > optee->teedev = teedev;
> >
> > @@ -810,50 +812,57 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> > optee);
> > if (IS_ERR(teedev)) {
> > rc = PTR_ERR(teedev);
> > - goto err;
> > + goto err_unreg_teedev;
> > }
> > optee->supp_teedev = teedev;
> >
> > rc = tee_device_register(optee->teedev);
> > if (rc)
> > - goto err;
> > + goto err_unreg_supp_teedev;
> >
> > rc = tee_device_register(optee->supp_teedev);
> > if (rc)
> > - goto err;
> > + goto err_unreg_supp_teedev;
> >
> > rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
> > if (rc)
> > - goto err;
> > + goto err_unreg_supp_teedev;
> > mutex_init(&optee->ffa.mutex);
> > mutex_init(&optee->call_queue.mutex);
> > INIT_LIST_HEAD(&optee->call_queue.waiters);
> > optee_supp_init(&optee->supp);
> > ffa_dev_set_drvdata(ffa_dev, optee);
> > + ctx = teedev_open(optee->teedev);
> > + if (IS_ERR(ctx))
> > + goto err_rhashtable_free;
> > + optee->ctx = ctx;
> > rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE);
> > - if (rc) {
> > - optee_ffa_remove(ffa_dev);
> > - return rc;
> > - }
> > + if (rc)
> > + goto err_close_ctx;
> >
> > rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
> > - if (rc) {
> > - optee_ffa_remove(ffa_dev);
> > - return rc;
> > - }
> > + if (rc)
> > + goto err_unregister_devices;
> >
> > pr_info("initialized driver\n");
> > return 0;
> > -err:
> > - /*
> > - * tee_device_unregister() is safe to call even if the
> > - * devices hasn't been registered with
> > - * tee_device_register() yet.
> > - */
> > +
> > +err_unregister_devices:
> > + optee_unregister_devices();
> > + optee_notif_uninit(optee);
> > +err_close_ctx:
> > + teedev_close_context(ctx);
> > +err_rhashtable_free:
> > + rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL);
> > + optee_supp_uninit(&optee->supp);
> > + mutex_destroy(&optee->call_queue.mutex);
> > +err_unreg_supp_teedev:
> > tee_device_unregister(optee->supp_teedev);
> > +err_unreg_teedev:
> > tee_device_unregister(optee->teedev);
> > - if (optee->pool)
> > - tee_shm_pool_free(optee->pool);
> > +err_free_pool:
> > + tee_shm_pool_free(pool);
> > +err_free_optee:
> > kfree(optee);
> > return rc;
> > }
> > diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> > index df2450921464..df3a483bbf46 100644
> > --- a/drivers/tee/optee/optee_private.h
> > +++ b/drivers/tee/optee/optee_private.h
> > @@ -53,7 +53,6 @@ struct optee_call_queue {
> >
> > struct optee_notif {
> > u_int max_key;
> > - struct tee_context *ctx;
> > /* Serializes access to the elements below in this struct */
> > spinlock_t lock;
> > struct list_head db;
> > @@ -134,9 +133,10 @@ struct optee_ops {
> > /**
> > * struct optee - main service struct
> > * @supp_teedev: supplicant device
> > + * @teedev: client device
> > * @ops: internal callbacks for different ways to reach secure
> > * world
> > - * @teedev: client device
> > + * @ctx: driver internal TEE context
> > * @smc: specific to SMC ABI
> > * @ffa: specific to FF-A ABI
> > * @call_queue: queue of threads waiting to call @invoke_fn
> > @@ -152,6 +152,7 @@ struct optee {
> > struct tee_device *supp_teedev;
> > struct tee_device *teedev;
> > const struct optee_ops *ops;
> > + struct tee_context *ctx;
> > union {
> > struct optee_smc smc;
> > struct optee_ffa ffa;
> > diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> > index 196cd4316d7d..1dbb13b08381 100644
> > --- a/drivers/tee/optee/smc_abi.c
> > +++ b/drivers/tee/optee/smc_abi.c
> > @@ -952,57 +952,34 @@ static irqreturn_t notif_irq_thread_fn(int irq, void *dev_id)
> > {
> > struct optee *optee = dev_id;
> >
> > - optee_smc_do_bottom_half(optee->notif.ctx);
> > + optee_smc_do_bottom_half(optee->ctx);
> >
> > return IRQ_HANDLED;
> > }
> >
> > static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
> > {
> > - struct tee_context *ctx;
> > int rc;
> >
> > - ctx = teedev_open(optee->teedev);
> > - if (IS_ERR(ctx))
> > - return PTR_ERR(ctx);
> > -
> > - optee->notif.ctx = ctx;
> > rc = request_threaded_irq(irq, notif_irq_handler,
> > notif_irq_thread_fn,
> > 0, "optee_notification", optee);
> > if (rc)
> > - goto err_close_ctx;
> > + return rc;
> >
> > optee->smc.notif_irq = irq;
> >
> > return 0;
> > -
> > -err_close_ctx:
> > - teedev_close_context(optee->notif.ctx);
> > - optee->notif.ctx = NULL;
> > -
> > - return rc;
> > }
> >
> > static void optee_smc_notif_uninit_irq(struct optee *optee)
> > {
> > - if (optee->notif.ctx) {
> > - optee_smc_stop_async_notif(optee->notif.ctx);
> > + if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
> > + optee_smc_stop_async_notif(optee->ctx);
> > if (optee->smc.notif_irq) {
> > free_irq(optee->smc.notif_irq, optee);
> > irq_dispose_mapping(optee->smc.notif_irq);
> > }
> > -
> > - /*
> > - * The thread normally working with optee->notif.ctx was
> > - * stopped with free_irq() above.
> > - *
> > - * Note we're not using teedev_close_context() or
> > - * tee_client_close_context() since we have already called
> > - * tee_device_put() while initializing to avoid a circular
> > - * reference counting.
> > - */
> > - teedev_close_context(optee->notif.ctx);
> > }
> > }
> >
> > @@ -1307,6 +1284,7 @@ static int optee_probe(struct platform_device *pdev)
> > struct optee *optee = NULL;
> > void *memremaped_shm = NULL;
> > struct tee_device *teedev;
> > + struct tee_context *ctx;
> > u32 max_notif_value;
> > u32 sec_caps;
> > int rc;
> > @@ -1387,9 +1365,13 @@ static int optee_probe(struct platform_device *pdev)
> > optee->pool = pool;
> >
> > platform_set_drvdata(pdev, optee);
> > + ctx = teedev_open(optee->teedev);
> > + if (IS_ERR(ctx))
> > + goto err_supp_uninit;
> > + optee->ctx = ctx;
> > rc = optee_notif_init(optee, max_notif_value);
> > if (rc)
> > - goto err_supp_uninit;
> > + goto err_close_ctx;
> >
> > if (sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
> > unsigned int irq;
> > @@ -1437,6 +1419,8 @@ static int optee_probe(struct platform_device *pdev)
> > optee_unregister_devices();
> > err_notif_uninit:
> > optee_notif_uninit(optee);
> > +err_close_ctx:
> > + teedev_close_context(ctx);
> > err_supp_uninit:
> > optee_supp_uninit(&optee->supp);
> > mutex_destroy(&optee->call_queue.mutex);
> > --
> > 2.31.1
> >