Skip to content

Commit 00093f6

Browse files
etienne-lmsomasse-nxp
authored andcommitted
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. Co-Developed-by: Etienne Carriere <[email protected]> Signed-off-by: Olivier Masse <[email protected]> From: https://github.com/linaro-swg/linux.git (cherry picked from commit 41e21e5)
1 parent 112e3e1 commit 00093f6

File tree

4 files changed

+178
-7
lines changed

4 files changed

+178
-7
lines changed

drivers/tee/tee_core.c

+38
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,42 @@ tee_ioctl_shm_register(struct tee_context *ctx,
356356
return ret;
357357
}
358358

359+
static int tee_ioctl_shm_register_fd(struct tee_context *ctx,
360+
struct tee_ioctl_shm_register_fd_data __user *udata)
361+
{
362+
struct tee_ioctl_shm_register_fd_data data;
363+
struct tee_shm *shm;
364+
long ret;
365+
366+
if (copy_from_user(&data, udata, sizeof(data)))
367+
return -EFAULT;
368+
369+
/* Currently no input flags are supported */
370+
if (data.flags)
371+
return -EINVAL;
372+
373+
shm = tee_shm_register_fd(ctx, data.fd);
374+
if (IS_ERR(shm))
375+
return -EINVAL;
376+
377+
data.id = shm->id;
378+
data.flags = shm->flags;
379+
data.size = shm->size;
380+
381+
if (copy_to_user(udata, &data, sizeof(data)))
382+
ret = -EFAULT;
383+
else
384+
ret = tee_shm_get_fd(shm);
385+
386+
/*
387+
* When user space closes the file descriptor the shared memory
388+
* should be freed or if tee_shm_get_fd() failed then it will
389+
* be freed immediately.
390+
*/
391+
tee_shm_put(shm);
392+
return ret;
393+
}
394+
359395
static int params_from_user(struct tee_context *ctx, struct tee_param *params,
360396
size_t num_params,
361397
struct tee_ioctl_param __user *uparams)
@@ -830,6 +866,8 @@ static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
830866
return tee_ioctl_shm_alloc(ctx, uarg);
831867
case TEE_IOC_SHM_REGISTER:
832868
return tee_ioctl_shm_register(ctx, uarg);
869+
case TEE_IOC_SHM_REGISTER_FD:
870+
return tee_ioctl_shm_register_fd(ctx, uarg);
833871
case TEE_IOC_OPEN_SESSION:
834872
return tee_ioctl_open_session(ctx, uarg);
835873
case TEE_IOC_INVOKE:

drivers/tee/tee_shm.c

+99-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
#include <linux/anon_inodes.h>
66
#include <linux/device.h>
7+
#include <linux/dma-buf.h>
78
#include <linux/idr.h>
89
#include <linux/mm.h>
910
#include <linux/sched.h>
@@ -12,6 +13,14 @@
1213
#include <linux/uio.h>
1314
#include "tee_private.h"
1415

