Received: by 10.213.65.68 with SMTP id h4csp443030imn; Tue, 13 Mar 2018 09:11:48 -0700 (PDT) X-Google-Smtp-Source: AG47ELt7/mhHtWB7JmmtxTKHmq1bW/LlDUGHztLfOaqsVxNNgScHZWrgmehssVZrZfhsjly34wBJ X-Received: by 2002:a17:902:5303:: with SMTP id b3-v6mr1047029pli.19.1520957508826; Tue, 13 Mar 2018 09:11:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1520957508; cv=none; d=google.com; s=arc-20160816; b=vZJ+VR35o4KE1Fv0godi2lT6dA+2WPswpZi/LvA8VPhFYOlbGVJRnCDIk/fFSGspod 8HgJQ/q/EMcfLgZeCR0norlKtUFuaxq3hEvmzhTUgCWyx0vQSUPdUIlZbMEmYFJWbTW6 8eEQJHN116DNnt84DaryNG4p64RbDTIXp3UQh1Yrl+wHvKbp1lF5JiMlmYTnmqS6WNze fM/FB7oWVywFcl9o7CQUsJX61lwtVIXVMw6QSDScFRW5zzpeywiBxrUOBiKDarzUlAW1 6+q0ImlD9++iofyog2dwJaaKg3zB/QOyzxcxq5e3LfJp3ZycG65b1ZIduw+7TWCsH5C9 dpqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-transfer-encoding:content-disposition:mime-version :references:mail-followup-to:message-id:subject:cc:to:from:date :dkim-signature:arc-authentication-results; bh=yroFc2jbFKf5C7uvH8aJZXudQTCCtnignWpVywkx1eY=; b=m+6/Qj3+ZFOOxsZbe6+BKcmfZIgO9Ye/2SeDmLJDOHoK5mKyJSlaq8n7SacpHEwwRy pUUmI4XQUkBks3HwstGIhbzYJmcKcNuFaqHGyBQ5sqFu44Ke3mlmT7auUvg+qoPQFyFE 8lRvVn/I6H846ChtsdWz2BFwPhK47ZNf/NEnk9J7yrDgiRqv0EWqHXp2pOA7y+MoOgkH uJjR7e0CLKZtZHMDGKdni+sVSAyDQTuLC71L1z+K0ObRsVvMpETh4S+yniNiGf6r9kWT ajcY9nzI+iK6h/Xm5mtFjlw+i6S9rGAuSjaSuDMZiHXIKBsF8iVPcgApgUOtrzGE2Y5z C59A== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@ffwll.ch header.s=google header.b=d1EJpyc6; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y8-v6si281356plt.378.2018.03.13.09.11.34; Tue, 13 Mar 2018 09:11:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail header.i=@ffwll.ch header.s=google header.b=d1EJpyc6; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934097AbeCMQKn (ORCPT + 99 others); Tue, 13 Mar 2018 12:10:43 -0400 Received: from mail-wr0-f194.google.com ([209.85.128.194]:38207 "EHLO mail-wr0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933466AbeCMQKk (ORCPT ); Tue, 13 Mar 2018 12:10:40 -0400 Received: by mail-wr0-f194.google.com with SMTP id l8so413144wrg.5 for ; Tue, 13 Mar 2018 09:10:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=sender:date:from:to:cc:subject:message-id:mail-followup-to :references:mime-version:content-disposition :content-transfer-encoding:in-reply-to:user-agent; bh=yroFc2jbFKf5C7uvH8aJZXudQTCCtnignWpVywkx1eY=; b=d1EJpyc69FLpiFNhdwObQ/F/c+xkf/4QavN3hoOh2lFvOu9bO2fhSEqC//kzhHRvpf zEm6YPA/v5QMpqZYvj6//2oF09Gjtx4dyrjX/l4iY0kncjETVKTV5U0gpJeWMuqLBWho d7vuBlL6WlDN3owM/QiaFLrNzwXQpJavnjHyw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:from:to:cc:subject:message-id :mail-followup-to:references:mime-version:content-disposition :content-transfer-encoding:in-reply-to:user-agent; bh=yroFc2jbFKf5C7uvH8aJZXudQTCCtnignWpVywkx1eY=; b=bSbpHto1lIvKi37WA8XgliBXOLnlcGnacVjomt2EYlCJtSed5pYcIJmzBfRu72XEzL JuVWm1I43vJvqbtnyr46uwvrFGZxGguXQUH3Gjja1Zi/u0DrSEexYmebSLn1+XvttnUP GfzeHS7G8OOubmwXXZJRjPdOqmeWq2taVFuy2i5BJXZy4AxZqum9gy5ZaESe+ZXO+E0v UpnUECXpCO6VvQBqke+hseqXBZW/JpH8c7UB+E5VZHuw7ZvjJiC8MqwR5DB8ziO+ket8 lXISvaOrKbMM1RnvmpmzPa/NlCqOmylQT+kZOdRkeO23gM1ChL8L6JoivFPXOrTJrbPS /GPA== X-Gm-Message-State: AElRT7HNnRPCEHxlNKNM/2p+2ReKp4luG7O/vBe69vEvhzYQZlNxYMzG +yYwp3QIszHx7jPM8PxUds9kRg== X-Received: by 10.80.179.181 with SMTP id s50mr1470738edd.190.1520957438587; Tue, 13 Mar 2018 09:10:38 -0700 (PDT) Received: from phenom.ffwll.local ([2a02:168:56e6:0:e4bc:76a0:8042:669e]) by smtp.gmail.com with ESMTPSA id e24sm474140edb.0.2018.03.13.09.10.37 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 13 Mar 2018 09:10:37 -0700 (PDT) Date: Tue, 13 Mar 2018 17:10:35 +0100 From: Daniel Vetter To: Gerd Hoffmann Cc: dri-devel@lists.freedesktop.org, Tomeu Vizoso , David Airlie , open list , qemu-devel@nongnu.org, "moderated list:DMA BUFFER SHARING FRAMEWORK" , "open list:DMA BUFFER SHARING FRAMEWORK" Subject: Re: [RfC PATCH] Add udmabuf misc device Message-ID: <20180313161035.GL4788@phenom.ffwll.local> Mail-Followup-To: Gerd Hoffmann , dri-devel@lists.freedesktop.org, Tomeu Vizoso , David Airlie , open list , qemu-devel@nongnu.org, "moderated list:DMA BUFFER SHARING FRAMEWORK" , "open list:DMA BUFFER SHARING FRAMEWORK" References: <20180313154826.20436-1-kraxel@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20180313154826.20436-1-kraxel@redhat.com> X-Operating-System: Linux phenom 4.15.0-1-amd64 User-Agent: Mutt/1.9.4 (2018-02-28) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Mar 13, 2018 at 04:48:26PM +0100, Gerd Hoffmann wrote: > A driver to let userspace turn iovecs into dma-bufs. > > Use case: Allows qemu pass around dmabufs for the guest framebuffer. > https://www.kraxel.org/cgit/qemu/log/?h=sirius/udmabuf has an > experimental patch. > > Also allows qemu to export guest virtio-gpu resources as host dmabufs. > Should be possible to use it to display guest wayland windows on the > host display server. virtio-gpu ressources can be chunked so we will > actually need multiple iovec entries. UNTESTED. > > Want collect some feedback on the general approach with this RfC series. > Can this work? If not, better ideas? > > Question: Must this be hooked into some kind of mlock accounting, to > limit the amout of memory userspace is allowed to pin this way? Or will > get_user_pages_fast() handle that for me? Either mlock account (because it's mlocked defacto), and get_user_pages won't do that for you. Or you write the full-blown userptr implementation, including mmu_notifier support (see i915 or amdgpu), but that also requires Christian K?nigs latest ->invalidate_mapping RFC for dma-buf (since atm exporting userptr buffers is a no-go). > > Known issue: Driver API isn't complete yet. Need add some flags, for > example to support read-only buffers. dma-buf has no concept of read-only. I don't think we can even enforce that (not many iommus can enforce this iirc), so pretty much need to require r/w memory. > Cc: David Airlie > Cc: Tomeu Vizoso > Signed-off-by: Gerd Hoffmann btw there's also the hyperdmabuf stuff from the xen folks, but imo their solution of forwarding the entire dma-buf api is over the top. This here looks _much_ better, pls cc all the hyperdmabuf people on your next version. Overall I like the idea, but too lazy to review. Can maybe be bribed :-) Oh, some kselftests for this stuff would be lovely. -Daniel > --- > include/uapi/linux/udmabuf.h | 21 ++++ > drivers/dma-buf/udmabuf.c | 250 +++++++++++++++++++++++++++++++++++++++++++ > drivers/dma-buf/Kconfig | 7 ++ > drivers/dma-buf/Makefile | 1 + > 4 files changed, 279 insertions(+) > create mode 100644 include/uapi/linux/udmabuf.h > create mode 100644 drivers/dma-buf/udmabuf.c > > diff --git a/include/uapi/linux/udmabuf.h b/include/uapi/linux/udmabuf.h > new file mode 100644 > index 0000000000..fd2fa441fe > --- /dev/null > +++ b/include/uapi/linux/udmabuf.h > @@ -0,0 +1,21 @@ > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ > +#ifndef _UAPI_LINUX_UDMABUF_H > +#define _UAPI_LINUX_UDMABUF_H > + > +#include > +#include > + > +struct udmabuf_iovec { > + __u64 base; > + __u64 len; > +}; > + > +struct udmabuf_create { > + __u32 flags; > + __u32 niov; > + struct udmabuf_iovec iovs[]; > +}; > + > +#define UDMABUF_CREATE _IOW(0x42, 0x23, struct udmabuf_create) > + > +#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..ec012d7ac7 > --- /dev/null > +++ b/drivers/dma-buf/udmabuf.c > @@ -0,0 +1,250 @@ > +/* > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +struct udmabuf { > + u32 pagecount; > + struct page **pages; > +}; > + > +static int udmabuf_vm_fault(struct vm_fault *vmf) > +{ > + struct vm_area_struct *vma = vmf->vma; > + struct udmabuf *ubuf = vma->vm_private_data; > + > + if (WARN_ON(vmf->pgoff >= ubuf->pagecount)) > + return VM_FAULT_SIGBUS; > + > + vmf->page = ubuf->pages[vmf->pgoff]; > + get_page(vmf->page); > + return 0; > +} > + > +static const struct vm_operations_struct udmabuf_vm_ops = { > + .fault = udmabuf_vm_fault, > +}; > + > +static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma) > +{ > + struct udmabuf *ubuf = buf->priv; > + > + if ((vma->vm_flags & VM_SHARED) == 0) > + return -EINVAL; > + > + vma->vm_ops = &udmabuf_vm_ops; > + vma->vm_private_data = ubuf; > + return 0; > +} > + > +static struct sg_table *map_udmabuf(struct dma_buf_attachment *at, > + enum dma_data_direction direction) > +{ > + struct udmabuf *ubuf = at->dmabuf->priv; > + struct sg_table *sg; > + > + sg = kzalloc(sizeof(*sg), GFP_KERNEL); > + if (!sg) > + goto err1; > + if (sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->pagecount, > + 0, ubuf->pagecount << PAGE_SHIFT, > + GFP_KERNEL) < 0) > + goto err2; > + if (!dma_map_sg(at->dev, sg->sgl, sg->nents, direction)) > + goto err3; > + > + return sg; > + > +err3: > + sg_free_table(sg); > +err2: > + kfree(sg); > +err1: > + return ERR_PTR(-ENOMEM); > +} > + > +static void unmap_udmabuf(struct dma_buf_attachment *at, > + struct sg_table *sg, > + enum dma_data_direction direction) > +{ > + sg_free_table(sg); > + kfree(sg); > +} > + > +static void release_udmabuf(struct dma_buf *buf) > +{ > + struct udmabuf *ubuf = buf->priv; > + pgoff_t pg; > + > + for (pg = 0; pg < ubuf->pagecount; pg++) > + put_page(ubuf->pages[pg]); > + kfree(ubuf->pages); > + kfree(ubuf); > +} > + > +static void *kmap_atomic_udmabuf(struct dma_buf *buf, unsigned long offset) > +{ > + struct udmabuf *ubuf = buf->priv; > + struct page *page = ubuf->pages[offset >> PAGE_SHIFT]; > + > + return kmap_atomic(page); > +} > + > +static void *kmap_udmabuf(struct dma_buf *buf, unsigned long offset) > +{ > + struct udmabuf *ubuf = buf->priv; > + struct page *page = ubuf->pages[offset >> PAGE_SHIFT]; > + > + return kmap(page); > +} > + > +static struct dma_buf_ops udmabuf_ops = { > + .map_dma_buf = map_udmabuf, > + .unmap_dma_buf = unmap_udmabuf, > + .release = release_udmabuf, > + .map_atomic = kmap_atomic_udmabuf, > + .map = kmap_udmabuf, > + .mmap = mmap_udmabuf, > +}; > + > +static long udmabuf_ioctl_create(struct file *filp, unsigned long arg) > +{ > + struct udmabuf_create create; > + struct udmabuf_iovec *iovs; > + struct udmabuf *ubuf; > + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); > + struct dma_buf *buf; > + pgoff_t pgoff, pgcnt; > + u32 iov; > + int ret; > + > + if (copy_from_user(&create, (void __user *)arg, > + sizeof(struct udmabuf_create))) > + return -EFAULT; > + > + iovs = kmalloc_array(create.niov, sizeof(struct udmabuf_iovec), > + GFP_KERNEL); > + if (!iovs) > + return -ENOMEM; > + > + arg += offsetof(struct udmabuf_create, iovs); > + ret = -EFAULT; > + if (copy_from_user(iovs, (void __user *)arg, > + create.niov * sizeof(struct udmabuf_iovec))) > + goto err_free_iovs; > + > + ubuf = kzalloc(sizeof(struct udmabuf), GFP_KERNEL); > + if (!ubuf) > + goto err_free_iovs; > + > + ret = -EINVAL; > + for (iov = 0; iov < create.niov; iov++) { > + if (!IS_ALIGNED(iovs[iov].base, PAGE_SIZE)) > + goto err_free_iovs; > + if (!IS_ALIGNED(iovs[iov].len, PAGE_SIZE)) > + goto err_free_iovs; > + ubuf->pagecount += iovs[iov].len >> PAGE_SHIFT; > + } > + > + ret = -ENOMEM; > + ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(struct page*), > + GFP_KERNEL); > + if (!ubuf->pages) > + goto err_free_buf; > + > + pgoff = 0; > + for (iov = 0; iov < create.niov; iov++) { > + pgcnt = iovs[iov].len >> PAGE_SHIFT; > + while (pgcnt > 0) { > + ret = get_user_pages_fast(iovs[iov].base, pgcnt, > + true, /* write */ > + ubuf->pages + pgoff); > + if (ret < 0) > + goto err_put_pages; > + pgoff += ret; > + pgcnt -= ret; > + } > + } > + > + 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; > + } > + > + kfree(iovs); > + return dma_buf_fd(buf, 0); > + > +err_put_pages: > + while (pgoff > 0) > + put_page(ubuf->pages[--pgoff]); > +err_free_buf: > + kfree(ubuf->pages); > + kfree(ubuf); > +err_free_iovs: > + kfree(iovs); > + return ret; > +} > + > +static long udmabuf_ioctl(struct file *filp, unsigned int ioctl, > + unsigned long arg) > +{ > + long ret; > + > + switch (ioctl) { > + case UDMABUF_CREATE: > + ret = udmabuf_ioctl_create(filp, arg); > + break; > + default: > + ret = -EINVAL; > + break; > + } > + return ret; > +} > + > +static const struct file_operations udmabuf_fops = { > + .owner = THIS_MODULE, > + .unlocked_ioctl = udmabuf_ioctl, > +}; > + > +static struct miscdevice udmabuf_misc = { > + .minor = MISC_DYNAMIC_MINOR, > + .name = "udmabuf", > + .fops = &udmabuf_fops, > +}; > + > +static int __init udmabuf_dev_init(void) > +{ > + int ret; > + > + ret = misc_register(&udmabuf_misc); > + if (ret) > + return ret; > + > + return 0; > +} > + > +static void __exit udmabuf_dev_exit(void) > +{ > + misc_deregister(&udmabuf_misc); > +} > + > +module_init(udmabuf_dev_init) > +module_exit(udmabuf_dev_exit) > + > +MODULE_LICENSE("GPL v2"); > diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig > index ed3b785bae..5876b52554 100644 > --- a/drivers/dma-buf/Kconfig > +++ b/drivers/dma-buf/Kconfig > @@ -30,4 +30,11 @@ config SW_SYNC > WARNING: improper use of this can result in deadlocking kernel > drivers from userspace. Intended for test and debug only. > > +config UDMABUF > + tristate "userspace dmabuf misc driver" > + default n > + depends on DMA_SHARED_BUFFER > + ---help--- > + A driver to let userspace turn iovs into dma-bufs. > + > endmenu > diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile > index c33bf88631..0913a6ccab 100644 > --- a/drivers/dma-buf/Makefile > +++ b/drivers/dma-buf/Makefile > @@ -1,3 +1,4 @@ > obj-y := dma-buf.o dma-fence.o dma-fence-array.o reservation.o seqno-fence.o > obj-$(CONFIG_SYNC_FILE) += sync_file.o > obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o > +obj-$(CONFIG_UDMABUF) += udmabuf.o > -- > 2.9.3 > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch