All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleksandr Andrushchenko <andr2000@gmail.com>
To: xen-devel@lists.xenproject.org, ian.jackson@eu.citrix.com,
	wei.liu2@citrix.com, boris.ostrovsky@oracle.com, jgross@suse.com
Cc: andr2000@gmail.com,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Subject: [PATCH] libgnttab: Add support for Linux dma-buf
Date: Mon, 23 Jul 2018 15:27:25 +0300	[thread overview]
Message-ID: <20180723122725.5476-1-andr2000@gmail.com> (raw)

From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>

Add support for Linux grant device driver extension which allows
converting existing dma-buf's into an array of grant references
and vise versa. This is only implemented for Linux as other OSes
have no Linux dma-buf support.

Bump gnttab library minor version to 3.

Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
 tools/include/xen-sys/Linux/gntdev.h  | 106 ++++++++++++++++++++++++
 tools/libs/gnttab/Makefile            |   2 +-
 tools/libs/gnttab/gnttab_core.c       |  26 ++++++
 tools/libs/gnttab/gnttab_unimp.c      |  26 ++++++
 tools/libs/gnttab/include/xengnttab.h |  61 ++++++++++++++
 tools/libs/gnttab/libxengnttab.map    |   8 ++
 tools/libs/gnttab/linux.c             | 113 ++++++++++++++++++++++++++
 tools/libs/gnttab/minios.c            |  26 ++++++
 tools/libs/gnttab/private.h           |  13 +++
 9 files changed, 380 insertions(+), 1 deletion(-)

diff --git a/tools/include/xen-sys/Linux/gntdev.h b/tools/include/xen-sys/Linux/gntdev.h
index 0ca07c92b21c..d16076044c71 100644
--- a/tools/include/xen-sys/Linux/gntdev.h
+++ b/tools/include/xen-sys/Linux/gntdev.h
@@ -4,6 +4,7 @@
  * Interface to /dev/xen/gntdev.
  * 
  * Copyright (c) 2007, D G Murray
+ * Copyright (c) 2018, Oleksandr Andrushchenko, EPAM Systems Inc.
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 2
@@ -168,4 +169,109 @@ struct ioctl_gntdev_grant_copy {
     struct ioctl_gntdev_grant_copy_segment *segments;
 };
 
+/*
+ * Flags to be used while requesting memory mapping's backing storage
+ * to be allocated with DMA API.
+ */
+
+/*
+ * The buffer is backed with memory allocated with dma_alloc_wc.
+ */
+#define GNTDEV_DMA_FLAG_WC		(1 << 0)
+
+/*
+ * The buffer is backed with memory allocated with dma_alloc_coherent.
+ */
+#define GNTDEV_DMA_FLAG_COHERENT	(1 << 1)
+
+/*
+ * Create a dma-buf [1] from grant references @refs of count @count provided
+ * by the foreign domain @domid with flags @flags.
+ *
+ * By default dma-buf is backed by system memory pages, but by providing
+ * one of the GNTDEV_DMA_FLAG_XXX flags it can also be created as
+ * a DMA write-combine or coherent buffer, e.g. allocated with dma_alloc_wc/
+ * dma_alloc_coherent.
+ *
+ * Returns 0 if dma-buf was successfully created and the corresponding
+ * dma-buf's file descriptor is returned in @fd.
+ *
+ * [1] https://elixir.bootlin.com/linux/latest/source/Documentation/driver-api/dma-buf.rst
+ */
+
+#define IOCTL_GNTDEV_DMABUF_EXP_FROM_REFS \
+    _IOC(_IOC_NONE, 'G', 9, \
+         sizeof(struct ioctl_gntdev_dmabuf_exp_from_refs))
+struct ioctl_gntdev_dmabuf_exp_from_refs {
+    /* IN parameters. */
+    /* Specific options for this dma-buf: see GNTDEV_DMABUF_FLAG_XXX. */
+    uint32_t flags;
+    /* Number of grant references in @refs array. */
+    uint32_t count;
+    /* OUT parameters. */
+    /* File descriptor of the dma-buf. */
+    uint32_t fd;
+    /* The domain ID of the grant references to be mapped. */
+    uint32_t domid;
+    /* Variable IN parameter. */
+    /* Array of grant references of size @count. */
+    uint32_t refs[1];
+};
+
+/*
+ * This will block until the dma-buf with the file descriptor @fd is
+ * released. This is only valid for buffers created with
+ * IOCTL_GNTDEV_DMABUF_EXP_FROM_REFS.
+ *
+ * If withing @wait_to_ms milliseconds the buffer is not released
+ * then -ETIMEDOUT error is returned.
+ * If the buffer with file descriptor @fd does not exist or has already
+ * been released, then -ENOENT is returned. For valid file descriptors
+ * this must not be treated as error.
+ */
+#define IOCTL_GNTDEV_DMABUF_EXP_WAIT_RELEASED \
+    _IOC(_IOC_NONE, 'G', 10, \
+         sizeof(struct ioctl_gntdev_dmabuf_exp_wait_released))
+struct ioctl_gntdev_dmabuf_exp_wait_released {
+    /* IN parameters */
+    uint32_t fd;
+    uint32_t wait_to_ms;
+};
+
+/*
+ * Import a dma-buf with file descriptor @fd and export granted references
+ * to the pages of that dma-buf into array @refs of size @count.
+ */
+#define IOCTL_GNTDEV_DMABUF_IMP_TO_REFS \
+    _IOC(_IOC_NONE, 'G', 11, \
+         sizeof(struct ioctl_gntdev_dmabuf_imp_to_refs))
+struct ioctl_gntdev_dmabuf_imp_to_refs {
+    /* IN parameters. */
+    /* File descriptor of the dma-buf. */
+    uint32_t fd;
+    /* Number of grant references in @refs array. */
+    uint32_t count;
+    /* The domain ID for which references to be granted. */
+    uint32_t domid;
+    /* Reserved - must be zero. */
+    uint32_t reserved;
+    /* OUT parameters. */
+    /* Array of grant references of size @count. */
+    uint32_t refs[1];
+};
+
+/*
+ * This will close all references to an imported buffer, so it can be
+ * released by the owner. This is only valid for buffers created with
+ * IOCTL_GNTDEV_DMABUF_IMP_TO_REFS.
+ */
+#define IOCTL_GNTDEV_DMABUF_IMP_RELEASE \
+    _IOC(_IOC_NONE, 'G', 12, \
+         sizeof(struct ioctl_gntdev_dmabuf_imp_release))
+struct ioctl_gntdev_dmabuf_imp_release {
+    /* IN parameters */
+    uint32_t fd;
+    uint32_t reserved;
+};
+
 #endif /* __LINUX_PUBLIC_GNTDEV_H__ */
diff --git a/tools/libs/gnttab/Makefile b/tools/libs/gnttab/Makefile
index 6c2e7e36a2c3..0befbd18f1af 100644
--- a/tools/libs/gnttab/Makefile
+++ b/tools/libs/gnttab/Makefile
@@ -2,7 +2,7 @@ XEN_ROOT = $(CURDIR)/../../..
 include $(XEN_ROOT)/tools/Rules.mk
 
 MAJOR    = 1
-MINOR    = 2
+MINOR    = 3
 SHLIB_LDFLAGS += -Wl,--version-script=libxengnttab.map
 
 CFLAGS   += -Werror -Wmissing-prototypes
diff --git a/tools/libs/gnttab/gnttab_core.c b/tools/libs/gnttab/gnttab_core.c
index bd075f818aa6..92e7228a2671 100644
--- a/tools/libs/gnttab/gnttab_core.c
+++ b/tools/libs/gnttab/gnttab_core.c
@@ -1,6 +1,7 @@
 /******************************************************************************
  *
  * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ * Copyright (c) 2018, Oleksandr Andrushchenko, EPAM Systems Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -134,6 +135,31 @@ int xengnttab_grant_copy(xengnttab_handle *xgt,
 {
     return osdep_gnttab_grant_copy(xgt, count, segs);
 }
+
+int xengnttab_dmabuf_exp_from_refs(xengnttab_handle *xgt, uint32_t domid,
+                                   uint32_t flags, uint32_t count,
+                                   const uint32_t *refs, uint32_t *fd)
+{
+    return osdep_gnttab_dmabuf_exp_from_refs(xgt, domid, flags, count,
+                                             refs, fd);
+}
+
+int xengnttab_dmabuf_exp_wait_released(xengnttab_handle *xgt, uint32_t fd,
+                                       uint32_t wait_to_ms)
+{
+    return osdep_gnttab_dmabuf_exp_wait_released(xgt, fd, wait_to_ms);
+}
+
+int xengnttab_dmabuf_imp_to_refs(xengnttab_handle *xgt, uint32_t domid,
+                                 uint32_t fd, uint32_t count, uint32_t *refs)
+{
+    return osdep_gnttab_dmabuf_imp_to_refs(xgt, domid, fd, count, refs);
+}
+
+int xengnttab_dmabuf_imp_release(xengnttab_handle *xgt, uint32_t fd)
+{
+    return osdep_gnttab_dmabuf_imp_release(xgt, fd);
+}
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libs/gnttab/gnttab_unimp.c b/tools/libs/gnttab/gnttab_unimp.c
index 26e4ee129d03..dee1afd2647f 100644
--- a/tools/libs/gnttab/gnttab_unimp.c
+++ b/tools/libs/gnttab/gnttab_unimp.c
@@ -1,6 +1,7 @@
 /******************************************************************************
  *
  * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ * Copyright (c) 2018, Oleksandr Andrushchenko, EPAM Systems Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -84,6 +85,31 @@ int xengnttab_grant_copy(xengnttab_handle *xgt,
 {
     abort();
 }
+
+int xengnttab_dmabuf_exp_from_refs(xengnttab_handle *xgt, uint32_t domid,
+                                   uint32_t flags, uint32_t count,
+                                   const uint32_t *refs, uint32_t *fd)
+{
+    abort();
+}
+
+int xengnttab_dmabuf_exp_wait_released(xengnttab_handle *xgt, uint32_t fd,
+                                       uint32_t wait_to_ms)
+{
+    abort();
+}
+
+int xengnttab_dmabuf_imp_to_refs(xengnttab_handle *xgt, uint32_t domid,
+                                 uint32_t fd, uint32_t count, uint32_t *refs)
+{
+    abort();
+}
+
+int xengnttab_dmabuf_imp_release(xengnttab_handle *xgt, uint32_t fd)
+{
+    abort();
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libs/gnttab/include/xengnttab.h b/tools/libs/gnttab/include/xengnttab.h
index 91d4cd5bdd88..111fc88caeb3 100644
--- a/tools/libs/gnttab/include/xengnttab.h
+++ b/tools/libs/gnttab/include/xengnttab.h
@@ -18,6 +18,7 @@
  * A library for low-level access to the Xen control interfaces.
  *
  * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ * Copyright (c) 2018, Oleksandr Andrushchenko, EPAM Systems Inc.
  */
 #ifndef XENGNTTAB_H
 #define XENGNTTAB_H
@@ -295,6 +296,66 @@ int xengnttab_grant_copy(xengnttab_handle *xgt,
                          uint32_t count,
                          xengnttab_grant_copy_segment_t *segs);
 
+/*
+ * Flags to be used while requesting memory mapping's backing storage
+ * to be allocated with DMA API.
+ */
+
+/*
+ * The buffer is backed with memory allocated with dma_alloc_wc.
+ */
+#define GNTDEV_DMA_FLAG_WC		(1 << 0)
+
+/*
+ * The buffer is backed with memory allocated with dma_alloc_coherent.
+ */
+#define GNTDEV_DMA_FLAG_COHERENT	(1 << 1)
+
+/**
+ * Create a dma-buf [1] from grant references @refs of count @count provided
+ * by the foreign domain @domid with flags @flags.
+ *
+ * By default dma-buf is backed by system memory pages, but by providing
+ * one of the GNTDEV_DMA_FLAG_XXX flags it can also be created as
+ * a DMA write-combine or coherent buffer.
+ *
+ * Returns 0 if dma-buf was successfully created and the corresponding
+ * dma-buf's file descriptor is returned in @fd.
+ *
+ * [1] https://elixir.bootlin.com/linux/latest/source/Documentation/driver-api/dma-buf.rst
+ */
+int xengnttab_dmabuf_exp_from_refs(xengnttab_handle *xgt, uint32_t domid,
+                                   uint32_t flags, uint32_t count,
+                                   const uint32_t *refs, uint32_t *fd);
+
+/*
+ * This will block until the dma-buf with the file descriptor @fd is
+ * released. This is only valid for buffers created with
+ * IOCTL_GNTDEV_DMABUF_EXP_FROM_REFS.
+ *
+ * If withing @wait_to_ms milliseconds the buffer is not released
+ * then -ETIMEDOUT error is returned.
+ * If the buffer with file descriptor @fd does not exist or has already
+ * been released, then -ENOENT is returned. For valid file descriptors
+ * this must not be treated as error.
+ */
+int xengnttab_dmabuf_exp_wait_released(xengnttab_handle *xgt, uint32_t fd,
+                                       uint32_t wait_to_ms);
+
+/*
+ * Import a dma-buf with file descriptor @fd and export granted references
+ * to the pages of that dma-buf into array @refs of size @count.
+ */
+int xengnttab_dmabuf_imp_to_refs(xengnttab_handle *xgt, uint32_t domid,
+                                 uint32_t fd, uint32_t count, uint32_t *refs);
+
+/*
+ * This will close all references to an imported buffer, so it can be
+ * released by the owner. This is only valid for buffers created with
+ * IOCTL_GNTDEV_DMABUF_IMP_TO_REFS.
+ */
+int xengnttab_dmabuf_imp_release(xengnttab_handle *xgt, uint32_t fd);
+
 /*
  * Grant Sharing Interface (allocating and granting pages to others)
  */
