Skip to content

Commit 1d42655

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. Signed-off-by: Etienne Carriere <[email protected]> From: https://github.com/linaro-swg/linux.git (cherry picked from commit 41e21e5)
1 parent 84d0439 commit 1d42655

File tree

4 files changed

+193
-4
lines changed

4 files changed

+193
-4
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_OR_NULL(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

+104-4
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

@@ -145,6 +162,89 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
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+
void *rc;
169+
170+
if (!tee_device_get(ctx->teedev))
171+
return ERR_PTR(-EINVAL);
172+
173+
ref = kzalloc(sizeof(*ref), GFP_KERNEL);
174+
if (!ref) {
175+
rc = ERR_PTR(-ENOMEM);
176+
goto err;
177+
}
178+
179+
refcount_set(&ref->shm.refcount, 1);
180+
ref->shm.ctx = ctx;
181+
ref->shm.id = -1;
182+
183+
ref->dmabuf = dma_buf_get(fd);
184+
if (!ref->dmabuf) {
185+
rc = ERR_PTR(-EINVAL);
186+
goto err;
187+
}
188+
189+
ref->attach = dma_buf_attach(ref->dmabuf, &ref->shm.ctx->teedev->dev);
190+
if (IS_ERR_OR_NULL(ref->attach)) {
191+
rc = ERR_PTR(-EINVAL);
192+
goto err;
193+
}
194+
195+
ref->sgt = dma_buf_map_attachment(ref->attach, DMA_BIDIRECTIONAL);
196+
if (IS_ERR_OR_NULL(ref->sgt)) {
197+
rc = ERR_PTR(-EINVAL);
198+
goto err;
199+
}
200+
201+
if (sg_nents(ref->sgt->sgl) != 1) {
202+
rc = ERR_PTR(-EINVAL);
203+
goto err;
204+
}
205+
206+
ref->shm.paddr = sg_dma_address(ref->sgt->sgl);
207+
ref->shm.size = sg_dma_len(ref->sgt->sgl);
208+
ref->shm.flags = TEE_SHM_DMA_BUF | TEE_SHM_EXT_DMA_BUF;
209+
210+
mutex_lock(&ref->shm.ctx->teedev->mutex);
211+
ref->shm.id = idr_alloc(&ref->shm.ctx->teedev->idr, &ref->shm,
212+
1, 0, GFP_KERNEL);
213+
mutex_unlock(&ref->shm.ctx->teedev->mutex);
214+
if (ref->shm.id < 0) {
215+
rc = ERR_PTR(ref->shm.id);
216+
goto err;
217+
}
218+
219+
if (ctx) {
220+
teedev_ctx_get(ctx);
221+
mutex_lock(&ref->shm.ctx->teedev->mutex);
222+
mutex_unlock(&ref->shm.ctx->teedev->mutex);
223+
}
224+
225+
return &ref->shm;
226+
227+
err:
228+
if (ref) {
229+
if (ref->shm.id >= 0) {
230+
mutex_lock(&ctx->teedev->mutex);
231+
idr_remove(&ctx->teedev->idr, ref->shm.id);
232+
mutex_unlock(&ctx->teedev->mutex);
233+
}
234+
if (ref->sgt)
235+
dma_buf_unmap_attachment(ref->attach, ref->sgt,
236+
DMA_BIDIRECTIONAL);
237+
if (ref->attach)
238+
dma_buf_detach(ref->dmabuf, ref->attach);
239+
if (ref->dmabuf)
240+
dma_buf_put(ref->dmabuf);
241+
}
242+
kfree(ref);
243+
tee_device_put(ctx->teedev);
244+
return rc;
245+
}
246+
EXPORT_SYMBOL_GPL(tee_shm_register_fd);
247+
148248
struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
149249
size_t length, u32 flags)
150250
{

include/linux/tee_drv.h

+22
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,28 @@ void *tee_get_drvdata(struct tee_device *teedev);
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'
350+
*/
351+
struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd);
352+
353+
/**
354+
* tee_shm_priv_alloc() - Allocate shared memory privately
355+
* @dev: Device that allocates the shared memory
356+
* @size: Requested size of shared memory
357+
*
358+
* Allocates shared memory buffer that is not associated with any client
359+
* context. Such buffers are owned by TEE driver and used for internal calls.
360+
*
361+
* @returns a pointer to 'struct tee_shm'
362+
*/
363+
struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size);
364+
343365
/**
344366
* tee_shm_register() - Register shared memory buffer
345367
* @ctx: Context that registers the shared memory

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_ALLOC 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)