In addition to memfd, a blob resource can also have its backing
storage in a VFIO device region. Since, there is no effective way
to determine where the backing storage is located, we first try to
create a dmabuf assuming it is in memfd. If that fails, we try to
create a dmabuf assuming it is in VFIO device region.
So, we first call virtio_gpu_create_udmabuf() to check if the blob's
backing storage is located in a memfd or not. If it is not, we invoke
the vfio_device_create_dmabuf() API which identifies the right VFIO
device and eventually creates a dmabuf fd.
Note that in virtio_gpu_remap_dmabuf(), we first try to test if
the VFIO dmabuf exporter supports mmap or not. If it doesn't, we
fall back to the vfio_device_mmap_dmabuf() API to get a mapping
created for the dmabuf.
Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Cc: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Cc: Alex Williamson <alex@shazbot.org>
Cc: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/display/Kconfig | 5 ++++
hw/display/virtio-gpu-dmabuf.c | 49 ++++++++++++++++++++++++++--------
2 files changed, 43 insertions(+), 11 deletions(-)
diff --git a/hw/display/Kconfig b/hw/display/Kconfig
index 1e95ab28ef..0d090f25f5 100644
--- a/hw/display/Kconfig
+++ b/hw/display/Kconfig
@@ -106,6 +106,11 @@ config VIRTIO_VGA
depends on VIRTIO_PCI
select VGA
+config VIRTIO_GPU_VFIO_BLOB
+ bool
+ default y
+ depends on VFIO
+
config VHOST_USER_GPU
bool
default y
diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
index 22e66fbb12..2e65f21dda 100644
--- a/hw/display/virtio-gpu-dmabuf.c
+++ b/hw/display/virtio-gpu-dmabuf.c
@@ -18,6 +18,7 @@
#include "ui/console.h"
#include "hw/virtio/virtio-gpu.h"
#include "hw/virtio/virtio-gpu-pixman.h"
+#include "hw/vfio/vfio-device.h"
#include "trace.h"
#include "system/ramblock.h"
#include "system/hostmem.h"
@@ -27,6 +28,23 @@
#include "standard-headers/linux/udmabuf.h"
#include "standard-headers/drm/drm_fourcc.h"
+static bool virtio_gpu_create_vfio_dmabuf(struct virtio_gpu_simple_resource *r,
+ Error **errp)
+{
+ bool ret = false;
+#if defined(VIRTIO_GPU_VFIO_BLOB)
+ int fd;
+
+ if (!vfio_device_create_dmabuf(r->iov, r->iov_cnt, &fd, errp)) {
+ return false;
+ }
+
+ ret = true;
+ r->dmabuf_fd = fd;
+#endif
+ return ret;
+}
+
static bool virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res,
Error **errp)
{
@@ -72,18 +90,25 @@ static bool virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res,
}
static bool virtio_gpu_remap_dmabuf(struct virtio_gpu_simple_resource *res,
- Error **err1)
+ Error **err1, Error **err2)
{
+ bool ret = true;
void *map;
map = mmap(NULL, res->blob_size, PROT_READ, MAP_SHARED, res->dmabuf_fd, 0);
if (map == MAP_FAILED) {
error_setg_errno(err1, errno, "dmabuf mmap failed");
- res->remapped = NULL;
- return false;
+ map = NULL;
+ ret = false;
+#if defined(VIRTIO_GPU_VFIO_BLOB)
+ if (vfio_device_mmap_dmabuf(res->iov, res->iov_cnt, &map,
+ res->blob_size, err2)) {
+ ret = true;
+ }
+#endif
}
res->remapped = map;
- return true;
+ return ret;
}
static void virtio_gpu_destroy_dmabuf(struct virtio_gpu_simple_resource *res)
@@ -137,7 +162,7 @@ bool virtio_gpu_have_udmabuf(void)
void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
{
- Error *err1 = NULL;
+ Error *err1 = NULL, *err2 = NULL;
void *pdata = NULL;
res->dmabuf_fd = -1;
@@ -146,12 +171,16 @@ void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
pdata = res->iov[0].iov_base;
} else {
if (!virtio_gpu_create_udmabuf(res, &err1)) {
- error_report_err(err1);
- return;
+ if (!virtio_gpu_create_vfio_dmabuf(res, &err2)) {
+ error_report_err(err1);
+ error_report_err(err2);
+ return;
+ }
}
- if (!virtio_gpu_remap_dmabuf(res, &err1)) {
+ if (!virtio_gpu_remap_dmabuf(res, &err1, &err2)) {
error_report_err(err1);
+ error_report_err(err2);
return;
}
pdata = res->remapped;
@@ -162,9 +191,7 @@ void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res)
{
- if (res->remapped) {
- virtio_gpu_destroy_dmabuf(res);
- }
+ virtio_gpu_destroy_dmabuf(res);
}
static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)
--
2.50.1
On 2/3/26 08:30, Vivek Kasireddy wrote:
> In addition to memfd, a blob resource can also have its backing
> storage in a VFIO device region. Since, there is no effective way
> to determine where the backing storage is located, we first try to
> create a dmabuf assuming it is in memfd. If that fails, we try to
> create a dmabuf assuming it is in VFIO device region.
>
> So, we first call virtio_gpu_create_udmabuf() to check if the blob's
> backing storage is located in a memfd or not. If it is not, we invoke
> the vfio_device_create_dmabuf() API which identifies the right VFIO
> device and eventually creates a dmabuf fd.
>
> Note that in virtio_gpu_remap_dmabuf(), we first try to test if
> the VFIO dmabuf exporter supports mmap or not. If it doesn't, we
> fall back to the vfio_device_mmap_dmabuf() API to get a mapping
> created for the dmabuf.
>
> Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
> Cc: Alex Bennée <alex.bennee@linaro.org>
> Cc: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> Cc: Dmitry Osipenko <dmitry.osipenko@collabora.com>
> Cc: Alex Williamson <alex@shazbot.org>
> Cc: Cédric Le Goater <clg@redhat.com>
> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> ---
> hw/display/Kconfig | 5 ++++
> hw/display/virtio-gpu-dmabuf.c | 49 ++++++++++++++++++++++++++--------
> 2 files changed, 43 insertions(+), 11 deletions(-)
>
> diff --git a/hw/display/Kconfig b/hw/display/Kconfig
> index 1e95ab28ef..0d090f25f5 100644
> --- a/hw/display/Kconfig
> +++ b/hw/display/Kconfig
> @@ -106,6 +106,11 @@ config VIRTIO_VGA
> depends on VIRTIO_PCI
> select VGA
>
> +config VIRTIO_GPU_VFIO_BLOB
> + bool
> + default y
> + depends on VFIO
> +
> config VHOST_USER_GPU
> bool
> default y
> diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
> index 22e66fbb12..2e65f21dda 100644
> --- a/hw/display/virtio-gpu-dmabuf.c
> +++ b/hw/display/virtio-gpu-dmabuf.c
> @@ -18,6 +18,7 @@
> #include "ui/console.h"
> #include "hw/virtio/virtio-gpu.h"
> #include "hw/virtio/virtio-gpu-pixman.h"
> +#include "hw/vfio/vfio-device.h"
> #include "trace.h"
> #include "system/ramblock.h"
> #include "system/hostmem.h"
> @@ -27,6 +28,23 @@
> #include "standard-headers/linux/udmabuf.h"
> #include "standard-headers/drm/drm_fourcc.h"
>
> +static bool virtio_gpu_create_vfio_dmabuf(struct virtio_gpu_simple_resource *r,
> + Error **errp)
> +{
> + bool ret = false;
> +#if defined(VIRTIO_GPU_VFIO_BLOB)
> + int fd;
> +
> + if (!vfio_device_create_dmabuf(r->iov, r->iov_cnt, &fd, errp)) {
> + return false;
> + }
> +
> + ret = true;
> + r->dmabuf_fd = fd;
> +#endif
> + return ret;
> +}
> +
> static bool virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res,
> Error **errp)
> {
> @@ -72,18 +90,25 @@ static bool virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res,
> }
>
> static bool virtio_gpu_remap_dmabuf(struct virtio_gpu_simple_resource *res,
> - Error **err1)
> + Error **err1, Error **err2)
This looks wrong. Why do we need 2 errors ?
C.
> {
> + bool ret = true;
> void *map;
>
> map = mmap(NULL, res->blob_size, PROT_READ, MAP_SHARED, res->dmabuf_fd, 0);
> if (map == MAP_FAILED) {
> error_setg_errno(err1, errno, "dmabuf mmap failed");
> - res->remapped = NULL;
> - return false;
> + map = NULL;
> + ret = false;
> +#if defined(VIRTIO_GPU_VFIO_BLOB)
> + if (vfio_device_mmap_dmabuf(res->iov, res->iov_cnt, &map,
> + res->blob_size, err2)) {
> + ret = true;
> + }
> +#endif
> }
> res->remapped = map;
> - return true;
> + return ret;
> }
>
> static void virtio_gpu_destroy_dmabuf(struct virtio_gpu_simple_resource *res)
> @@ -137,7 +162,7 @@ bool virtio_gpu_have_udmabuf(void)
>
> void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
> {
> - Error *err1 = NULL;
> + Error *err1 = NULL, *err2 = NULL;
> void *pdata = NULL;
>
> res->dmabuf_fd = -1;
> @@ -146,12 +171,16 @@ void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
> pdata = res->iov[0].iov_base;
> } else {
> if (!virtio_gpu_create_udmabuf(res, &err1)) {
> - error_report_err(err1);
> - return;
> + if (!virtio_gpu_create_vfio_dmabuf(res, &err2)) {
> + error_report_err(err1);
> + error_report_err(err2);
> + return;
> + }
> }
>
> - if (!virtio_gpu_remap_dmabuf(res, &err1)) {
> + if (!virtio_gpu_remap_dmabuf(res, &err1, &err2)) {
> error_report_err(err1);
> + error_report_err(err2);
> return;
> }
> pdata = res->remapped;
> @@ -162,9 +191,7 @@ void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
>
> void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res)
> {
> - if (res->remapped) {
> - virtio_gpu_destroy_dmabuf(res);
> - }
> + virtio_gpu_destroy_dmabuf(res);
> }
>
> static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)
Hi Cedric,
> Subject: Re: [PATCH v5 12/12] virtio-gpu-dmabuf: Create dmabuf for
> blobs associated with VFIO devices
>
> On 2/3/26 08:30, Vivek Kasireddy wrote:
> > In addition to memfd, a blob resource can also have its backing
> > storage in a VFIO device region. Since, there is no effective way
> > to determine where the backing storage is located, we first try to
> > create a dmabuf assuming it is in memfd. If that fails, we try to
> > create a dmabuf assuming it is in VFIO device region.
> >
> > So, we first call virtio_gpu_create_udmabuf() to check if the blob's
> > backing storage is located in a memfd or not. If it is not, we invoke
> > the vfio_device_create_dmabuf() API which identifies the right VFIO
> > device and eventually creates a dmabuf fd.
> >
> > Note that in virtio_gpu_remap_dmabuf(), we first try to test if
> > the VFIO dmabuf exporter supports mmap or not. If it doesn't, we
> > fall back to the vfio_device_mmap_dmabuf() API to get a mapping
> > created for the dmabuf.
> >
> > Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
> > Cc: Alex Bennée <alex.bennee@linaro.org>
> > Cc: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> > Cc: Dmitry Osipenko <dmitry.osipenko@collabora.com>
> > Cc: Alex Williamson <alex@shazbot.org>
> > Cc: Cédric Le Goater <clg@redhat.com>
> > Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> > ---
> > hw/display/Kconfig | 5 ++++
> > hw/display/virtio-gpu-dmabuf.c | 49 ++++++++++++++++++++++++++--
> ------
> > 2 files changed, 43 insertions(+), 11 deletions(-)
> >
> > diff --git a/hw/display/Kconfig b/hw/display/Kconfig
> > index 1e95ab28ef..0d090f25f5 100644
> > --- a/hw/display/Kconfig
> > +++ b/hw/display/Kconfig
> > @@ -106,6 +106,11 @@ config VIRTIO_VGA
> > depends on VIRTIO_PCI
> > select VGA
> >
> > +config VIRTIO_GPU_VFIO_BLOB
> > + bool
> > + default y
> > + depends on VFIO
> > +
> > config VHOST_USER_GPU
> > bool
> > default y
> > diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-
> dmabuf.c
> > index 22e66fbb12..2e65f21dda 100644
> > --- a/hw/display/virtio-gpu-dmabuf.c
> > +++ b/hw/display/virtio-gpu-dmabuf.c
> > @@ -18,6 +18,7 @@
> > #include "ui/console.h"
> > #include "hw/virtio/virtio-gpu.h"
> > #include "hw/virtio/virtio-gpu-pixman.h"
> > +#include "hw/vfio/vfio-device.h"
> > #include "trace.h"
> > #include "system/ramblock.h"
> > #include "system/hostmem.h"
> > @@ -27,6 +28,23 @@
> > #include "standard-headers/linux/udmabuf.h"
> > #include "standard-headers/drm/drm_fourcc.h"
> >
> > +static bool virtio_gpu_create_vfio_dmabuf(struct
> virtio_gpu_simple_resource *r,
> > + Error **errp)
> > +{
> > + bool ret = false;
> > +#if defined(VIRTIO_GPU_VFIO_BLOB)
> > + int fd;
> > +
> > + if (!vfio_device_create_dmabuf(r->iov, r->iov_cnt, &fd, errp)) {
> > + return false;
> > + }
> > +
> > + ret = true;
> > + r->dmabuf_fd = fd;
> > +#endif
> > + return ret;
> > +}
> > +
> > static bool virtio_gpu_create_udmabuf(struct
> virtio_gpu_simple_resource *res,
> > Error **errp)
> > {
> > @@ -72,18 +90,25 @@ static bool virtio_gpu_create_udmabuf(struct
> virtio_gpu_simple_resource *res,
> > }
> >
> > static bool virtio_gpu_remap_dmabuf(struct
> virtio_gpu_simple_resource *res,
> > - Error **err1)
> > + Error **err1, Error **err2)
>
> This looks wrong. Why do we need 2 errors ?
As seen below in virtio_gpu_init_dmabuf(), we have a situation where
there is a need to collect errors from two different paths and report
them only if both the paths fail. In other words, we do not want to
return an error when the first path fails. The intended goal is to inform
the user that one or both paths were tried when a failure is seen.
For example, in virtio_gpu_remap_dmabuf(), we first try to do mmap()
and if that fails, we capture the error in err1. Next, we call
vfio_device_mmap_dmabuf() and if that succeeds, then we do not need
to report err1. However, if it fails, we then collect the error in err2 and
report both err1 and err2.
Is there a better way to handle the above situation?
Thanks,
Vivek
>
> C.
>
> > {
> > + bool ret = true;
> > void *map;
> >
> > map = mmap(NULL, res->blob_size, PROT_READ, MAP_SHARED,
> res->dmabuf_fd, 0);
> > if (map == MAP_FAILED) {
> > error_setg_errno(err1, errno, "dmabuf mmap failed");
> > - res->remapped = NULL;
> > - return false;
> > + map = NULL;
> > + ret = false;
> > +#if defined(VIRTIO_GPU_VFIO_BLOB)
> > + if (vfio_device_mmap_dmabuf(res->iov, res->iov_cnt, &map,
> > + res->blob_size, err2)) {
> > + ret = true;
> > + }
> > +#endif
> > }
> > res->remapped = map;
> > - return true;
> > + return ret;
> > }
> >
> > static void virtio_gpu_destroy_dmabuf(struct
> virtio_gpu_simple_resource *res)
> > @@ -137,7 +162,7 @@ bool virtio_gpu_have_udmabuf(void)
> >
> > void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
> > {
> > - Error *err1 = NULL;
> > + Error *err1 = NULL, *err2 = NULL;
> > void *pdata = NULL;
> >
> > res->dmabuf_fd = -1;
> > @@ -146,12 +171,16 @@ void virtio_gpu_init_dmabuf(struct
> virtio_gpu_simple_resource *res)
> > pdata = res->iov[0].iov_base;
> > } else {
> > if (!virtio_gpu_create_udmabuf(res, &err1)) {
> > - error_report_err(err1);
> > - return;
> > + if (!virtio_gpu_create_vfio_dmabuf(res, &err2)) {
> > + error_report_err(err1);
> > + error_report_err(err2);
> > + return;
> > + }
> > }
> >
> > - if (!virtio_gpu_remap_dmabuf(res, &err1)) {
> > + if (!virtio_gpu_remap_dmabuf(res, &err1, &err2)) {
> > error_report_err(err1);
> > + error_report_err(err2);
> > return;
> > }
> > pdata = res->remapped;
> > @@ -162,9 +191,7 @@ void virtio_gpu_init_dmabuf(struct
> virtio_gpu_simple_resource *res)
> >
> > void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res)
> > {
> > - if (res->remapped) {
> > - virtio_gpu_destroy_dmabuf(res);
> > - }
> > + virtio_gpu_destroy_dmabuf(res);
> > }
> >
> > static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf
> *dmabuf)
© 2016 - 2026 Red Hat, Inc.