Secure dmabuf support - #101
Conversation
From the commit below, the mt8173-evb failed to boot to console due to changes in the mt8173 device tree files. commit c0d6fe2 Merge: b44a3d2 3e4dda7 Author: Linus Torvalds <torvalds@linux-foundation.org> 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 <joakim.bech@linaro.org> Reviewed-by: Pascal Brand <pascal.brand@linaro.org>
Configures foundation-v8 with OP-TEE. Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org> [jf: rebase onto v5.9-rc7] Signed-off-by: Jerome Forissier <jerome@forissier.org>
Configures Juno with OP-TEE. Reviewed-by: Pascal Brand <pascal.brand@linaro.org> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org> [jf: rebase onto v5.9-rc7] Signed-off-by: Jerome Forissier <jerome@forissier.org>
…dation-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 <jens.wiklander@linaro.org>
… **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 <jens.wiklander@linaro.org>
Signed-off-by: Joakim Bech <joakim.bech@linaro.org> Reviewed-by: Pascal Brand <pascal.brand@linaro.org> Reviewed-by: Jerome Forissier <jerome.forissier@linaro.org>
Reserve memory for bootloader purposes. Acked-by: Jerome Forissier <jerome@forissier.org> Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
Add optee node, so OP-TEE driver is probed properly. Acked-by: Jerome Forissier <jerome@forissier.org> Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
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 <etienne.carriere@linaro.org> [jf: rebase onto v5.9] Signed-off-by: Jerome Forissier <jerome@forissier.org>
Signed-off-by: Javier Almansa Sobrino <javier.almansasobrino@arm.com> Acked-by: Joakim Bech <joakim.bech@linaro.org> Link: linaro-swg#85 [jf: not currently intended for upstream; add link to PR] Signed-off-by: Jerome Forissier <jerome@forissier.org>
The optee device status is disabled by default, change its status to 'okay' in the dts of the EV1 board Signed-off-by: Timothée Cercueil <timothee.cercueil@st.com> [jf: rebase onto v5.17] Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
This change fixes EV1 configuration which lacked OP-TEE reserved memory. This change also makes ED1 board ready the host OP-TEE by enabling OP-TEE node and defining the OP-TEE reserved memory for that board. This change defines these resources in ED1 DTS file which is included in EV1 DTS file. Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org> Acked-by: Jerome Forissier <jerome@forissier.org> [jf: rebase onto v5.17] Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
3382a00 to
1a1543f
Compare
1a1543f to
769569a
Compare
commented
May 23, 2022
|
Tested on Hikey960 |
fb42f9e to
b68bcbc
Compare
|
|
||
| description: | ||
| Linaro OP-TEE firmware need a reserved memory for the | ||
| Secure Data Path feature. |
There was a problem hiding this comment.
It would be nice to explain a bit more about SDP here (its purpose and how it achieves it in a few words).
b68bcbc to
1d42655
Compare
| #include <linux/list.h> | ||
| #include <linux/slab.h> | ||
| #include <linux/swap.h> | ||
| #include <linux/sched/signal.h> |
| static LIST_HEAD(free_list); | ||
| static size_t list_nr_pages; | ||
| wait_queue_head_t freelist_waitqueue; | ||
| struct task_struct *freelist_task; |
| * | ||
| */ | ||
|
|
||
| #include <linux/genalloc.h> |
| struct list_head list; | ||
| bool no_map; | ||
| bool mapped; | ||
|
|
| "%s", "dmabuf-deferred-free-worker"); | ||
| if (IS_ERR(freelist_task)) { | ||
| pr_err("Creating thread for deferred free failed\n"); | ||
| return -1; |
There was a problem hiding this comment.
kthread_run returns the kthread or ERR_PTR(-ENOMEM).
There was a problem hiding this comment.
Then return -ENOMEM? (I still think return PTR_ERR(freelist_task); is more appropriate).
-1 stands for -EPERM which is not relevant here.
There was a problem hiding this comment.
ok, I misunderstood the comment.
you mean return PTR_ERR(freelist_task) when I understood to modify the if (IS_ERR(freelist_task))
| #address-cells = <2>; | ||
| #size-cells = <2>; | ||
|
|
||
| sdp@0x3e800000 { |
| } | ||
|
|
||
| static int tee_ioctl_shm_register_fd(struct tee_context *ctx, | ||
| struct tee_ioctl_shm_register_fd_data __user *udata) |
| * tee_shm_register_fd() - Register shared memory from file descriptor | ||
| * | ||
| * @ctx: Context that allocates the shared memory | ||
| * @fd: shared memory file descriptor reference. |
There was a problem hiding this comment.
nitpciking (for consistency): s/shared/Shared/ and remove trailing period.
|
|
||
| /** | ||
| * tee_shm_priv_alloc() - Allocate shared memory privately | ||
| * @dev: Device that allocates the shared memory |
|
|
||
| /** | ||
| * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument | ||
| * @fd: [in] file descriptor identifying the shared memory |
1d42655 to
9217cd1
Compare
| * is under memory pressure. Usually | ||
| * from a shrinker. Avoid allocating | ||
| * memory in the free call, as it may | ||
| * fail. |
| static DEFINE_MUTEX(pool_list_lock); | ||
|
|
||
| static | ||
| struct page *dmabuf_page_pool_alloc_pages(struct dmabuf_page_pool *pool) |
| depends on DMABUF_HEAPS && DMABUF_HEAPS_DEFERRED_FREE | ||
| help | ||
| Choose this option to enable the secure dmabuf heap. The secure heap | ||
| is allocated by gen allocater. it's allocated according the dts. |
There was a problem hiding this comment.
The secure heap is allocated by gen allocater. it's allocated according the dts.
If i understood is correctly, it should rather be phrased as:
The secure heap pools are defined according to the DT. Heaps are allocated
in the pools using gen allocater.
| gen_pool_free(info->pool, | ||
| sg_dma_address(sg), | ||
| sg_dma_len(sg)); | ||
| } |
There was a problem hiding this comment.
coding style (move braces and line breaks):
for_each_sg(table->sgl, sg, table->nents, i)
gen_pool_free(info->pool, sg_dma_address(sg), sg_dma_len(sg));
|
|
||
| for (i = 0; i < secure_data_count; i++) { | ||
| if (secure_data[i].base == 0 || secure_data[i].size == 0) | ||
| return -EINVAL; |
There was a problem hiding this comment.
already tested/handled from secure_heap_add().
| s++; | ||
| } | ||
|
|
||
| strncpy(secure_data[secure_data_count].name, rmem->name, name_len); |
There was a problem hiding this comment.
if name_len == MAX_HEAP_NAME_LEN, then secure_data[secure_data_count].name will no be null terminated, which is likely an issue, at least at line 584.
| secure_data_count++; | ||
| return 0; | ||
| } else { | ||
| return -EINVAL; |
There was a problem hiding this comment.
Suggestion:
WARN_ONCE("Cannot handle more than %u secure heaps\n", MAX_SECURE_HEAP);
| rmem->ops = &rmem_dma_ops; | ||
| pr_info("Reserved memory: DMA buf secure pool %s at %pa, size %ld MiB\n", | ||
| secure_data[secure_data_count].name, | ||
| &rmem->base, (unsigned long)rmem->size / SZ_1M); |
6768628 to
f9e9b79
Compare
|
|
||
| static int deferred_freelist_init(void) | ||
| { | ||
| list_nr_pages = 0; |
There was a problem hiding this comment.
not needed IMHO, list_nr_pages is already zero initialized.
| "%s", "dmabuf-deferred-free-worker"); | ||
| if (IS_ERR(freelist_task)) { | ||
| pr_err("Creating thread for deferred free failed\n"); | ||
| return -1; |
There was a problem hiding this comment.
Then return -ENOMEM? (I still think return PTR_ERR(freelist_task); is more appropriate).
-1 stands for -EPERM which is not relevant here.
| }; | ||
|
|
||
| /** | ||
| * deferred_free - call to add item to the deferred free list |
There was a problem hiding this comment.
Remove call to, simply * deferred_free() - Add item to the deferred free list
| mutex_lock(&buffer->lock); | ||
| if (buffer->vmap_cnt) { | ||
| buffer->vmap_cnt++; | ||
| vaddr = buffer->vaddr; |
| struct secure_heap_buffer *buffer; | ||
| struct secure_heap_info *info = dma_heap_get_drvdata(heap); | ||
| DEFINE_DMA_BUF_EXPORT_INFO(exp_info); | ||
| unsigned long size = roundup(len, PAGE_SIZE); |
| goto free_pool; | ||
|
|
||
| sg_set_page(table->sgl, | ||
| phys_to_page(phy_addr), |
There was a problem hiding this comment.
sg_set_page(table->sgl, phys_to_page(phy_addr), size, 0);| * @ctx: Context that allocates the shared memory | ||
| * @fd: Shared memory file descriptor reference | ||
| * | ||
| * @returns a pointer to 'struct tee_shm' |
There was a problem hiding this comment.
* @returns a pointer to 'struct tee_shm' on success, or a errno on failure
There was a problem hiding this comment.
From other inline description, could be
* @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
| * | ||
| * @returns a pointer to 'struct tee_shm' | ||
| */ | ||
| struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size); |
There was a problem hiding this comment.
Can remove this declaration, function is not implemented.
| * | ||
| * 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. |
| return -EINVAL; | ||
|
|
||
| shm = tee_shm_register_fd(ctx, data.fd); | ||
| if (IS_ERR_OR_NULL(shm)) |
| * @ctx: Context that allocates the shared memory | ||
| * @fd: Shared memory file descriptor reference | ||
| * | ||
| * @returns a pointer to 'struct tee_shm' |
There was a problem hiding this comment.
From other inline description, could be
* @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
| } | ||
|
|
||
| ref->attach = dma_buf_attach(ref->dmabuf, &ref->shm.ctx->teedev->dev); | ||
| if (IS_ERR_OR_NULL(ref->attach)) { |
|
|
||
| ref->attach = dma_buf_attach(ref->dmabuf, &ref->shm.ctx->teedev->dev); | ||
| if (IS_ERR_OR_NULL(ref->attach)) { | ||
| rc = ERR_PTR(-EINVAL); |
There was a problem hiding this comment.
Instead of return -EINVAL, i think this should better return the error reported by dma_buf_attach().
Actually I think it would be better for maintenance to change rc from void * type int and use return ERR_PTR(rc); in the error path, at line 244.
f9e9b79 to
d15d2b5
Compare
d15d2b5 to
234b8cc
Compare
left a comment
There was a problem hiding this comment.
Could you squash commit "tee: remove unused tee_shm_priv_alloc function definition" into commit "tee: new ioctl to a register tee_shm from a dmabuf file descriptor" into commit". Feel free to use Co-developed-by: Etienne ... tag and add your S-o-b tag on the resulting commit.
Same for the 1st commits: prefer squash commits "ANDROID: dma-buf: heaps: fix dma-buf heap pool pages stat" and "ANDROID: dma-buf: heaps: fix a warning in dmabuf page pools" into commit "ANDROID: dma-buf: heaps: Add a shrinker controlled page pool" and add "Co-dev" + your S-o-b tag on the resulting commit. This is how, I think, these patch should be eventually posted to the LKML, to prevent introducing bugged commits in the kernel commit history.
| if (!tee_device_get(ctx->teedev)) | ||
| { | ||
| rc = -EINVAL; | ||
| goto out; |
There was a problem hiding this comment.
if (!tee_device_get(ctx->teedev))
return ERR_PTR(-EINVAL);| goto error; | ||
| } | ||
|
|
||
| pool = gen_pool_create(PAGE_SHIFT+4, -1); |
There was a problem hiding this comment.
I think granule should be 4kByte, the MMU mapping granule. It is the client responsibility to allocate large enough buffers for its needs.
| @@ -0,0 +1,55 @@ | |||
| /* SPDX-License-Identifier: GPL-2.0 */ | |||
|
|
|||
| * DMABUF secure heap exporter | ||
| * | ||
| * Copyright 2021 NXP. | ||
| * |
| ref->shm.id = -1; | ||
|
|
||
| ref->dmabuf = dma_buf_get(fd); | ||
| if (!ref->dmabuf) { |
There was a problem hiding this comment.
I've checked dma_buf_get(). It returns a ERR_PTR value hence must use IS_ERR() here.
Line below, should be rc = PTR_ERR(ref->dmabuf);
Ditto for the other below error cases.
| teedev_ctx_get(ctx); | ||
| mutex_lock(&ref->shm.ctx->teedev->mutex); | ||
| mutex_unlock(&ref->shm.ctx->teedev->mutex); | ||
| } |
There was a problem hiding this comment.
Remove this 5 lines. No need to get tee context, already done at function entry and balanced in fucntion error path and in tee_shm_release() (line 70 added by this P-R).
There was a problem hiding this comment.
do we need to replace this block by teedev_ctx_get(ctx); instead ?
I guess we still need to increment tee ctx refcount , isn't it ?
There was a problem hiding this comment.
Yes, indeed you're right. Sorry, i mess-up with tee_device_get/put().
| DMA_BIDIRECTIONAL); | ||
| if (ref->attach) | ||
| dma_buf_detach(ref->dmabuf, ref->attach); | ||
| if (ref->dmabuf) |
There was a problem hiding this comment.
All these will not work since those references are not NULL if the related resource failed to be retrieved: they all get a non-0 ERR_PTR value. Here you must use the standard Linux kernel error sequence scheme:
err_idr_remove:
mutex_lock(&ctx->teedev->mutex);
idr_remove(&ctx->teedev->idr, ref->shm.id);
mutex_unlock(&ctx->teedev->mutex);
err_unmap_attachement:
dma_buf_unmap_attachment(ref->attach, ref->sgt, DMA_BIDIRECTIONAL);
err_detach:
dma_buf_detach(ref->dmabuf, ref->attach);
err_put_dmabuf:
dma_buf_put(ref->dmabuf);
err_free_ref:
kfree(ref);
err_put_tee:
tee_device_put(ctx->teedev);
return ERR_PTR(rc);This patch provides infrastructure for deferring buffer frees. This is a feature ION provided which when used with some form of a page pool, provides a nice performance boost in an allocation microbenchmark. The reason it helps is it allows the page-zeroing to be done out of the normal allocation/free path, and pushed off to a kthread. As not all heaps will find this useful, its implemented as a optional helper library that heaps can utilize. Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Sumit Semwal <sumit.semwal@linaro.org> Cc: Liam Mark <lmark@codeaurora.org> Cc: Chris Goldsworthy <cgoldswo@codeaurora.org> Cc: Laura Abbott <labbott@kernel.org> Cc: Brian Starkey <Brian.Starkey@arm.com> Cc: Hridya Valsaraju <hridya@google.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Sandeep Patil <sspatil@google.com> Cc: Daniel Mentz <danielmentz@google.com> Cc: Ørjan Eide <orjan.eide@arm.com> Cc: Robin Murphy <robin.murphy@arm.com> Cc: Ezequiel Garcia <ezequiel@collabora.com> Cc: Simon Ser <contact@emersion.fr> Cc: James Jones <jajones@nvidia.com> Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: John Stultz <john.stultz@linaro.org> Bug: 168742043
2da9c70 to
74420c1
Compare
This patch adds a simple shrinker controlled page pool to the dmabuf heaps subsystem. This replaces the use of the networking page_pool, over concerns that the lack of a shrinker for that implementation may cause additional low-memory kills TODO: Take another pass at trying to unify this w/ the ttm pool Thoughts and feedback would be greatly appreciated! Cc: Sumit Semwal <sumit.semwal@linaro.org> Cc: Liam Mark <lmark@codeaurora.org> Cc: Laura Abbott <labbott@kernel.org> Cc: Brian Starkey <Brian.Starkey@arm.com> Cc: Hridya Valsaraju <hridya@google.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Sandeep Patil <sspatil@google.com> Cc: Daniel Mentz <danielmentz@google.com> Cc: Chris Goldsworthy <cgoldswo@codeaurora.org> Cc: Ørjan Eide <orjan.eide@arm.com> Cc: Robin Murphy <robin.murphy@arm.com> Cc: Ezequiel Garcia <ezequiel@collabora.com> Cc: Simon Ser <contact@emersion.fr> Cc: James Jones <jajones@nvidia.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Dave Hansen <dave.hansen@intel.com> Cc: linux-mm@kvack.org Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: Olivier Masse <olivier.masse@nxp.com> Bug: 168742043
add Linaro secure heap bindings: linaro,secure-heap use genalloc to allocate/free buffer from buffer pool. buffer pool info is from dts. use sg_table instore the allocated memory info, the length of sg_table is 1. implement secure_heap_buf_ops to implement buffer share in difference device: 1. Userspace passes this fd to all drivers it wants this buffer to share with: First the filedescriptor is converted to a &dma_buf using dma_buf_get(). Then the buffer is attached to the device using dma_buf_attach(). 2. Once the buffer is attached to all devices userspace can initiate DMA access to the shared buffer. In the kernel this is done by calling dma_buf_map_attachment() 3. get sg_table with dma_buf_map_attachment in difference device. Signed-off-by: Olivier Masse <olivier.masse@nxp.com>
DMABUF Reserved memory definition for OP-TEE SDP feaure. Signed-off-by: Olivier Masse <olivier.masse@nxp.com>
Add DMABUF_HEAPS_SECURE in defconfig Signed-off-by: Olivier Masse <olivier.masse@nxp.com>
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. Co-Developed-by: Etienne Carriere <etienne.carriere@linaro.org> Signed-off-by: Olivier Masse <olivier.masse@nxp.com> From: https://github.com/linaro-swg/linux.git (cherry picked from commit 41e21e5)
74420c1 to
00093f6
Compare
ok, squash done and commit message updated. |
No description provided.