From 9e38023fe6f6c594afc343475c6e8d06959fd89f Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Wed, 4 Apr 2018 16:46:23 +0200 Subject: [PATCH 01/30] Add upstream-tee-subsys-patches.txt Adds upstream-tee-subsys-patches.txt describing all upstream patches related to the TEE subsystem. Signed-off-by: Jens Wiklander [jf: rebase on top of v4.18] Signed-off-by: Jerome Forissier --- upstream-tee-subsys-patches.txt | 53 +++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 upstream-tee-subsys-patches.txt diff --git a/upstream-tee-subsys-patches.txt b/upstream-tee-subsys-patches.txt new file mode 100644 index 00000000000000..311de9bb2c26c2 --- /dev/null +++ b/upstream-tee-subsys-patches.txt @@ -0,0 +1,53 @@ +Patches relating to the TEE subsystem +===================================== + +This is a list of all the patches that relates to the TEE subsystem. The +text inside the brackets are the kernel version where it was introduced, +followed by the sha1 hash in the upstream kernel tree. + + +[v4.17] f5d5641b90b3 optee: check shm reference are consistent in offset/size +[v4.17] bb765d1c331f tee: shm: fix use-after-free via temporarily dropped reference +[v4.16] 5c5f80307ab2 tee: optee: report OP-TEE revision information +[v4.16] 6e112de04278 tee: optee: GET_OS_REVISION: document a2 as a build identifier +[v4.16] 7dd003aec201 correct max value for id allocation +[v4.16] ded4c39e93f3 arm/arm64: smccc: Make function identifiers an unsigned quantity +[v4.16] 2490cdf6435b tee: shm: Potential NULL dereference calling tee_shm_register() +[v4.16] c94f31b526fe tee: shm: don't put_page on null shm->pages +[v4.16] 80ec6f5de60b tee: shm: make function __tee_shm_alloc static +[v4.16] cdbcf83d29c1 tee: optee: check type of registered shared memory +[v4.16] 95ffe4ca4387 tee: add start argument to shm_register callback +[v4.16] f681e08f671a tee: optee: fix header dependencies +[v4.16] ef8e08d24ca8 tee: shm: inline tee_shm_get_id() +[v4.16] 217e0250cccb tee: use reference counting for tee_context +[v4.16] f58e236c9d66 tee: optee: enable dynamic SHM support +[v4.16] abd135ba215c tee: optee: add optee-specific shared pool implementation +[v4.16] d885cc5e0759 tee: optee: store OP-TEE capabilities in private data +[v4.16] 53a107c812de tee: optee: add registered buffers handling into RPC calls +[v4.16] 64cf9d8a672e tee: optee: add registered shared parameters handling +[v4.16] 06ca79179c4e tee: optee: add shared buffer registration functions +[v4.16] 3bb48ba5cd60 tee: optee: add page list manipulation functions +[v4.16] de5c6dfc43da tee: optee: Update protocol definitions +[v4.16] e0c69ae8bfb5 tee: shm: add page accessor functions +[v4.16] b25946ad951c tee: shm: add accessors for buffer size and page offset +[v4.16] 033ddf12bcf5 tee: add register user memory +[v4.16] e2aca5d8928a tee: flexible shared memory pool creation +[v4.16] 1647a5ac1754 optee: support asynchronous supplicant requests +[v4.16] f2aa97240c84 tee: add TEE_IOCTL_PARAM_ATTR_META +[v4.16] 84debcc53533 tee: add tee_param_is_memref() for driver use +[v4.15] f044113113dd optee: fix invalid of_node_put() in optee_driver_init() +[v4.14] 39e6519a3f13 tee: optee: sync with new naming of interrupts +[v4.14] 059cf566e123 tee: indicate privileged dev in gen_caps +[v4.14] a9980e947ec9 tee: optee: interruptible RPC sleep +[v4.14] 96e72ddeec45 tee: optee: add const to tee_driver_ops and tee_desc structures +[v4.14] 53e3ca5cee24 tee: tee_shm: Constify dma_buf_ops structures. +[v4.14] 999616b8536c tee: add forward declaration for struct device +[v4.14] efb14036bd7f tee: optee: fix uninitialized symbol 'parg' +[v4.12] e84188852a72 tee: add ARM_SMCCC dependency +[v4.12] 4fb0a5eb364d tee: add OP-TEE driver +[v4.12] 967c9cca2cc5 tee: generic TEE subsystem +[v4.5] 14457459f9ca ARM: 8480/2: arm64: add implementation for arm-smccc +[v4.5] b329f95d70f3 ARM: 8479/2: add implementation for arm-smccc +[v4.5] 98dd64f34f47 ARM: 8478/2: arm/arm64: add arm-smccc + + From 9d5c773e6ff2250f39bff8b311127bf75ff3c39d Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Thu, 27 Oct 2016 23:18:35 +0200 Subject: [PATCH 02/30] tee: new ioctl to a register tee_shm from a dmabuf file descriptor This change allows userland to create a tee_shm object that refers to a dmabuf reference. Userland provides a dmabuf file descriptor as buffer reference. The created tee_shm object exported as a brand new dmabuf reference used to provide a clean fd to userland. Userland shall closed this new fd to release the tee_shm object resources. The initial dmabuf resources are tracked independently through original dmabuf file descriptor. Once the buffer is registered and until it is released, TEE driver keeps a refcount on the registered dmabuf structure. This change only support dmabuf references that relates to physically contiguous memory buffers. New tee_shm flag to identify tee_shm objects built from a registered dmabuf: TEE_SHM_EXT_DMA_BUF. Such tee_shm structures are flagged both TEE_SHM_DMA_BUF and TEE_SHM_EXT_DMA_BUF. Signed-off-by: Etienne Carriere Reviewed-by: Jens Wiklander [jf: squash fixup commit ("tee: fix unbalanced context refcount in register shm from fd")] [jf: rebase onto v5.9-rc8] Signed-off-by: Jerome Forissier --- drivers/tee/tee_core.c | 38 ++++++++++++++ drivers/tee/tee_shm.c | 111 ++++++++++++++++++++++++++++++++++++++- include/linux/tee_drv.h | 10 ++++ include/uapi/linux/tee.h | 29 ++++++++++ 4 files changed, 186 insertions(+), 2 deletions(-) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 64637e09a09536..6492aee9b8451f 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -351,6 +351,42 @@ tee_ioctl_shm_register(struct tee_context *ctx, return ret; } +static int tee_ioctl_shm_register_fd(struct tee_context *ctx, + struct tee_ioctl_shm_register_fd_data __user *udata) +{ + struct tee_ioctl_shm_register_fd_data data; + struct tee_shm *shm; + long ret; + + if (copy_from_user(&data, udata, sizeof(data))) + return -EFAULT; + + /* Currently no input flags are supported */ + if (data.flags) + return -EINVAL; + + shm = tee_shm_register_fd(ctx, data.fd); + if (IS_ERR_OR_NULL(shm)) + return -EINVAL; + + data.id = shm->id; + data.flags = shm->flags; + data.size = shm->size; + + if (copy_to_user(udata, &data, sizeof(data))) + ret = -EFAULT; + else + ret = tee_shm_get_fd(shm); + + /* + * When user space closes the file descriptor the shared memory + * should be freed or if tee_shm_get_fd() failed then it will + * be freed immediately. + */ + tee_shm_put(shm); + return ret; +} + static int params_from_user(struct tee_context *ctx, struct tee_param *params, size_t num_params, struct tee_ioctl_param __user *uparams) @@ -811,6 +847,8 @@ static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return tee_ioctl_shm_alloc(ctx, uarg); case TEE_IOC_SHM_REGISTER: return tee_ioctl_shm_register(ctx, uarg); + case TEE_IOC_SHM_REGISTER_FD: + return tee_ioctl_shm_register_fd(ctx, uarg); case TEE_IOC_OPEN_SESSION: return tee_ioctl_open_session(ctx, uarg); case TEE_IOC_INVOKE: diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 827ac3d0fea96c..7cf16603e26ba6 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -12,6 +12,14 @@ #include #include "tee_private.h" +/* extra references appended to shm object for registered shared memory */ +struct tee_shm_dmabuf_ref { + struct tee_shm shm; + struct dma_buf *dmabuf; + struct dma_buf_attachment *attach; + struct sg_table *sgt; +}; + static void tee_shm_release(struct tee_shm *shm) { struct tee_device *teedev = shm->ctx->teedev; @@ -22,7 +30,15 @@ static void tee_shm_release(struct tee_shm *shm) mutex_unlock(&teedev->mutex); } - if (shm->flags & TEE_SHM_POOL) { + if (shm->flags & TEE_SHM_EXT_DMA_BUF) { + struct tee_shm_dmabuf_ref *ref; + + ref = container_of(shm, struct tee_shm_dmabuf_ref, shm); + dma_buf_unmap_attachment(ref->attach, ref->sgt, + DMA_BIDIRECTIONAL); + dma_buf_detach(shm->dmabuf, ref->attach); + dma_buf_put(ref->dmabuf); + } else if (shm->flags & TEE_SHM_POOL) { struct tee_shm_pool_mgr *poolm; if (shm->flags & TEE_SHM_DMA_BUF) @@ -48,7 +64,6 @@ static void tee_shm_release(struct tee_shm *shm) teedev_ctx_put(shm->ctx); kfree(shm); - tee_device_put(teedev); } @@ -312,6 +327,98 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, } EXPORT_SYMBOL_GPL(tee_shm_register); +struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd) +{ + struct tee_shm_dmabuf_ref *ref; + void *rc; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + + if (!tee_device_get(ctx->teedev)) + return ERR_PTR(-EINVAL); + + teedev_ctx_get(ctx); + + ref = kzalloc(sizeof(*ref), GFP_KERNEL); + if (!ref) { + rc = ERR_PTR(-ENOMEM); + goto err; + } + + ref->shm.ctx = ctx; + ref->shm.id = -1; + + ref->dmabuf = dma_buf_get(fd); + if (!ref->dmabuf) { + rc = ERR_PTR(-EINVAL); + goto err; + } + + ref->attach = dma_buf_attach(ref->dmabuf, &ctx->teedev->dev); + if (IS_ERR_OR_NULL(ref->attach)) { + rc = ERR_PTR(-EINVAL); + goto err; + } + + ref->sgt = dma_buf_map_attachment(ref->attach, DMA_BIDIRECTIONAL); + if (IS_ERR_OR_NULL(ref->sgt)) { + rc = ERR_PTR(-EINVAL); + goto err; + } + + if (sg_nents(ref->sgt->sgl) != 1) { + rc = ERR_PTR(-EINVAL); + goto err; + } + + ref->shm.paddr = sg_dma_address(ref->sgt->sgl); + ref->shm.size = sg_dma_len(ref->sgt->sgl); + ref->shm.flags = TEE_SHM_DMA_BUF | TEE_SHM_EXT_DMA_BUF; + + mutex_lock(&ctx->teedev->mutex); + ref->shm.id = idr_alloc(&ctx->teedev->idr, &ref->shm, + 1, 0, GFP_KERNEL); + mutex_unlock(&ctx->teedev->mutex); + if (ref->shm.id < 0) { + rc = ERR_PTR(ref->shm.id); + goto err; + } + + /* export a dmabuf to later get a userland ref */ + exp_info.ops = &tee_shm_dma_buf_ops; + exp_info.size = ref->shm.size; + exp_info.flags = O_RDWR; + exp_info.priv = &ref->shm; + + ref->shm.dmabuf = dma_buf_export(&exp_info); + if (IS_ERR(ref->shm.dmabuf)) { + rc = ERR_PTR(-EINVAL); + goto err; + } + + return &ref->shm; + +err: + if (ref) { + if (ref->shm.id >= 0) { + mutex_lock(&ctx->teedev->mutex); + idr_remove(&ctx->teedev->idr, ref->shm.id); + mutex_unlock(&ctx->teedev->mutex); + } + if (ref->sgt) + dma_buf_unmap_attachment(ref->attach, ref->sgt, + DMA_BIDIRECTIONAL); + if (ref->attach) + dma_buf_detach(ref->dmabuf, ref->attach); + if (ref->dmabuf) + dma_buf_put(ref->dmabuf); + } + kfree(ref); + teedev_ctx_put(ctx); + tee_device_put(ctx->teedev); + return rc; +} +EXPORT_SYMBOL_GPL(tee_shm_register_fd); + /** * tee_shm_get_fd() - Increase reference count and return file descriptor * @shm: Shared memory handle diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index d074302989ddd2..f4c6d6e7ced7ab 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -342,6 +342,16 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags); struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, size_t length, u32 flags); +/** + * tee_shm_register_fd() - Register shared memory from file descriptor + * + * @ctx: Context that allocates the shared memory + * @fd: shared memory file descriptor reference. + * + * @returns a pointer to 'struct tee_shm' + */ +struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd); + /** * tee_shm_is_registered() - Check if shared memory object in registered in TEE * @shm: Shared memory handle diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h index b619f37ee03e53..b7148b5ebf792f 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h @@ -118,6 +118,35 @@ struct tee_ioctl_shm_alloc_data { #define TEE_IOC_SHM_ALLOC _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \ struct tee_ioctl_shm_alloc_data) +/** + * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument + * @fd: [in] file descriptor identifying the shared memory + * @size: [out] Size of shared memory to allocate + * @flags: [in] Flags to/from allocation. + * @id: [out] Identifier of the shared memory + * + * The flags field should currently be zero as input. Updated by the call + * with actual flags as defined by TEE_IOCTL_SHM_* above. + * This structure is used as argument for TEE_IOC_SHM_ALLOC below. + */ +struct tee_ioctl_shm_register_fd_data { + __s64 fd; + __u64 size; + __u32 flags; + __s32 id; +} __aligned(8); + +/** + * TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor + * + * Returns a file descriptor on success or < 0 on failure + * + * The returned file descriptor refers to the shared memory object in kernel + * land. The shared memory is freed when the descriptor is closed. + */ +#define TEE_IOC_SHM_REGISTER_FD _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \ + struct tee_ioctl_shm_register_fd_data) + /** * struct tee_ioctl_buf_data - Variable sized buffer * @buf_ptr: [in] A __user pointer to a buffer From 595188c94fef5a864ccab8e703f11c4e251ce45c Mon Sep 17 00:00:00 2001 From: Joakim Bech Date: Fri, 1 Apr 2016 14:39:54 +0200 Subject: [PATCH 03/30] arm64: dt: Remove timer from mt8173 **not for mainline** From the commit below, the mt8173-evb failed to boot to console due to changes in the mt8173 device tree files. commit c0d6fe2f01c475cc137d90607a07578586883df8 Merge: b44a3d2 3e4dda7 Author: Linus Torvalds Date: Tue Nov 10 15:06:26 2015 -0800 Merge tag 'armsoc-dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Until properly solved, let's just remove the section in the device tree blob that causes this. Signed-off-by: Joakim Bech Reviewed-by: Pascal Brand --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 5e046f9d48ce91..13b40caafb2be5 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -468,15 +468,6 @@ reg = <0 0x10007000 0 0x100>; }; - timer: timer@10008000 { - compatible = "mediatek,mt8173-timer", - "mediatek,mt6577-timer"; - reg = <0 0x10008000 0 0x1000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_CLK_13M>, - <&topckgen CLK_TOP_RTC_SEL>; - }; - pwrap: pwrap@1000d000 { compatible = "mediatek,mt8173-pwrap"; reg = <0 0x1000d000 0 0x1000>; From 1d5f2c312aa9084913f0ed29bb707de82b039efb Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Wed, 17 Aug 2016 14:08:08 +0200 Subject: [PATCH 04/30] arm64: dt: OP-TEE for foundation-v8 **not for mainline** Configures foundation-v8 with OP-TEE. Signed-off-by: Jens Wiklander [jf: rebase onto v5.9-rc7] Signed-off-by: Jerome Forissier --- arch/arm64/boot/dts/arm/foundation-v8.dtsi | 27 ++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dtsi b/arch/arm64/boot/dts/arm/foundation-v8.dtsi index 05ae893d1b2ee7..597660c50ce4fe 100644 --- a/arch/arm64/boot/dts/arm/foundation-v8.dtsi +++ b/arch/arm64/boot/dts/arm/foundation-v8.dtsi @@ -22,7 +22,6 @@ aliases { serial0 = &v2m_serial0; - serial1 = &v2m_serial1; serial2 = &v2m_serial2; serial3 = &v2m_serial3; }; @@ -67,6 +66,16 @@ <0x00000008 0x80000000 0 0x80000000>; }; + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + optee@0x83000000 { + reg = <0x00000000 0x83000000 0 0x01000000>; + }; + }; + timer { compatible = "arm,armv8-timer"; interrupts = , @@ -197,14 +206,6 @@ clock-names = "uartclk", "apb_pclk"; }; - v2m_serial1: serial@a0000 { - compatible = "arm,pl011", "arm,primecell"; - reg = <0x0a0000 0x1000>; - interrupts = <6>; - clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; - clock-names = "uartclk", "apb_pclk"; - }; - v2m_serial2: serial@b0000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x0b0000 0x1000>; @@ -228,4 +229,12 @@ }; }; }; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; + }; From ef79f9efaf72c657e8be36bf7f35ff4f64466401 Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Tue, 29 Mar 2016 11:01:28 +0200 Subject: [PATCH 05/30] arm64: dt: OP-TEE for Juno **not for mainline** Configures Juno with OP-TEE. Reviewed-by: Pascal Brand Signed-off-by: Jens Wiklander [jf: rebase onto v5.9-rc7] Signed-off-by: Jerome Forissier --- arch/arm64/boot/dts/arm/juno-base.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi index f6c55877fbd94f..0ff5d784ccb582 100644 --- a/arch/arm64/boot/dts/arm/juno-base.dtsi +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi @@ -800,6 +800,17 @@ <0x00000008 0x80000000 0x1 0x80000000>; }; + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* Shared memory between secure and non-secure world */ + optee@0xfee00000 { + reg = <0x00000000 0xfee00000 0 0x00200000>; + }; + }; + bus@8000000 { compatible = "simple-bus"; #address-cells = <2>; @@ -837,4 +848,11 @@ interrupt-map-mask = <0 0>; interrupt-map = <0 0 &gic 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; }; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; }; From 767ffb63218664b0ffb42e7940b16c137dacf78b Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Fri, 2 Dec 2016 09:45:32 +0100 Subject: [PATCH 06/30] arm64: dt: Add no-map to the reserved-memory node for OP-TEE for foundation-v8 **not for mainline** All the platforms that reserve memory for OP-TEE statically via the DT (i.e., not those that reserve it via UEFI or that patch the DT dynamically thanks to OP-TEE's CFG_DT option) have to mark it 'no-map' so that only the TEE driver may map it. Signed-off-by: Jens Wiklander --- arch/arm64/boot/dts/arm/foundation-v8.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dtsi b/arch/arm64/boot/dts/arm/foundation-v8.dtsi index 597660c50ce4fe..acbf17520b3043 100644 --- a/arch/arm64/boot/dts/arm/foundation-v8.dtsi +++ b/arch/arm64/boot/dts/arm/foundation-v8.dtsi @@ -73,6 +73,7 @@ optee@0x83000000 { reg = <0x00000000 0x83000000 0 0x01000000>; + no-map; }; }; From c9108c8957d0cb86262b52286fbb9f0ec8f49949 Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Tue, 3 Jan 2017 17:09:23 +0100 Subject: [PATCH 07/30] arm64: dt: Add no-map to the reserved-memory node for OP-TEE for juno **not for mainline** All the platforms that reserve memory for OP-TEE statically via the DT (i.e., not those that reserve it via UEFI or that patch the DT dynamically thanks to OP-TEE's CFG_DT option) have to mark it 'no-map' so that only the TEE driver may map it. Signed-off-by: Jens Wiklander --- arch/arm64/boot/dts/arm/juno-base.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi index 0ff5d784ccb582..0ac89a86ae946c 100644 --- a/arch/arm64/boot/dts/arm/juno-base.dtsi +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi @@ -808,6 +808,7 @@ /* Shared memory between secure and non-secure world */ optee@0xfee00000 { reg = <0x00000000 0xfee00000 0 0x00200000>; + no-map; }; }; From f9029fed1f3872956264b32685b257ada1ea7b2c Mon Sep 17 00:00:00 2001 From: Joakim Bech Date: Thu, 24 Mar 2016 09:50:14 +0100 Subject: [PATCH 08/30] arm64: dt: Add OP-TEE firmware to mt8173 **not for mainline** Signed-off-by: Joakim Bech Reviewed-by: Pascal Brand Reviewed-by: Jerome Forissier --- arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts index 6dffada2e66b4c..e9ba9bf34143e0 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts @@ -60,6 +60,13 @@ gpio = <&pio 9 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; }; &cec { From 9f5731cfa0ce7bd049d0149d36c10e020972e61a Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Tue, 25 Oct 2016 19:03:38 +0300 Subject: [PATCH 09/30] OP-TEE Benchmark **not for mainline** Add Benchmark support Reviewed-by: Joakim Bech Signed-off-by: Igor Opaniuk [jf: squash fixup commit "tee: optee: optee_bench.h: remove useless include **not for mainline**"] [jf: rebase onto v5.9-rc7] Signed-off-by: Jerome Forissier --- drivers/tee/optee/Kconfig | 7 ++ drivers/tee/optee/Makefile | 1 + drivers/tee/optee/bench.c | 157 ++++++++++++++++++++++++++++++++ drivers/tee/optee/call.c | 5 + drivers/tee/optee/core.c | 3 + drivers/tee/optee/optee_bench.h | 68 ++++++++++++++ drivers/tee/optee/optee_msg.h | 8 ++ drivers/tee/optee/rpc.c | 49 ++++++++++ 8 files changed, 298 insertions(+) create mode 100644 drivers/tee/optee/bench.c create mode 100644 drivers/tee/optee/optee_bench.h diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig index 3ca71e3812ed4b..be57a62d5c6e57 100644 --- a/drivers/tee/optee/Kconfig +++ b/drivers/tee/optee/Kconfig @@ -15,3 +15,10 @@ config OPTEE_SHM_NUM_PRIV_PAGES help This sets the number of private shared memory pages to be used by OP-TEE TEE driver. + +config OPTEE_BENCHMARK + bool "OP-TEE Benchmark (EXPERIMENTAL)" + depends on OPTEE + help + This enables benchmarking feature in the OP-TEE Trusted + Execution Environment (TEE) driver. diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index 56263ae3b1d7a3..92247436bf856a 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -6,3 +6,4 @@ optee-objs += rpc.o optee-objs += supp.o optee-objs += shm_pool.o optee-objs += device.o +optee-objs += bench.o diff --git a/drivers/tee/optee/bench.c b/drivers/tee/optee/bench.c new file mode 100644 index 00000000000000..9e73b2fb54adc1 --- /dev/null +++ b/drivers/tee/optee/bench.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2017, Linaro Limited + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include "optee_bench.h" + +/* + * Specific defines for ARM performance timers + */ +/* aarch32 */ +#define OPTEE_BENCH_DEF_OPTS (1 | 16) +#define OPTEE_BENCH_DEF_OVER 0x8000000f +/* enable 64 divider for CCNT */ +#define OPTEE_BENCH_DIVIDER_OPTS (OPTEE_BENCH_DEF_OPTS | 8) + +/* aarch64 */ +#define OPTEE_BENCH_ARMV8_PMCR_MASK 0x3f +#define OPTEE_BENCH_ARMV8_PMCR_E (1 << 0) /* Enable all counters */ +#define OPTEE_BENCH_ARMV8_PMCR_P (1 << 1) /* Reset all counters */ +#define OPTEE_BENCH_ARMV8_PMCR_C (1 << 2) /* Cycle counter reset */ +#define OPTEE_BENCH_ARMV8_PMCR_D (1 << 3) /* 64 divider */ + +#define OPTEE_BENCH_ARMV8_PMUSERENR_EL0 (1 << 0) /* EL0 access enable */ +#define OPTEE_BENCH_ARMV8_PMUSERENR_CR (1 << 2) /* CCNT read enable */ + +struct optee_ts_global *optee_bench_ts_global; +struct rw_semaphore optee_bench_ts_rwsem; + +#ifdef CONFIG_OPTEE_BENCHMARK +static inline u32 armv8pmu_pmcr_read(void) +{ + u32 val = 0; + + asm volatile("mrs %0, pmcr_el0" : "=r"(val)); + + return (u32)val; +} + +static inline void armv8pmu_pmcr_write(u32 val) +{ + val &= OPTEE_BENCH_ARMV8_PMCR_MASK; + asm volatile("msr pmcr_el0, %0" :: "r"((u64)val)); +} + +static inline u64 read_ccounter(void) +{ + u64 ccounter; + +#ifdef __aarch64__ + asm volatile("mrs %0, PMCCNTR_EL0" : "=r"(ccounter)); +#else + asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(ccounter)); +#endif + + return ccounter * OPTEE_BENCH_DIVIDER; +} + +static void optee_pmu_setup(void *data) +{ +#ifdef __aarch64__ + /* Enable EL0 access to PMU counters. */ + asm volatile("msr pmuserenr_el0, %0" :: "r"((u64) + OPTEE_BENCH_ARMV8_PMUSERENR_EL0 | + OPTEE_BENCH_ARMV8_PMUSERENR_CR)); + /* Enable PMU counters */ + armv8pmu_pmcr_write(OPTEE_BENCH_ARMV8_PMCR_P | + OPTEE_BENCH_ARMV8_PMCR_C | + OPTEE_BENCH_ARMV8_PMCR_D); + asm volatile("msr pmcntenset_el0, %0" :: "r"((u64)(1 << 31))); + armv8pmu_pmcr_write(armv8pmu_pmcr_read() | + OPTEE_BENCH_ARMV8_PMCR_E); +#else + /* Enable EL0 access to PMU counters */ + asm volatile("mcr p15, 0, %0, c9, c14, 0" :: "r"(1)); + /* Enable all PMU counters */ + asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r" + (OPTEE_BENCH_DIVIDER_OPTS)); + /* Disable counter overflow interrupts */ + asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(OPTEE_BENCH_DEF_OVER)); +#endif +} + +static void optee_pmu_disable(void *data) +{ +#ifdef __aarch64__ + /* Disable EL0 access */ + asm volatile("msr pmuserenr_el0, %0" :: "r"((u64)0)); + /* Disable PMU counters */ + armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ~OPTEE_BENCH_ARMV8_PMCR_E); +#else + /* Disable all PMU counters */ + asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r"(0)); + /* Enable counter overflow interrupts */ + asm volatile("mcr p15, 0, %0, c9, c12, 2" :: "r"(OPTEE_BENCH_DEF_OVER)); + /* Disable EL0 access to PMU counters. */ + asm volatile("mcr p15, 0, %0, c9, c14, 0" :: "r"(0)); +#endif +} + +void optee_bm_enable(void) +{ + on_each_cpu(optee_pmu_setup, NULL, 1); +} + +void optee_bm_disable(void) +{ + on_each_cpu(optee_pmu_disable, NULL, 1); +} + +void optee_bm_timestamp(void) +{ + struct optee_ts_cpu_buf *cpu_buf; + struct optee_time_st ts_data; + uint64_t ts_i; + void *ret_addr; + int cur_cpu = 0; + int ret; + + down_read(&optee_bench_ts_rwsem); + + if (!optee_bench_ts_global) { + up_read(&optee_bench_ts_rwsem); + return; + } + + cur_cpu = get_cpu(); + + if (cur_cpu >= optee_bench_ts_global->cores) { + put_cpu(); + up_read(&optee_bench_ts_rwsem); + return; + } + + ret_addr = __builtin_return_address(0); + + cpu_buf = &optee_bench_ts_global->cpu_buf[cur_cpu]; + ts_i = __sync_fetch_and_add(&cpu_buf->head, 1); + ts_data.cnt = read_ccounter(); + ts_data.addr = (uintptr_t)ret_addr; + ts_data.src = OPTEE_BENCH_KMOD; + cpu_buf->stamps[ts_i & OPTEE_BENCH_MAX_MASK] = ts_data; + + up_read(&optee_bench_ts_rwsem); + + put_cpu(); +} +#endif /* CONFIG_OPTEE_BENCHMARK */ diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index 20b6fd7383c54b..3945041e661557 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -13,6 +13,7 @@ #include #include "optee_private.h" #include "optee_smc.h" +#include "optee_bench.h" struct optee_call_waiter { struct list_head list_node; @@ -137,10 +138,14 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) while (true) { struct arm_smccc_res res; + optee_bm_timestamp(); + optee->invoke_fn(param.a0, param.a1, param.a2, param.a3, param.a4, param.a5, param.a6, param.a7, &res); + optee_bm_timestamp(); + if (res.a0 == OPTEE_SMC_RETURN_ETHREAD_LIMIT) { /* * Out of threads in secure world, wait for a thread diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index b373b1b08b6dee..77733866c65502 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -18,6 +18,7 @@ #include #include #include +#include "optee_bench.h" #include "optee_private.h" #include "optee_smc.h" #include "shm_pool.h" @@ -602,6 +603,7 @@ static int optee_remove(struct platform_device *pdev) kfree(optee); + optee_bm_disable(); return 0; } @@ -703,6 +705,7 @@ static int optee_probe(struct platform_device *pdev) } pr_info("initialized driver\n"); + optee_bm_enable(); return 0; err: if (optee) { diff --git a/drivers/tee/optee/optee_bench.h b/drivers/tee/optee/optee_bench.h new file mode 100644 index 00000000000000..985e6a011f58f7 --- /dev/null +++ b/drivers/tee/optee/optee_bench.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Linaro Limited + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _OPTEE_BENCH_H +#define _OPTEE_BENCH_H + +#include + +/* + * Cycle count divider is enabled (in PMCR), + * CCNT value is incremented every 64th clock cycle + */ +#define OPTEE_BENCH_DIVIDER 64 + +/* max amount of timestamps */ +#define OPTEE_BENCH_MAX_STAMPS 32 +#define OPTEE_BENCH_MAX_MASK (OPTEE_BENCH_MAX_STAMPS - 1) + +/* OP-TEE susbsystems ids */ +#define OPTEE_BENCH_KMOD 0x20000000 + +#define OPTEE_MSG_RPC_CMD_BENCH_REG_NEW 0 +#define OPTEE_MSG_RPC_CMD_BENCH_REG_DEL 1 + +/* storing timestamp */ +struct optee_time_st { + uint64_t cnt; /* stores value from CNTPCT register */ + uint64_t addr; /* stores value from program counter register */ + uint64_t src; /* OP-TEE subsystem id */ +}; + +/* per-cpu circular buffer for timestamps */ +struct optee_ts_cpu_buf { + uint64_t head; + uint64_t tail; + struct optee_time_st stamps[OPTEE_BENCH_MAX_STAMPS]; +}; + +/* memory layout for shared memory, where timestamps will be stored */ +struct optee_ts_global { + uint64_t cores; + struct optee_ts_cpu_buf cpu_buf[]; +}; + +extern struct optee_ts_global *optee_bench_ts_global; +extern struct rw_semaphore optee_bench_ts_rwsem; + +#ifdef CONFIG_OPTEE_BENCHMARK +void optee_bm_enable(void); +void optee_bm_disable(void); +void optee_bm_timestamp(void); +#else +static inline void optee_bm_enable(void) {} +static inline void optee_bm_disable(void) {} +static inline void optee_bm_timestamp(void) {} +#endif /* CONFIG_OPTEE_BENCHMARK */ +#endif /* _OPTEE_BENCH_H */ diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h index 795bc19ae17a6d..7788cc4a8e0554 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -419,4 +419,12 @@ struct optee_msg_arg { */ #define OPTEE_MSG_RPC_CMD_SHM_FREE 7 +/* + * Register timestamp buffer + * + * [in] param[0].u.value.a Subcommand (register buffer, unregister buffer) + * [in] param[0].u.value.b Physical address of timestamp buffer + * [in] param[0].u.value.c Size of buffer + */ +#define OPTEE_MSG_RPC_CMD_BENCH_REG 20 #endif /* _OPTEE_MSG_H */ diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index b4ade54d1f280a..b886ae38eeb64b 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -7,8 +7,10 @@ #include #include +#include #include #include +#include "optee_bench.h" #include "optee_private.h" #include "optee_smc.h" @@ -353,6 +355,50 @@ void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx) free_pages_list(call_ctx); } +static void handle_rpc_func_cmd_bm_reg(struct optee_msg_arg *arg) +{ + u64 size; + u64 type; + u64 paddr; + + if (arg->num_params != 1) + goto bad; + + if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) != + OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) + goto bad; + + type = arg->params[0].u.value.a; + switch (type) { + case OPTEE_MSG_RPC_CMD_BENCH_REG_NEW: + size = arg->params[0].u.value.c; + paddr = arg->params[0].u.value.b; + down_write(&optee_bench_ts_rwsem); + optee_bench_ts_global = + memremap(paddr, size, MEMREMAP_WB); + if (!optee_bench_ts_global) { + up_write(&optee_bench_ts_rwsem); + goto bad; + } + up_write(&optee_bench_ts_rwsem); + break; + case OPTEE_MSG_RPC_CMD_BENCH_REG_DEL: + down_write(&optee_bench_ts_rwsem); + if (optee_bench_ts_global) + memunmap(optee_bench_ts_global); + optee_bench_ts_global = NULL; + up_write(&optee_bench_ts_rwsem); + break; + default: + goto bad; + } + + arg->ret = TEEC_SUCCESS; + return; +bad: + arg->ret = TEEC_ERROR_BAD_PARAMETERS; +} + static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, struct tee_shm *shm, struct optee_call_ctx *call_ctx) @@ -382,6 +428,9 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, case OPTEE_MSG_RPC_CMD_SHM_FREE: handle_rpc_func_cmd_shm_free(ctx, arg); break; + case OPTEE_MSG_RPC_CMD_BENCH_REG: + handle_rpc_func_cmd_bm_reg(arg); + break; default: handle_rpc_supp_cmd(ctx, arg); } From 41e9290b04e0addda81c00413099493a70da4dbd Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Mon, 5 Feb 2018 18:43:34 +0200 Subject: [PATCH 10/30] tee: support of allocating DMA shared buffers **not for mainline** Add support of allocating DMA shared buffers via RPC calls. The main difference with OPTEE_MSG_RPC_SHM_TYPE_KERNEL is that SHM pool manager for shared memory exported to user space is explicitly chosen. As dma-buf is used for exporting buffers to userspace, it provides a possiblity to mmap an allocated SHM buffer into multiple TEE client applications (unlike OPTEE_MSG_RPC_SHM_TYPE_APPL, which leverages tee-supplicant for private allocations). Such buffers should be used only for internal purposes, when there is a need to share meta data between different OP-TEE components (for debugging/profiling purposes). Signed-off-by: Igor Opaniuk [jf: squash fixup commit] Signed-off-by: Jerome Forissier --- drivers/tee/optee/optee_msg.h | 2 ++ drivers/tee/optee/rpc.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h index 7788cc4a8e0554..8839fa1b2ea767 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -407,6 +407,8 @@ struct optee_msg_arg { #define OPTEE_MSG_RPC_SHM_TYPE_APPL 0 /* Memory only shared with non-secure kernel */ #define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1 +/* Memory shared with non-secure kernel, but exported to userspace */ +#define OPTEE_MSG_RPC_SHM_TYPE_GLOBAL 2 /* * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index b886ae38eeb64b..817b1caee28c3e 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -224,6 +224,9 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, case OPTEE_MSG_RPC_SHM_TYPE_KERNEL: shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED); break; + case OPTEE_MSG_RPC_SHM_TYPE_GLOBAL: + shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF); + break; default: arg->ret = TEEC_ERROR_BAD_PARAMETERS; return; @@ -332,6 +335,7 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx, cmd_free_suppl(ctx, shm); break; case OPTEE_MSG_RPC_SHM_TYPE_KERNEL: + case OPTEE_MSG_RPC_SHM_TYPE_GLOBAL: tee_shm_free(shm); break; default: From 0b1c1035aa6898f8e3946d935f3c394a89fcc768 Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Mon, 5 Nov 2018 14:23:42 +0100 Subject: [PATCH 11/30] upstream-tee-subsys-patches.txt: patches up to v4.20-rc1 Records patches available upstream up to v4.20-rc1. Acked-by: Joakim Bech Signed-off-by: Jens Wiklander --- upstream-tee-subsys-patches.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/upstream-tee-subsys-patches.txt b/upstream-tee-subsys-patches.txt index 311de9bb2c26c2..8d6c47a183df06 100644 --- a/upstream-tee-subsys-patches.txt +++ b/upstream-tee-subsys-patches.txt @@ -6,7 +6,11 @@ text inside the brackets are the kernel version where it was introduced, followed by the sha1 hash in the upstream kernel tree. -[v4.17] f5d5641b90b3 optee: check shm reference are consistent in offset/size +[v4.20-rc1] 25559c22cef8 tee: add kernel internal client interface +[v4.20-rc1] db878f76b9ff tee: optee: take DT status property into account +[v4.19] 3249527f19d6 tee: optee: making OPTEE_SHM_NUM_PRIV_PAGES configurable via Kconfig +[v4.19] cf89fe88a676 tee: replace getnstimeofday64() with ktime_get_real_ts64() +[v4.17] ab9d3db5b320 tee: check shm references are consistent in offset/size [v4.17] bb765d1c331f tee: shm: fix use-after-free via temporarily dropped reference [v4.16] 5c5f80307ab2 tee: optee: report OP-TEE revision information [v4.16] 6e112de04278 tee: optee: GET_OS_REVISION: document a2 as a build identifier From f795a4f50c0089c12947025caae30d4d69b9a8b8 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Mon, 4 Mar 2019 17:46:33 +0100 Subject: [PATCH 12/30] upstream-tee-subsys-patches.txt: patches up to v5.0 Records patches available upstream up to v5.0. Signed-off-by: Jerome Forissier --- upstream-tee-subsys-patches.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/upstream-tee-subsys-patches.txt b/upstream-tee-subsys-patches.txt index 8d6c47a183df06..0208cfaa5b6137 100644 --- a/upstream-tee-subsys-patches.txt +++ b/upstream-tee-subsys-patches.txt @@ -5,7 +5,9 @@ This is a list of all the patches that relates to the TEE subsystem. The text inside the brackets are the kernel version where it was introduced, followed by the sha1 hash in the upstream kernel tree. - +[v5.0] c7c0d8df0b94 tee: optee: add missing of_node_put after of_device_is_available +[v5.0-rc1] 3c15ddb97c77 tee: optee: log message if dynamic shm is enabled +[v5.0-rc1] b2d102bd0146 tee: optee: avoid possible double list_del() [v4.20-rc1] 25559c22cef8 tee: add kernel internal client interface [v4.20-rc1] db878f76b9ff tee: optee: take DT status property into account [v4.19] 3249527f19d6 tee: optee: making OPTEE_SHM_NUM_PRIV_PAGES configurable via Kconfig From 578ce3c9d8cbb07d527f2b6919e58bce3aeb1a5a Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Tue, 7 May 2019 09:59:45 +0200 Subject: [PATCH 13/30] upstream-tee-subsys-patches.txt: patches up to v5.1 Records patches available upstream up to v5.1. Signed-off-by: Jerome Forissier --- upstream-tee-subsys-patches.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/upstream-tee-subsys-patches.txt b/upstream-tee-subsys-patches.txt index 0208cfaa5b6137..39ff9bdac16c68 100644 --- a/upstream-tee-subsys-patches.txt +++ b/upstream-tee-subsys-patches.txt @@ -5,6 +5,14 @@ This is a list of all the patches that relates to the TEE subsystem. The text inside the brackets are the kernel version where it was introduced, followed by the sha1 hash in the upstream kernel tree. +[v5.1-rc1] 32356d309c22 tee: optee: update optee_msg.h and optee_smc.h to dual license +[v5.1-rc1] 4f062dc1b759 tee: add cancellation support to client interface +[v5.1-rc1] 62ade1bed27c tee: optee: Fix unsigned comparison with less than zero +[v5.1-rc1] bb342f016862 tee: fix possible error pointer ctx dereferencing +[v5.1-rc1] 50ceca6894ad tee: optee: Initialize some structs using memset instead of braces +[v5.1-rc1] c3fa24af9244 tee: optee: add TEE bus device enumeration support +[v5.1-rc1] 0fc1db9d1059 tee: add bus driver framework for TEE based devices +[v5.1-rc1] 42bf4152d8a7 tee: add supp_nowait flag in tee_context struct [v5.0] c7c0d8df0b94 tee: optee: add missing of_node_put after of_device_is_available [v5.0-rc1] 3c15ddb97c77 tee: optee: log message if dynamic shm is enabled [v5.0-rc1] b2d102bd0146 tee: optee: avoid possible double list_del() From fa11127f89d77b4da33c1a804446d74232c6b951 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 14 Aug 2017 17:13:34 +0200 Subject: [PATCH 14/30] staging/ion: add Allwinner ION "secure" heap Dumped from: https://github.com/loboris/OrangePI-Kernel/tree/master/linux-3.4 0cc8d855adb457d1860d6e25cb93b6cc75d5a09d Author: Sunny for Allwinner. Changes made on original "secure heap" implementation: - minor coding style: fix includes, empty lines and overlong lines, indentation, comment layout. - Original path modified the ion uapi. We do not attempt to modify uapi/ion.h. "secure" (or "domain") heaps are under ID ION_HEAP_TYPE_CUSTOM + 1 (legacy 'secure heap type' value). Signed-off-by: Etienne Carriere --- drivers/staging/android/ion/ion_secure_heap.c | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 drivers/staging/android/ion/ion_secure_heap.c diff --git a/drivers/staging/android/ion/ion_secure_heap.c b/drivers/staging/android/ion/ion_secure_heap.c new file mode 100644 index 00000000000000..57a75b3e578a01 --- /dev/null +++ b/drivers/staging/android/ion/ion_secure_heap.c @@ -0,0 +1,178 @@ +/* + * drivers/gpu/ion/ion_secure_heap.c + * + * Copyright (C) 2016-2017 Linaro, Inc. All rigths reserved. + * Copyright (C) Allwinner 2014 + * Author: for Allwinner. + * + * Add secure heap support. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ion.h" +#include "ion_priv.h" + +#ifndef ION_HEAP_TYPE_SECURE +#define ION_HEAP_TYPE_SECURE (ION_HEAP_TYPE_CUSTOM + 1) +#endif + +struct ion_secure_heap { + struct ion_heap heap; + struct gen_pool *pool; + ion_phys_addr_t base; + size_t size; +}; + +ion_phys_addr_t ion_secure_allocate(struct ion_heap *heap, + unsigned long size, + unsigned long align) +{ + struct ion_secure_heap *secure_heap = + container_of(heap, struct ion_secure_heap, heap); + unsigned long offset = gen_pool_alloc(secure_heap->pool, size); + + if (!offset) { + pr_err("%s(%d) err: alloc 0x%08x bytes failed\n", + __func__, __LINE__, (u32)size); + return ION_CARVEOUT_ALLOCATE_FAIL; + } + return offset; +} + +void ion_secure_free(struct ion_heap *heap, ion_phys_addr_t addr, + unsigned long size) +{ + struct ion_secure_heap *secure_heap = + container_of(heap, struct ion_secure_heap, heap); + + if (addr == ION_CARVEOUT_ALLOCATE_FAIL) + return; + gen_pool_free(secure_heap->pool, addr, size); +} + +static int ion_secure_heap_phys(struct ion_heap *heap, + struct ion_buffer *buffer, + ion_phys_addr_t *addr, size_t *len) +{ + *addr = buffer->priv_phys; + *len = buffer->size; + return 0; +} + +static int ion_secure_heap_allocate(struct ion_heap *heap, + struct ion_buffer *buffer, + unsigned long size, unsigned long align, + unsigned long flags) +{ + buffer->priv_phys = ion_secure_allocate(heap, size, align); + return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0; +} + +static void ion_secure_heap_free(struct ion_buffer *buffer) +{ + struct ion_heap *heap = buffer->heap; + + ion_secure_free(heap, buffer->priv_phys, buffer->size); + buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL; +} + +struct sg_table *ion_secure_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + struct sg_table *table; + int ret; + + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) + return ERR_PTR(-ENOMEM); + ret = sg_alloc_table(table, 1, GFP_KERNEL); + if (ret) { + kfree(table); + return ERR_PTR(ret); + } + sg_set_page(table->sgl, phys_to_page(buffer->priv_phys), buffer->size, + 0); + return table; +} + +void ion_secure_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + sg_free_table(buffer->sg_table); + kfree(buffer->sg_table); +} + +int ion_secure_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, + struct vm_area_struct *vma) +{ + /* + * when user call ION_IOC_ALLOC not with ION_FLAG_CACHED, ion_mmap will + * change prog to pgprot_writecombine itself, so we donot need change to + * pgprot_writecombine here manually. + */ + return remap_pfn_range(vma, vma->vm_start, + __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); +} + +static struct ion_heap_ops secure_heap_ops = { + .allocate = ion_secure_heap_allocate, + .free = ion_secure_heap_free, + .phys = ion_secure_heap_phys, + .map_dma = ion_secure_heap_map_dma, + .unmap_dma = ion_secure_heap_unmap_dma, + .map_user = ion_secure_heap_map_user, + .map_kernel = ion_heap_map_kernel, + .unmap_kernel = ion_heap_unmap_kernel, +}; + +struct ion_heap *ion_secure_heap_create(struct ion_platform_heap *heap_data) +{ + struct ion_secure_heap *secure_heap; + + secure_heap = kzalloc(sizeof(struct ion_secure_heap), GFP_KERNEL); + if (!secure_heap) + return ERR_PTR(-ENOMEM); + + secure_heap->pool = gen_pool_create(12, -1); + if (!secure_heap->pool) { + kfree(secure_heap); + return ERR_PTR(-ENOMEM); + } + secure_heap->base = heap_data->base; + secure_heap->size = heap_data->size; + gen_pool_add(secure_heap->pool, secure_heap->base, heap_data->size, -1); + secure_heap->heap.ops = &secure_heap_ops; + secure_heap->heap.type = ION_HEAP_TYPE_SECURE; + + return &secure_heap->heap; +} + +void ion_secure_heap_destroy(struct ion_heap *heap) +{ + struct ion_secure_heap *secure_heap = + container_of(heap, struct ion_secure_heap, heap); + + gen_pool_destroy(secure_heap->pool); + kfree(secure_heap); + secure_heap = NULL; +} From 11ed7aed729224ebfe2dadb2672932995f4e6628 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 14 Aug 2017 17:16:39 +0200 Subject: [PATCH 15/30] ion: "unmapped" heap for secure data path OP-TEE/SDP (Secure Data Path) memory pools are created through ION secure type heap" from Allwinner. This change renames "secure" into "unmapped" as, from Linux point of view, the heap constraint is manipulating unampped memory pools/buffers. "Unmapped" heap support is integrated in ION UAPI (actually this was the Allwinner initial proposal) and ION DT parsing support. Based in work from Sunny for Allwinner. Changes: - rename "secure_heap" into "unmapped_heap" - define ION_HEAP_TYPE_UNMAPPED in ION UAPI (sic!) - add structure "struct unmapped_buffer_priv" to hold allocated buffer private data (currently only the buffer physical address. - adapt to recent ION (i.e ion_phys_addr_t => phys_addr_t) - Support dummy heap configuration: one can hard code into the Linux kernel configuration the location of a "unmapped heap". It will be created during ION device inits: see CONFIG_ION_DUMMY_UNMAPPED_HEAP. Signed-off-by: Etienne Carriere --- drivers/staging/android/ion/Kconfig | 32 +++ drivers/staging/android/ion/Makefile | 1 + drivers/staging/android/ion/ion_secure_heap.c | 178 ------------- .../staging/android/ion/ion_unmapped_heap.c | 252 ++++++++++++++++++ drivers/staging/android/uapi/ion.h | 3 + 5 files changed, 288 insertions(+), 178 deletions(-) delete mode 100644 drivers/staging/android/ion/ion_secure_heap.c create mode 100644 drivers/staging/android/ion/ion_unmapped_heap.c diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 989fe84a9f9d79..23ada1edb2deb5 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -25,3 +25,35 @@ config ION_CMA_HEAP Choose this option to enable CMA heaps with Ion. This heap is backed by the Contiguous Memory Allocator (CMA). If your system has these regions, you should say Y here. + +config ION_UNMAPPED_HEAP + bool "ION unmapped heap support" + depends on ION + help + Choose this option to enable UNMAPPED heaps with Ion. This heap is + backed in specific memory pools, carveout from the Linux memory. + Unless you know your system has these regions, you should say N here. + +config ION_DUMMY_UNMAPPED_HEAP + bool "ION dummy driver define an ION unmapped heap" + depends on ION_UNMAPPED_HEAP + help + Dummy ION driver will create a unmapped heap from physical + location provided through CONFIG_ION_DUMMY_UNMAPPED_BASE and + CONFIG_ION_DUMMY_UNMAPPED_SIZE. + +config ION_DUMMY_UNMAPPED_BASE + hex "Physical base address of the ION unmapped heap" + depends on ION_DUMMY_UNMAPPED_HEAP + default 0 + help + Allows one the statically define an unmapped heap from the + ION dummy driver to exercice unamped heaps buffer managment. + +config ION_DUMMY_UNMAPPED_SIZE + hex "Physical byte size of the ION unmapped heap" + depends on ION_DUMMY_UNMAPPED_HEAP + default 0 + help + Allows one the statically define an unmapped heap from the + ION dummy driver to exercice unamped heaps buffer managment. diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 5f4487b1a22440..8cc78673661aea 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_ION) += ion.o ion_heap.o obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o +obj-$(CONFIG_ION_UNMAPPED_HEAP) += ion_unmapped_heap.o diff --git a/drivers/staging/android/ion/ion_secure_heap.c b/drivers/staging/android/ion/ion_secure_heap.c deleted file mode 100644 index 57a75b3e578a01..00000000000000 --- a/drivers/staging/android/ion/ion_secure_heap.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * drivers/gpu/ion/ion_secure_heap.c - * - * Copyright (C) 2016-2017 Linaro, Inc. All rigths reserved. - * Copyright (C) Allwinner 2014 - * Author: for Allwinner. - * - * Add secure heap support. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ion.h" -#include "ion_priv.h" - -#ifndef ION_HEAP_TYPE_SECURE -#define ION_HEAP_TYPE_SECURE (ION_HEAP_TYPE_CUSTOM + 1) -#endif - -struct ion_secure_heap { - struct ion_heap heap; - struct gen_pool *pool; - ion_phys_addr_t base; - size_t size; -}; - -ion_phys_addr_t ion_secure_allocate(struct ion_heap *heap, - unsigned long size, - unsigned long align) -{ - struct ion_secure_heap *secure_heap = - container_of(heap, struct ion_secure_heap, heap); - unsigned long offset = gen_pool_alloc(secure_heap->pool, size); - - if (!offset) { - pr_err("%s(%d) err: alloc 0x%08x bytes failed\n", - __func__, __LINE__, (u32)size); - return ION_CARVEOUT_ALLOCATE_FAIL; - } - return offset; -} - -void ion_secure_free(struct ion_heap *heap, ion_phys_addr_t addr, - unsigned long size) -{ - struct ion_secure_heap *secure_heap = - container_of(heap, struct ion_secure_heap, heap); - - if (addr == ION_CARVEOUT_ALLOCATE_FAIL) - return; - gen_pool_free(secure_heap->pool, addr, size); -} - -static int ion_secure_heap_phys(struct ion_heap *heap, - struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len) -{ - *addr = buffer->priv_phys; - *len = buffer->size; - return 0; -} - -static int ion_secure_heap_allocate(struct ion_heap *heap, - struct ion_buffer *buffer, - unsigned long size, unsigned long align, - unsigned long flags) -{ - buffer->priv_phys = ion_secure_allocate(heap, size, align); - return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0; -} - -static void ion_secure_heap_free(struct ion_buffer *buffer) -{ - struct ion_heap *heap = buffer->heap; - - ion_secure_free(heap, buffer->priv_phys, buffer->size); - buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL; -} - -struct sg_table *ion_secure_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - struct sg_table *table; - int ret; - - table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!table) - return ERR_PTR(-ENOMEM); - ret = sg_alloc_table(table, 1, GFP_KERNEL); - if (ret) { - kfree(table); - return ERR_PTR(ret); - } - sg_set_page(table->sgl, phys_to_page(buffer->priv_phys), buffer->size, - 0); - return table; -} - -void ion_secure_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - sg_free_table(buffer->sg_table); - kfree(buffer->sg_table); -} - -int ion_secure_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - struct vm_area_struct *vma) -{ - /* - * when user call ION_IOC_ALLOC not with ION_FLAG_CACHED, ion_mmap will - * change prog to pgprot_writecombine itself, so we donot need change to - * pgprot_writecombine here manually. - */ - return remap_pfn_range(vma, vma->vm_start, - __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); -} - -static struct ion_heap_ops secure_heap_ops = { - .allocate = ion_secure_heap_allocate, - .free = ion_secure_heap_free, - .phys = ion_secure_heap_phys, - .map_dma = ion_secure_heap_map_dma, - .unmap_dma = ion_secure_heap_unmap_dma, - .map_user = ion_secure_heap_map_user, - .map_kernel = ion_heap_map_kernel, - .unmap_kernel = ion_heap_unmap_kernel, -}; - -struct ion_heap *ion_secure_heap_create(struct ion_platform_heap *heap_data) -{ - struct ion_secure_heap *secure_heap; - - secure_heap = kzalloc(sizeof(struct ion_secure_heap), GFP_KERNEL); - if (!secure_heap) - return ERR_PTR(-ENOMEM); - - secure_heap->pool = gen_pool_create(12, -1); - if (!secure_heap->pool) { - kfree(secure_heap); - return ERR_PTR(-ENOMEM); - } - secure_heap->base = heap_data->base; - secure_heap->size = heap_data->size; - gen_pool_add(secure_heap->pool, secure_heap->base, heap_data->size, -1); - secure_heap->heap.ops = &secure_heap_ops; - secure_heap->heap.type = ION_HEAP_TYPE_SECURE; - - return &secure_heap->heap; -} - -void ion_secure_heap_destroy(struct ion_heap *heap) -{ - struct ion_secure_heap *secure_heap = - container_of(heap, struct ion_secure_heap, heap); - - gen_pool_destroy(secure_heap->pool); - kfree(secure_heap); - secure_heap = NULL; -} diff --git a/drivers/staging/android/ion/ion_unmapped_heap.c b/drivers/staging/android/ion/ion_unmapped_heap.c new file mode 100644 index 00000000000000..28898360920190 --- /dev/null +++ b/drivers/staging/android/ion/ion_unmapped_heap.c @@ -0,0 +1,252 @@ +/* + * drivers/staging/android/ion/ion_unmapped_heap.c + * + * Copyright (C) 2016-2017 Linaro, Inc. + * Copyright (C) Allwinner 2014 + * Author: for Allwinner. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * ION heap type for handling physical memory heap not mapped + * in the linux-based OS. + * + * "unmapped heap" buffers are default not mapped but buffer owner + * can explicitly request mapping for some specific purpose. + * + * Based on Allwinner work (allocation thru gen_pool) and + * HiSilicon work (create ION heaps from DT nodes, + * Author: Chen Feng ). + */ + +#include +#include +#include +#include + +#include "ion.h" + +/* + * TODO: non-contigous unammped heaps: + * - add a flag to specify contiguity constraint? + * - define antoher heap type that allocate to the smae pool(s)? + */ + +struct ion_unmapped_heap { + struct ion_heap heap; + struct gen_pool *pool; + phys_addr_t base; + size_t size; +}; + +struct unmapped_buffer_priv { + phys_addr_t base; +}; + +static phys_addr_t get_buffer_base(struct unmapped_buffer_priv *priv) +{ + return priv->base; +} + +static struct device *heap2dev(struct ion_heap *heap) +{ + return heap->dev->dev.this_device; +} + +static phys_addr_t ion_unmapped_allocate(struct ion_heap *heap, + unsigned long size, + phys_addr_t *addr) +{ + struct ion_unmapped_heap *umh = + container_of(heap, struct ion_unmapped_heap, heap); + unsigned long offset = gen_pool_alloc(umh->pool, size); + + if (!offset) { + dev_err(heap2dev(heap), + "%s(%d) err: alloc 0x%08x bytes failed\n", + __func__, __LINE__, (u32)size); + return false; + } + + *addr = offset; + return true; +} + +static void ion_unmapped_free(struct ion_heap *heap, phys_addr_t addr, + unsigned long size) +{ + struct ion_unmapped_heap *umh = + container_of(heap, struct ion_unmapped_heap, heap); + + gen_pool_free(umh->pool, addr, size); +} + +static struct sg_table *ion_unmapped_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + struct sg_table *table; + int ret; + + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) + return ERR_PTR(-ENOMEM); + ret = sg_alloc_table(table, 1, GFP_KERNEL); + if (ret) { + kfree(table); + return ERR_PTR(ret); + } + sg_set_page(table->sgl, + phys_to_page(get_buffer_base(buffer->priv_virt)), + buffer->size, 0); + + return table; +} + +void ion_unmapped_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + sg_free_table(buffer->sg_table); + kfree(buffer->sg_table); +} + +static int ion_unmapped_heap_allocate(struct ion_heap *heap, + struct ion_buffer *buffer, + unsigned long size, + unsigned long flags) +{ + struct unmapped_buffer_priv *priv; + phys_addr_t base; + int rc = -EINVAL; + + if (!ion_unmapped_allocate(heap, size, &base)) + return -ENOMEM; + + priv = devm_kzalloc(heap2dev(heap), sizeof(*priv), GFP_KERNEL); + if (IS_ERR_OR_NULL(priv)) { + rc = -ENOMEM; + goto err; + } + + priv->base = base; + buffer->size = roundup(size, PAGE_SIZE); + buffer->priv_virt = priv; + + buffer->sg_table = ion_unmapped_heap_map_dma(heap, buffer); + if (!buffer->sg_table) { + rc = -ENOMEM; + goto err; + } + sg_dma_address(buffer->sg_table->sgl) = priv->base; + sg_dma_len(buffer->sg_table->sgl) = size; + return 0; +err: + ion_unmapped_free(heap, base, size); + devm_kfree(heap2dev(heap), priv); + buffer->priv_virt = NULL; + return rc; +} + +static void ion_unmapped_heap_free(struct ion_buffer *buffer) +{ + struct ion_heap *heap = buffer->heap; + + ion_unmapped_heap_unmap_dma(heap, buffer); + ion_unmapped_free(heap, get_buffer_base(buffer->priv_virt), + buffer->size); + devm_kfree(heap2dev(heap), buffer->priv_virt); + buffer->priv_virt = NULL; +} + +static int ion_unmapped_heap_map_user(struct ion_heap *heap, + struct ion_buffer *buffer, + struct vm_area_struct *vma) +{ + phys_addr_t pa = get_buffer_base(buffer->priv_virt); + + /* + * when user call ION_IOC_ALLOC not with ION_FLAG_CACHED, ion_mmap will + * change vma->vm_page_prot to pgprot_writecombine itself, so we do not + * need change to pgprot_writecombine here manually. + */ + return remap_pfn_range(vma, vma->vm_start, + __phys_to_pfn(pa) + vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); +} + +static struct ion_heap_ops unmapped_heap_ops = { + .allocate = ion_unmapped_heap_allocate, + .free = ion_unmapped_heap_free, + .map_user = ion_unmapped_heap_map_user, + .map_kernel = ion_heap_map_kernel, + .unmap_kernel = ion_heap_unmap_kernel, +}; + +struct ion_heap *ion_unmapped_heap_create(phys_addr_t base, size_t size) +{ + struct ion_unmapped_heap *umh; + + umh = kzalloc(sizeof(struct ion_unmapped_heap), GFP_KERNEL); + if (!umh) + return ERR_PTR(-ENOMEM); + + umh->pool = gen_pool_create(PAGE_SHIFT, -1); + if (!umh->pool) { + kfree(umh); + return ERR_PTR(-ENOMEM); + } + umh->base = base; + umh->size = size; + + gen_pool_add(umh->pool, umh->base, size, -1); + umh->heap.ops = &unmapped_heap_ops; + umh->heap.type = ION_HEAP_TYPE_UNMAPPED; + + return &umh->heap; +} +EXPORT_SYMBOL(ion_unmapped_heap_create); + +void ion_unmapped_heap_destroy(struct ion_heap *heap) +{ + struct ion_unmapped_heap *umh = + container_of(heap, struct ion_unmapped_heap, heap); + + gen_pool_destroy(umh->pool); + kfree(umh); + umh = NULL; +} +EXPORT_SYMBOL(ion_unmapped_heap_destroy); + +#if defined(CONFIG_ION_DUMMY_UNMAPPED_HEAP) && CONFIG_ION_DUMMY_UNMAPPED_SIZE +#define DUMMY_UNAMMPED_HEAP_NAME "unmapped_contiguous" + +static int ion_add_dummy_unmapped_heaps(void) +{ + struct ion_heap *heap; + const char name[] = DUMMY_UNAMMPED_HEAP_NAME; + + heap = ion_unmapped_heap_create(CONFIG_ION_DUMMY_UNMAPPED_BASE, + CONFIG_ION_DUMMY_UNMAPPED_SIZE); + if (IS_ERR(heap)) + return PTR_ERR(heap); + + heap->name = kzalloc(sizeof(name), GFP_KERNEL); + if (IS_ERR(heap->name)) { + kfree(heap); + return PTR_ERR(heap->name); + } + memcpy((char *)heap->name, name, sizeof(name)); + + ion_device_add_heap(heap); + return 0; +} +device_initcall(ion_add_dummy_unmapped_heaps); +#endif diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index 46c93fcb46d6e6..32862f2623d397 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -19,6 +19,8 @@ * carveout heap, allocations are physically * contiguous * @ION_HEAP_TYPE_DMA: memory allocated via DMA API + * @ION_HEAP_TYPE_UNMAPPED: memory not intended to be mapped into the + * linux address space unless for debug cases * @ION_NUM_HEAPS: helper for iterating over heaps, a bit mask * is used to identify the heaps, so only 32 * total heap types are supported @@ -29,6 +31,7 @@ enum ion_heap_type { ION_HEAP_TYPE_CARVEOUT, ION_HEAP_TYPE_CHUNK, ION_HEAP_TYPE_DMA, + ION_HEAP_TYPE_UNMAPPED, ION_HEAP_TYPE_CUSTOM, /* * must be last so device specific heaps always * are at the end of this enum From 366e674916bc6c88d83edc8a88908ec3e1085cf8 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Fri, 8 Sep 2017 13:53:10 +0200 Subject: [PATCH 16/30] staging/ion: condition unmapped heap to supported architectures Condition ION unmapped heap implementation to architectures that currently support it. ARM is one of these. Signed-off-by: Etienne Carriere Reviewed-by: Joakim Bech --- drivers/staging/android/ion/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 23ada1edb2deb5..3473a88a3cfc82 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -28,7 +28,7 @@ config ION_CMA_HEAP config ION_UNMAPPED_HEAP bool "ION unmapped heap support" - depends on ION + depends on ION && ARM help Choose this option to enable UNMAPPED heaps with Ion. This heap is backed in specific memory pools, carveout from the Linux memory. From 05790c9df7e4f800024580c37edcb85e992082e6 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Thu, 14 Sep 2017 17:52:51 +0200 Subject: [PATCH 17/30] staging/ion: ARM64 supports ION_UNMAPPED_HEAP Signed-off-by: Etienne Carriere --- drivers/staging/android/ion/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 3473a88a3cfc82..f3cfa1171a2bfe 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -28,7 +28,7 @@ config ION_CMA_HEAP config ION_UNMAPPED_HEAP bool "ION unmapped heap support" - depends on ION && ARM + depends on ION && (ARM || ARM64) help Choose this option to enable UNMAPPED heaps with Ion. This heap is backed in specific memory pools, carveout from the Linux memory. From 6af0afc0fbbeb0fe5a1dc5ae01bb19a5caf8d656 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 9 Oct 2017 13:47:40 +0200 Subject: [PATCH 18/30] staging:ion: add a no-map property to ion dmabuf attachment Ion unmapped heap aims at not being mapped. This change prevents Ion from calling dma-mapping support on dma_buf_attach for buffers in an unmapped heap. This change is a bit intrusive in the Ion driver. Maybe there is another way to deal with the dma-mapping resources used for the unmapped heap. Signed-off-by: Etienne Carriere [jf: rebase onto v5.9-rc7] Signed-off-by: Jerome Forissier --- drivers/staging/android/ion/ion.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 3c9f09506ffa22..2f6b7a7c6697b0 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -173,6 +173,7 @@ struct ion_dma_buf_attachment { struct device *dev; struct sg_table *table; struct list_head list; + bool no_map; }; static int ion_dma_buf_attach(struct dma_buf *dmabuf, @@ -192,6 +193,9 @@ static int ion_dma_buf_attach(struct dma_buf *dmabuf, return -ENOMEM; } + if (buffer->heap->type == ION_HEAP_TYPE_UNMAPPED) + a->no_map = true; + a->table = table; a->dev = attachment->dev; INIT_LIST_HEAD(&a->list); @@ -228,6 +232,9 @@ static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, table = a->table; + if (a->no_map) + return table; + ret = dma_map_sgtable(attachment->dev, table, direction, 0); if (ret) return ERR_PTR(ret); @@ -239,6 +246,11 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, struct sg_table *table, enum dma_data_direction direction) { + struct ion_dma_buf_attachment *a = attachment->priv; + + if (a->no_map) + return; + dma_unmap_sgtable(attachment->dev, table, direction, 0); } From 816b96777488ac5bf3c2ef50a1210a2eb31606ec Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Fri, 31 Aug 2018 11:53:16 +0100 Subject: [PATCH 19/30] staging: android: ion: do not clear dma_address of unmapped heap Since commit 54ef5b9db767 (staging: android: ion: Initialize dma_address of new sg list") (Linux v4.17), the helper function dup_sg_table() called by ion_dma_buf_attach() does not preserve the dma_address from the original SG list. It is a problem for the unmapped heap, because dma_buf_attach() followed by dma_buf_map_attachment() now returns a SG table with NULL dma_address, which breaks tee_shm_register_fd(). This commit avoids the dma_address reset for the unmapped heap. Signed-off-by: Jerome Forissier Tested-by: Jerome Forissier (HiKey960, SDP) Tested-by: Etienne Carriere (Qemu_v7/v8, SDP) --- drivers/staging/android/ion/ion.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 2f6b7a7c6697b0..c007cfffc2c531 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -137,7 +137,8 @@ static void ion_buffer_kmap_put(struct ion_buffer *buffer) } } -static struct sg_table *dup_sg_table(struct sg_table *table) +static struct sg_table *dup_sg_table(struct sg_table *table, + bool preserve_dma_address) { struct sg_table *new_table; int ret, i; @@ -156,7 +157,8 @@ static struct sg_table *dup_sg_table(struct sg_table *table) new_sg = new_table->sgl; for_each_sgtable_sg(table, sg, i) { memcpy(new_sg, sg, sizeof(*sg)); - new_sg->dma_address = 0; + if (!preserve_dma_address) + new_sg->dma_address = 0; new_sg = sg_next(new_sg); } @@ -187,15 +189,15 @@ static int ion_dma_buf_attach(struct dma_buf *dmabuf, if (!a) return -ENOMEM; - table = dup_sg_table(buffer->sg_table); + if (buffer->heap->type == ION_HEAP_TYPE_UNMAPPED) + a->no_map = true; + + table = dup_sg_table(buffer->sg_table, a->no_map); if (IS_ERR(table)) { kfree(a); return -ENOMEM; } - if (buffer->heap->type == ION_HEAP_TYPE_UNMAPPED) - a->no_map = true; - a->table = table; a->dev = attachment->dev; INIT_LIST_HEAD(&a->list); From bfc70e107bec12fc63abd6b3efd626de5ccc9c7c Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Fri, 15 Nov 2019 13:55:02 +0100 Subject: [PATCH 20/30] upstream-tee-subsys-patches.txt: patches up to v5.4-rc7 Records patches available upstream up to v5.4-rc7. Signed-off-by: Jerome Forissier --- upstream-tee-subsys-patches.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/upstream-tee-subsys-patches.txt b/upstream-tee-subsys-patches.txt index 39ff9bdac16c68..89a7b1a4f83603 100644 --- a/upstream-tee-subsys-patches.txt +++ b/upstream-tee-subsys-patches.txt @@ -5,6 +5,8 @@ This is a list of all the patches that relates to the TEE subsystem. The text inside the brackets are the kernel version where it was introduced, followed by the sha1 hash in the upstream kernel tree. +[v5.4-rc1] 9f02b8f61f29 tee: optee: add might_sleep for RPC requests +[v5.2-rc1] 9733b072a12a optee: allow to work without static shared memory [v5.1-rc1] 32356d309c22 tee: optee: update optee_msg.h and optee_smc.h to dual license [v5.1-rc1] 4f062dc1b759 tee: add cancellation support to client interface [v5.1-rc1] 62ade1bed27c tee: optee: Fix unsigned comparison with less than zero From 10ef4b839197f3eabbf6365341b6cada8d746885 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Fri, 15 Nov 2019 13:55:02 +0100 Subject: [PATCH 21/30] upstream-tee-subsys-patches.txt: patches up to v5.5 Records patches available upstream up to v5.5. Signed-off-by: Jerome Forissier --- upstream-tee-subsys-patches.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/upstream-tee-subsys-patches.txt b/upstream-tee-subsys-patches.txt index 89a7b1a4f83603..5f1df980c11428 100644 --- a/upstream-tee-subsys-patches.txt +++ b/upstream-tee-subsys-patches.txt @@ -5,6 +5,11 @@ This is a list of all the patches that relates to the TEE subsystem. The text inside the brackets are the kernel version where it was introduced, followed by the sha1 hash in the upstream kernel tree. +[v5.5] 9e0caab8e0f9 tee: optee: Fix compilation issue with nommu +[v5.5-rc7] 5a769f6ff439 optee: Fix multi page dynamic shm pool alloc +[v5.5-rc1] 03212e347f94 tee: optee: fix device enumeration error handling +[v5.5-rc1] a249dd200d03 tee: optee: Fix dynamic shm pool allocations +[v5.5-rc1] 1832f2d8ff69 compat_ioctl: move more drivers to compat_ptr_ioctl [v5.4-rc1] 9f02b8f61f29 tee: optee: add might_sleep for RPC requests [v5.2-rc1] 9733b072a12a optee: allow to work without static shared memory [v5.1-rc1] 32356d309c22 tee: optee: update optee_msg.h and optee_smc.h to dual license From 185d7548c96847b52481e7920cc46d5250835cfd Mon Sep 17 00:00:00 2001 From: Cedric Neveux Date: Mon, 4 Mar 2019 08:54:23 +0100 Subject: [PATCH 22/30] driver: tee: Handle NULL pointer indication from client TEE Client introduce a new capability "TEE_GEN_CAP_MEMREF_NULL" to handle the support of the shared memory buffer with a NULL pointer. This capability depends on TEE Capabilities and driver support. Driver and TEE exchange capabilities at driver initialization. Signed-off-by: Michael Whitfield Signed-off-by: Cedric Neveux Reviewed-by: Jens Wiklander Reviewed-by: Joakim Bech Tested-by: Joakim Bech (QEMU) --- drivers/tee/optee/core.c | 7 +++++ drivers/tee/optee/optee_smc.h | 3 +++ drivers/tee/tee_core.c | 49 ++++++++++++++++++++++------------- include/linux/tee_drv.h | 3 +++ include/uapi/linux/tee.h | 13 ++++++++++ 5 files changed, 57 insertions(+), 18 deletions(-) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 77733866c65502..f4846c6a7ee79d 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -217,6 +217,8 @@ static void optee_get_version(struct tee_device *teedev, if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) v.gen_caps |= TEE_GEN_CAP_REG_MEM; + if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL) + v.gen_caps |= TEE_GEN_CAP_MEMREF_NULL; *vers = v; } @@ -263,6 +265,11 @@ static int optee_open(struct tee_context *ctx) mutex_init(&ctxdata->mutex); INIT_LIST_HEAD(&ctxdata->sess_list); + if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL) + ctx->cap_memref_null = true; + else + ctx->cap_memref_null = false; + ctx->data = ctxdata; return 0; } diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h index c72122d9c99724..777ad54d4c2c20 100644 --- a/drivers/tee/optee/optee_smc.h +++ b/drivers/tee/optee/optee_smc.h @@ -215,6 +215,9 @@ struct optee_smc_get_shm_config_result { */ #define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2) +/* Secure world supports Shared Memory with a NULL buffer reference */ +#define OPTEE_SMC_SEC_CAP_MEMREF_NULL BIT(4) + #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9 #define OPTEE_SMC_EXCHANGE_CAPABILITIES \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 6492aee9b8451f..c57c85d60d668e 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -419,25 +419,38 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params, case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: /* - * If we fail to get a pointer to a shared memory - * object (and increase the ref count) from an - * identifier we return an error. All pointers that - * has been added in params have an increased ref - * count. It's the callers responibility to do - * tee_shm_put() on all resolved pointers. + * If a NULL pointer is passed to a TA in the TEE, + * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL + * indicating a NULL memory reference. */ - shm = tee_shm_get_from_id(ctx, ip.c); - if (IS_ERR(shm)) - return PTR_ERR(shm); - - /* - * Ensure offset + size does not overflow offset - * and does not overflow the size of the referred - * shared memory object. - */ - if ((ip.a + ip.b) < ip.a || - (ip.a + ip.b) > shm->size) { - tee_shm_put(shm); + if (ip.c != TEE_MEMREF_NULL) { + /* + * If we fail to get a pointer to a shared + * memory object (and increase the ref count) + * from an identifier we return an error. All + * pointers that has been added in params have + * an increased ref count. It's the callers + * responibility to do tee_shm_put() on all + * resolved pointers. + */ + shm = tee_shm_get_from_id(ctx, ip.c); + if (IS_ERR(shm)) + return PTR_ERR(shm); + + /* + * Ensure offset + size does not overflow + * offset and does not overflow the size of + * the referred shared memory object. + */ + if ((ip.a + ip.b) < ip.a || + (ip.a + ip.b) > shm->size) { + tee_shm_put(shm); + return -EINVAL; + } + } else if (ctx->cap_memref_null) { + /* Pass NULL pointer to OP-TEE */ + shm = NULL; + } else { return -EINVAL; } diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index f4c6d6e7ced7ab..aed7390899689e 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -47,6 +47,8 @@ struct tee_shm_pool; * and just return with an error code. It is needed for requests * that arises from TEE based kernel drivers that should be * non-blocking in nature. + * @cap_memref_null: flag indicating if the TEE Client support shared + * memory buffer with a NULL pointer. */ struct tee_context { struct tee_device *teedev; @@ -54,6 +56,7 @@ struct tee_context { struct kref refcount; bool releasing; bool supp_nowait; + bool cap_memref_null; }; struct tee_param_memref { diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h index b7148b5ebf792f..9eed9deddcc672 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h @@ -51,6 +51,9 @@ #define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */ #define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */ #define TEE_GEN_CAP_REG_MEM (1 << 2)/* Supports registering shared memory */ +#define TEE_GEN_CAP_MEMREF_NULL (1 << 3)/* NULL MemRef support */ + +#define TEE_MEMREF_NULL (__u64)(-1) /* NULL MemRef Buffer */ /* * TEE Implementation ID @@ -229,6 +232,16 @@ struct tee_ioctl_buf_data { * a part of a shared memory by specifying an offset (@a) and size (@b) of * the object. To supply the entire shared memory object set the offset * (@a) to 0 and size (@b) to the previously returned size of the object. + * + * A client may need to present a NULL pointer in the argument + * passed to a trusted application in the TEE. + * This is also a requirement in GlobalPlatform Client API v1.0c + * (section 3.2.5 memory references), which can be found at + * http://www.globalplatform.org/specificationsdevice.asp + * + * If a NULL pointer is passed to a TA in the TEE, the (@c) + * IOCTL parameters value must be set to TEE_MEMREF_NULL indicating a NULL + * memory reference. */ struct tee_ioctl_param { __u64 attr; From 4b38a0a6dadf40f030fd2d6183f1f2afffe5e631 Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Mon, 11 May 2020 19:10:48 +0300 Subject: [PATCH 23/30] arm64: dts: hi3798cv200-poplar: memreserve for bootloader Reserve memory for bootloader purposes. Acked-by: Jerome Forissier Signed-off-by: Igor Opaniuk --- arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts b/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts index 7d370dac4c8571..ec3b55eb49042d 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts +++ b/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts @@ -6,6 +6,7 @@ */ /dts-v1/; +/memreserve/ 0x00000000 0x04080000; #include #include "hi3798cv200.dtsi" From 50c596553cf2f151e4007529d944edbd5a8f991e Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Mon, 11 May 2020 19:09:31 +0300 Subject: [PATCH 24/30] arm64: dts: hi3798cv200-poplar: add optee node Add optee node, so OP-TEE driver is probed properly. Acked-by: Jerome Forissier Signed-off-by: Igor Opaniuk --- arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts b/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts index ec3b55eb49042d..3bb161655313c4 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts +++ b/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts @@ -71,6 +71,13 @@ gpio = <&gpio6 7 0>; enable-active-high; }; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; }; &ehci { From bc1e1358aabfc76704371eee477970c17f82fdb4 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Wed, 27 May 2020 10:38:12 +0200 Subject: [PATCH 25/30] ARM: dts: stm32: Define OP-TEE resources on stm32mp15 and enable on DK2 Define OP-TEE firmware node for stm32mp15 based platforms. The node if disable by default. Enable the OP-TEE node and define OP-TEE reserved memory for stm32mp157c-dk2. Signed-off-by: Etienne Carriere [jf: rebase onto v5.9] Signed-off-by: Jerome Forissier --- arch/arm/boot/dts/stm32mp151.dtsi | 8 ++++++++ arch/arm/boot/dts/stm32mp157c-dk2.dts | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi index bfe29023fbd511..07772510b7afb7 100644 --- a/arch/arm/boot/dts/stm32mp151.dtsi +++ b/arch/arm/boot/dts/stm32mp151.dtsi @@ -28,6 +28,14 @@ method = "smc"; }; + firmware { + optee: optee { + compatible = "linaro,optee-tz"; + method = "smc"; + status = "disabled"; + }; + }; + intc: interrupt-controller@a0021000 { compatible = "arm,cortex-a7-gic"; #interrupt-cells = <3>; diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts index 045636555dddfc..2868dd8b4dd963 100644 --- a/arch/arm/boot/dts/stm32mp157c-dk2.dts +++ b/arch/arm/boot/dts/stm32mp157c-dk2.dts @@ -16,6 +16,13 @@ model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; + reserved-memory { + optee_memory: optee@0xde000000 { + reg = <0xde000000 0x02000000>; + no-map; + }; + }; + aliases { ethernet0 = ðernet0; serial0 = &uart4; @@ -95,3 +102,7 @@ pinctrl-2 = <&usart2_idle_pins_c>; status = "disabled"; }; + +&optee { + status = "okay"; +}; From d2977196ce200e5855e9ef860ba448a0760ed460 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Fri, 15 Nov 2019 13:55:02 +0100 Subject: [PATCH 26/30] upstream-tee-subsys-patches.txt: patches up to v5.9 Records patches available upstream up to v5.9. Signed-off-by: Jerome Forissier --- upstream-tee-subsys-patches.txt | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/upstream-tee-subsys-patches.txt b/upstream-tee-subsys-patches.txt index 5f1df980c11428..551b23fe0cc1ee 100644 --- a/upstream-tee-subsys-patches.txt +++ b/upstream-tee-subsys-patches.txt @@ -5,6 +5,34 @@ This is a list of all the patches that relates to the TEE subsystem. The text inside the brackets are the kernel version where it was introduced, followed by the sha1 hash in the upstream kernel tree. +[v5.9-rc1] 5f178bb71e3a optee: enable support for multi-stage bus enumeration +[v5.9-rc1] 58df195cd47d optee: use uuid for sysfs driver entry +[v5.8-rc1] d8ed45c5dcd4 mmap locking API: use coccinelle to convert mmap_sem rwsem call sites +[v5.8-rc1] 60b4000f5464 tee: fix crypto select +[v5.8-rc1] c5b4312bea5d tee: optee: Add support for session login client UUID generation +[v5.8-rc1] e33bcbab16d1 tee: add support for session's client UUID generation +[v5.8-rc1] 104edb94cc4b tee: add private login method for kernel clients +[v5.8-rc1] 2a6ba3f794e8 tee: enable support to register kernel memory +[v5.8-rc1] 1115899e7aad tee: remove unnecessary NULL check in tee_shm_alloc() +[v5.7-rc1] 758ecf13a41a tee: tee_shm_op_mmap(): use TEE_SHM_USER_MAPPED +[v5.7-rc1] 5271b2011e44 tee: remove redundant teedev in struct tee_shm +[v5.7-rc1] f1bbacedb0af tee: don't assign shm id for private shms +[v5.7-rc1] c180f9bbe29a tee: remove unused tee_shm_priv_alloc() +[v5.7-rc1] 59a135f6fb66 tee: remove linked list of struct tee_shm +[v5.6] 36fa3e50085e tee: amdtee: out of bounds read in find_session() +[v5.6-rc5] 483685bceedb tee: amdtee: fix memory leak in amdtee_open_session() +[v5.6-rc4] 872d92dec353 tee: amdtee: amdtee depends on CRYPTO_DEV_CCP_DD +[v5.6-rc1] 48d625e4c4ce tee: fix memory allocation failure checks on drv_data and amdtee +[v5.6-rc1] 279c075dc1d2 tee: amdtee: remove redundant NULL check for pool +[v5.6-rc1] f9568eae9247 tee: amdtee: rename err label to err_device_unregister +[v5.6-rc1] 2929015535fa tee: amdtee: skip tee_device_unregister if tee_device_alloc fails +[v5.6-rc1] f4c58c3758f9 tee: amdtee: print error message if tee not present +[v5.6-rc1] 5ae63958a6de tee: amdtee: remove unused variable initialization +[v5.6-rc1] bade7e1fbd34 tee: amdtee: check TEE status during driver initialization +[v5.6-rc1] 757cc3e9ff1d tee: add AMD-TEE driver +[v5.6-rc1] 1a74fa3894e7 tee: allow compilation of tee subsystem for AMD CPUs +[v5.6-rc1] f349710e413a optee: model OP-TEE as a platform device/driver +[v5.6-rc1] 42aa7c6eb3eb drm/tee_shm: Drop dma_buf_k(unmap) support [v5.5] 9e0caab8e0f9 tee: optee: Fix compilation issue with nommu [v5.5-rc7] 5a769f6ff439 optee: Fix multi page dynamic shm pool alloc [v5.5-rc1] 03212e347f94 tee: optee: fix device enumeration error handling From a1f8ac03637d0808053975d4870375b084d6ed7c Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Thu, 17 Sep 2020 19:10:22 +0530 Subject: [PATCH 27/30] tee: client UUID: Skip REE kernel login method as well Since the addition of session's client UUID generation via commit [1], login via REE kernel method was disallowed. So fix that via passing nill UUID in case of TEE_IOCTL_LOGIN_REE_KERNEL method as well. Fixes: e33bcbab16d1 ("tee: add support for session's client UUID generation") [1] Signed-off-by: Sumit Garg Signed-off-by: Jens Wiklander --- drivers/tee/tee_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index c57c85d60d668e..e0674bf29b5a63 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -200,7 +200,8 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method, int name_len; int rc; - if (connection_method == TEE_IOCTL_LOGIN_PUBLIC) { + if (connection_method == TEE_IOCTL_LOGIN_PUBLIC || + connection_method == TEE_IOCTL_LOGIN_REE_KERNEL) { /* Nil UUID to be passed to TEE environment */ uuid_copy(uuid, &uuid_null); return 0; From 28676a5aba66dc983023ac3bea45e2aa9a06f5ce Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Thu, 15 Oct 2020 20:11:49 -0700 Subject: [PATCH 28/30] checkpatch: add --kconfig-prefix Kconfig allows to customize the CONFIG_ prefix via the $CONFIG_ environment variable. Out-of-tree projects may therefore use Kconfig with a different prefix, or they may use a custom configuration tool which does not use the CONFIG_ prefix at all. Such projects may still want to adhere to the Linux kernel coding style and run checkpatch.pl. One example is OP-TEE [1] which does not use Kconfig but does have configuration options prefixed with CFG_. It also mostly follows the kernel coding style and therefore being able to use checkpatch is quite valuable. To make this possible, add the --kconfig-prefix command line option. [1] https://github.com/OP-TEE/optee_os Signed-off-by: Jerome Forissier Signed-off-by: Andrew Morton Acked-by: Joe Perches Link: http://lkml.kernel.org/r/20200818081732.800449-1-jerome@forissier.org Signed-off-by: Linus Torvalds [jf: commit 3e89ad8506f3 from upstream] Signed-off-by: Jerome Forissier --- scripts/checkpatch.pl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 504d2e431c6041..9998340d69c676 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -65,6 +65,7 @@ # git output parsing needs US English output, so first set backtick child process LANGUAGE my $git_command ='export LANGUAGE=en_US.UTF-8; git'; my $tabsize = 8; +my ${CONFIG_} = "CONFIG_"; sub help { my ($exitcode) = @_; @@ -127,6 +128,8 @@ sub help { --typedefsfile Read additional types from this file --color[=WHEN] Use colors 'always', 'never', or only when output is a terminal ('auto'). Default is 'auto'. + --kconfig-prefix=WORD use WORD as a prefix for Kconfig symbols (default + ${CONFIG_}) -h, --help, --version display this help and exit When FILE is - read standard input. @@ -235,6 +238,7 @@ sub list_types { 'color=s' => \$color, 'no-color' => \$color, #keep old behaviors of -nocolor 'nocolor' => \$color, #keep old behaviors of -nocolor + 'kconfig-prefix=s' => \${CONFIG_}, 'h|help' => \$help, 'version' => \$help ) or help(1); @@ -6524,16 +6528,16 @@ sub process { } # check for IS_ENABLED() without CONFIG_ ($rawline for comments too) - if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^CONFIG_/) { + if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) { WARN("IS_ENABLED_CONFIG", - "IS_ENABLED($1) is normally used as IS_ENABLED(CONFIG_$1)\n" . $herecurr); + "IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr); } # check for #if defined CONFIG_ || defined CONFIG__MODULE - if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(CONFIG_[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) { + if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(${CONFIG_}[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) { my $config = $1; if (WARN("PREFER_IS_ENABLED", - "Prefer IS_ENABLED() to CONFIG_ || CONFIG__MODULE\n" . $herecurr) && + "Prefer IS_ENABLED() to ${CONFIG_} || ${CONFIG_}_MODULE\n" . $herecurr) && $fix) { $fixed[$fixlinenr] = "\+#if IS_ENABLED($config)"; } From 436d15c681f41d15ff26adc5d6bc29c757188185 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Thu, 14 Jan 2021 12:00:15 +0100 Subject: [PATCH 29/30] upstream-tee-subsys-patches.txt: fix wrong commit ID The ID for commit b83685bceedb ("tee: amdtee: fix memory leak in amdtee_open_session()") is wrong in upstream-tee-subsys-patches.txt. Fix it. Reported-by: Victor Chong Signed-off-by: Jerome Forissier --- upstream-tee-subsys-patches.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/upstream-tee-subsys-patches.txt b/upstream-tee-subsys-patches.txt index 551b23fe0cc1ee..5d69a73616e39a 100644 --- a/upstream-tee-subsys-patches.txt +++ b/upstream-tee-subsys-patches.txt @@ -20,7 +20,7 @@ followed by the sha1 hash in the upstream kernel tree. [v5.7-rc1] c180f9bbe29a tee: remove unused tee_shm_priv_alloc() [v5.7-rc1] 59a135f6fb66 tee: remove linked list of struct tee_shm [v5.6] 36fa3e50085e tee: amdtee: out of bounds read in find_session() -[v5.6-rc5] 483685bceedb tee: amdtee: fix memory leak in amdtee_open_session() +[v5.6-rc5] b83685bceedb tee: amdtee: fix memory leak in amdtee_open_session() [v5.6-rc4] 872d92dec353 tee: amdtee: amdtee depends on CRYPTO_DEV_CCP_DD [v5.6-rc1] 48d625e4c4ce tee: fix memory allocation failure checks on drv_data and amdtee [v5.6-rc1] 279c075dc1d2 tee: amdtee: remove redundant NULL check for pool From 18c7ae79cb4f912948f797d5594a2fff0514649f Mon Sep 17 00:00:00 2001 From: Shown Han Date: Tue, 19 Jan 2021 16:12:47 +0800 Subject: [PATCH 30/30] tee: optee: Fix RPC call break system sleep operation. The system sleep can be break when freezer try to freeze tasks who are waitting for unreachable conditions. All RPC calls waiting on tee-supplicant results are unreachable conditions when tee-supplicant be frozen. And TEE wait queue sleep becomes to unreachable condition on the corresponding wakeup process be frozen. By introduce freezer help functions tell to freezer ignoring tasks which can help to avoid freezer wakeup those tasks and wait them call into try_to_freeze(), the wait of those tasks are constantly timeout because they are waitting on unreachable conditions. This patch utilize freezer help functions to enclose those potential unreachable conditions boundaries to avoid breaking system sleep. Signed-off-by: Shown Han --- drivers/tee/optee/call.c | 6 ++++++ drivers/tee/optee/optee_private.h | 1 + drivers/tee/optee/rpc.c | 6 ++++++ drivers/tee/optee/supp.c | 7 +++++++ 4 files changed, 20 insertions(+) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index 3945041e661557..16b56fa979afc0 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -48,8 +48,14 @@ static void optee_cq_wait_init(struct optee_call_queue *cq, static void optee_cq_wait_for_completion(struct optee_call_queue *cq, struct optee_call_waiter *w) { + /* Tell freezers to ignore the current task. */ + freezer_do_not_count(); + wait_for_completion(&w->c); + /* Tell freezer to stop ignoring current task. */ + freezer_count(); + mutex_lock(&cq->mutex); /* Move to end of list to get out of the way for other waiters */ diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 8b71839a357ede..4efc2879af5606 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "optee_msg.h" #define OPTEE_MAX_ARG_SIZE 1024 diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index 817b1caee28c3e..f3136305702597 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -77,7 +77,13 @@ static void wq_sleep(struct optee_wait_queue *wq, u32 key) struct wq_entry *w = wq_entry_get(wq, key); if (w) { + /* Tell freezers to ignore the current task. */ + freezer_do_not_count(); + wait_for_completion(&w->c); + + /* Tell freezer to stop ignoring current task. */ + freezer_count(); mutex_lock(&wq->mu); list_del(&w->link); mutex_unlock(&wq->mu); diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c index 322a543b8c278a..46172edac191f0 100644 --- a/drivers/tee/optee/supp.c +++ b/drivers/tee/optee/supp.c @@ -108,6 +108,10 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, /* Tell an eventual waiter there's a new request */ complete(&supp->reqs_c); + + /* Tell freezers to ignore the current task. */ + freezer_do_not_count(); + /* * Wait for supplicant to process and return result, once we've * returned from wait_for_completion(&req->c) successfully we have @@ -143,6 +147,9 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, } } + /* Tell freezer to stop ignoring current task. */ + freezer_count(); + ret = req->ret; kfree(req);