On Wed, May 15, 2024 at 1:25 PM Yong Wu <yong.wu@xxxxxxxxxxxx> 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@xxxxxxxxxxxx> > --- > 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@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel