mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
libgnttab: Add support for Linux dma-buf
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> Acked-by: Wei Liu <wei.liu2@citrix.com>
This commit is contained in:
1 parent
10c3fd91bd
commit
ee8105cabc
9 files changed
+384
-1
No files matched your search
@@ -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__ */
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
@@ -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,122 @@ 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 = NULL;
|
||||
int rc = -1;
|
||||
|
||||
if ( !count )
|
||||
{
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
from_refs = malloc(sizeof(*from_refs) +
|
||||
(count - 1) * sizeof(from_refs->refs[0]));
|
||||
if ( !from_refs )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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;
|
||||
rc = 0;
|
||||
|
||||
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 = NULL;
|
||||
int rc = -1;
|
||||
|
||||
if ( !count )
|
||||
{
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
to_refs = malloc(sizeof(*to_refs) +
|
||||
(count - 1) * sizeof(to_refs->refs[0]));
|
||||
if ( !to_refs )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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));
|
||||
rc = 0;
|
||||
|
||||
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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||