16+
/* extra references appended to shm object for registered shared memory */
17+
struct tee_shm_dmabuf_ref {
18+
struct tee_shm shm;
19+
struct dma_buf *dmabuf;
20+
struct dma_buf_attachment *attach;
21+
struct sg_table *sgt;
22+
};
23+
1524
static void release_registered_pages(struct tee_shm *shm)
1625
{
1726
if (shm->pages) {
@@ -30,7 +39,16 @@ static void release_registered_pages(struct tee_shm *shm)
3039

3140
static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
3241
{
33-
if (shm->flags & TEE_SHM_POOL) {
42+
if (shm->flags & TEE_SHM_EXT_DMA_BUF) {
43+
struct tee_shm_dmabuf_ref *ref;
44+
45+
ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
46+
dma_buf_unmap_attachment(ref->attach, ref->sgt,
47+
DMA_BIDIRECTIONAL);
48+
49+
dma_buf_detach(ref->dmabuf, ref->attach);
50+
dma_buf_put(ref->dmabuf);
51+
} else if (shm->flags & TEE_SHM_POOL) {
3452
struct tee_shm_pool_mgr *poolm;
3553

3654
if (shm->flags & TEE_SHM_DMA_BUF)
@@ -48,11 +66,10 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
4866

4967
release_registered_pages(shm);
5068
}
51-
52-
teedev_ctx_put(shm->ctx);
69+
if (shm->ctx)
70+
teedev_ctx_put(shm->ctx);
5371

5472
kfree(shm);
55-
5673
tee_device_put(teedev);
5774
}
5875

@@ -137,14 +154,91 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc);
137154
* tee_client_invoke_func(). The memory allocated is later freed with a
138155
* call to tee_shm_free().
139156
*
140-
* @returns a pointer to 'struct tee_shm'
157+
* @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
141158
*/
142159
struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
143160
{
144161
return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED);
145162
}
146163
EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
147164

165+
struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd)
166+
{
167+
struct tee_shm_dmabuf_ref *ref;
168+
int rc;
169+
170+
if (!tee_device_get(ctx->teedev))
171+
return ERR_PTR(-EINVAL);
172+
173+
teedev_ctx_get(ctx);
174+
175+
ref = kzalloc(sizeof(*ref), GFP_KERNEL);
176+
if (!ref) {
177+
rc = -ENOMEM;
178+
goto err_put_tee;
179+
}
180+
181+
refcount_set(&ref->shm.refcount, 1);
182+
ref->shm.ctx = ctx;
183+
ref->shm.id = -1;
184+
185+
ref->dmabuf = dma_buf_get(fd);
186+
if (IS_ERR(ref->dmabuf)) {
187+
rc = PTR_ERR(ref->dmabuf);
188+
goto err_put_dmabuf;
189+
}
190+
191+
ref->attach = dma_buf_attach(ref->dmabuf, &ref->shm.ctx->teedev->dev);
192+
if (IS_ERR(ref->attach)) {
193+
rc = PTR_ERR(ref->attach);
194+
goto err_detach;
195+
}
196+
197+
ref->sgt = dma_buf_map_attachment(ref->attach, DMA_BIDIRECTIONAL);
198+
if (IS_ERR(ref->sgt)) {
199+
rc = PTR_ERR(ref->sgt);
200+
goto err_unmap_attachement;
201+
}
202+
203+
if (sg_nents(ref->sgt->sgl) != 1) {
204+
rc = PTR_ERR(ref->sgt->sgl);
205+
goto err_unmap_attachement;
206+
}
207+
208+
ref->shm.paddr = sg_dma_address(ref->sgt->sgl);
209+
ref->shm.size = sg_dma_len(ref->sgt->sgl);
210+
ref->shm.flags = TEE_SHM_DMA_BUF | TEE_SHM_EXT_DMA_BUF;
211+
212+
mutex_lock(&ref->shm.ctx->teedev->mutex);
213+
ref->shm.id = idr_alloc(&ref->shm.ctx->teedev->idr, &ref->shm,
214+
1, 0, GFP_KERNEL);
215+
mutex_unlock(&ref->shm.ctx->teedev->mutex);
216+
if (ref->shm.id < 0) {
217+
rc = ref->shm.id;
218+
goto err_idr_remove;
219+
}
220+
221+
return &ref->shm;
222+
223+
err_idr_remove:
224+
mutex_lock(&ctx->teedev->mutex);
225+
idr_remove(&ctx->teedev->idr, ref->shm.id);
226+
mutex_unlock(&ctx->teedev->mutex);
227+
err_unmap_attachement:
228+
dma_buf_unmap_attachment(ref->attach, ref->sgt, DMA_BIDIRECTIONAL);
229+
err_detach:
230+
dma_buf_detach(ref->dmabuf, ref->attach);
231+
err_put_dmabuf:
232+
dma_buf_put(ref->dmabuf);
233+
kfree(ref);
234+
err_put_tee:
235+
teedev_ctx_put(ctx);
236+
tee_device_put(ctx->teedev);
237+
238+
return ERR_PTR(rc);
239+
}
240+
EXPORT_SYMBOL_GPL(tee_shm_register_fd);
241+
148242
struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
149243
size_t length, u32 flags)
150244
{

include/linux/tee_drv.h

+12-2
Original file line numberDiff line numberDiff line change
@@ -335,19 +335,29 @@ void *tee_get_drvdata(struct tee_device *teedev);
335335
* TEE_SHM_DMA_BUF global shared memory will be allocated and associated
336336
* with a dma-buf handle, else driver private memory.
337337
*
338-
* @returns a pointer to 'struct tee_shm'
338+
* @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
339339
*/
340340
struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
341341
struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
342342

343+
/**
344+
* tee_shm_register_fd() - Register shared memory from file descriptor
345+
*
346+
* @ctx: Context that allocates the shared memory
347+
* @fd: Shared memory file descriptor reference
348+
*
349+
* @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
350+
*/
351+
struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd);
352+
343353
/**
344354
* tee_shm_register() - Register shared memory buffer
345355
* @ctx: Context that registers the shared memory
346356
* @addr: Address is userspace of the shared buffer
347357
* @length: Length of the shared buffer
348358
* @flags: Flags setting properties for the requested shared memory.
349359
*
350-
* @returns a pointer to 'struct tee_shm'
360+
* @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
351361
*/
352362
struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
353363
size_t length, u32 flags);

include/uapi/linux/tee.h

+29
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,35 @@ struct tee_ioctl_shm_alloc_data {
121121
#define TEE_IOC_SHM_ALLOC _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \
122122
struct tee_ioctl_shm_alloc_data)
123123

124+
/**
125+
* struct tee_ioctl_shm_register_fd_data - Shared memory registering argument
126+
* @fd: [in] File descriptor identifying the shared memory
127+
* @size: [out] Size of shared memory to allocate
128+
* @flags: [in] Flags to/from allocation.
129+
* @id: [out] Identifier of the shared memory
130+
*
131+
* The flags field should currently be zero as input. Updated by the call
132+
* with actual flags as defined by TEE_IOCTL_SHM_* above.
133+
* This structure is used as argument for TEE_IOC_SHM_REGISTER_FD below.
134+
*/
135+
struct tee_ioctl_shm_register_fd_data {
136+
__s64 fd;
137+
__u64 size;
138+
__u32 flags;
139+
__s32 id;
140+
} __aligned(8);
141+
142+
/**
143+
* TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor
144+
*
145+
* Returns a file descriptor on success or < 0 on failure
146+
*
147+
* The returned file descriptor refers to the shared memory object in kernel
148+
* land. The shared memory is freed when the descriptor is closed.
149+
*/
150+
#define TEE_IOC_SHM_REGISTER_FD _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \
151+
struct tee_ioctl_shm_register_fd_data)
152+
124153
/**
125154
* struct tee_ioctl_buf_data - Variable sized buffer
126155
* @buf_ptr: [in] A __user pointer to a buffer

0 commit comments

Comments
 (0)