[PATCH v5 7/9] dma-buf: heaps: restricted_heap: Add MediaTek restricted heap and heap_init
Jens Wiklander
jens.wiklander at linaro.org
Thu Aug 22 15:11:57 UTC 2024
On Wed, May 15, 2024 at 1:25 PM Yong Wu <yong.wu at mediatek.com> wrote:
>
> Add a MediaTek restricted heap which uses TEE service call to restrict
> buffer. Currently this restricted heap is NULL, Prepare for the later
> patch. Mainly there are two changes:
> a) Add a heap_init ops since TEE probe late than restricted heap, thus
> initialize the heap when we require the buffer the first time.
> b) Add a priv_data for each heap, like the special data used by MTK
> (such as "TEE session") can be placed in priv_data.
>
> Currently our heap depends on CMA which could only be bool, thus
> depend on "TEE=y".
>
> Signed-off-by: Yong Wu <yong.wu at mediatek.com>
> ---
> drivers/dma-buf/heaps/Kconfig | 7 ++
> drivers/dma-buf/heaps/Makefile | 1 +
> drivers/dma-buf/heaps/restricted_heap.c | 11 ++
> drivers/dma-buf/heaps/restricted_heap.h | 2 +
> drivers/dma-buf/heaps/restricted_heap_mtk.c | 115 ++++++++++++++++++++
> 5 files changed, 136 insertions(+)
> create mode 100644 drivers/dma-buf/heaps/restricted_heap_mtk.c
>
> diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
> index e54506f480ea..84f748fb2856 100644
> --- a/drivers/dma-buf/heaps/Kconfig
> +++ b/drivers/dma-buf/heaps/Kconfig
> @@ -21,3 +21,10 @@ config DMABUF_HEAPS_RESTRICTED
> heap is to manage buffers that are inaccessible to the kernel and user space.
> There may be several ways to restrict it, for example it may be encrypted or
> protected by a TEE or hypervisor. If in doubt, say N.
> +
> +config DMABUF_HEAPS_RESTRICTED_MTK
> + bool "MediaTek DMA-BUF Restricted Heap"
> + depends on DMABUF_HEAPS_RESTRICTED && TEE=y
> + help
> + Enable restricted dma-buf heaps for MediaTek platform. This heap is backed by
> + TEE client interfaces. If in doubt, say N.
> diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
> index a2437c1817e2..0028aa9d875f 100644
> --- a/drivers/dma-buf/heaps/Makefile
> +++ b/drivers/dma-buf/heaps/Makefile
> @@ -1,4 +1,5 @@
> # SPDX-License-Identifier: GPL-2.0
> obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
> obj-$(CONFIG_DMABUF_HEAPS_RESTRICTED) += restricted_heap.o
> +obj-$(CONFIG_DMABUF_HEAPS_RESTRICTED_MTK) += restricted_heap_mtk.o
> obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o
> diff --git a/drivers/dma-buf/heaps/restricted_heap.c b/drivers/dma-buf/heaps/restricted_heap.c
> index 4e45d46a6467..8bc8a5e3f969 100644
> --- a/drivers/dma-buf/heaps/restricted_heap.c
> +++ b/drivers/dma-buf/heaps/restricted_heap.c
> @@ -151,11 +151,22 @@ restricted_heap_allocate(struct dma_heap *heap, unsigned long size,
> unsigned long fd_flags, unsigned long heap_flags)
> {
> struct restricted_heap *rheap = dma_heap_get_drvdata(heap);
> + const struct restricted_heap_ops *ops = rheap->ops;
> struct restricted_buffer *restricted_buf;
> DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
> struct dma_buf *dmabuf;
> int ret;
>
> + /*
> + * In some implements, TEE is required to protect buffer. However TEE probe
> + * may be late, Thus heap_init is performed when the first buffer is requested.
> + */
> + if (ops->heap_init) {
> + ret = ops->heap_init(rheap);
> + if (ret)
> + return ERR_PTR(ret);
> + }
> +
> restricted_buf = kzalloc(sizeof(*restricted_buf), GFP_KERNEL);
> if (!restricted_buf)
> return ERR_PTR(-ENOMEM);
> diff --git a/drivers/dma-buf/heaps/restricted_heap.h b/drivers/dma-buf/heaps/restricted_heap.h
> index 6d9599a4a34e..2a33a1c7a48b 100644
> --- a/drivers/dma-buf/heaps/restricted_heap.h
> +++ b/drivers/dma-buf/heaps/restricted_heap.h
> @@ -19,6 +19,8 @@ struct restricted_heap {
> const char *name;
>
> const struct restricted_heap_ops *ops;
> +
> + void *priv_data;
> };
>
> struct restricted_heap_ops {
> diff --git a/drivers/dma-buf/heaps/restricted_heap_mtk.c b/drivers/dma-buf/heaps/restricted_heap_mtk.c
> new file mode 100644
> index 000000000000..52e805eb9858
> --- /dev/null
> +++ b/drivers/dma-buf/heaps/restricted_heap_mtk.c
> @@ -0,0 +1,115 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * DMABUF restricted heap exporter for MediaTek
> + *
> + * Copyright (C) 2024 MediaTek Inc.
> + */
> +#define pr_fmt(fmt) "rheap_mtk: " fmt
> +
> +#include <linux/dma-buf.h>
> +#include <linux/err.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/tee_drv.h>
> +#include <linux/uuid.h>
> +
> +#include "restricted_heap.h"
> +
> +#define TZ_TA_MEM_UUID_MTK "4477588a-8476-11e2-ad15-e41f1390d676"
> +
> +#define TEE_PARAM_NUM 4
> +
> +enum mtk_secure_mem_type {
> + /*
> + * MediaTek static chunk memory carved out for TrustZone. The memory
> + * management is inside the TEE.
> + */
> + MTK_SECURE_MEMORY_TYPE_CM_TZ = 1,
> +};
> +
> +struct mtk_restricted_heap_data {
> + struct tee_context *tee_ctx;
> + u32 tee_session;
> +
> + const enum mtk_secure_mem_type mem_type;
> +
> +};
> +
> +static int mtk_tee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
> +{
> + return ver->impl_id == TEE_IMPL_ID_OPTEE;
> +}
> +
> +static int mtk_tee_session_init(struct mtk_restricted_heap_data *data)
> +{
> + struct tee_param t_param[TEE_PARAM_NUM] = {0};
> + struct tee_ioctl_open_session_arg arg = {0};
> + uuid_t ta_mem_uuid;
> + int ret;
> +
> + data->tee_ctx = tee_client_open_context(NULL, mtk_tee_ctx_match, NULL, NULL);
> + if (IS_ERR(data->tee_ctx)) {
> + pr_err_once("%s: open context failed, ret=%ld\n", __func__,
> + PTR_ERR(data->tee_ctx));
> + return -ENODEV;
> + }
> +
> + arg.num_params = TEE_PARAM_NUM;
> + arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
> + ret = uuid_parse(TZ_TA_MEM_UUID_MTK, &ta_mem_uuid);
> + if (ret)
> + goto close_context;
> + memcpy(&arg.uuid, &ta_mem_uuid.b, sizeof(ta_mem_uuid));
> +
> + ret = tee_client_open_session(data->tee_ctx, &arg, t_param);
> + if (ret < 0 || arg.ret) {
> + pr_err_once("%s: open session failed, ret=%d:%d\n",
> + __func__, ret, arg.ret);
> + ret = -EINVAL;
> + goto close_context;
> + }
> + data->tee_session = arg.session;
> + return 0;
> +
> +close_context:
> + tee_client_close_context(data->tee_ctx);
There's a
data->tee_ctx = NULL;
missing here.
Cheers,
Jens
> + return ret;
> +}
> +
> +static int mtk_restricted_heap_init(struct restricted_heap *rheap)
> +{
> + struct mtk_restricted_heap_data *data = rheap->priv_data;
> +
> + if (!data->tee_ctx)
> + return mtk_tee_session_init(data);
> + return 0;
> +}
> +
> +static const struct restricted_heap_ops mtk_restricted_heap_ops = {
> + .heap_init = mtk_restricted_heap_init,
> +};
> +
> +static struct mtk_restricted_heap_data mtk_restricted_heap_data = {
> + .mem_type = MTK_SECURE_MEMORY_TYPE_CM_TZ,
> +};
> +
> +static struct restricted_heap mtk_restricted_heaps[] = {
> + {
> + .name = "restricted_mtk_cm",
> + .ops = &mtk_restricted_heap_ops,
> + .priv_data = &mtk_restricted_heap_data,
> + },
> +};
> +
> +static int mtk_restricted_heap_initialize(void)
> +{
> + struct restricted_heap *rheap = mtk_restricted_heaps;
> + unsigned int i;
> +
> + for (i = 0; i < ARRAY_SIZE(mtk_restricted_heaps); i++, rheap++)
> + restricted_heap_add(rheap);
> + return 0;
> +}
> +module_init(mtk_restricted_heap_initialize);
> +MODULE_DESCRIPTION("MediaTek Restricted Heap Driver");
> +MODULE_LICENSE("GPL");
> --
> 2.25.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
More information about the dri-devel
mailing list