diff --git a/tools/libs/gnttab/libxengnttab.map b/tools/libs/gnttab/libxengnttab.map
index d5da388a0d8d..9de2183810a9 100644
--- a/tools/libs/gnttab/libxengnttab.map
+++ b/tools/libs/gnttab/libxengnttab.map
@@ -32,3 +32,11 @@ VERS_1.2 {
 		xengnttab_fd;
 		xengntshr_fd;
 } VERS_1.1;
+
+VERS_1.3 {
+	global:
+		xengnttab_dmabuf_exp_from_refs;
+		xengnttab_dmabuf_exp_wait_released;
+		xengnttab_dmabuf_imp_to_refs;
+		xengnttab_dmabuf_imp_release;
+} VERS_1.2;
diff --git a/tools/libs/gnttab/linux.c b/tools/libs/gnttab/linux.c
index 8347ddd3d9cf..9765146f7eb6 100644
--- a/tools/libs/gnttab/linux.c
+++ b/tools/libs/gnttab/linux.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ * Copyright (c) 2018, Oleksandr Andrushchenko, EPAM Systems Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -309,6 +310,118 @@ int osdep_gnttab_grant_copy(xengnttab_handle *xgt,
     return rc;
 }
 
+int osdep_gnttab_dmabuf_exp_from_refs(xengnttab_handle *xgt, uint32_t domid,
+                                      uint32_t flags, uint32_t count,
+                                      const uint32_t *refs,
+                                      uint32_t *dmabuf_fd)
+{
+    struct ioctl_gntdev_dmabuf_exp_from_refs *from_refs;
+    int rc = 0;
+
+    if ( !count )
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    from_refs = malloc(sizeof(*from_refs) +
+                       (count - 1) * sizeof(from_refs->refs[0]));
+    if ( !from_refs )
+    {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    from_refs->flags = flags;
+    from_refs->count = count;
+    from_refs->domid = domid;
+
+    memcpy(from_refs->refs, refs, count * sizeof(from_refs->refs[0]));
+
+    if ( (rc = ioctl(xgt->fd, IOCTL_GNTDEV_DMABUF_EXP_FROM_REFS, from_refs)) )
+    {
+        GTERROR(xgt->logger, "ioctl DMABUF_EXP_FROM_REFS failed");
+        goto out;
+    }
+
+    *dmabuf_fd = from_refs->fd;
+
+out:
+    free(from_refs);
+    return rc;
+}
+
+int osdep_gnttab_dmabuf_exp_wait_released(xengnttab_handle *xgt,
+                                          uint32_t fd, uint32_t wait_to_ms)
+{
+    struct ioctl_gntdev_dmabuf_exp_wait_released wait;
+    int rc;
+
+    wait.fd = fd;
+    wait.wait_to_ms = wait_to_ms;
+
+    if ( (rc = ioctl(xgt->fd, IOCTL_GNTDEV_DMABUF_EXP_WAIT_RELEASED, &wait)) ) {
+        if ( errno == ENOENT ) {
+            /* The buffer may have already been released. */
+            errno = 0;
+            rc = 0;
+        } else
+            GTERROR(xgt->logger, "ioctl DMABUF_EXP_WAIT_RELEASED failed");
+    }
+
+    return rc;
+}
+
+int osdep_gnttab_dmabuf_imp_to_refs(xengnttab_handle *xgt, uint32_t domid,
+                                    uint32_t fd, uint32_t count, uint32_t *refs)
+{
+    struct ioctl_gntdev_dmabuf_imp_to_refs *to_refs;
+    int rc = 0;
+
+    if ( !count )
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    to_refs = malloc(sizeof(*to_refs) +
+                     (count - 1) * sizeof(to_refs->refs[0]));
+    if ( !to_refs )
+    {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    to_refs->fd = fd;
+    to_refs->count = count;
+    to_refs->domid = domid;
+
+    if ( (rc = ioctl(xgt->fd, IOCTL_GNTDEV_DMABUF_IMP_TO_REFS, to_refs)) )
+    {
+        GTERROR(xgt->logger, "ioctl DMABUF_IMP_TO_REFS failed");
+        goto out;
+    }
+
+    memcpy(refs, to_refs->refs, count * sizeof(*refs));
+
+out:
+    free(to_refs);
+    return rc;
+}
+
+int osdep_gnttab_dmabuf_imp_release(xengnttab_handle *xgt, uint32_t fd)
+{
+    struct ioctl_gntdev_dmabuf_imp_release release;
+    int rc;
+
+    release.fd = fd;
+
+    if ( (rc = ioctl(xgt->fd, IOCTL_GNTDEV_DMABUF_IMP_RELEASE, &release)) )
+        GTERROR(xgt->logger, "ioctl DMABUF_IMP_RELEASE failed");
+
+    return rc;
+}
+
 int osdep_gntshr_open(xengntshr_handle *xgs)
 {
     int fd = open(DEVXEN "gntalloc", O_RDWR);
diff --git a/tools/libs/gnttab/minios.c b/tools/libs/gnttab/minios.c
index 0951bc9bac5b..f78caadd3043 100644
--- a/tools/libs/gnttab/minios.c
+++ b/tools/libs/gnttab/minios.c
@@ -112,6 +112,32 @@ int osdep_gnttab_grant_copy(xengnttab_handle *xgt,
 {
     return -1;
 }
+
+int osdep_gnttab_dmabuf_exp_from_refs(xengnttab_handle *xgt, uint32_t domid,
+                                      uint32_t flags, uint32_t count,
+                                      const uint32_t *refs, uint32_t *fd)
+{
+    return -1;
+}
+
+int osdep_gnttab_dmabuf_exp_wait_released(xengnttab_handle *xgt,
+                                          uint32_t fd, uint32_t wait_to_ms)
+{
+    return -1;
+}
+
+int osdep_gnttab_dmabuf_imp_to_refs(xengnttab_handle *xgt, uint32_t domid,
+                                    uint32_t fd, uint32_t count,
+                                    uint32_t *refs)
+{
+    return -1;
+}
+
+int osdep_gnttab_dmabuf_imp_release(xengnttab_handle *xgt, uint32_t fd)
+{
+    return -1;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libs/gnttab/private.h b/tools/libs/gnttab/private.h
index ed8df40def0d..c5e23639b141 100644
--- a/tools/libs/gnttab/private.h
+++ b/tools/libs/gnttab/private.h
@@ -35,6 +35,19 @@ int osdep_gnttab_grant_copy(xengnttab_handle *xgt,
                             uint32_t count,
                             xengnttab_grant_copy_segment_t *segs);
 
+int osdep_gnttab_dmabuf_exp_from_refs(xengnttab_handle *xgt, uint32_t domid,
+                                      uint32_t flags, uint32_t count,
+                                      const uint32_t *refs, uint32_t *fd);
+
+int osdep_gnttab_dmabuf_exp_wait_released(xengnttab_handle *xgt,
+                                          uint32_t fd, uint32_t wait_to_ms);
+
+int osdep_gnttab_dmabuf_imp_to_refs(xengnttab_handle *xgt, uint32_t domid,
+                                    uint32_t fd, uint32_t count,
+                                    uint32_t *refs);
+
+int osdep_gnttab_dmabuf_imp_release(xengnttab_handle *xgt, uint32_t fd);
+
 int osdep_gntshr_open(xengntshr_handle *xgs);
 int osdep_gntshr_close(xengntshr_handle *xgs);
 
-- 
2.18.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

             reply	other threads:[~2018-07-23 12:27 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-23 12:27 Oleksandr Andrushchenko [this message]
2018-07-25  9:39 ` [PATCH] libgnttab: Add support for Linux dma-buf Wei Liu
2018-07-25  9:49   ` Oleksandr Andrushchenko
2018-07-25  9:53     ` Wei Liu
2018-07-25 10:00       ` Oleksandr Andrushchenko
2018-07-25 12:23         ` Boris Ostrovsky
2018-07-30  7:38   ` Oleksandr Andrushchenko
2018-08-20  8:43 ` Oleksandr Andrushchenko
2018-08-20 14:40 ` Wei Liu
2018-08-21  5:47   ` Oleksandr Andrushchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180723122725.5476-1-andr2000@gmail.com \
    --to=andr2000@gmail.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=jgross@suse.com \
    --cc=oleksandr_andrushchenko@epam.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.