On Wed, Sep 12, 2018 at 12:03 AM Yann Droneaud <ydroneaud@xxxxxxxxxx> wrote: > > Hi, > > Le lundi 27 août 2018 à 11:34 +0200, Gerd Hoffmann a écrit : > > A driver to let userspace turn memfd regions into dma-bufs. > > > > Use case: Allows qemu create dmabufs for the vga framebuffer or > > virtio-gpu ressources. Then they can be passed around to display > > those guest things on the host. To spice client for classic full > > framebuffer display, and hopefully some day to wayland server for > > seamless guest window display. Something like this is definitely needed. I assume one flow will be: 1) guest compositor allocates a buffer using udmabuf 2) 3D driver imports the udmabuf and renders to it 3) qemu turns this udmabuf into a host dma-buf 4) host compositor displays this dma-buf In that case, how does the guest know about the host's stride / alignment restrictions? For example, x-tiling on Intel (good for display) needs to have a stride that's a multiple of 512 bytes. > > > > qemu test branch: > > https://git.kraxel.org/cgit/qemu/log/?h=sirius/udmabuf > > > > Cc: David Airlie <airlied@xxxxxxxx> > > Cc: Tomeu Vizoso <tomeu.vizoso@xxxxxxxxxxxxx> > > Cc: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > > Cc: Daniel Vetter <daniel@xxxxxxxx> > > Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxxxxx> > > Acked-by: Daniel Vetter <daniel.vetter@xxxxxxxx> > > --- > > Documentation/ioctl/ioctl-number.txt | 1 + > > include/uapi/linux/udmabuf.h | 33 +++ > > drivers/dma-buf/udmabuf.c | 287 > > ++++++++++++++++++++++ > > tools/testing/selftests/drivers/dma-buf/udmabuf.c | 96 ++++++++ > > MAINTAINERS | 16 ++ > > drivers/dma-buf/Kconfig | 8 + > > drivers/dma-buf/Makefile | 1 + > > tools/testing/selftests/drivers/dma-buf/Makefile | 5 + > > 8 files changed, 447 insertions(+) > > create mode 100644 include/uapi/linux/udmabuf.h > > create mode 100644 drivers/dma-buf/udmabuf.c > > create mode 100644 tools/testing/selftests/drivers/dma-buf/udmabuf.c > > create mode 100644 tools/testing/selftests/drivers/dma-buf/Makefile > > > > diff --git a/include/uapi/linux/udmabuf.h > > b/include/uapi/linux/udmabuf.h > > new file mode 100644 > > index 0000000000..46b6532ed8 > > --- /dev/null > > +++ b/include/uapi/linux/udmabuf.h > > @@ -0,0 +1,33 @@ > > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ > > +#ifndef _UAPI_LINUX_UDMABUF_H > > +#define _UAPI_LINUX_UDMABUF_H > > + > > +#include <linux/types.h> > > +#include <linux/ioctl.h> > > + > > +#define UDMABUF_FLAGS_CLOEXEC 0x01 > > + > > +struct udmabuf_create { > > + __u32 memfd; > > + __u32 flags; > > + __u64 offset; > > + __u64 size; > > +}; > > + > > +struct udmabuf_create_item { > > + __u32 memfd; > > + __u32 __pad; > > + __u64 offset; > > + __u64 size; > > +}; > > + > > +struct udmabuf_create_list { > > + __u32 flags; > > + __u32 count; > > + struct udmabuf_create_item list[]; > > +}; > > + > > +#define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create) > > +#define UDMABUF_CREATE_LIST _IOW('u', 0x43, struct > > udmabuf_create_list) > > + > > +#endif /* _UAPI_LINUX_UDMABUF_H */ > > diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c > > new file mode 100644 > > index 0000000000..8e24204526 > > --- /dev/null > > +++ b/drivers/dma-buf/udmabuf.c > > +static long udmabuf_create(struct udmabuf_create_list *head, > > + struct udmabuf_create_item *list) > > +{ > > + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); > > + struct file *memfd = NULL; > > + struct udmabuf *ubuf; > > + struct dma_buf *buf; > > + pgoff_t pgoff, pgcnt, pgidx, pgbuf; > > + struct page *page; > > + int seals, ret = -EINVAL; > > + u32 i, flags; > > + > > + ubuf = kzalloc(sizeof(struct udmabuf), GFP_KERNEL); > > + if (!ubuf) > > + return -ENOMEM; > > + > > + for (i = 0; i < head->count; i++) { > > You need to check .__pad for unsupported value: > > if (list[i].__pad) { > ret = -EINVAL; > goto err_free_ubuf; > } > > > + if (!IS_ALIGNED(list[i].offset, PAGE_SIZE)) > > + goto err_free_ubuf; > > + if (!IS_ALIGNED(list[i].size, PAGE_SIZE)) > > + goto err_free_ubuf; > > + ubuf->pagecount += list[i].size >> PAGE_SHIFT; > > + } > > + ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(struct page > > *), > > + GFP_KERNEL); > > + if (!ubuf->pages) { > > + ret = -ENOMEM; > > + goto err_free_ubuf; > > + } > > + > > + pgbuf = 0; > > + for (i = 0; i < head->count; i++) { > > + memfd = fget(list[i].memfd); > > + if (!memfd) > > + goto err_put_pages; > > + if (!shmem_mapping(file_inode(memfd)->i_mapping)) > > + goto err_put_pages; > > + seals = memfd_fcntl(memfd, F_GET_SEALS, 0); > > + if (seals == -EINVAL || > > + (seals & SEALS_WANTED) != SEALS_WANTED || > > + (seals & SEALS_DENIED) != 0) > > + goto err_put_pages; > > + pgoff = list[i].offset >> PAGE_SHIFT; > > + pgcnt = list[i].size >> PAGE_SHIFT; > > + for (pgidx = 0; pgidx < pgcnt; pgidx++) { > > + page = shmem_read_mapping_page( > > + file_inode(memfd)->i_mapping, pgoff + > > pgidx); > > + if (IS_ERR(page)) { > > + ret = PTR_ERR(page); > > + goto err_put_pages; > > + } > > + ubuf->pages[pgbuf++] = page; > > + } > > + fput(memfd); > > + } > > + memfd = NULL; > > + > > + exp_info.ops = &udmabuf_ops; > > + exp_info.size = ubuf->pagecount << PAGE_SHIFT; > > + exp_info.priv = ubuf; > > + > > + buf = dma_buf_export(&exp_info); > > + if (IS_ERR(buf)) { > > + ret = PTR_ERR(buf); > > + goto err_put_pages; > > + } > > + > > + flags = 0; > > You need to check .flags for unsupported value: > > if (head->flags & ~UDMABUF_FLAGS_CLOEXEC) > return -EINVAL; > > (at the beginning of the function, of course). > > > + if (head->flags & UDMABUF_FLAGS_CLOEXEC) > > + flags |= O_CLOEXEC; > > + return dma_buf_fd(buf, flags); > > + > > +err_put_pages: > > + while (pgbuf > 0) > > + put_page(ubuf->pages[--pgbuf]); > > +err_free_ubuf: > > + fput(memfd); > > + kfree(ubuf->pages); > > + kfree(ubuf); > > + return ret; > > +} > > + > > Regards > > -- > Yann Droneaud > OPTEYA > > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel