[PATCH 2/5] udmabuf: allow userspace to set map attributes

Gurchetan Singh gurchetansingh at chromium.org
Tue Nov 26 01:10:53 UTC 2019


The main use for udmabuf is sending guest memory pages
to the host.

It's generally a bad idea to have to separate mappings with
different attributes. For example, a WC mapping the guest
kernel and cached mapping on the host is problematic.

v2: Cache attribute flags instead of read/write flags (kraxel@)
---
 drivers/dma-buf/udmabuf.c    | 12 ++++++++++++
 include/uapi/linux/udmabuf.h |  2 ++
 2 files changed, 14 insertions(+)

diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index b345e91d831a..ce9caaaa9e4b 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -16,6 +16,7 @@ static const u32    list_limit = 1024;  /* udmabuf_create_list->count limit */
 static const size_t size_limit_mb = 64; /* total dmabuf size, in megabytes  */
 
 struct udmabuf {
+	u32 flags;
 	pgoff_t pagecount;
 	struct page **pages;
 };
@@ -37,6 +38,12 @@ static const struct vm_operations_struct udmabuf_vm_ops = {
 static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma)
 {
 	struct udmabuf *ubuf = buf->priv;
+	pgprot_t pgprot = vm_get_page_prot(vma->vm_flags);
+
+	if (ubuf->flags & UDMABUF_FLAGS_WC)
+		vma->vm_page_prot = pgprot_writecombine(pgprot);
+	else if (ubuf->flags & UDMABUF_FLAGS_NONCACHED)
+		vma->vm_page_prot = pgprot_noncached(pgprot);
 
 	if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0)
 		return -EINVAL;
@@ -132,6 +139,10 @@ static long udmabuf_create(const struct udmabuf_create_list *head,
 	int seals, ret = -EINVAL;
 	u32 i, flags;
 
+	if ((head->flags & UDMABUF_FLAGS_NONCACHED) &&
+	    (head->flags & UDMABUF_FLAGS_WC))
+		return -EINVAL;
+
 	ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL);
 	if (!ubuf)
 		return -ENOMEM;
@@ -188,6 +199,7 @@ static long udmabuf_create(const struct udmabuf_create_list *head,
 	exp_info.priv = ubuf;
 	exp_info.flags = O_RDWR;
 
+	ubuf->flags = head->flags;
 	buf = dma_buf_export(&exp_info);
 	if (IS_ERR(buf)) {
 		ret = PTR_ERR(buf);
diff --git a/include/uapi/linux/udmabuf.h b/include/uapi/linux/udmabuf.h
index 46b6532ed855..f90831f2bb0d 100644
--- a/include/uapi/linux/udmabuf.h
+++ b/include/uapi/linux/udmabuf.h
@@ -6,6 +6,8 @@
 #include <linux/ioctl.h>
 
 #define UDMABUF_FLAGS_CLOEXEC	0x01
+#define UDMABUF_FLAGS_WC	0x02
+#define UDMABUF_FLAGS_NONCACHED 0x04
 
 struct udmabuf_create {
 	__u32 memfd;
-- 
2.24.0.432.g9d3f5f5b63-goog



More information about the dri-devel mailing list