[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] libgnttab: Add support for Linux dma-buf



From: Oleksandr Andrushchenko <oleksandr_andrushchenko@xxxxxxxx>

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@xxxxxxxx>
---
 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@xxxxxxxxxxxx>
+ * 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@xxxxxxxxxxxx>
+ * 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@xxxxxxxxxxxx>
+ * 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@xxxxxxxxxxxx>
+ * 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@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.