* [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu
@ 2026-10-07 20:09 Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device Vivek Kasireddy
` (8 more replies)
0 siblings, 9 replies; 36+ messages in thread
From: Vivek Kasireddy @ 2026-10-07 20:09 UTC (permalink / raw)
To: qemu-devel
Cc: Vivek Kasireddy, Marc-André Lureau, Alex Bennée,
Akihiko Odaki, Dmitry Osipenko, Alex Williamson,
Cédric Le Goater, Dongwon Kim
The virtio-gpu driver running in the Guest VM can create Guest blob
resources (by importing dmabufs) that are backed by System RAM. This
is made possible by making use of memfd memory backend and udmabuf
driver on the Host side. However, in order to create Guest blobs
that are backed by vfio-pci device regions (which happens when
virtio-gpu imports dmabufs from devices that have local memory such
as dGPU VFs), we have to add support for creating dmabuf from multiple
VFIO device ranges (same region) and leverage it in virtio-gpu.
So, while creating the blobs we first try to create a dmabuf by
calling into the udmabuf driver assuming that the backing memory
is memfd based. If that fails, and if it is determined that the blob
is backed by a vfio-pci device region, we would then call into the
vfio-pci driver to have a dmabuf fd created.
Changelog:
v12 -> v13:
- Drop the blob_size parameter and iov size check from
vfio_device_create_dmabuf_fd() and vfio_device_mmap_dmabuf()
(Akihiko, Cedric)
- Explain the rationale behind using VFIO error enums (Akihiko)
- Have vfio_get_region_from_mr() return VFIORegion * instead of
void * (Cedric)
- Fix the compilation error in vfio_device_create_dmabuf_fd() stub
by returning the correct error enum (Cedric)
- Drop the patch that recreated the dmabuf in
virtio_gpu_resource_attach_backing() as this is now merged
v11 -> v12:
- Collect R-b tags from Akihiko
- Rebase and test on top of Qemu master
- Have the helper return VFIO region instead of index (Cedric)
- Introduce a helper to retrieve VFIO region from a MR (Cedric)
- Document the helpers introduced in vfio/device.c (Cedric)
- Verify that the total size of IOV entries is equal to the size
of the dmabuf (Cedric)
v10 -> v11:
- Have virtio_gpu_remap_dmabuf() and vfio_device_mmap_dmabuf()
return the mapped pointer on success and NULL on error (Akihiko)
v9 -> v10:
- Adopt the logic structure and style recommended by Akihiko in
virtio_gpu_init_dmabuf() while creating and mmaping dmabuf
- Destroy the dmabuf by calling virtio_gpu_destroy_dmabuf() if
mmap fails
- Set res->dmabuf_fd to -1 after closing it to improve consistency
v8 -> v9:
- Replace VFIO_DMABUF_CREATE_GUEST_ERROR/VFIO_DMABUF_CREATE_HOST_ERROR
with VFIO_DMABUF_CREATE_ERR_INVALID_IOV/VFIO_DMABUF_CREATE_ERR_UNSPEC
(Akihiko)
- Drop the error_prepend() in virtio_gpu_init_dmabuf() (Akihiko)
- Improve the logic structure in virtio_gpu_init_dmabuf() by calling
the map memory function immediately after creating the dmabuf
in both memfd/udmabuf and VFIO cases (Akihiko)
v7 -> v8:
- Move the error enum to vfio and include only negative values (Akihiko)
- Reuse the same VFIO err enum to categorize Guest/Host errors in
virtio_gpu_create_udmabuf() (Akihiko)
- Make the error messages more descriptive and readable (Akihiko)
- Do not print any error messages on Guest triggered errors (Akihiko)
- Move the vfio dmabuf stubs file to hw/vfio directory (Akihiko)
- Make vfio_device_create_dmabuf() return an fd on success (Akihiko)
- Rename vfio_device_create_dmabuf to vfio_device_create_dmabuf_fd
since it now returns an fd on success
v6 -> v7:
- Introduce an enum to categorize Guest and Host errors (Akihiko)
- Drop the CONFIG_VIRTIO_GPU_VFIO_BLOB Kconfig option and add stubs
for VFIO dmabuf helpers when CONFIG_VFIO is not enabled (Akihiko)
- Check the correct return value of vfio_device_get_region_info()
in vfio_device_mmap_dmabuf()
v5 -> v6:
- Drop the additional error_setg() call in virtio_gpu_create_udmabuf()
and only have LOG_GUEST_ERROR for invalid ramblocks (Akihiko)
- Merge the patch that introduces vfio_device_lookup() helper with the
one that adds support for vfio_device_create_dmabuf() (Cedric)
- Use only one 'Error **' parameter instead of two while creating
and mmapping the dmabuf (Cedric)
- Collect R-b tags from Akihiko
v4 -> v5:
- Improve commit message for the patch that replaces dma_memory_map()
with virtio_gpu_dma_memory_map() (Akihiko)
- Create separate patches to remove rcu_read_lock/unlock and use
g_autofree for list pointer in virtio_gpu_create_udmabuf()
(Akihiko, Cedric)
- Create a separate patch to improve error handling (Cedric)
- Make vfio_device_lookup() a common helper local to vfio/device.c
(Cedric, Akihiko)
- Move the dmabuf mmap helper to vfio/device.c (Akihiko)
- Replace PROT_READ with PROT_NONE and vbasedev->fd with -1 while
creating the placeholder mapping in dmabuf mmap helper (Akihiko)
v3 -> v4:
- Drop the patch that introduces ram_block_is_memfd_backed()
- Drop the additional check in virtio_gpu_create_udmabuf() that
checks for memfd backed ram blocks (Akihiko)
- Remove rcu_read_lock/unlock and replace warn_report() with
qemu_log_mask() in virtio_gpu_create_udmabuf()
- Improve the commit message and logic in the patch that adds
support for vfio_device_create_dmabuf_fd()
- Rebase on top of vfio-next
v2 -> v3:
- Use memory_region_get_ram_ptr() to obtain hva for both memfd and
VFIO backed memory regions (Akihiko)
- Drop the patch that introduced qemu_iovec_same_memory_regions()
helper and move the "same memory region" check into
virtio_gpu_create_udmabuf(), vfio_device_create_dmabuf_fd() (Akihiko)
- Refactor virtio_gpu_init_dmabuf() to not rely on helpers such as
memory_region_is_ram_device() to identify memory regions and
instead call virtio_gpu_create_udmabuf() unconditionally (Akihiko)
- Add a patch to introduce ram_block_is_memfd_backed() helper
v1 -> v2:
- Drop the patch that uses res->blob_size instead of res->blob to
identify blob resources (Akihiko)
- Remove the res->dmabuf_fd < 0 check while attaching backing to a
resource (Akihiko)
- Remove cmd->cmd_hdr.type != VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB
check while attaching backing (Akihiko)
- Improve vfio_get_region_index_from_mr() and add documentation (Cedric)
- Remove rcu_read_lock/unlock around qemu_ram_block_from_host()
(Akihiko, Cedric)
- Improve, document and rename vfio_device_create_dmabuf() to
vfio_device_create_dmabuf_fd() (Cedric)
- Add a new helper to lookup VFIO device from memory region (Cedric)
- Document vfio_device_get_region_info() (Cedric)
- Ensure that info variable (in vfio_dmabuf_mmap()) is initialized
before use (Cedric)
- Rename udmabuf files and helpers to dmabuf (Akihiko)
- Remove the redundant check for virtio_gpu_have_udmabuf() in
virtio_gpu_init_dmabuf() (Akihiko)
- Add a helper to check whether all the entries of a dmabuf belong
to a single memory region or not (Akihiko)
RFC -> v1:
- Create the CPU mapping using vfio device fd if the dmabuf exporter
(vfio-pci) does not provide mmap() support (Akihiko)
- Log a warning with LOG_GUEST_ERROR instead of warn_report() when
dmabuf cannot be created using Guest provided addresses (Akihiko)
- Use address_space_translate() instead of gpa2hva() to obtain the
Host addresses (Akihiko)
- Rearrange the patches and improve the commit messages (Akihiko)
- Fix compilation error when VFIO is not enabled (Alex)
- Add a new helper to obtain VFIO region index from memory region
- Move vfio_device_create_dmabuf() to hw/vfio/device.c
Tested with an SRIOV enabled Intel dGPU (B60) by running Gnome Wayland
(in the VM) and Qemu with the following (relevant) parameters:
-device vfio-pci,host=0000:03:00.1
-device virtio-vga,max_outputs=1,xres=1920,yres=1080,blob=true
-display gtk,gl=on
Associated virtio-gpu kernel driver series (merged):
https://lore.kernel.org/dri-devel/20241126031643.3490496-1-vivek.kasireddy@intel.com/
---
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>
Cc: Dongwon Kim <dongwon.kim@intel.com>
Vivek Kasireddy (9):
virtio-gpu: Find hva for Guest's DMA addr associated with a ram device
virtio-gpu: Rename udmabuf files and helpers to dmabuf
virtio-gpu-dmabuf: Remove rcu_read_lock/unlock from
virtio_gpu_create_udmabuf()
virtio-gpu-dmabuf: Use g_autofree for the list pointer
vfio/region: Add a helper to get VFIO region from memory region
vfio/device: Add support for creating dmabuf from multiple ranges
vfio/device: Add a helper to mmap a dmabuf
virtio-gpu-dmabuf: Improve error handling with 'Error **' and err enum
virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO
devices
hw/vfio/vfio-region.h | 10 ++
include/hw/vfio/vfio-device.h | 37 ++++
include/hw/virtio/virtio-gpu.h | 6 +-
...abuf-stubs.c => virtio-gpu-dmabuf-stubs.c} | 4 +-
...rtio-gpu-udmabuf.c => virtio-gpu-dmabuf.c} | 96 ++++++----
hw/display/virtio-gpu.c | 29 +++-
hw/vfio/device.c | 164 ++++++++++++++++++
hw/vfio/dmabuf-stubs.c | 24 +++
hw/vfio/region.c | 11 ++
hw/display/meson.build | 4 +-
hw/vfio/meson.build | 1 +
11 files changed, 341 insertions(+), 45 deletions(-)
rename hw/display/{virtio-gpu-udmabuf-stubs.c => virtio-gpu-dmabuf-stubs.c} (79%)
rename hw/display/{virtio-gpu-udmabuf.c => virtio-gpu-dmabuf.c} (62%)
create mode 100644 hw/vfio/dmabuf-stubs.c
--
2.53.0
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device
2026-10-07 20:09 [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu Vivek Kasireddy
@ 2026-10-07 20:09 ` Vivek Kasireddy
2026-10-08 9:02 ` Akihiko Odaki
2026-10-07 20:09 ` [PATCH v13 2/9] virtio-gpu: Rename udmabuf files and helpers to dmabuf Vivek Kasireddy
` (7 subsequent siblings)
8 siblings, 1 reply; 36+ messages in thread
From: Vivek Kasireddy @ 2026-10-07 20:09 UTC (permalink / raw)
To: qemu-devel
Cc: Vivek Kasireddy, Marc-André Lureau, Alex Bennée,
Akihiko Odaki, Dmitry Osipenko, Alex Williamson,
Cédric Le Goater
If the Guest provides a DMA address that is associated with a ram
device (such as a VFIO PCI device region and not its system memory),
then we can obtain the hva (host virtual address) by invoking
address_space_translate() followed by memory_region_get_ram_ptr().
We cannot use dma_memory_map() because for memory regions that do
not support direct access, it would create bounce buffers instead
of returning the actual hva, which is not desirable here. And, since
VFIO device regions are not considered directly accessible (because
they are mostly MMIO based), virtio-gpu cannot invoke dma_memory_map()
to obtain the hva in this case.
Therefore, in order to handle addresses associated with VFIO devices,
we need to use the address_space_translate() API to first identify
the right memory region and the appropriate offset within that
region and then use memory_region_get_ram_ptr() to get the hva.
This approach also works for addresses associated with the system
memory region.
Note that, although we take an explicit reference on the memory
region, we would still rely on dma_memory_unmap() to drop that
reference when the dma mapping is eventually unmapped.
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>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/display/virtio-gpu.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index bb0f41bb1e..386db05e5b 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -948,6 +948,23 @@ static void virtio_gpu_set_scanout_blob(VirtIOGPU *g,
&fb, res, &ss.r, &cmd->error);
}
+static void *virtio_gpu_dma_memory_map(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd,
+ uint64_t a, hwaddr *len)
+{
+ MemoryRegion *mr;
+ hwaddr xlat;
+
+ mr = address_space_translate(VIRTIO_DEVICE(g)->dma_as, a, &xlat, len,
+ DMA_DIRECTION_TO_DEVICE,
+ MEMTXATTRS_UNSPECIFIED);
+ if (memory_region_is_ram(mr)) {
+ memory_region_ref(mr);
+ return memory_region_get_ram_ptr(mr) + xlat;
+ }
+ return NULL;
+}
+
int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
uint32_t nr_entries, uint32_t offset,
struct virtio_gpu_ctrl_command *cmd,
@@ -993,9 +1010,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
/* TODO: a common DMA map SG helper */
do {
len = l;
- map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, &len,
- DMA_DIRECTION_TO_DEVICE,
- MEMTXATTRS_UNSPECIFIED);
+ map = virtio_gpu_dma_memory_map(g, cmd, a, &len);
if (!map) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
" element %d\n", __func__, e);
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v13 2/9] virtio-gpu: Rename udmabuf files and helpers to dmabuf
2026-10-07 20:09 [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device Vivek Kasireddy
@ 2026-10-07 20:09 ` Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 3/9] virtio-gpu-dmabuf: Remove rcu_read_lock/unlock from virtio_gpu_create_udmabuf() Vivek Kasireddy
` (6 subsequent siblings)
8 siblings, 0 replies; 36+ messages in thread
From: Vivek Kasireddy @ 2026-10-07 20:09 UTC (permalink / raw)
To: qemu-devel
Cc: Vivek Kasireddy, Marc-André Lureau, Alex Bennée,
Akihiko Odaki, Dmitry Osipenko, Alex Williamson,
Cédric Le Goater
This is prep-work for adding the ability to create dmabuf fds from
VFIO devices in addition to udmabuf.
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>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
include/hw/virtio/virtio-gpu.h | 6 +++---
...o-gpu-udmabuf-stubs.c => virtio-gpu-dmabuf-stubs.c} | 4 ++--
.../{virtio-gpu-udmabuf.c => virtio-gpu-dmabuf.c} | 10 +++++-----
hw/display/virtio-gpu.c | 8 ++++----
hw/display/meson.build | 4 ++--
5 files changed, 16 insertions(+), 16 deletions(-)
rename hw/display/{virtio-gpu-udmabuf-stubs.c => virtio-gpu-dmabuf-stubs.c} (79%)
rename hw/display/{virtio-gpu-udmabuf.c => virtio-gpu-dmabuf.c} (94%)
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 631dfc63a4..4f3a5c6fb3 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -388,10 +388,10 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
struct virtio_gpu_set_scanout_blob *ss,
uint64_t blob_size);
-/* virtio-gpu-udmabuf.c */
+/* virtio-gpu-dmabuf.c */
bool virtio_gpu_have_udmabuf(void);
-bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
-void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res);
+bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res);
+void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res);
int virtio_gpu_update_dmabuf(VirtIOGPU *g,
uint32_t scanout_id,
struct virtio_gpu_simple_resource *res,
diff --git a/hw/display/virtio-gpu-udmabuf-stubs.c b/hw/display/virtio-gpu-dmabuf-stubs.c
similarity index 79%
rename from hw/display/virtio-gpu-udmabuf-stubs.c
rename to hw/display/virtio-gpu-dmabuf-stubs.c
index 1a9dfbdec1..83c3e16c23 100644
--- a/hw/display/virtio-gpu-udmabuf-stubs.c
+++ b/hw/display/virtio-gpu-dmabuf-stubs.c
@@ -7,13 +7,13 @@ bool virtio_gpu_have_udmabuf(void)
return false;
}
-bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
+bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
{
/* nothing (stub) */
return false;
}
-void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res)
+void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res)
{
/* nothing (stub) */
}
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-dmabuf.c
similarity index 94%
rename from hw/display/virtio-gpu-udmabuf.c
rename to hw/display/virtio-gpu-dmabuf.c
index 6d2bc8d977..c537ec0a8c 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-dmabuf.c
@@ -71,7 +71,7 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
g_free(list);
}
-static void virtio_gpu_remap_udmabuf(struct virtio_gpu_simple_resource *res)
+static void virtio_gpu_remap_dmabuf(struct virtio_gpu_simple_resource *res)
{
res->remapped = mmap(NULL, res->blob_size, PROT_READ,
MAP_SHARED, res->dmabuf_fd, 0);
@@ -82,7 +82,7 @@ static void virtio_gpu_remap_udmabuf(struct virtio_gpu_simple_resource *res)
}
}
-void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res)
+void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res)
{
if (res->remapped) {
munmap(res->remapped, res->blob_size);
@@ -133,7 +133,7 @@ bool virtio_gpu_have_udmabuf(void)
return memfd_backend;
}
-bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
+bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
{
void *pdata = NULL;
@@ -146,9 +146,9 @@ bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
if (res->dmabuf_fd < 0) {
return false;
}
- virtio_gpu_remap_udmabuf(res);
+ virtio_gpu_remap_dmabuf(res);
if (!res->remapped) {
- virtio_gpu_fini_udmabuf(res);
+ virtio_gpu_fini_dmabuf(res);
return false;
}
res->share_handle = res->dmabuf_fd;
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 386db05e5b..c7346c8c68 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -407,7 +407,7 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
return;
}
- if (!virtio_gpu_init_udmabuf(res)) {
+ if (!virtio_gpu_init_dmabuf(res)) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
virtio_gpu_cleanup_mapping(g, res);
g_free(res);
@@ -1091,7 +1091,7 @@ void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
res->addrs = NULL;
if (res->blob) {
- virtio_gpu_fini_udmabuf(res);
+ virtio_gpu_fini_dmabuf(res);
}
}
@@ -1136,7 +1136,7 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
return;
}
- if (!res->image && !virtio_gpu_init_udmabuf(res)) {
+ if (!res->image && !virtio_gpu_init_dmabuf(res)) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
virtio_gpu_cleanup_mapping(g, res);
}
@@ -1652,7 +1652,7 @@ static int virtio_gpu_blob_load(QEMUFile *f, void *opaque, size_t size,
return -EINVAL;
}
- if (!virtio_gpu_init_udmabuf(res)) {
+ if (!virtio_gpu_init_dmabuf(res)) {
virtio_gpu_cleanup_mapping(g, res);
g_free(res);
return -EINVAL;
diff --git a/hw/display/meson.build b/hw/display/meson.build
index d8b4e121fe..89b8f74b7d 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -73,9 +73,9 @@ if config_all_devices.has_key('CONFIG_VIRTIO_GPU')
virtio_gpu_ss.add(when: 'CONFIG_VIRTIO_GPU',
if_true: [files('virtio-gpu-base.c', 'virtio-gpu.c'), pixman])
if host_os == 'linux'
- virtio_gpu_ss.add(files('virtio-gpu-udmabuf.c'))
+ virtio_gpu_ss.add(files('virtio-gpu-dmabuf.c'))
else
- virtio_gpu_ss.add(files('virtio-gpu-udmabuf-stubs.c'))
+ virtio_gpu_ss.add(files('virtio-gpu-dmabuf-stubs.c'))
endif
virtio_gpu_ss.add(when: 'CONFIG_VHOST_USER_GPU', if_true: files('vhost-user-gpu.c'))
hw_display_modules += {'virtio-gpu': virtio_gpu_ss}
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v13 3/9] virtio-gpu-dmabuf: Remove rcu_read_lock/unlock from virtio_gpu_create_udmabuf()
2026-10-07 20:09 [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 2/9] virtio-gpu: Rename udmabuf files and helpers to dmabuf Vivek Kasireddy
@ 2026-10-07 20:09 ` Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 4/9] virtio-gpu-dmabuf: Use g_autofree for the list pointer Vivek Kasireddy
` (5 subsequent siblings)
8 siblings, 0 replies; 36+ messages in thread
From: Vivek Kasireddy @ 2026-10-07 20:09 UTC (permalink / raw)
To: qemu-devel
Cc: Vivek Kasireddy, Marc-André Lureau, Alex Bennée,
Akihiko Odaki, Dmitry Osipenko, Alex Williamson,
Cédric Le Goater
There is no need to wrap the call to qemu_ram_block_from_host() with
rcu_read_lock/unlock as we already hold a reference to the memory
region that owns the ram block. Note that, the reference was obtained
via dma_memory_map() while creating the mapping.
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>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/display/virtio-gpu-dmabuf.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
index c537ec0a8c..0ed8d9250e 100644
--- a/hw/display/virtio-gpu-dmabuf.c
+++ b/hw/display/virtio-gpu-dmabuf.c
@@ -46,10 +46,7 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
}
for (i = 0; i < res->iov_cnt; i++) {
- rcu_read_lock();
rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
- rcu_read_unlock();
-
if (!rb || rb->fd < 0) {
g_free(list);
return;
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v13 4/9] virtio-gpu-dmabuf: Use g_autofree for the list pointer
2026-10-07 20:09 [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu Vivek Kasireddy
` (2 preceding siblings ...)
2026-10-07 20:09 ` [PATCH v13 3/9] virtio-gpu-dmabuf: Remove rcu_read_lock/unlock from virtio_gpu_create_udmabuf() Vivek Kasireddy
@ 2026-10-07 20:09 ` Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 5/9] vfio/region: Add a helper to get VFIO region from memory region Vivek Kasireddy
` (4 subsequent siblings)
8 siblings, 0 replies; 36+ messages in thread
From: Vivek Kasireddy @ 2026-10-07 20:09 UTC (permalink / raw)
To: qemu-devel
Cc: Vivek Kasireddy, Marc-André Lureau, Alex Bennée,
Akihiko Odaki, Dmitry Osipenko, Alex Williamson,
Cédric Le Goater
Avoid the manual g_free() calls for the list pointer by using
g_autofree in virtio_gpu_create_udmabuf().
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>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/display/virtio-gpu-dmabuf.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
index 0ed8d9250e..6f05f367d0 100644
--- a/hw/display/virtio-gpu-dmabuf.c
+++ b/hw/display/virtio-gpu-dmabuf.c
@@ -29,7 +29,7 @@
static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
{
- struct udmabuf_create_list *list;
+ g_autofree struct udmabuf_create_list *list = NULL;
RAMBlock *rb;
ram_addr_t offset;
int udmabuf, i;
@@ -48,7 +48,6 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
for (i = 0; i < res->iov_cnt; i++) {
rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
if (!rb || rb->fd < 0) {
- g_free(list);
return;
}
@@ -65,7 +64,6 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
warn_report("%s: UDMABUF_CREATE_LIST: %s", __func__,
strerror(errno));
}
- g_free(list);
}
static void virtio_gpu_remap_dmabuf(struct virtio_gpu_simple_resource *res)
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v13 5/9] vfio/region: Add a helper to get VFIO region from memory region
2026-10-07 20:09 [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu Vivek Kasireddy
` (3 preceding siblings ...)
2026-10-07 20:09 ` [PATCH v13 4/9] virtio-gpu-dmabuf: Use g_autofree for the list pointer Vivek Kasireddy
@ 2026-10-07 20:09 ` Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges Vivek Kasireddy
` (3 subsequent siblings)
8 siblings, 0 replies; 36+ messages in thread
From: Vivek Kasireddy @ 2026-10-07 20:09 UTC (permalink / raw)
To: qemu-devel; +Cc: Vivek Kasireddy, Alex Williamson, Cédric Le Goater
Having a way to get the VFIO region associated with a memory region
is helpful in various scenarios. For example, this capability can
be useful in retrieving the region info such as index and offset
needed for mapping a part of a VFIO region or creating a dmabuf.
Cc: Alex Williamson <alex@shazbot.org>
Cc: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/vfio/vfio-region.h | 10 ++++++++++
hw/vfio/region.c | 11 +++++++++++
2 files changed, 21 insertions(+)
diff --git a/hw/vfio/vfio-region.h b/hw/vfio/vfio-region.h
index 58b236f113..004be67269 100644
--- a/hw/vfio/vfio-region.h
+++ b/hw/vfio/vfio-region.h
@@ -44,4 +44,14 @@ void vfio_region_mmaps_set_enabled(VFIORegion *region, bool enabled);
void vfio_region_exit(VFIORegion *region);
void vfio_region_finalize(VFIORegion *region);
+/**
+ * Return the VFIO region associated with a given MemoryRegion. This can
+ * be useful in retrieving region info such as index and offset.
+ *
+ * @mr: MemoryRegion to use
+ *
+ * Returns the region or NULL on error.
+ */
+VFIORegion *vfio_get_region_from_mr(MemoryRegion *mr);
+
#endif /* HW_VFIO_REGION_H */
diff --git a/hw/vfio/region.c b/hw/vfio/region.c
index 54ad11a6c8..37678aeb2d 100644
--- a/hw/vfio/region.c
+++ b/hw/vfio/region.c
@@ -528,3 +528,14 @@ void vfio_region_mmaps_set_enabled(VFIORegion *region, bool enabled)
trace_vfio_region_mmaps_set_enabled(memory_region_name(region->mem),
enabled);
}
+
+VFIORegion *vfio_get_region_from_mr(MemoryRegion *mr)
+{
+ while (mr->container) {
+ if (mr->ops == &vfio_region_ops) {
+ return mr->opaque;
+ }
+ mr = mr->container;
+ }
+ return NULL;
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-07 20:09 [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu Vivek Kasireddy
` (4 preceding siblings ...)
2026-10-07 20:09 ` [PATCH v13 5/9] vfio/region: Add a helper to get VFIO region from memory region Vivek Kasireddy
@ 2026-10-07 20:09 ` Vivek Kasireddy
2026-10-08 9:08 ` Akihiko Odaki
2026-10-09 8:13 ` Cédric Le Goater
2026-10-07 20:09 ` [PATCH v13 7/9] vfio/device: Add a helper to mmap a dmabuf Vivek Kasireddy
` (2 subsequent siblings)
8 siblings, 2 replies; 36+ messages in thread
From: Vivek Kasireddy @ 2026-10-07 20:09 UTC (permalink / raw)
To: qemu-devel; +Cc: Vivek Kasireddy, Alex Williamson, Cédric Le Goater
In order to create a dmabuf associated with a buffer that spans
multiple ranges, we first need to identify the VFIO region and
index the buffer (represented by iovec) belongs to and then
translate its addresses to offsets within that region.
The qemu_ram_block_from_host() API gives us both the region and
the offset info we need to populate the dma ranges so that we can
invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the dmabuf.
Also, instead of iterating over all QOM devices to find the
VFIODevice associated with a memory region, introduce a helper
to just use the vfio_device_list to lookup the VFIODevice.
And, introduce another helper to lookup the VFIO region given an
address.
Lastly, introduce an enum to return the type of error encountered
while creating the dmabuf fd.
Cc: Alex Williamson <alex@shazbot.org>
Cc: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
include/hw/vfio/vfio-device.h | 22 +++++++
hw/vfio/device.c | 109 ++++++++++++++++++++++++++++++++++
hw/vfio/dmabuf-stubs.c | 17 ++++++
hw/vfio/meson.build | 1 +
4 files changed, 149 insertions(+)
create mode 100644 hw/vfio/dmabuf-stubs.c
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index 8472420d3f..c05430be8a 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -41,6 +41,13 @@ enum {
VFIO_DEVICE_TYPE_AP = 3,
};
+enum {
+ /* The Guest passed addresses stored in IOV are invalid */
+ VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
+ /* Guest or Host may be at fault for this type of error */
+ VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
+};
+
typedef struct VFIODeviceOps VFIODeviceOps;
typedef struct VFIODeviceIOOps VFIODeviceIOOps;
typedef struct VFIOMigration VFIOMigration;
@@ -323,6 +330,21 @@ bool vfio_device_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_t
int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
struct vfio_irq_info *info);
+
+/**
+ * Create a dmabuf fd by first translating the addresses in the
+ * iovec array into VFIO region offsets and then invoking the
+ * VFIO_DEVICE_FEATURE_DMA_BUF feature.
+ *
+ * @iov: array of iovec entries associated with a buffer
+ * @iov_cnt: number of entries in the iovec array
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Returns the created dmabuf fd or either VFIO_DMABUF_CREATE_ERR_UNSPEC
+ * or VFIO_DMABUF_CREATE_ERR_INVALID_IOV on error.
+ */
+int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
+ Error **errp);
#endif
/* Returns 0 on success, or a negative errno. */
diff --git a/hw/vfio/device.c b/hw/vfio/device.c
index 4f11959633..d95503a5f1 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -21,7 +21,9 @@
#include "qemu/osdep.h"
#include <sys/ioctl.h>
+#include "system/ramblock.h"
#include "hw/vfio/vfio-device.h"
+#include "hw/vfio/vfio-region.h"
#include "hw/vfio/pci.h"
#include "hw/core/iommu.h"
#include "trace.h"
@@ -667,3 +669,110 @@ static VFIODeviceIOOps vfio_device_io_ops_ioctl = {
.region_read = vfio_device_io_region_read,
.region_write = vfio_device_io_region_write,
};
+
+/*
+ * This helper looks up the VFIODevice corresponding to the given iov. It
+ * can be useful to determinine if a buffer (represented by the iov) belongs
+ * to a VFIO device or not. This is mainly invoked when external components
+ * such as virtio-gpu request creation of dmabuf fds for buffers that may
+ * belong to a VFIO device.
+ */
+static bool vfio_device_lookup(struct iovec *iov, VFIODevice **vbasedevp,
+ RAMBlock **first_rbp, Error **errp)
+{
+ VFIODevice *vbasedev;
+ RAMBlock *first_rb;
+ ram_addr_t offset;
+
+ first_rb = qemu_ram_block_from_host(iov[0].iov_base, false, &offset);
+ if (!first_rb) {
+ error_setg(errp, "Could not find first ramblock\n");
+ return false;
+ }
+
+ *first_rbp = first_rb;
+ QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
+ if (vbasedev->dev == first_rb->mr->dev) {
+ *vbasedevp = vbasedev;
+ return true;
+ }
+ }
+ error_setg(errp, "No VFIO device found to create dmabuf from\n");
+ return false;
+}
+
+/*
+ * This helper looks up the VFIORegion corresponding to the given address.
+ * It also verifies that the RAMBlock associated with the address is the
+ * same as the first_rb passed in. This is to ensure that all addresses
+ * in the iov belong to the same region.
+ */
+static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
+ RAMBlock *first_rb, ram_addr_t *offsetp,
+ Error **errp)
+{
+ VFIORegion *region;
+ RAMBlock *rb;
+
+ rb = qemu_ram_block_from_host(addr, false, offsetp);
+ if (!rb || rb != first_rb) {
+ error_setg(errp, "Dmabuf segments must belong to the same region\n");
+ return false;
+ }
+
+ region = vfio_get_region_from_mr(rb->mr);
+ if (region) {
+ *regionp = region;
+ return true;
+ }
+ error_setg(errp, "Could not find valid region for dmabuf segment\n");
+ return false;
+}
+
+int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
+ Error **errp)
+{
+ g_autofree struct vfio_device_feature *feature = NULL;
+ struct vfio_device_feature_dma_buf *dma_buf;
+ RAMBlock *first_rb = NULL;
+ VFIODevice *vbasedev;
+ VFIORegion *region;
+ ram_addr_t offset;
+ size_t argsz;
+ int i, ret;
+
+ if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
+ return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ }
+
+ argsz = sizeof(*feature) + sizeof (*dma_buf) +
+ sizeof(struct vfio_region_dma_range) * iov_cnt;
+ feature = g_malloc0(argsz);
+ *feature = (struct vfio_device_feature) {
+ .argsz = argsz,
+ .flags = VFIO_DEVICE_FEATURE_GET | VFIO_DEVICE_FEATURE_DMA_BUF,
+ };
+ dma_buf = (struct vfio_device_feature_dma_buf *)feature->data;
+
+ for (i = 0; i < iov_cnt; i++) {
+ if (!vfio_region_lookup(iov[i].iov_base, ®ion,
+ first_rb, &offset, errp)) {
+ return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ }
+
+ dma_buf->region_index = region->nr;
+ dma_buf->dma_ranges[i].offset = offset;
+ dma_buf->dma_ranges[i].length = iov[i].iov_len;
+ }
+
+ dma_buf->nr_ranges = iov_cnt;
+ dma_buf->open_flags = O_RDONLY | O_CLOEXEC;
+
+ ret = vfio_device_get_feature(vbasedev, feature);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret,
+ "Could not create dmabuf fd via VFIO device");
+ return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ }
+ return ret;
+}
diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
new file mode 100644
index 0000000000..fb5318e929
--- /dev/null
+++ b/hw/vfio/dmabuf-stubs.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2026 Intel and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu/iov.h"
+#include "hw/vfio/vfio-device.h"
+
+int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
+ Error **errp)
+{
+ error_setg(errp, "VFIO dmabuf support is not enabled");
+ return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+}
diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build
index c7c31b78f6..aa6f4bc1b4 100644
--- a/hw/vfio/meson.build
+++ b/hw/vfio/meson.build
@@ -38,3 +38,4 @@ stub_ss.add(files('iommufd-stubs.c'))
system_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files(
'display.c',
))
+system_ss.add(when: 'CONFIG_VFIO', if_false: files('dmabuf-stubs.c'))
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v13 7/9] vfio/device: Add a helper to mmap a dmabuf
2026-10-07 20:09 [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu Vivek Kasireddy
` (5 preceding siblings ...)
2026-10-07 20:09 ` [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges Vivek Kasireddy
@ 2026-10-07 20:09 ` Vivek Kasireddy
2026-10-09 8:13 ` Cédric Le Goater
2026-10-07 20:09 ` [PATCH v13 8/9] virtio-gpu-dmabuf: Improve error handling with 'Error **' and err enum Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices Vivek Kasireddy
8 siblings, 1 reply; 36+ messages in thread
From: Vivek Kasireddy @ 2026-10-07 20:09 UTC (permalink / raw)
To: qemu-devel; +Cc: Vivek Kasireddy, Alex Williamson, Cédric Le Goater
In order to mmap a dmabuf, we first need to create a placeholder
mapping that would fit the entire size of the dmabuf. This mapping
would then be replaced with smaller mappings of individual dmabuf
segments.
Cc: Alex Williamson <alex@shazbot.org>
Cc: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
include/hw/vfio/vfio-device.h | 15 ++++++++++
hw/vfio/device.c | 55 +++++++++++++++++++++++++++++++++++
hw/vfio/dmabuf-stubs.c | 7 +++++
3 files changed, 77 insertions(+)
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index c05430be8a..4b8fb62056 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -345,6 +345,21 @@ int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
*/
int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
Error **errp);
+
+/**
+ * Mmap a dmabuf by first translating the addresses in the iovec
+ * array into VFIO region offsets and then creating a placeholder
+ * mapping that would be replaced later with mappings that
+ * correspond to the dmabuf segments.
+ *
+ * @iov: array of iovec entries associated with the dmabuf
+ * @iov_cnt: number of entries in the iovec array
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Returns the mapped pointer on success and NULL on error.
+ */
+void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
+ Error **errp);
#endif
/* Returns 0 on success, or a negative errno. */
diff --git a/hw/vfio/device.c b/hw/vfio/device.c
index d95503a5f1..5bc0443764 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -776,3 +776,58 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
}
return ret;
}
+
+void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
+ Error **errp)
+{
+ size_t total_size = iov_size(iov, iov_cnt);
+ struct vfio_region_info *info = NULL;
+ ram_addr_t offset, len = 0;
+ VFIODevice *vbasedev;
+ VFIORegion *region;
+ RAMBlock *first_rb;
+ void *map, *submap;
+ int i;
+
+ if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
+ return NULL;
+ }
+
+ /*
+ * We first reserve a contiguous chunk of address space for the entire
+ * dmabuf, then replace it with smaller mappings that correspond to the
+ * individual segments of the dmabuf.
+ */
+ map = mmap(NULL, total_size, PROT_NONE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ if (map == MAP_FAILED) {
+ error_setg_errno(errp, errno, "Could not reserve placeholder mapping");
+ return NULL;
+ }
+
+ for (i = 0; i < iov_cnt; i++) {
+ if (!vfio_region_lookup(iov[i].iov_base, ®ion,
+ first_rb, &offset, errp)) {
+ goto err;
+ }
+
+ if (vfio_device_get_region_info(vbasedev, region->nr, &info)) {
+ error_setg(errp, "Cannot find region info for dmabuf segment\n");
+ goto err;
+ }
+
+ submap = mmap(map + len, iov[i].iov_len, PROT_READ,
+ MAP_SHARED | MAP_FIXED, vbasedev->fd,
+ info->offset + offset);
+ if (submap == MAP_FAILED) {
+ error_setg_errno(errp, errno, "Could not mmap dmabuf segment\n");
+ goto err;
+ }
+ len += iov[i].iov_len;
+ }
+ return map;
+err:
+ munmap(map, total_size);
+ error_prepend(errp, "VFIO dmabuf mmap failed: ");
+ return NULL;
+}
+
diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
index fb5318e929..b9e03a162a 100644
--- a/hw/vfio/dmabuf-stubs.c
+++ b/hw/vfio/dmabuf-stubs.c
@@ -15,3 +15,10 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
error_setg(errp, "VFIO dmabuf support is not enabled");
return VFIO_DMABUF_CREATE_ERR_UNSPEC;
}
+
+void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
+ Error **errp)
+{
+ error_setg(errp, "VFIO mmap dmabuf support is not enabled");
+ return NULL;
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v13 8/9] virtio-gpu-dmabuf: Improve error handling with 'Error **' and err enum
2026-10-07 20:09 [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu Vivek Kasireddy
` (6 preceding siblings ...)
2026-10-07 20:09 ` [PATCH v13 7/9] vfio/device: Add a helper to mmap a dmabuf Vivek Kasireddy
@ 2026-10-07 20:09 ` Vivek Kasireddy
2026-10-09 8:17 ` Cédric Le Goater
2026-10-07 20:09 ` [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices Vivek Kasireddy
8 siblings, 1 reply; 36+ messages in thread
From: Vivek Kasireddy @ 2026-10-07 20:09 UTC (permalink / raw)
To: qemu-devel
Cc: Vivek Kasireddy, Marc-André Lureau, Alex Bennée,
Akihiko Odaki, Dmitry Osipenko, Alex Williamson,
Cédric Le Goater
Make the error handling more robust in virtio_gpu_init_udmabuf()
by introducing 'Error **' parameter to capture errors and using
an enum from VFIO to categorize different errors. This allows for
better error reporting and handling of errors from
virtio_gpu_create_udmabuf() and virtio_gpu_remap_dmabuf().
Furtheremore, the main reason for using the VFIO enum is to handle
the special INVALID_IOV case which can happen in two scenarios:
1) When the Blob resource's memory is backed by a VFIO region. This
would cause INVALID_IOV error when we try to create a dmabuf via
udmabuf driver but we can recover from this error by having the
dmabuf be created by the VFIO driver instead.
2) When the Blob resource's memory is not backed by memfd or VFIO
region. In this case, since the error can be attributed to the
guest, we should use qemu_log_mask() instead of error_report_err()
and emit a message that can be used to debug the guest error.
Note that, to diagnose errors, a common pattern is to return -errno
to enable the caller to implement specific error handling. However, in
this case, since we want to distinguish the INVALID_IOV error from other
errors, using the VFIO enum allows us to do so and is very convenient.
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>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/display/virtio-gpu-dmabuf.c | 69 ++++++++++++++++++++++------------
1 file changed, 46 insertions(+), 23 deletions(-)
diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
index 6f05f367d0..c9de8e9ba3 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,28 +28,32 @@
#include "standard-headers/linux/udmabuf.h"
#include "standard-headers/drm/drm_fourcc.h"
-static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
+static int virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res,
+ Error **errp)
{
g_autofree struct udmabuf_create_list *list = NULL;
RAMBlock *rb;
ram_addr_t offset;
- int udmabuf, i;
+ int udmabuf, i, fd;
udmabuf = udmabuf_fd();
if (udmabuf < 0) {
- return;
+ error_setg(errp, "udmabuf device not available or enabled");
+ return VFIO_DMABUF_CREATE_ERR_UNSPEC;
}
list = g_try_malloc0(sizeof(struct udmabuf_create_list) +
sizeof(struct udmabuf_create_item) * res->iov_cnt);
if (!list) {
- return;
+ error_setg(errp, "failed to allocate udmabuf create list");
+ return VFIO_DMABUF_CREATE_ERR_UNSPEC;
}
for (i = 0; i < res->iov_cnt; i++) {
rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
if (!rb || rb->fd < 0) {
- return;
+ error_setg(errp, "IOV memory address incompatible with udmabuf ");
+ return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
}
list->list[i].memfd = rb->fd;
@@ -59,22 +64,28 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
list->count = res->iov_cnt;
list->flags = UDMABUF_FLAGS_CLOEXEC;
- res->dmabuf_fd = ioctl(udmabuf, UDMABUF_CREATE_LIST, list);
- if (res->dmabuf_fd < 0) {
- warn_report("%s: UDMABUF_CREATE_LIST: %s", __func__,
- strerror(errno));
+ fd = ioctl(udmabuf, UDMABUF_CREATE_LIST, list);
+ if (fd < 0) {
+ error_setg_errno(errp, errno, "UDMABUF_CREATE_LIST: ioctl failed");
+ if (errno == EINVAL || errno == EBADFD) {
+ return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ }
+ return VFIO_DMABUF_CREATE_ERR_UNSPEC;
}
+ return fd;
}
-static void virtio_gpu_remap_dmabuf(struct virtio_gpu_simple_resource *res)
+static void *virtio_gpu_remap_dmabuf(struct virtio_gpu_simple_resource *res,
+ Error **errp)
{
- res->remapped = mmap(NULL, res->blob_size, PROT_READ,
- MAP_SHARED, res->dmabuf_fd, 0);
- if (res->remapped == MAP_FAILED) {
- warn_report("%s: dmabuf mmap failed: %s", __func__,
- strerror(errno));
- res->remapped = NULL;
+ void *map;
+
+ map = mmap(NULL, res->blob_size, PROT_READ, MAP_SHARED, res->dmabuf_fd, 0);
+ if (map == MAP_FAILED) {
+ error_setg_errno(errp, errno, "dmabuf mmap failed");
+ return NULL;
}
+ return map;
}
void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res)
@@ -130,6 +141,7 @@ bool virtio_gpu_have_udmabuf(void)
bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
{
+ Error *local_err = NULL;
void *pdata = NULL;
res->dmabuf_fd = -1;
@@ -137,17 +149,28 @@ bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
res->iov[0].iov_len < 4096) {
pdata = res->iov[0].iov_base;
} else if (res->blob_size) {
- virtio_gpu_create_udmabuf(res);
+ res->dmabuf_fd = virtio_gpu_create_udmabuf(res, &local_err);
+ if (res->dmabuf_fd == VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
+ error_free_or_abort(&local_err);
+
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Cannot create dmabuf: incompatible memory\n");
+ return false;
+ } else if (res->dmabuf_fd >= 0) {
+ pdata = virtio_gpu_remap_dmabuf(res, &local_err);
+ if (!pdata) {
+ virtio_gpu_fini_dmabuf(res);
+ }
+ } else {
+ res->dmabuf_fd = -1;
+ }
+
if (res->dmabuf_fd < 0) {
- return false;
- }
- virtio_gpu_remap_dmabuf(res);
- if (!res->remapped) {
- virtio_gpu_fini_dmabuf(res);
+ error_report_err(local_err);
return false;
}
res->share_handle = res->dmabuf_fd;
- pdata = res->remapped;
+ res->remapped = pdata;
}
res->blob = pdata;
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2026-10-07 20:09 [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu Vivek Kasireddy
` (7 preceding siblings ...)
2026-10-07 20:09 ` [PATCH v13 8/9] virtio-gpu-dmabuf: Improve error handling with 'Error **' and err enum Vivek Kasireddy
@ 2026-10-07 20:09 ` Vivek Kasireddy
2026-10-08 9:11 ` Akihiko Odaki
8 siblings, 1 reply; 36+ messages in thread
From: Vivek Kasireddy @ 2026-10-07 20:09 UTC (permalink / raw)
To: qemu-devel
Cc: Vivek Kasireddy, Marc-André Lureau, Alex Bennée,
Akihiko Odaki, Dmitry Osipenko, Alex Williamson,
Cédric Le Goater
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_fd() API which identifies the right
VFIO device and eventually creates a dmabuf fd.
Note that, for mmapping the dmabuf, we directly call mmap() if the
dmabuf fd was created via virtio_gpu_create_udmabuf() since we know
that the udmabuf driver supports mmap(). However, if the dmabuf was
created via vfio_device_create_dmabuf_fd(), we use the
vfio_device_mmap_dmabuf() API to get a mapping 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>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/display/virtio-gpu-dmabuf.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
index c9de8e9ba3..f59a5e76ff 100644
--- a/hw/display/virtio-gpu-dmabuf.c
+++ b/hw/display/virtio-gpu-dmabuf.c
@@ -153,9 +153,25 @@ bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
if (res->dmabuf_fd == VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
error_free_or_abort(&local_err);
- qemu_log_mask(LOG_GUEST_ERROR,
- "Cannot create dmabuf: incompatible memory\n");
- return false;
+ res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
+ res->iov_cnt,
+ &local_err);
+ if (res->dmabuf_fd == VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
+ error_free_or_abort(&local_err);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Cannot create dmabuf: incompatible memory\n");
+ return false;
+ }
+
+ if (res->dmabuf_fd >= 0) {
+ pdata = vfio_device_mmap_dmabuf(res->iov, res->iov_cnt,
+ &local_err);
+ if (!pdata) {
+ virtio_gpu_fini_dmabuf(res);
+ }
+ } else {
+ res->dmabuf_fd = -1;
+ }
} else if (res->dmabuf_fd >= 0) {
pdata = virtio_gpu_remap_dmabuf(res, &local_err);
if (!pdata) {
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device
2026-10-07 20:09 ` [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device Vivek Kasireddy
@ 2026-10-08 9:02 ` Akihiko Odaki
2026-10-09 4:32 ` Kasireddy, Vivek
0 siblings, 1 reply; 36+ messages in thread
From: Akihiko Odaki @ 2026-10-08 9:02 UTC (permalink / raw)
To: Vivek Kasireddy, qemu-devel
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
On 2026/10/08 5:09, Vivek Kasireddy wrote:
> If the Guest provides a DMA address that is associated with a ram
> device (such as a VFIO PCI device region and not its system memory),
> then we can obtain the hva (host virtual address) by invoking
> address_space_translate() followed by memory_region_get_ram_ptr().
>
> We cannot use dma_memory_map() because for memory regions that do
> not support direct access, it would create bounce buffers instead
> of returning the actual hva, which is not desirable here. And, since
> VFIO device regions are not considered directly accessible (because
> they are mostly MMIO based), virtio-gpu cannot invoke dma_memory_map()
> to obtain the hva in this case.
>
> Therefore, in order to handle addresses associated with VFIO devices,
> we need to use the address_space_translate() API to first identify
> the right memory region and the appropriate offset within that
> region and then use memory_region_get_ram_ptr() to get the hva.
> This approach also works for addresses associated with the system
> memory region.
>
> Note that, although we take an explicit reference on the memory
> region, we would still rely on dma_memory_unmap() to drop that
> reference when the dma mapping is eventually unmapped.
>
> 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>
> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> ---
> hw/display/virtio-gpu.c | 21 ++++++++++++++++++---
> 1 file changed, 18 insertions(+), 3 deletions(-)
>
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> index bb0f41bb1e..386db05e5b 100644
> --- a/hw/display/virtio-gpu.c
> +++ b/hw/display/virtio-gpu.c
> @@ -948,6 +948,23 @@ static void virtio_gpu_set_scanout_blob(VirtIOGPU *g,
> &fb, res, &ss.r, &cmd->error);
> }
>
> +static void *virtio_gpu_dma_memory_map(VirtIOGPU *g,
> + struct virtio_gpu_ctrl_command *cmd,
> + uint64_t a, hwaddr *len)
> +{
> + MemoryRegion *mr;
> + hwaddr xlat;
> +
> + mr = address_space_translate(VIRTIO_DEVICE(g)->dma_as, a, &xlat, len,
> + DMA_DIRECTION_TO_DEVICE,
> + MEMTXATTRS_UNSPECIFIED);
> + if (memory_region_is_ram(mr)) {
> + memory_region_ref(mr);
> + return memory_region_get_ram_ptr(mr) + xlat;
On rechecking this, I don't think it is safe with Xen.
memory_region_get_ram_ptr(mr) + xlat assumes a contiguous host mapping
of the entire region. Xen maps guest RAM on demand through its mapcache.
Here, memory_region_get_ram_ptr() obtains a mapping at offset zero
without pinning the cache entry, and adding xlat afterward does not
ensure that the requested range is mapped.
The MemoryRegion reference keeps the region alive, but does not prevent
the mapcache entry from being reused. Resource backing can therefore
receive an invalid or unpinned pointer.
I think we need to extend dma_memory_map() for this use case instead of
replacing it, preserving its mapping and unmapping semantics.
Regards,
Akihiko Odaki
> + }
> + return NULL;
> +}
> +
> int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
> uint32_t nr_entries, uint32_t offset,
> struct virtio_gpu_ctrl_command *cmd,
> @@ -993,9 +1010,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
> /* TODO: a common DMA map SG helper */
> do {
> len = l;
> - map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, &len,
> - DMA_DIRECTION_TO_DEVICE,
> - MEMTXATTRS_UNSPECIFIED);
> + map = virtio_gpu_dma_memory_map(g, cmd, a, &len);
> if (!map) {
> qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
> " element %d\n", __func__, e);
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-07 20:09 ` [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges Vivek Kasireddy
@ 2026-10-08 9:08 ` Akihiko Odaki
2026-10-09 4:24 ` Kasireddy, Vivek
2026-10-09 8:13 ` Cédric Le Goater
1 sibling, 1 reply; 36+ messages in thread
From: Akihiko Odaki @ 2026-10-08 9:08 UTC (permalink / raw)
To: Vivek Kasireddy, qemu-devel; +Cc: Alex Williamson, Cédric Le Goater
On 2026/10/08 5:09, Vivek Kasireddy wrote:
> In order to create a dmabuf associated with a buffer that spans
> multiple ranges, we first need to identify the VFIO region and
> index the buffer (represented by iovec) belongs to and then
> translate its addresses to offsets within that region.
>
> The qemu_ram_block_from_host() API gives us both the region and
> the offset info we need to populate the dma ranges so that we can
> invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the dmabuf.
>
> Also, instead of iterating over all QOM devices to find the
> VFIODevice associated with a memory region, introduce a helper
> to just use the vfio_device_list to lookup the VFIODevice.
> And, introduce another helper to lookup the VFIO region given an
> address.
>
> Lastly, introduce an enum to return the type of error encountered
> while creating the dmabuf fd.
>
> Cc: Alex Williamson <alex@shazbot.org>
> Cc: Cédric Le Goater <clg@redhat.com>
> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> ---
> include/hw/vfio/vfio-device.h | 22 +++++++
> hw/vfio/device.c | 109 ++++++++++++++++++++++++++++++++++
> hw/vfio/dmabuf-stubs.c | 17 ++++++
> hw/vfio/meson.build | 1 +
> 4 files changed, 149 insertions(+)
> create mode 100644 hw/vfio/dmabuf-stubs.c
>
> diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
> index 8472420d3f..c05430be8a 100644
> --- a/include/hw/vfio/vfio-device.h
> +++ b/include/hw/vfio/vfio-device.h
> @@ -41,6 +41,13 @@ enum {
> VFIO_DEVICE_TYPE_AP = 3,
> };
>
> +enum {
> + /* The Guest passed addresses stored in IOV are invalid */
> + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
> + /* Guest or Host may be at fault for this type of error */
> + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
> +};
> +
> typedef struct VFIODeviceOps VFIODeviceOps;
> typedef struct VFIODeviceIOOps VFIODeviceIOOps;
> typedef struct VFIOMigration VFIOMigration;
> @@ -323,6 +330,21 @@ bool vfio_device_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_t
>
> int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
> struct vfio_irq_info *info);
> +
> +/**
> + * Create a dmabuf fd by first translating the addresses in the
> + * iovec array into VFIO region offsets and then invoking the
> + * VFIO_DEVICE_FEATURE_DMA_BUF feature.
> + *
> + * @iov: array of iovec entries associated with a buffer
> + * @iov_cnt: number of entries in the iovec array
> + * @errp: pointer to Error*, to store an error if it happens.
> + *
> + * Returns the created dmabuf fd or either VFIO_DMABUF_CREATE_ERR_UNSPEC
> + * or VFIO_DMABUF_CREATE_ERR_INVALID_IOV on error.
> + */
> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
> + Error **errp);
> #endif
>
> /* Returns 0 on success, or a negative errno. */
> diff --git a/hw/vfio/device.c b/hw/vfio/device.c
> index 4f11959633..d95503a5f1 100644
> --- a/hw/vfio/device.c
> +++ b/hw/vfio/device.c
> @@ -21,7 +21,9 @@
> #include "qemu/osdep.h"
> #include <sys/ioctl.h>
>
> +#include "system/ramblock.h"
> #include "hw/vfio/vfio-device.h"
> +#include "hw/vfio/vfio-region.h"
> #include "hw/vfio/pci.h"
> #include "hw/core/iommu.h"
> #include "trace.h"
> @@ -667,3 +669,110 @@ static VFIODeviceIOOps vfio_device_io_ops_ioctl = {
> .region_read = vfio_device_io_region_read,
> .region_write = vfio_device_io_region_write,
> };
> +
> +/*
> + * This helper looks up the VFIODevice corresponding to the given iov. It
> + * can be useful to determinine if a buffer (represented by the iov) belongs
> + * to a VFIO device or not. This is mainly invoked when external components
> + * such as virtio-gpu request creation of dmabuf fds for buffers that may
> + * belong to a VFIO device.
> + */
> +static bool vfio_device_lookup(struct iovec *iov, VFIODevice **vbasedevp,
> + RAMBlock **first_rbp, Error **errp)
> +{
> + VFIODevice *vbasedev;
> + RAMBlock *first_rb;
> + ram_addr_t offset;
> +
> + first_rb = qemu_ram_block_from_host(iov[0].iov_base, false, &offset);
> + if (!first_rb) {
> + error_setg(errp, "Could not find first ramblock\n");
> + return false;
> + }
> +
> + *first_rbp = first_rb;
> + QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
This traverses vfio_device_list using next. next belongs to the legacy
IOMMU-group list. With devices in separate groups, or multiple devices
using iommufd, buffers belonging to devices beyond the global head are
missed and DMA-BUF creation fails. Please use global_next.
> + if (vbasedev->dev == first_rb->mr->dev) {
> + *vbasedevp = vbasedev;
> + return true;
> + }
> + }
> + error_setg(errp, "No VFIO device found to create dmabuf from\n");
> + return false;
> +}
> +
> +/*
> + * This helper looks up the VFIORegion corresponding to the given address.
> + * It also verifies that the RAMBlock associated with the address is the
> + * same as the first_rb passed in. This is to ensure that all addresses
> + * in the iov belong to the same region.
> + */
> +static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
> + RAMBlock *first_rb, ram_addr_t *offsetp,
> + Error **errp)
> +{
> + VFIORegion *region;
> + RAMBlock *rb;
> +
> + rb = qemu_ram_block_from_host(addr, false, offsetp);
> + if (!rb || rb != first_rb) {
> + error_setg(errp, "Dmabuf segments must belong to the same region\n");
> + return false;
> + }
> +
> + region = vfio_get_region_from_mr(rb->mr);
> + if (region) {
> + *regionp = region;
> + return true;
> + }
> + error_setg(errp, "Could not find valid region for dmabuf segment\n");
> + return false;
> +}
> +
> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
> + Error **errp)
> +{
> + g_autofree struct vfio_device_feature *feature = NULL;
> + struct vfio_device_feature_dma_buf *dma_buf;
> + RAMBlock *first_rb = NULL;
> + VFIODevice *vbasedev;
> + VFIORegion *region;
> + ram_addr_t offset;
> + size_t argsz;
> + int i, ret;
> +
> + if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
> + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
> + }
> +
> + argsz = sizeof(*feature) + sizeof (*dma_buf) +
> + sizeof(struct vfio_region_dma_range) * iov_cnt;
> + feature = g_malloc0(argsz);
> + *feature = (struct vfio_device_feature) {
> + .argsz = argsz,
> + .flags = VFIO_DEVICE_FEATURE_GET | VFIO_DEVICE_FEATURE_DMA_BUF,
> + };
> + dma_buf = (struct vfio_device_feature_dma_buf *)feature->data;
> +
> + for (i = 0; i < iov_cnt; i++) {
> + if (!vfio_region_lookup(iov[i].iov_base, ®ion,
> + first_rb, &offset, errp)) {
> + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
> + }
> +
> + dma_buf->region_index = region->nr;
> + dma_buf->dma_ranges[i].offset = offset;
> + dma_buf->dma_ranges[i].length = iov[i].iov_len;
> + }
> +
> + dma_buf->nr_ranges = iov_cnt;
> + dma_buf->open_flags = O_RDONLY | O_CLOEXEC;
> +
> + ret = vfio_device_get_feature(vbasedev, feature);
> + if (ret < 0) {
> + error_setg_errno(errp, -ret,
> + "Could not create dmabuf fd via VFIO device");
> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
> + }
> + return ret;
> +}
> diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
> new file mode 100644
> index 0000000000..fb5318e929
> --- /dev/null
> +++ b/hw/vfio/dmabuf-stubs.c
> @@ -0,0 +1,17 @@
> +/*
> + * Copyright (c) 2026 Intel and/or its affiliates.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/error-report.h"
> +#include "qemu/iov.h"
> +#include "hw/vfio/vfio-device.h"
> +
> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
> + Error **errp)
> +{
> + error_setg(errp, "VFIO dmabuf support is not enabled");
> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
> +}
The new stub builds when VFIO is disabled, but its declaration is inside
#ifdef CONFIG_LINUX. Consequently, -Wmissing-prototypes fails builds
such as macOS CI.
Regards,
Akihiko Odaki
> diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build
> index c7c31b78f6..aa6f4bc1b4 100644
> --- a/hw/vfio/meson.build
> +++ b/hw/vfio/meson.build
> @@ -38,3 +38,4 @@ stub_ss.add(files('iommufd-stubs.c'))
> system_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files(
> 'display.c',
> ))
> +system_ss.add(when: 'CONFIG_VFIO', if_false: files('dmabuf-stubs.c'))
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2026-10-07 20:09 ` [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices Vivek Kasireddy
@ 2026-10-08 9:11 ` Akihiko Odaki
2026-10-09 4:26 ` Kasireddy, Vivek
0 siblings, 1 reply; 36+ messages in thread
From: Akihiko Odaki @ 2026-10-08 9:11 UTC (permalink / raw)
To: Vivek Kasireddy, qemu-devel
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
On 2026/10/08 5:09, 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_fd() API which identifies the right
> VFIO device and eventually creates a dmabuf fd.
>
> Note that, for mmapping the dmabuf, we directly call mmap() if the
> dmabuf fd was created via virtio_gpu_create_udmabuf() since we know
> that the udmabuf driver supports mmap(). However, if the dmabuf was
> created via vfio_device_create_dmabuf_fd(), we use the
> vfio_device_mmap_dmabuf() API to get a mapping 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>
> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> ---
> hw/display/virtio-gpu-dmabuf.c | 22 +++++++++++++++++++---
> 1 file changed, 19 insertions(+), 3 deletions(-)
>
> diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
> index c9de8e9ba3..f59a5e76ff 100644
> --- a/hw/display/virtio-gpu-dmabuf.c
> +++ b/hw/display/virtio-gpu-dmabuf.c
> @@ -153,9 +153,25 @@ bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
> if (res->dmabuf_fd == VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
> error_free_or_abort(&local_err);
>
> - qemu_log_mask(LOG_GUEST_ERROR,
> - "Cannot create dmabuf: incompatible memory\n");
> - return false;
> + res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
> + res->iov_cnt,
> + &local_err);
> + if (res->dmabuf_fd == VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
> + error_free_or_abort(&local_err);
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "Cannot create dmabuf: incompatible memory\n");
> + return false;
> + }
> +
> + if (res->dmabuf_fd >= 0) {
> + pdata = vfio_device_mmap_dmabuf(res->iov, res->iov_cnt,
> + &local_err);
This maps the complete IOV size, while virtio_gpu_fini_dmabuf() unmaps
only blob_size. Create and attach accept backing larger than the blob,
so excess pages remain mapped after detach, unref or reset.
Regards,
Akihiko Odaki
> + if (!pdata) {
> + virtio_gpu_fini_dmabuf(res);
> + }
> + } else {
> + res->dmabuf_fd = -1;
> + }
> } else if (res->dmabuf_fd >= 0) {
> pdata = virtio_gpu_remap_dmabuf(res, &local_err);
> if (!pdata) {
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-08 9:08 ` Akihiko Odaki
@ 2026-10-09 4:24 ` Kasireddy, Vivek
0 siblings, 0 replies; 36+ messages in thread
From: Kasireddy, Vivek @ 2026-10-09 4:24 UTC (permalink / raw)
To: Akihiko Odaki, qemu-devel@nongnu.org
Cc: Alex Williamson, Cédric Le Goater
Hi Akihiko,
> Subject: Re: [PATCH v13 6/9] vfio/device: Add support for creating
> dmabuf from multiple ranges
>
> On 2026/10/08 5:09, Vivek Kasireddy wrote:
> > In order to create a dmabuf associated with a buffer that spans
> > multiple ranges, we first need to identify the VFIO region and
> > index the buffer (represented by iovec) belongs to and then
> > translate its addresses to offsets within that region.
> >
> > The qemu_ram_block_from_host() API gives us both the region and
> > the offset info we need to populate the dma ranges so that we can
> > invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the
> dmabuf.
> >
> > Also, instead of iterating over all QOM devices to find the
> > VFIODevice associated with a memory region, introduce a helper
> > to just use the vfio_device_list to lookup the VFIODevice.
> > And, introduce another helper to lookup the VFIO region given an
> > address.
> >
> > Lastly, introduce an enum to return the type of error encountered
> > while creating the dmabuf fd.
> >
> > Cc: Alex Williamson <alex@shazbot.org>
> > Cc: Cédric Le Goater <clg@redhat.com>
> > Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> > ---
> > include/hw/vfio/vfio-device.h | 22 +++++++
> > hw/vfio/device.c | 109
> ++++++++++++++++++++++++++++++++++
> > hw/vfio/dmabuf-stubs.c | 17 ++++++
> > hw/vfio/meson.build | 1 +
> > 4 files changed, 149 insertions(+)
> > create mode 100644 hw/vfio/dmabuf-stubs.c
> >
> > diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-
> device.h
> > index 8472420d3f..c05430be8a 100644
> > --- a/include/hw/vfio/vfio-device.h
> > +++ b/include/hw/vfio/vfio-device.h
> > @@ -41,6 +41,13 @@ enum {
> > VFIO_DEVICE_TYPE_AP = 3,
> > };
> >
> > +enum {
> > + /* The Guest passed addresses stored in IOV are invalid */
> > + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
> > + /* Guest or Host may be at fault for this type of error */
> > + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
> > +};
> > +
> > typedef struct VFIODeviceOps VFIODeviceOps;
> > typedef struct VFIODeviceIOOps VFIODeviceIOOps;
> > typedef struct VFIOMigration VFIOMigration;
> > @@ -323,6 +330,21 @@ bool vfio_device_has_region_cap(VFIODevice
> *vbasedev, int region, uint16_t cap_t
> >
> > int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
> > struct vfio_irq_info *info);
> > +
> > +/**
> > + * Create a dmabuf fd by first translating the addresses in the
> > + * iovec array into VFIO region offsets and then invoking the
> > + * VFIO_DEVICE_FEATURE_DMA_BUF feature.
> > + *
> > + * @iov: array of iovec entries associated with a buffer
> > + * @iov_cnt: number of entries in the iovec array
> > + * @errp: pointer to Error*, to store an error if it happens.
> > + *
> > + * Returns the created dmabuf fd or either
> VFIO_DMABUF_CREATE_ERR_UNSPEC
> > + * or VFIO_DMABUF_CREATE_ERR_INVALID_IOV on error.
> > + */
> > +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
> iov_cnt,
> > + Error **errp);
> > #endif
> >
> > /* Returns 0 on success, or a negative errno. */
> > diff --git a/hw/vfio/device.c b/hw/vfio/device.c
> > index 4f11959633..d95503a5f1 100644
> > --- a/hw/vfio/device.c
> > +++ b/hw/vfio/device.c
> > @@ -21,7 +21,9 @@
> > #include "qemu/osdep.h"
> > #include <sys/ioctl.h>
> >
> > +#include "system/ramblock.h"
> > #include "hw/vfio/vfio-device.h"
> > +#include "hw/vfio/vfio-region.h"
> > #include "hw/vfio/pci.h"
> > #include "hw/core/iommu.h"
> > #include "trace.h"
> > @@ -667,3 +669,110 @@ static VFIODeviceIOOps
> vfio_device_io_ops_ioctl = {
> > .region_read = vfio_device_io_region_read,
> > .region_write = vfio_device_io_region_write,
> > };
> > +
> > +/*
> > + * This helper looks up the VFIODevice corresponding to the given
> iov. It
> > + * can be useful to determinine if a buffer (represented by the iov)
> belongs
> > + * to a VFIO device or not. This is mainly invoked when external
> components
> > + * such as virtio-gpu request creation of dmabuf fds for buffers that
> may
> > + * belong to a VFIO device.
> > + */
> > +static bool vfio_device_lookup(struct iovec *iov, VFIODevice
> **vbasedevp,
> > + RAMBlock **first_rbp, Error **errp)
> > +{
> > + VFIODevice *vbasedev;
> > + RAMBlock *first_rb;
> > + ram_addr_t offset;
> > +
> > + first_rb = qemu_ram_block_from_host(iov[0].iov_base, false,
> &offset);
> > + if (!first_rb) {
> > + error_setg(errp, "Could not find first ramblock\n");
> > + return false;
> > + }
> > +
> > + *first_rbp = first_rb;
> > + QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
>
> This traverses vfio_device_list using next. next belongs to the legacy
> IOMMU-group list. With devices in separate groups, or multiple devices
> using iommufd, buffers belonging to devices beyond the global head are
> missed and DMA-BUF creation fails. Please use global_next.
Ok, will replace next with global_next.
>
> > + if (vbasedev->dev == first_rb->mr->dev) {
> > + *vbasedevp = vbasedev;
> > + return true;
> > + }
> > + }
> > + error_setg(errp, "No VFIO device found to create dmabuf from\n");
> > + return false;
> > +}
> > +
> > +/*
> > + * This helper looks up the VFIORegion corresponding to the given
> address.
> > + * It also verifies that the RAMBlock associated with the address is
> the
> > + * same as the first_rb passed in. This is to ensure that all addresses
> > + * in the iov belong to the same region.
> > + */
> > +static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
> > + RAMBlock *first_rb, ram_addr_t *offsetp,
> > + Error **errp)
> > +{
> > + VFIORegion *region;
> > + RAMBlock *rb;
> > +
> > + rb = qemu_ram_block_from_host(addr, false, offsetp);
> > + if (!rb || rb != first_rb) {
> > + error_setg(errp, "Dmabuf segments must belong to the same
> region\n");
> > + return false;
> > + }
> > +
> > + region = vfio_get_region_from_mr(rb->mr);
> > + if (region) {
> > + *regionp = region;
> > + return true;
> > + }
> > + error_setg(errp, "Could not find valid region for dmabuf
> segment\n");
> > + return false;
> > +}
> > +
> > +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
> iov_cnt,
> > + Error **errp)
> > +{
> > + g_autofree struct vfio_device_feature *feature = NULL;
> > + struct vfio_device_feature_dma_buf *dma_buf;
> > + RAMBlock *first_rb = NULL;
> > + VFIODevice *vbasedev;
> > + VFIORegion *region;
> > + ram_addr_t offset;
> > + size_t argsz;
> > + int i, ret;
> > +
> > + if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
> > + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
> > + }
> > +
> > + argsz = sizeof(*feature) + sizeof (*dma_buf) +
> > + sizeof(struct vfio_region_dma_range) * iov_cnt;
> > + feature = g_malloc0(argsz);
> > + *feature = (struct vfio_device_feature) {
> > + .argsz = argsz,
> > + .flags = VFIO_DEVICE_FEATURE_GET |
> VFIO_DEVICE_FEATURE_DMA_BUF,
> > + };
> > + dma_buf = (struct vfio_device_feature_dma_buf *)feature->data;
> > +
> > + for (i = 0; i < iov_cnt; i++) {
> > + if (!vfio_region_lookup(iov[i].iov_base, ®ion,
> > + first_rb, &offset, errp)) {
> > + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
> > + }
> > +
> > + dma_buf->region_index = region->nr;
> > + dma_buf->dma_ranges[i].offset = offset;
> > + dma_buf->dma_ranges[i].length = iov[i].iov_len;
> > + }
> > +
> > + dma_buf->nr_ranges = iov_cnt;
> > + dma_buf->open_flags = O_RDONLY | O_CLOEXEC;
> > +
> > + ret = vfio_device_get_feature(vbasedev, feature);
> > + if (ret < 0) {
> > + error_setg_errno(errp, -ret,
> > + "Could not create dmabuf fd via VFIO device");
> > + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
> > + }
> > + return ret;
> > +}
> > diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
> > new file mode 100644
> > index 0000000000..fb5318e929
> > --- /dev/null
> > +++ b/hw/vfio/dmabuf-stubs.c
> > @@ -0,0 +1,17 @@
> > +/*
> > + * Copyright (c) 2026 Intel and/or its affiliates.
> > + *
> > + * SPDX-License-Identifier: GPL-2.0-or-later
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qemu/error-report.h"
> > +#include "qemu/iov.h"
> > +#include "hw/vfio/vfio-device.h"
> > +
> > +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
> iov_cnt,
> > + Error **errp)
> > +{
> > + error_setg(errp, "VFIO dmabuf support is not enabled");
> > + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
> > +}
>
> The new stub builds when VFIO is disabled, but its declaration is inside
> #ifdef CONFIG_LINUX. Consequently, -Wmissing-prototypes fails builds
> such as macOS CI.
Thanks for checking non-linux builds. I guess I'll need to move the declaration
out of the #ifdef CONFIG_LINUX block in vfio-device.h to fix this issue.
Thanks,
Vivek
>
> Regards,
> Akihiko Odaki
>
> > diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build
> > index c7c31b78f6..aa6f4bc1b4 100644
> > --- a/hw/vfio/meson.build
> > +++ b/hw/vfio/meson.build
> > @@ -38,3 +38,4 @@ stub_ss.add(files('iommufd-stubs.c'))
> > system_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files(
> > 'display.c',
> > ))
> > +system_ss.add(when: 'CONFIG_VFIO', if_false: files('dmabuf-stubs.c'))
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2026-10-08 9:11 ` Akihiko Odaki
@ 2026-10-09 4:26 ` Kasireddy, Vivek
2026-10-09 9:51 ` Akihiko Odaki
0 siblings, 1 reply; 36+ messages in thread
From: Kasireddy, Vivek @ 2026-10-09 4:26 UTC (permalink / raw)
To: Akihiko Odaki, qemu-devel@nongnu.org
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
Hi Akihiko,
> Subject: Re: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for
> blobs associated with VFIO devices
>
> On 2026/10/08 5:09, 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_fd() API which identifies the right
> > VFIO device and eventually creates a dmabuf fd.
> >
> > Note that, for mmapping the dmabuf, we directly call mmap() if the
> > dmabuf fd was created via virtio_gpu_create_udmabuf() since we
> know
> > that the udmabuf driver supports mmap(). However, if the dmabuf
> was
> > created via vfio_device_create_dmabuf_fd(), we use the
> > vfio_device_mmap_dmabuf() API to get a mapping 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>
> > Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> > Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> > ---
> > hw/display/virtio-gpu-dmabuf.c | 22 +++++++++++++++++++---
> > 1 file changed, 19 insertions(+), 3 deletions(-)
> >
> > diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-
> dmabuf.c
> > index c9de8e9ba3..f59a5e76ff 100644
> > --- a/hw/display/virtio-gpu-dmabuf.c
> > +++ b/hw/display/virtio-gpu-dmabuf.c
> > @@ -153,9 +153,25 @@ bool virtio_gpu_init_dmabuf(struct
> virtio_gpu_simple_resource *res)
> > if (res->dmabuf_fd ==
> VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
> > error_free_or_abort(&local_err);
> >
> > - qemu_log_mask(LOG_GUEST_ERROR,
> > - "Cannot create dmabuf: incompatible memory\n");
> > - return false;
> > + res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
> > + res->iov_cnt,
> > + &local_err);
> > + if (res->dmabuf_fd ==
> VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
> > + error_free_or_abort(&local_err);
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "Cannot create dmabuf: incompatible memory\n");
> > + return false;
> > + }
> > +
> > + if (res->dmabuf_fd >= 0) {
> > + pdata = vfio_device_mmap_dmabuf(res->iov, res->iov_cnt,
> > + &local_err);
>
> This maps the complete IOV size, while virtio_gpu_fini_dmabuf()
> unmaps
> only blob_size. Create and attach accept backing larger than the blob,
> so excess pages remain mapped after detach, unref or reset.
Good catch. I'll add a check in virtio_gpu_fini_dmabuf() to determine if
IOV size > blob_size, then do munmap(res->remapped, IOV size);
I think this should be safe even if the mapping (created with mmap)
size is blob_size. Or, is there a better solution you can think of such as
tracking the exact mapping size in res object?
Thanks,
Vivek
>
> Regards,
> Akihiko Odaki
>
> > + if (!pdata) {
> > + virtio_gpu_fini_dmabuf(res);
> > + }
> > + } else {
> > + res->dmabuf_fd = -1;
> > + }
> > } else if (res->dmabuf_fd >= 0) {
> > pdata = virtio_gpu_remap_dmabuf(res, &local_err);
> > if (!pdata) {
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device
2026-10-08 9:02 ` Akihiko Odaki
@ 2026-10-09 4:32 ` Kasireddy, Vivek
2026-10-09 9:26 ` Akihiko Odaki
0 siblings, 1 reply; 36+ messages in thread
From: Kasireddy, Vivek @ 2026-10-09 4:32 UTC (permalink / raw)
To: Akihiko Odaki, qemu-devel@nongnu.org
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
Hi Akihiko,
> Subject: Re: [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr
> associated with a ram device
>
> On 2026/10/08 5:09, Vivek Kasireddy wrote:
> > If the Guest provides a DMA address that is associated with a ram
> > device (such as a VFIO PCI device region and not its system memory),
> > then we can obtain the hva (host virtual address) by invoking
> > address_space_translate() followed by memory_region_get_ram_ptr().
> >
> > We cannot use dma_memory_map() because for memory regions that
> do
> > not support direct access, it would create bounce buffers instead
> > of returning the actual hva, which is not desirable here. And, since
> > VFIO device regions are not considered directly accessible (because
> > they are mostly MMIO based), virtio-gpu cannot invoke
> dma_memory_map()
> > to obtain the hva in this case.
> >
> > Therefore, in order to handle addresses associated with VFIO devices,
> > we need to use the address_space_translate() API to first identify
> > the right memory region and the appropriate offset within that
> > region and then use memory_region_get_ram_ptr() to get the hva.
> > This approach also works for addresses associated with the system
> > memory region.
> >
> > Note that, although we take an explicit reference on the memory
> > region, we would still rely on dma_memory_unmap() to drop that
> > reference when the dma mapping is eventually unmapped.
> >
> > 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>
> > Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> > Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> > ---
> > hw/display/virtio-gpu.c | 21 ++++++++++++++++++---
> > 1 file changed, 18 insertions(+), 3 deletions(-)
> >
> > diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> > index bb0f41bb1e..386db05e5b 100644
> > --- a/hw/display/virtio-gpu.c
> > +++ b/hw/display/virtio-gpu.c
> > @@ -948,6 +948,23 @@ static void
> virtio_gpu_set_scanout_blob(VirtIOGPU *g,
> > &fb, res, &ss.r, &cmd->error);
> > }
> >
> > +static void *virtio_gpu_dma_memory_map(VirtIOGPU *g,
> > + struct virtio_gpu_ctrl_command *cmd,
> > + uint64_t a, hwaddr *len)
> > +{
> > + MemoryRegion *mr;
> > + hwaddr xlat;
> > +
> > + mr = address_space_translate(VIRTIO_DEVICE(g)->dma_as, a,
> &xlat, len,
> > + DMA_DIRECTION_TO_DEVICE,
> > + MEMTXATTRS_UNSPECIFIED);
> > + if (memory_region_is_ram(mr)) {
> > + memory_region_ref(mr);
> > + return memory_region_get_ram_ptr(mr) + xlat;
>
> On rechecking this, I don't think it is safe with Xen.
>
> memory_region_get_ram_ptr(mr) + xlat assumes a contiguous host
> mapping
> of the entire region. Xen maps guest RAM on demand through its
> mapcache.
> Here, memory_region_get_ram_ptr() obtains a mapping at offset zero
> without pinning the cache entry, and adding xlat afterward does not
> ensure that the requested range is mapped.
>
> The MemoryRegion reference keeps the region alive, but does not
> prevent
> the mapcache entry from being reused. Resource backing can therefore
> receive an invalid or unpinned pointer.
>
> I think we need to extend dma_memory_map() for this use case instead
> of
> replacing it, preserving its mapping and unmapping semantics.
I am not sure if extending dma_memory_map() might be a better/cleaner
solution for this use-case. If obtaining the hva/host ptr via
memory_region_get_ram_ptr(mr) + xlat for guest RAM is not safe with
Xen, then would it not make more sense to go back to using dma_memory_map()
for Guest RAM and memory_region_get_ram_ptr(mr) + xlat for VFIO
backed regions? That is, doing the following:
static void *virtio_gpu_dma_memory_map(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd,
uint64_t a, hwaddr *len)
{
MemoryRegion *mr = NULL;
hwaddr xlat;
mr = address_space_translate(VIRTIO_DEVICE(g)->dma_as, a, &xlat, len,
DMA_DIRECTION_TO_DEVICE,
MEMTXATTRS_UNSPECIFIED);
if (memory_region_is_ram_device(mr)) {
memory_region_ref(mr);
return memory_region_get_ram_ptr(mr) + xlat;
}
return dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, len,
DMA_DIRECTION_TO_DEVICE,
MEMTXATTRS_UNSPECIFIED);
}
Thanks,
Vivek
>
> Regards,
> Akihiko Odaki
>
> > + }
> > + return NULL;
> > +}
> > +
> > int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
> > uint32_t nr_entries, uint32_t offset,
> > struct virtio_gpu_ctrl_command *cmd,
> > @@ -993,9 +1010,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU
> *g,
> > /* TODO: a common DMA map SG helper */
> > do {
> > len = l;
> > - map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a,
> &len,
> > - DMA_DIRECTION_TO_DEVICE,
> > - MEMTXATTRS_UNSPECIFIED);
> > + map = virtio_gpu_dma_memory_map(g, cmd, a, &len);
> > if (!map) {
> > qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map
> MMIO memory for"
> > " element %d\n", __func__, e);
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-07 20:09 ` [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges Vivek Kasireddy
2026-10-08 9:08 ` Akihiko Odaki
@ 2026-10-09 8:13 ` Cédric Le Goater
2026-10-12 6:27 ` Kasireddy, Vivek
1 sibling, 1 reply; 36+ messages in thread
From: Cédric Le Goater @ 2026-10-09 8:13 UTC (permalink / raw)
To: Vivek Kasireddy, qemu-devel; +Cc: Alex Williamson
On 10/7/26 22:09, Vivek Kasireddy wrote:
> In order to create a dmabuf associated with a buffer that spans
> multiple ranges, we first need to identify the VFIO region and
> index the buffer (represented by iovec) belongs to and then
> translate its addresses to offsets within that region.
>
> The qemu_ram_block_from_host() API gives us both the region and
> the offset info we need to populate the dma ranges so that we can
> invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the dmabuf.
>
> Also, instead of iterating over all QOM devices to find the
> VFIODevice associated with a memory region, introduce a helper
> to just use the vfio_device_list to lookup the VFIODevice.
> And, introduce another helper to lookup the VFIO region given an
> address.
>
> Lastly, introduce an enum to return the type of error encountered
> while creating the dmabuf fd.
>
> Cc: Alex Williamson <alex@shazbot.org>
> Cc: Cédric Le Goater <clg@redhat.com>
> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> ---
> include/hw/vfio/vfio-device.h | 22 +++++++
> hw/vfio/device.c | 109 ++++++++++++++++++++++++++++++++++
> hw/vfio/dmabuf-stubs.c | 17 ++++++
> hw/vfio/meson.build | 1 +
> 4 files changed, 149 insertions(+)
> create mode 100644 hw/vfio/dmabuf-stubs.c
>
> diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
> index 8472420d3f..c05430be8a 100644
> --- a/include/hw/vfio/vfio-device.h
> +++ b/include/hw/vfio/vfio-device.h
> @@ -41,6 +41,13 @@ enum {
> VFIO_DEVICE_TYPE_AP = 3,
> };
>
> +enum {
> + /* The Guest passed addresses stored in IOV are invalid */
> + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
> + /* Guest or Host may be at fault for this type of error */
> + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
> +};
Nack.
As said a few times already : it's a VFIO-specific enum leaking
into vfio-device.h to serve virtio-gpu's fallback logic. The
cleanest alternative is to use standard -errno returns and
make the fd an output parameter.
> typedef struct VFIODeviceOps VFIODeviceOps;
> typedef struct VFIODeviceIOOps VFIODeviceIOOps;
> typedef struct VFIOMigration VFIOMigration;
> @@ -323,6 +330,21 @@ bool vfio_device_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_t
>
> int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
> struct vfio_irq_info *info);
> +
> +/**
> + * Create a dmabuf fd by first translating the addresses in the
> + * iovec array into VFIO region offsets and then invoking the
> + * VFIO_DEVICE_FEATURE_DMA_BUF feature.
> + *
> + * @iov: array of iovec entries associated with a buffer
> + * @iov_cnt: number of entries in the iovec array
> + * @errp: pointer to Error*, to store an error if it happens.
> + *
> + * Returns the created dmabuf fd or either VFIO_DMABUF_CREATE_ERR_UNSPEC
> + * or VFIO_DMABUF_CREATE_ERR_INVALID_IOV on error.
> + */
> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
> + Error **errp);
> #endif
>
> /* Returns 0 on success, or a negative errno. */
> diff --git a/hw/vfio/device.c b/hw/vfio/device.c
> index 4f11959633..d95503a5f1 100644
> --- a/hw/vfio/device.c
> +++ b/hw/vfio/device.c
> @@ -21,7 +21,9 @@
> #include "qemu/osdep.h"
> #include <sys/ioctl.h>
>
> +#include "system/ramblock.h"
> #include "hw/vfio/vfio-device.h"
> +#include "hw/vfio/vfio-region.h"
> #include "hw/vfio/pci.h"
> #include "hw/core/iommu.h"
> #include "trace.h"
> @@ -667,3 +669,110 @@ static VFIODeviceIOOps vfio_device_io_ops_ioctl = {
> .region_read = vfio_device_io_region_read,
> .region_write = vfio_device_io_region_write,
> };
> +
> +/*
> + * This helper looks up the VFIODevice corresponding to the given iov. It
> + * can be useful to determinine if a buffer (represented by the iov) belongs
> + * to a VFIO device or not. This is mainly invoked when external components
> + * such as virtio-gpu request creation of dmabuf fds for buffers that may
> + * belong to a VFIO device.
> + */
> +static bool vfio_device_lookup(struct iovec *iov, VFIODevice **vbasedevp,
> + RAMBlock **first_rbp, Error **errp)
> +{
> + VFIODevice *vbasedev;
> + RAMBlock *first_rb;
> + ram_addr_t offset;
> +
> + first_rb = qemu_ram_block_from_host(iov[0].iov_base, false, &offset);
> + if (!first_rb) {
> + error_setg(errp, "Could not find first ramblock\n");
no \n
> + return false;
> + }
> +
> + *first_rbp = first_rb;
> + QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
wrong list : global_next.
> + if (vbasedev->dev == first_rb->mr->dev) {
> + *vbasedevp = vbasedev;
> + return true;
> + }
> + }
> + error_setg(errp, "No VFIO device found to create dmabuf from\n");
no \n
> + return false;
> +}
> +
> +/*
> + * This helper looks up the VFIORegion corresponding to the given address.
> + * It also verifies that the RAMBlock associated with the address is the
> + * same as the first_rb passed in. This is to ensure that all addresses
> + * in the iov belong to the same region.
> + */
> +static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
> + RAMBlock *first_rb, ram_addr_t *offsetp,
> + Error **errp)
> +{
> + VFIORegion *region;
> + RAMBlock *rb;
> +
> + rb = qemu_ram_block_from_host(addr, false, offsetp);
> + if (!rb || rb != first_rb) {
> + error_setg(errp, "Dmabuf segments must belong to the same region\n");
remove \n
> + return false;
> + }
> +
> + region = vfio_get_region_from_mr(rb->mr);
> + if (region) {
> + *regionp = region;
> + return true;
> + }
> + error_setg(errp, "Could not find valid region for dmabuf segment\n");
here too.
> + return false;
> +}
> +
> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
> + Error **errp)
> +{
> + g_autofree struct vfio_device_feature *feature = NULL;
> + struct vfio_device_feature_dma_buf *dma_buf;
> + RAMBlock *first_rb = NULL;
> + VFIODevice *vbasedev;
> + VFIORegion *region;
> + ram_addr_t offset;
> + size_t argsz;
> + int i, ret;
> +
> + if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
> + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
return -EINVAL;
> + }
> +
> + argsz = sizeof(*feature) + sizeof (*dma_buf) +
> + sizeof(struct vfio_region_dma_range) * iov_cnt;
> + feature = g_malloc0(argsz);
> + *feature = (struct vfio_device_feature) {
> + .argsz = argsz,
> + .flags = VFIO_DEVICE_FEATURE_GET | VFIO_DEVICE_FEATURE_DMA_BUF,
> + };
> + dma_buf = (struct vfio_device_feature_dma_buf *)feature->data;
> +
> + for (i = 0; i < iov_cnt; i++) {
> + if (!vfio_region_lookup(iov[i].iov_base, ®ion,
> + first_rb, &offset, errp)) {
> + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
return -EINVAL;
> + }
> +
> + dma_buf->region_index = region->nr;
> + dma_buf->dma_ranges[i].offset = offset;
> + dma_buf->dma_ranges[i].length = iov[i].iov_len;
> + }
> +
> + dma_buf->nr_ranges = iov_cnt;
> + dma_buf->open_flags = O_RDONLY | O_CLOEXEC;
> +
> + ret = vfio_device_get_feature(vbasedev, feature);
> + if (ret < 0) {
> + error_setg_errno(errp, -ret,
> + "Could not create dmabuf fd via VFIO device");
> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
return ret;
> + }
> + return ret;
> +}
> diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
> new file mode 100644
> index 0000000000..fb5318e929
> --- /dev/null
> +++ b/hw/vfio/dmabuf-stubs.c
Fails to build on MinGW/Windows.
hw/vfio/dmabuf-stubs.c:12:5: error: no previous prototype for
'vfio_device_create_dmabuf_fd'
hw/vfio/dmabuf-stubs.c:19:7: error: no previous prototype for
'vfio_device_mmap_dmabuf'
> @@ -0,0 +1,17 @@
> +/*
> + * Copyright (c) 2026 Intel and/or its affiliates.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/error-report.h"
> +#include "qemu/iov.h"
> +#include "hw/vfio/vfio-device.h"
> +
> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
> + Error **errp)
> +{
> + error_setg(errp, "VFIO dmabuf support is not enabled");
> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
return -ENOTSUP;
> +}
> diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build
> index c7c31b78f6..aa6f4bc1b4 100644
> --- a/hw/vfio/meson.build
> +++ b/hw/vfio/meson.build
> @@ -38,3 +38,4 @@ stub_ss.add(files('iommufd-stubs.c'))
> system_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files(
> 'display.c',
> ))
> +system_ss.add(when: 'CONFIG_VFIO', if_false: files('dmabuf-stubs.c'))
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 7/9] vfio/device: Add a helper to mmap a dmabuf
2026-10-07 20:09 ` [PATCH v13 7/9] vfio/device: Add a helper to mmap a dmabuf Vivek Kasireddy
@ 2026-10-09 8:13 ` Cédric Le Goater
0 siblings, 0 replies; 36+ messages in thread
From: Cédric Le Goater @ 2026-10-09 8:13 UTC (permalink / raw)
To: Vivek Kasireddy, qemu-devel; +Cc: Alex Williamson
On 10/7/26 22:09, Vivek Kasireddy wrote:
> In order to mmap a dmabuf, we first need to create a placeholder
> mapping that would fit the entire size of the dmabuf. This mapping
> would then be replaced with smaller mappings of individual dmabuf
> segments.
>
> Cc: Alex Williamson <alex@shazbot.org>
> Cc: Cédric Le Goater <clg@redhat.com>
> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> ---
> include/hw/vfio/vfio-device.h | 15 ++++++++++
> hw/vfio/device.c | 55 +++++++++++++++++++++++++++++++++++
> hw/vfio/dmabuf-stubs.c | 7 +++++
> 3 files changed, 77 insertions(+)
>
> diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
> index c05430be8a..4b8fb62056 100644
> --- a/include/hw/vfio/vfio-device.h
> +++ b/include/hw/vfio/vfio-device.h
> @@ -345,6 +345,21 @@ int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
> */
> int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
> Error **errp);
> +
> +/**
> + * Mmap a dmabuf by first translating the addresses in the iovec
> + * array into VFIO region offsets and then creating a placeholder
> + * mapping that would be replaced later with mappings that
> + * correspond to the dmabuf segments.
> + *
> + * @iov: array of iovec entries associated with the dmabuf
> + * @iov_cnt: number of entries in the iovec array
> + * @errp: pointer to Error*, to store an error if it happens.
> + *
> + * Returns the mapped pointer on success and NULL on error.
> + */
> +void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
> + Error **errp);
> #endif
>
> /* Returns 0 on success, or a negative errno. */
> diff --git a/hw/vfio/device.c b/hw/vfio/device.c
> index d95503a5f1..5bc0443764 100644
> --- a/hw/vfio/device.c
> +++ b/hw/vfio/device.c
> @@ -776,3 +776,58 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
> }
> return ret;
> }
> +
> +void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
> + Error **errp)
> +{
> + size_t total_size = iov_size(iov, iov_cnt);
> + struct vfio_region_info *info = NULL;
> + ram_addr_t offset, len = 0;
> + VFIODevice *vbasedev;
> + VFIORegion *region;
> + RAMBlock *first_rb;
> + void *map, *submap;
> + int i;
> +
> + if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
> + return NULL;
> + }
> +
> + /*
> + * We first reserve a contiguous chunk of address space for the entire
> + * dmabuf, then replace it with smaller mappings that correspond to the
> + * individual segments of the dmabuf.
> + */
> + map = mmap(NULL, total_size, PROT_NONE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> + if (map == MAP_FAILED) {
> + error_setg_errno(errp, errno, "Could not reserve placeholder mapping");
> + return NULL;
> + }
> +
> + for (i = 0; i < iov_cnt; i++) {
> + if (!vfio_region_lookup(iov[i].iov_base, ®ion,
> + first_rb, &offset, errp)) {
> + goto err;
> + }
> +
> + if (vfio_device_get_region_info(vbasedev, region->nr, &info)) {
> + error_setg(errp, "Cannot find region info for dmabuf segment\n");
no \n
> + goto err;
> + }
> +
> + submap = mmap(map + len, iov[i].iov_len, PROT_READ,
> + MAP_SHARED | MAP_FIXED, vbasedev->fd,
> + info->offset + offset);
> + if (submap == MAP_FAILED) {
> + error_setg_errno(errp, errno, "Could not mmap dmabuf segment\n");
again.
> + goto err;
> + }
> + len += iov[i].iov_len;
> + }
> + return map;
> +err:
> + munmap(map, total_size);
> + error_prepend(errp, "VFIO dmabuf mmap failed: ");
> + return NULL;
> +}
> +
> diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
> index fb5318e929..b9e03a162a 100644
> --- a/hw/vfio/dmabuf-stubs.c
> +++ b/hw/vfio/dmabuf-stubs.c
> @@ -15,3 +15,10 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
> error_setg(errp, "VFIO dmabuf support is not enabled");
> return VFIO_DMABUF_CREATE_ERR_UNSPEC;
> }
> +
> +void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
> + Error **errp)
> +{
> + error_setg(errp, "VFIO mmap dmabuf support is not enabled");
> + return NULL;
> +}
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 8/9] virtio-gpu-dmabuf: Improve error handling with 'Error **' and err enum
2026-10-07 20:09 ` [PATCH v13 8/9] virtio-gpu-dmabuf: Improve error handling with 'Error **' and err enum Vivek Kasireddy
@ 2026-10-09 8:17 ` Cédric Le Goater
0 siblings, 0 replies; 36+ messages in thread
From: Cédric Le Goater @ 2026-10-09 8:17 UTC (permalink / raw)
To: Vivek Kasireddy, qemu-devel
Cc: Marc-André Lureau, Alex Bennée, Akihiko Odaki,
Dmitry Osipenko, Alex Williamson
On 10/7/26 22:09, Vivek Kasireddy wrote:
> Make the error handling more robust in virtio_gpu_init_udmabuf()
> by introducing 'Error **' parameter to capture errors and using
> an enum from VFIO to categorize different errors. This allows for
> better error reporting and handling of errors from
> virtio_gpu_create_udmabuf() and virtio_gpu_remap_dmabuf().
>
> Furtheremore, the main reason for using the VFIO enum is to handle
> the special INVALID_IOV case which can happen in two scenarios:
> 1) When the Blob resource's memory is backed by a VFIO region. This
> would cause INVALID_IOV error when we try to create a dmabuf via
> udmabuf driver but we can recover from this error by having the
> dmabuf be created by the VFIO driver instead.
> 2) When the Blob resource's memory is not backed by memfd or VFIO
> region. In this case, since the error can be attributed to the
> guest, we should use qemu_log_mask() instead of error_report_err()
> and emit a message that can be used to debug the guest error.
>
> Note that, to diagnose errors, a common pattern is to return -errno
> to enable the caller to implement specific error handling. However, in
> this case, since we want to distinguish the INVALID_IOV error from other
> errors, using the VFIO enum allows us to do so and is very convenient.
>
> 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>
> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> ---
> hw/display/virtio-gpu-dmabuf.c | 69 ++++++++++++++++++++++------------
> 1 file changed, 46 insertions(+), 23 deletions(-)
>
> diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
> index 6f05f367d0..c9de8e9ba3 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,28 +28,32 @@
> #include "standard-headers/linux/udmabuf.h"
> #include "standard-headers/drm/drm_fourcc.h"
>
> -static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
> +static int virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res,
> + Error **errp)
> {
> g_autofree struct udmabuf_create_list *list = NULL;
> RAMBlock *rb;
> ram_addr_t offset;
> - int udmabuf, i;
> + int udmabuf, i, fd;
>
> udmabuf = udmabuf_fd();
> if (udmabuf < 0) {
> - return;
> + error_setg(errp, "udmabuf device not available or enabled");
return -ENODEV
> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
> }
>
> list = g_try_malloc0(sizeof(struct udmabuf_create_list) +
> sizeof(struct udmabuf_create_item) * res->iov_cnt);
> if (!list) {
> - return;
> + error_setg(errp, "failed to allocate udmabuf create list");
return -ENOMEM;
> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
> }
>
> for (i = 0; i < res->iov_cnt; i++) {
> rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
> if (!rb || rb->fd < 0) {
> - return;
> + error_setg(errp, "IOV memory address incompatible with udmabuf ");
> + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
return -EINVAL;
> }
>
> list->list[i].memfd = rb->fd;
> @@ -59,22 +64,28 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
> list->count = res->iov_cnt;
> list->flags = UDMABUF_FLAGS_CLOEXEC;
>
> - res->dmabuf_fd = ioctl(udmabuf, UDMABUF_CREATE_LIST, list);
> - if (res->dmabuf_fd < 0) {
> - warn_report("%s: UDMABUF_CREATE_LIST: %s", __func__,
> - strerror(errno));
> + fd = ioctl(udmabuf, UDMABUF_CREATE_LIST, list);
> + if (fd < 0) {
int saved_errno = errno;
> + error_setg_errno(errp, errno, "UDMABUF_CREATE_LIST: ioctl failed");
> + if (errno == EINVAL || errno == EBADFD) {
> + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
return -EINVAL;
> + }
> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
return -saved_errno;
> }
> + return fd;
> }
>
> -static void virtio_gpu_remap_dmabuf(struct virtio_gpu_simple_resource *res)
> +static void *virtio_gpu_remap_dmabuf(struct virtio_gpu_simple_resource *res,
> + Error **errp)
> {
> - res->remapped = mmap(NULL, res->blob_size, PROT_READ,
> - MAP_SHARED, res->dmabuf_fd, 0);
> - if (res->remapped == MAP_FAILED) {
> - warn_report("%s: dmabuf mmap failed: %s", __func__,
> - strerror(errno));
> - res->remapped = NULL;
> + void *map;
> +
> + map = mmap(NULL, res->blob_size, PROT_READ, MAP_SHARED, res->dmabuf_fd, 0);
> + if (map == MAP_FAILED) {
> + error_setg_errno(errp, errno, "dmabuf mmap failed");
> + return NULL;
> }
> + return map;
> }
>
> void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res)
> @@ -130,6 +141,7 @@ bool virtio_gpu_have_udmabuf(void)
>
> bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
> {
> + Error *local_err = NULL;
> void *pdata = NULL;
>
> res->dmabuf_fd = -1;
> @@ -137,17 +149,28 @@ bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
> res->iov[0].iov_len < 4096) {
> pdata = res->iov[0].iov_base;
> } else if (res->blob_size) {
> - virtio_gpu_create_udmabuf(res);
> + res->dmabuf_fd = virtio_gpu_create_udmabuf(res, &local_err);
> + if (res->dmabuf_fd == VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
if (res->dmabuf_fd == -EINVAL) {
> + error_free_or_abort(&local_err);
> +
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "Cannot create dmabuf: incompatible memory\n");
> + return false;
> + } else if (res->dmabuf_fd >= 0) {
> + pdata = virtio_gpu_remap_dmabuf(res, &local_err);
> + if (!pdata) {
> + virtio_gpu_fini_dmabuf(res);
> + }
> + } else {
> + res->dmabuf_fd = -1;
> + }
> +
> if (res->dmabuf_fd < 0) {
> - return false;
> - }
> - virtio_gpu_remap_dmabuf(res);
> - if (!res->remapped) {
> - virtio_gpu_fini_dmabuf(res);
> + error_report_err(local_err);
> return false;
> }
> res->share_handle = res->dmabuf_fd;
> - pdata = res->remapped;
> + res->remapped = pdata;
> }
>
> res->blob = pdata;
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device
2026-10-09 4:32 ` Kasireddy, Vivek
@ 2026-10-09 9:26 ` Akihiko Odaki
2026-10-12 6:10 ` Kasireddy, Vivek
0 siblings, 1 reply; 36+ messages in thread
From: Akihiko Odaki @ 2026-10-09 9:26 UTC (permalink / raw)
To: Kasireddy, Vivek, qemu-devel@nongnu.org
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
On 2026/10/09 13:32, Kasireddy, Vivek wrote:
> Hi Akihiko,
>
>> Subject: Re: [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr
>> associated with a ram device
>>
>> On 2026/10/08 5:09, Vivek Kasireddy wrote:
>>> If the Guest provides a DMA address that is associated with a ram
>>> device (such as a VFIO PCI device region and not its system memory),
>>> then we can obtain the hva (host virtual address) by invoking
>>> address_space_translate() followed by memory_region_get_ram_ptr().
>>>
>>> We cannot use dma_memory_map() because for memory regions that
>> do
>>> not support direct access, it would create bounce buffers instead
>>> of returning the actual hva, which is not desirable here. And, since
>>> VFIO device regions are not considered directly accessible (because
>>> they are mostly MMIO based), virtio-gpu cannot invoke
>> dma_memory_map()
>>> to obtain the hva in this case.
>>>
>>> Therefore, in order to handle addresses associated with VFIO devices,
>>> we need to use the address_space_translate() API to first identify
>>> the right memory region and the appropriate offset within that
>>> region and then use memory_region_get_ram_ptr() to get the hva.
>>> This approach also works for addresses associated with the system
>>> memory region.
>>>
>>> Note that, although we take an explicit reference on the memory
>>> region, we would still rely on dma_memory_unmap() to drop that
>>> reference when the dma mapping is eventually unmapped.
>>>
>>> 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>
>>> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
>>> ---
>>> hw/display/virtio-gpu.c | 21 ++++++++++++++++++---
>>> 1 file changed, 18 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
>>> index bb0f41bb1e..386db05e5b 100644
>>> --- a/hw/display/virtio-gpu.c
>>> +++ b/hw/display/virtio-gpu.c
>>> @@ -948,6 +948,23 @@ static void
>> virtio_gpu_set_scanout_blob(VirtIOGPU *g,
>>> &fb, res, &ss.r, &cmd->error);
>>> }
>>>
>>> +static void *virtio_gpu_dma_memory_map(VirtIOGPU *g,
>>> + struct virtio_gpu_ctrl_command *cmd,
>>> + uint64_t a, hwaddr *len)
>>> +{
>>> + MemoryRegion *mr;
>>> + hwaddr xlat;
>>> +
>>> + mr = address_space_translate(VIRTIO_DEVICE(g)->dma_as, a,
>> &xlat, len,
>>> + DMA_DIRECTION_TO_DEVICE,
>>> + MEMTXATTRS_UNSPECIFIED);
>>> + if (memory_region_is_ram(mr)) {
>>> + memory_region_ref(mr);
>>> + return memory_region_get_ram_ptr(mr) + xlat;
>>
>> On rechecking this, I don't think it is safe with Xen.
>>
>> memory_region_get_ram_ptr(mr) + xlat assumes a contiguous host
>> mapping
>> of the entire region. Xen maps guest RAM on demand through its
>> mapcache.
>> Here, memory_region_get_ram_ptr() obtains a mapping at offset zero
>> without pinning the cache entry, and adding xlat afterward does not
>> ensure that the requested range is mapped.
>>
>> The MemoryRegion reference keeps the region alive, but does not
>> prevent
>> the mapcache entry from being reused. Resource backing can therefore
>> receive an invalid or unpinned pointer.
>>
>> I think we need to extend dma_memory_map() for this use case instead
>> of
>> replacing it, preserving its mapping and unmapping semantics.
> I am not sure if extending dma_memory_map() might be a better/cleaner
> solution for this use-case. If obtaining the hva/host ptr via
> memory_region_get_ram_ptr(mr) + xlat for guest RAM is not safe with
> Xen, then would it not make more sense to go back to using dma_memory_map()
> for Guest RAM and memory_region_get_ram_ptr(mr) + xlat for VFIO
> backed regions? That is, doing the following:
>
> static void *virtio_gpu_dma_memory_map(VirtIOGPU *g,
> struct virtio_gpu_ctrl_command *cmd,
> uint64_t a, hwaddr *len)
> {
> MemoryRegion *mr = NULL;
> hwaddr xlat;
>
> mr = address_space_translate(VIRTIO_DEVICE(g)->dma_as, a, &xlat, len,
> DMA_DIRECTION_TO_DEVICE,
> MEMTXATTRS_UNSPECIFIED);
> if (memory_region_is_ram_device(mr)) {
> memory_region_ref(mr);
> return memory_region_get_ram_ptr(mr) + xlat;
> }
>
> return dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, len,
> DMA_DIRECTION_TO_DEVICE,
> MEMTXATTRS_UNSPECIFIED);
> }
Checking this logic again, I found this patch is not necessary since
commit ff77a515113f ("system/memory: Make ram device region directly
accessible"). We can just drop it.
Regards,
Akihiko Odaki
>
> Thanks,
> Vivek
>
>>
>> Regards,
>> Akihiko Odaki
>>
>>> + }
>>> + return NULL;
>>> +}
>>> +
>>> int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
>>> uint32_t nr_entries, uint32_t offset,
>>> struct virtio_gpu_ctrl_command *cmd,
>>> @@ -993,9 +1010,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU
>> *g,
>>> /* TODO: a common DMA map SG helper */
>>> do {
>>> len = l;
>>> - map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a,
>> &len,
>>> - DMA_DIRECTION_TO_DEVICE,
>>> - MEMTXATTRS_UNSPECIFIED);
>>> + map = virtio_gpu_dma_memory_map(g, cmd, a, &len);
>>> if (!map) {
>>> qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map
>> MMIO memory for"
>>> " element %d\n", __func__, e);
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2026-10-09 4:26 ` Kasireddy, Vivek
@ 2026-10-09 9:51 ` Akihiko Odaki
2026-10-12 6:14 ` Kasireddy, Vivek
0 siblings, 1 reply; 36+ messages in thread
From: Akihiko Odaki @ 2026-10-09 9:51 UTC (permalink / raw)
To: Kasireddy, Vivek, qemu-devel@nongnu.org
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
On 2026/10/09 13:26, Kasireddy, Vivek wrote:
> Hi Akihiko,
>
>> Subject: Re: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for
>> blobs associated with VFIO devices
>>
>> On 2026/10/08 5:09, 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_fd() API which identifies the right
>>> VFIO device and eventually creates a dmabuf fd.
>>>
>>> Note that, for mmapping the dmabuf, we directly call mmap() if the
>>> dmabuf fd was created via virtio_gpu_create_udmabuf() since we
>> know
>>> that the udmabuf driver supports mmap(). However, if the dmabuf
>> was
>>> created via vfio_device_create_dmabuf_fd(), we use the
>>> vfio_device_mmap_dmabuf() API to get a mapping 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>
>>> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
>>> ---
>>> hw/display/virtio-gpu-dmabuf.c | 22 +++++++++++++++++++---
>>> 1 file changed, 19 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-
>> dmabuf.c
>>> index c9de8e9ba3..f59a5e76ff 100644
>>> --- a/hw/display/virtio-gpu-dmabuf.c
>>> +++ b/hw/display/virtio-gpu-dmabuf.c
>>> @@ -153,9 +153,25 @@ bool virtio_gpu_init_dmabuf(struct
>> virtio_gpu_simple_resource *res)
>>> if (res->dmabuf_fd ==
>> VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
>>> error_free_or_abort(&local_err);
>>>
>>> - qemu_log_mask(LOG_GUEST_ERROR,
>>> - "Cannot create dmabuf: incompatible memory\n");
>>> - return false;
>>> + res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
>>> + res->iov_cnt,
>>> + &local_err);
>>> + if (res->dmabuf_fd ==
>> VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
>>> + error_free_or_abort(&local_err);
>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>> + "Cannot create dmabuf: incompatible memory\n");
>>> + return false;
>>> + }
>>> +
>>> + if (res->dmabuf_fd >= 0) {
>>> + pdata = vfio_device_mmap_dmabuf(res->iov, res->iov_cnt,
>>> + &local_err);
>>
>> This maps the complete IOV size, while virtio_gpu_fini_dmabuf()
>> unmaps
>> only blob_size. Create and attach accept backing larger than the blob,
>> so excess pages remain mapped after detach, unref or reset.
> Good catch. I'll add a check in virtio_gpu_fini_dmabuf() to determine if
> IOV size > blob_size, then do munmap(res->remapped, IOV size);
> I think this should be safe even if the mapping (created with mmap)
> size is blob_size. Or, is there a better solution you can think of such as
> tracking the exact mapping size in res object?
Unmapping the IOV size is not safe if only blob_size was mapped:
munmap() can also remove unrelated mappings in the excess range.
A cleaner fix is to update vfio_device_mmap_dmabuf() to take the size to
map (or cap it to blob_size). This keeps it symmetric with the udmabuf
path and allows virtio_gpu_fini_dmabuf() to continue unmapping blob_size
without needing extra tracking variables.
Regards,
Akihiko Odaki
>
> Thanks,
> Vivek
>>
>> Regards,
>> Akihiko Odaki
>>
>>> + if (!pdata) {
>>> + virtio_gpu_fini_dmabuf(res);
>>> + }
>>> + } else {
>>> + res->dmabuf_fd = -1;
>>> + }
>>> } else if (res->dmabuf_fd >= 0) {
>>> pdata = virtio_gpu_remap_dmabuf(res, &local_err);
>>> if (!pdata) {
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device
2026-10-09 9:26 ` Akihiko Odaki
@ 2026-10-12 6:10 ` Kasireddy, Vivek
0 siblings, 0 replies; 36+ messages in thread
From: Kasireddy, Vivek @ 2026-10-12 6:10 UTC (permalink / raw)
To: Akihiko Odaki, qemu-devel@nongnu.org
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
Hi Akihiko,
> Subject: Re: [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr
> associated with a ram device
>
> >>> If the Guest provides a DMA address that is associated with a ram
> >>> device (such as a VFIO PCI device region and not its system memory),
> >>> then we can obtain the hva (host virtual address) by invoking
> >>> address_space_translate() followed by
> memory_region_get_ram_ptr().
> >>>
> >>> We cannot use dma_memory_map() because for memory regions that
> >> do
> >>> not support direct access, it would create bounce buffers instead
> >>> of returning the actual hva, which is not desirable here. And, since
> >>> VFIO device regions are not considered directly accessible (because
> >>> they are mostly MMIO based), virtio-gpu cannot invoke
> >> dma_memory_map()
> >>> to obtain the hva in this case.
> >>>
> >>> Therefore, in order to handle addresses associated with VFIO devices,
> >>> we need to use the address_space_translate() API to first identify
> >>> the right memory region and the appropriate offset within that
> >>> region and then use memory_region_get_ram_ptr() to get the hva.
> >>> This approach also works for addresses associated with the system
> >>> memory region.
> >>>
> >>> Note that, although we take an explicit reference on the memory
> >>> region, we would still rely on dma_memory_unmap() to drop that
> >>> reference when the dma mapping is eventually unmapped.
> >>>
> >>> 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>
> >>> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> >>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> >>> ---
> >>> hw/display/virtio-gpu.c | 21 ++++++++++++++++++---
> >>> 1 file changed, 18 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> >>> index bb0f41bb1e..386db05e5b 100644
> >>> --- a/hw/display/virtio-gpu.c
> >>> +++ b/hw/display/virtio-gpu.c
> >>> @@ -948,6 +948,23 @@ static void
> >> virtio_gpu_set_scanout_blob(VirtIOGPU *g,
> >>> &fb, res, &ss.r, &cmd->error);
> >>> }
> >>>
> >>> +static void *virtio_gpu_dma_memory_map(VirtIOGPU *g,
> >>> + struct virtio_gpu_ctrl_command *cmd,
> >>> + uint64_t a, hwaddr *len)
> >>> +{
> >>> + MemoryRegion *mr;
> >>> + hwaddr xlat;
> >>> +
> >>> + mr = address_space_translate(VIRTIO_DEVICE(g)->dma_as, a,
> >> &xlat, len,
> >>> + DMA_DIRECTION_TO_DEVICE,
> >>> + MEMTXATTRS_UNSPECIFIED);
> >>> + if (memory_region_is_ram(mr)) {
> >>> + memory_region_ref(mr);
> >>> + return memory_region_get_ram_ptr(mr) + xlat;
> >>
> >> On rechecking this, I don't think it is safe with Xen.
> >>
> >> memory_region_get_ram_ptr(mr) + xlat assumes a contiguous host
> >> mapping
> >> of the entire region. Xen maps guest RAM on demand through its
> >> mapcache.
> >> Here, memory_region_get_ram_ptr() obtains a mapping at offset zero
> >> without pinning the cache entry, and adding xlat afterward does not
> >> ensure that the requested range is mapped.
> >>
> >> The MemoryRegion reference keeps the region alive, but does not
> >> prevent
> >> the mapcache entry from being reused. Resource backing can therefore
> >> receive an invalid or unpinned pointer.
> >>
> >> I think we need to extend dma_memory_map() for this use case instead
> >> of
> >> replacing it, preserving its mapping and unmapping semantics.
> > I am not sure if extending dma_memory_map() might be a
> better/cleaner
> > solution for this use-case. If obtaining the hva/host ptr via
> > memory_region_get_ram_ptr(mr) + xlat for guest RAM is not safe with
> > Xen, then would it not make more sense to go back to using
> dma_memory_map()
> > for Guest RAM and memory_region_get_ram_ptr(mr) + xlat for VFIO
> > backed regions? That is, doing the following:
> >
> > static void *virtio_gpu_dma_memory_map(VirtIOGPU *g,
> > struct virtio_gpu_ctrl_command *cmd,
> > uint64_t a, hwaddr *len)
> > {
> > MemoryRegion *mr = NULL;
> > hwaddr xlat;
> >
> > mr = address_space_translate(VIRTIO_DEVICE(g)->dma_as, a, &xlat,
> len,
> > DMA_DIRECTION_TO_DEVICE,
> > MEMTXATTRS_UNSPECIFIED);
> > if (memory_region_is_ram_device(mr)) {
> > memory_region_ref(mr);
> > return memory_region_get_ram_ptr(mr) + xlat;
> > }
> >
> > return dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, len,
> > DMA_DIRECTION_TO_DEVICE,
> > MEMTXATTRS_UNSPECIFIED);
> > }
>
> Checking this logic again, I found this patch is not necessary since
> commit ff77a515113f ("system/memory: Make ram device region directly
> accessible"). We can just drop it.
You are right, this patch is no longer necessary in light of ff77a515113f.
I dropped it from this series and re-tested my use-case again and everything
seems to work as expected.
Thanks,
Vivek
>
> Regards,
> Akihiko Odaki
>
> >
> > Thanks,
> > Vivek
> >
> >>
> >> Regards,
> >> Akihiko Odaki
> >>
> >>> + }
> >>> + return NULL;
> >>> +}
> >>> +
> >>> int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
> >>> uint32_t nr_entries, uint32_t offset,
> >>> struct virtio_gpu_ctrl_command *cmd,
> >>> @@ -993,9 +1010,7 @@ int
> virtio_gpu_create_mapping_iov(VirtIOGPU
> >> *g,
> >>> /* TODO: a common DMA map SG helper */
> >>> do {
> >>> len = l;
> >>> - map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a,
> >> &len,
> >>> - DMA_DIRECTION_TO_DEVICE,
> >>> - MEMTXATTRS_UNSPECIFIED);
> >>> + map = virtio_gpu_dma_memory_map(g, cmd, a, &len);
> >>> if (!map) {
> >>> qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map
> >> MMIO memory for"
> >>> " element %d\n", __func__, e);
> >
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2026-10-09 9:51 ` Akihiko Odaki
@ 2026-10-12 6:14 ` Kasireddy, Vivek
2026-10-12 14:00 ` Akihiko Odaki
0 siblings, 1 reply; 36+ messages in thread
From: Kasireddy, Vivek @ 2026-10-12 6:14 UTC (permalink / raw)
To: Akihiko Odaki, qemu-devel@nongnu.org
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
Hi Akihiko,
> Subject: Re: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs
> associated with VFIO devices
> >
> >>> 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_fd() API which identifies the right
> >>> VFIO device and eventually creates a dmabuf fd.
> >>>
> >>> Note that, for mmapping the dmabuf, we directly call mmap() if the
> >>> dmabuf fd was created via virtio_gpu_create_udmabuf() since we
> >> know
> >>> that the udmabuf driver supports mmap(). However, if the dmabuf
> >> was
> >>> created via vfio_device_create_dmabuf_fd(), we use the
> >>> vfio_device_mmap_dmabuf() API to get a mapping 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>
> >>> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> >>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> >>> ---
> >>> hw/display/virtio-gpu-dmabuf.c | 22 +++++++++++++++++++---
> >>> 1 file changed, 19 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-
> >> dmabuf.c
> >>> index c9de8e9ba3..f59a5e76ff 100644
> >>> --- a/hw/display/virtio-gpu-dmabuf.c
> >>> +++ b/hw/display/virtio-gpu-dmabuf.c
> >>> @@ -153,9 +153,25 @@ bool virtio_gpu_init_dmabuf(struct
> >> virtio_gpu_simple_resource *res)
> >>> if (res->dmabuf_fd ==
> >> VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
> >>> error_free_or_abort(&local_err);
> >>>
> >>> - qemu_log_mask(LOG_GUEST_ERROR,
> >>> - "Cannot create dmabuf: incompatible memory\n");
> >>> - return false;
> >>> + res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
> >>> + res->iov_cnt,
> >>> + &local_err);
> >>> + if (res->dmabuf_fd ==
> >> VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
> >>> + error_free_or_abort(&local_err);
> >>> + qemu_log_mask(LOG_GUEST_ERROR,
> >>> + "Cannot create dmabuf: incompatible memory\n");
> >>> + return false;
> >>> + }
> >>> +
> >>> + if (res->dmabuf_fd >= 0) {
> >>> + pdata = vfio_device_mmap_dmabuf(res->iov, res->iov_cnt,
> >>> + &local_err);
> >>
> >> This maps the complete IOV size, while virtio_gpu_fini_dmabuf()
> >> unmaps
> >> only blob_size. Create and attach accept backing larger than the blob,
> >> so excess pages remain mapped after detach, unref or reset.
> > Good catch. I'll add a check in virtio_gpu_fini_dmabuf() to determine if
> > IOV size > blob_size, then do munmap(res->remapped, IOV size);
> > I think this should be safe even if the mapping (created with mmap)
> > size is blob_size. Or, is there a better solution you can think of such as
> > tracking the exact mapping size in res object?
>
> Unmapping the IOV size is not safe if only blob_size was mapped:
> munmap() can also remove unrelated mappings in the excess range.
Ok, got it.
>
> A cleaner fix is to update vfio_device_mmap_dmabuf() to take the size to
> map (or cap it to blob_size).
Currently, vfio_device_mmap_dmabuf() creates an IOV sized mapping, so it
is going to need extra logic to cap it to blob_size, which needs to be explicitly
passed in. So, are you ok with this given that you previously did not like the
idea of passing in blob_size as a parameter?
Thanks,
Vivek
> This keeps it symmetric with the udmabuf
> path and allows virtio_gpu_fini_dmabuf() to continue unmapping
> blob_size
> without needing extra tracking variables.
>
> Regards,
> Akihiko Odaki
>
> >
> > Thanks,
> > Vivek
> >>
> >> Regards,
> >> Akihiko Odaki
> >>
> >>> + if (!pdata) {
> >>> + virtio_gpu_fini_dmabuf(res);
> >>> + }
> >>> + } else {
> >>> + res->dmabuf_fd = -1;
> >>> + }
> >>> } else if (res->dmabuf_fd >= 0) {
> >>> pdata = virtio_gpu_remap_dmabuf(res, &local_err);
> >>> if (!pdata) {
> >
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-09 8:13 ` Cédric Le Goater
@ 2026-10-12 6:27 ` Kasireddy, Vivek
2026-10-12 14:01 ` Akihiko Odaki
2026-10-13 16:40 ` Cédric Le Goater
0 siblings, 2 replies; 36+ messages in thread
From: Kasireddy, Vivek @ 2026-10-12 6:27 UTC (permalink / raw)
To: odaki@rsg.ci.i.u-tokyo.ac.jp, Cédric Le Goater,
qemu-devel@nongnu.org
Cc: Alex Williamson
Hi Akihiko,
> Subject: Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf
> from multiple ranges
>
> > In order to create a dmabuf associated with a buffer that spans
> > multiple ranges, we first need to identify the VFIO region and
> > index the buffer (represented by iovec) belongs to and then
> > translate its addresses to offsets within that region.
> >
> > The qemu_ram_block_from_host() API gives us both the region and
> > the offset info we need to populate the dma ranges so that we can
> > invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the
> dmabuf.
> >
> > Also, instead of iterating over all QOM devices to find the
> > VFIODevice associated with a memory region, introduce a helper
> > to just use the vfio_device_list to lookup the VFIODevice.
> > And, introduce another helper to lookup the VFIO region given an
> > address.
> >
> > Lastly, introduce an enum to return the type of error encountered
> > while creating the dmabuf fd.
> >
> > Cc: Alex Williamson <alex@shazbot.org>
> > Cc: Cédric Le Goater <clg@redhat.com>
> > Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> > ---
> > include/hw/vfio/vfio-device.h | 22 +++++++
> > hw/vfio/device.c | 109 ++++++++++++++++++++++++++++++++++
> > hw/vfio/dmabuf-stubs.c | 17 ++++++
> > hw/vfio/meson.build | 1 +
> > 4 files changed, 149 insertions(+)
> > create mode 100644 hw/vfio/dmabuf-stubs.c
> >
> > diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-
> device.h
> > index 8472420d3f..c05430be8a 100644
> > --- a/include/hw/vfio/vfio-device.h
> > +++ b/include/hw/vfio/vfio-device.h
> > @@ -41,6 +41,13 @@ enum {
> > VFIO_DEVICE_TYPE_AP = 3,
> > };
> >
> > +enum {
> > + /* The Guest passed addresses stored in IOV are invalid */
> > + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
> > + /* Guest or Host may be at fault for this type of error */
> > + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
> > +};
>
> Nack.
>
> As said a few times already : it's a VFIO-specific enum leaking
> into vfio-device.h to serve virtio-gpu's fallback logic. The
> cleanest alternative is to use standard -errno returns and
> make the fd an output parameter.
It looks like Cedric remains unconvinced about the value or usefulness
of this error enum. Therefore, to make progress, I intend to adopt his
suggestion to use standard -errno returns for the next version, considering
that this series has been stuck for a year.
AFAICS, dropping this error enum means that we would not be able to
clearly identify and log (or attribute) Guest vs Host errors in virtio-gpu,
particularly the INVALID_IOV case. I am not sure if this can be considered
a significant limitation. However, if there is a reasonable middle ground
solution or an alternative that you can think of that does not involve
using VFIO error enums in virtio-gpu, then I would like to pursue that
instead.
Thanks,
Vivek
>
>
> > typedef struct VFIODeviceOps VFIODeviceOps;
> > typedef struct VFIODeviceIOOps VFIODeviceIOOps;
> > typedef struct VFIOMigration VFIOMigration;
> > @@ -323,6 +330,21 @@ bool vfio_device_has_region_cap(VFIODevice
> *vbasedev, int region, uint16_t cap_t
> >
> > int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
> > struct vfio_irq_info *info);
> > +
> > +/**
> > + * Create a dmabuf fd by first translating the addresses in the
> > + * iovec array into VFIO region offsets and then invoking the
> > + * VFIO_DEVICE_FEATURE_DMA_BUF feature.
> > + *
> > + * @iov: array of iovec entries associated with a buffer
> > + * @iov_cnt: number of entries in the iovec array
> > + * @errp: pointer to Error*, to store an error if it happens.
> > + *
> > + * Returns the created dmabuf fd or either
> VFIO_DMABUF_CREATE_ERR_UNSPEC
> > + * or VFIO_DMABUF_CREATE_ERR_INVALID_IOV on error.
> > + */
> > +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
> iov_cnt,
> > + Error **errp);
> > #endif
> >
> > /* Returns 0 on success, or a negative errno. */
> > diff --git a/hw/vfio/device.c b/hw/vfio/device.c
> > index 4f11959633..d95503a5f1 100644
> > --- a/hw/vfio/device.c
> > +++ b/hw/vfio/device.c
> > @@ -21,7 +21,9 @@
> > #include "qemu/osdep.h"
> > #include <sys/ioctl.h>
> >
> > +#include "system/ramblock.h"
> > #include "hw/vfio/vfio-device.h"
> > +#include "hw/vfio/vfio-region.h"
> > #include "hw/vfio/pci.h"
> > #include "hw/core/iommu.h"
> > #include "trace.h"
> > @@ -667,3 +669,110 @@ static VFIODeviceIOOps
> vfio_device_io_ops_ioctl = {
> > .region_read = vfio_device_io_region_read,
> > .region_write = vfio_device_io_region_write,
> > };
> > +
> > +/*
> > + * This helper looks up the VFIODevice corresponding to the given iov.
> It
> > + * can be useful to determinine if a buffer (represented by the iov)
> belongs
> > + * to a VFIO device or not. This is mainly invoked when external
> components
> > + * such as virtio-gpu request creation of dmabuf fds for buffers that may
> > + * belong to a VFIO device.
> > + */
> > +static bool vfio_device_lookup(struct iovec *iov, VFIODevice
> **vbasedevp,
> > + RAMBlock **first_rbp, Error **errp)
> > +{
> > + VFIODevice *vbasedev;
> > + RAMBlock *first_rb;
> > + ram_addr_t offset;
> > +
> > + first_rb = qemu_ram_block_from_host(iov[0].iov_base, false,
> &offset);
> > + if (!first_rb) {
> > + error_setg(errp, "Could not find first ramblock\n");
>
> no \n
>
>
> > + return false;
> > + }
> > +
> > + *first_rbp = first_rb;
> > + QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
>
> wrong list : global_next.
>
>
> > + if (vbasedev->dev == first_rb->mr->dev) {
> > + *vbasedevp = vbasedev;
> > + return true;
> > + }
> > + }
> > + error_setg(errp, "No VFIO device found to create dmabuf from\n");
>
> no \n
>
> > + return false;
> > +}
> > +
> > +/*
> > + * This helper looks up the VFIORegion corresponding to the given
> address.
> > + * It also verifies that the RAMBlock associated with the address is the
> > + * same as the first_rb passed in. This is to ensure that all addresses
> > + * in the iov belong to the same region.
> > + */
> > +static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
> > + RAMBlock *first_rb, ram_addr_t *offsetp,
> > + Error **errp)
> > +{
> > + VFIORegion *region;
> > + RAMBlock *rb;
> > +
> > + rb = qemu_ram_block_from_host(addr, false, offsetp);
> > + if (!rb || rb != first_rb) {
> > + error_setg(errp, "Dmabuf segments must belong to the same
> region\n");
>
> remove \n
>
> > + return false;
> > + }
> > +
> > + region = vfio_get_region_from_mr(rb->mr);
> > + if (region) {
> > + *regionp = region;
> > + return true;
> > + }
> > + error_setg(errp, "Could not find valid region for dmabuf segment\n");
>
> here too.
>
> > + return false;
> > +}
> > +
> > +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
> iov_cnt,
> > + Error **errp)
> > +{
> > + g_autofree struct vfio_device_feature *feature = NULL;
> > + struct vfio_device_feature_dma_buf *dma_buf;
> > + RAMBlock *first_rb = NULL;
> > + VFIODevice *vbasedev;
> > + VFIORegion *region;
> > + ram_addr_t offset;
> > + size_t argsz;
> > + int i, ret;
> > +
> > + if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
> > + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
>
> return -EINVAL;
>
> > + }
> > +
> > + argsz = sizeof(*feature) + sizeof (*dma_buf) +
> > + sizeof(struct vfio_region_dma_range) * iov_cnt;
> > + feature = g_malloc0(argsz);
> > + *feature = (struct vfio_device_feature) {
> > + .argsz = argsz,
> > + .flags = VFIO_DEVICE_FEATURE_GET |
> VFIO_DEVICE_FEATURE_DMA_BUF,
> > + };
> > + dma_buf = (struct vfio_device_feature_dma_buf *)feature->data;
> > +
> > + for (i = 0; i < iov_cnt; i++) {
> > + if (!vfio_region_lookup(iov[i].iov_base, ®ion,
> > + first_rb, &offset, errp)) {
> > + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
>
> return -EINVAL;
>
> > + }
> > +
> > + dma_buf->region_index = region->nr;
> > + dma_buf->dma_ranges[i].offset = offset;
> > + dma_buf->dma_ranges[i].length = iov[i].iov_len;
> > + }
> > +
> > + dma_buf->nr_ranges = iov_cnt;
> > + dma_buf->open_flags = O_RDONLY | O_CLOEXEC;
> > +
> > + ret = vfio_device_get_feature(vbasedev, feature);
> > + if (ret < 0) {
> > + error_setg_errno(errp, -ret,
> > + "Could not create dmabuf fd via VFIO device");
> > + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
>
> return ret;
>
> > + }
> > + return ret;
> > +}
> > diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
> > new file mode 100644
> > index 0000000000..fb5318e929
> > --- /dev/null
> > +++ b/hw/vfio/dmabuf-stubs.c
>
> Fails to build on MinGW/Windows.
>
> hw/vfio/dmabuf-stubs.c:12:5: error: no previous prototype for
> 'vfio_device_create_dmabuf_fd'
> hw/vfio/dmabuf-stubs.c:19:7: error: no previous prototype for
> 'vfio_device_mmap_dmabuf'
>
>
> > @@ -0,0 +1,17 @@
> > +/*
> > + * Copyright (c) 2026 Intel and/or its affiliates.
> > + *
> > + * SPDX-License-Identifier: GPL-2.0-or-later
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qemu/error-report.h"
> > +#include "qemu/iov.h"
> > +#include "hw/vfio/vfio-device.h"
> > +
> > +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
> iov_cnt,
> > + Error **errp)
> > +{
> > + error_setg(errp, "VFIO dmabuf support is not enabled");
> > + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
>
> return -ENOTSUP;
>
>
> > +}
> > diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build
> > index c7c31b78f6..aa6f4bc1b4 100644
> > --- a/hw/vfio/meson.build
> > +++ b/hw/vfio/meson.build
> > @@ -38,3 +38,4 @@ stub_ss.add(files('iommufd-stubs.c'))
> > system_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files(
> > 'display.c',
> > ))
> > +system_ss.add(when: 'CONFIG_VFIO', if_false: files('dmabuf-stubs.c'))
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2026-10-12 6:14 ` Kasireddy, Vivek
@ 2026-10-12 14:00 ` Akihiko Odaki
2026-10-13 3:57 ` Kasireddy, Vivek
0 siblings, 1 reply; 36+ messages in thread
From: Akihiko Odaki @ 2026-10-12 14:00 UTC (permalink / raw)
To: Kasireddy, Vivek, qemu-devel@nongnu.org
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
On 2026/10/12 15:14, Kasireddy, Vivek wrote:
> Hi Akihiko,
>
>> Subject: Re: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs
>> associated with VFIO devices
>>>
>>>>> 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_fd() API which identifies the right
>>>>> VFIO device and eventually creates a dmabuf fd.
>>>>>
>>>>> Note that, for mmapping the dmabuf, we directly call mmap() if the
>>>>> dmabuf fd was created via virtio_gpu_create_udmabuf() since we
>>>> know
>>>>> that the udmabuf driver supports mmap(). However, if the dmabuf
>>>> was
>>>>> created via vfio_device_create_dmabuf_fd(), we use the
>>>>> vfio_device_mmap_dmabuf() API to get a mapping 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>
>>>>> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
>>>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
>>>>> ---
>>>>> hw/display/virtio-gpu-dmabuf.c | 22 +++++++++++++++++++---
>>>>> 1 file changed, 19 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-
>>>> dmabuf.c
>>>>> index c9de8e9ba3..f59a5e76ff 100644
>>>>> --- a/hw/display/virtio-gpu-dmabuf.c
>>>>> +++ b/hw/display/virtio-gpu-dmabuf.c
>>>>> @@ -153,9 +153,25 @@ bool virtio_gpu_init_dmabuf(struct
>>>> virtio_gpu_simple_resource *res)
>>>>> if (res->dmabuf_fd ==
>>>> VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
>>>>> error_free_or_abort(&local_err);
>>>>>
>>>>> - qemu_log_mask(LOG_GUEST_ERROR,
>>>>> - "Cannot create dmabuf: incompatible memory\n");
>>>>> - return false;
>>>>> + res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
>>>>> + res->iov_cnt,
>>>>> + &local_err);
>>>>> + if (res->dmabuf_fd ==
>>>> VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
>>>>> + error_free_or_abort(&local_err);
>>>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>>>> + "Cannot create dmabuf: incompatible memory\n");
>>>>> + return false;
>>>>> + }
>>>>> +
>>>>> + if (res->dmabuf_fd >= 0) {
>>>>> + pdata = vfio_device_mmap_dmabuf(res->iov, res->iov_cnt,
>>>>> + &local_err);
>>>>
>>>> This maps the complete IOV size, while virtio_gpu_fini_dmabuf()
>>>> unmaps
>>>> only blob_size. Create and attach accept backing larger than the blob,
>>>> so excess pages remain mapped after detach, unref or reset.
>>> Good catch. I'll add a check in virtio_gpu_fini_dmabuf() to determine if
>>> IOV size > blob_size, then do munmap(res->remapped, IOV size);
>>> I think this should be safe even if the mapping (created with mmap)
>>> size is blob_size. Or, is there a better solution you can think of such as
>>> tracking the exact mapping size in res object?
>>
>> Unmapping the IOV size is not safe if only blob_size was mapped:
>> munmap() can also remove unrelated mappings in the excess range.
> Ok, got it.
>
>>
>> A cleaner fix is to update vfio_device_mmap_dmabuf() to take the size to
>> map (or cap it to blob_size).
> Currently, vfio_device_mmap_dmabuf() creates an IOV sized mapping, so it
> is going to need extra logic to cap it to blob_size, which needs to be explicitly
> passed in. So, are you ok with this given that you previously did not like the
> idea of passing in blob_size as a parameter?
Yes, I am fine with a mapping-length parameter for this purpose.
I should have made the distinction clearer.
Previously, total_size was required to equal the IOV size, adding
blob-specific validation to the VFIO helper. That validation belongs
in virtio-gpu.
Here, the parameter specifies how much of the IOV to map, which can
be less than its total size. That is a generic mapping operation;
the helper does not need to know about blobs. We can name the
parameter length and have virtio-gpu pass res->blob_size.
The extra logic to stop at that length and shorten the final mapped
segment as necessary is appropriate. This lets mapping and unmapping
use the same length without additional tracking.
Regards,
Akihiko Odaki
>
> Thanks,
> Vivek
>
>> This keeps it symmetric with the udmabuf
>> path and allows virtio_gpu_fini_dmabuf() to continue unmapping
>> blob_size
>> without needing extra tracking variables.
>>
>> Regards,
>> Akihiko Odaki
>>
>>>
>>> Thanks,
>>> Vivek
>>>>
>>>> Regards,
>>>> Akihiko Odaki
>>>>
>>>>> + if (!pdata) {
>>>>> + virtio_gpu_fini_dmabuf(res);
>>>>> + }
>>>>> + } else {
>>>>> + res->dmabuf_fd = -1;
>>>>> + }
>>>>> } else if (res->dmabuf_fd >= 0) {
>>>>> pdata = virtio_gpu_remap_dmabuf(res, &local_err);
>>>>> if (!pdata) {
>>>
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-12 6:27 ` Kasireddy, Vivek
@ 2026-10-12 14:01 ` Akihiko Odaki
2026-10-13 4:06 ` Kasireddy, Vivek
2026-10-13 16:40 ` Cédric Le Goater
1 sibling, 1 reply; 36+ messages in thread
From: Akihiko Odaki @ 2026-10-12 14:01 UTC (permalink / raw)
To: Kasireddy, Vivek, Cédric Le Goater, qemu-devel@nongnu.org
Cc: Alex Williamson
On 2026/10/12 15:27, Kasireddy, Vivek wrote:
> Hi Akihiko,
>
>> Subject: Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf
>> from multiple ranges
>>
>>> In order to create a dmabuf associated with a buffer that spans
>>> multiple ranges, we first need to identify the VFIO region and
>>> index the buffer (represented by iovec) belongs to and then
>>> translate its addresses to offsets within that region.
>>>
>>> The qemu_ram_block_from_host() API gives us both the region and
>>> the offset info we need to populate the dma ranges so that we can
>>> invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the
>> dmabuf.
>>>
>>> Also, instead of iterating over all QOM devices to find the
>>> VFIODevice associated with a memory region, introduce a helper
>>> to just use the vfio_device_list to lookup the VFIODevice.
>>> And, introduce another helper to lookup the VFIO region given an
>>> address.
>>>
>>> Lastly, introduce an enum to return the type of error encountered
>>> while creating the dmabuf fd.
>>>
>>> Cc: Alex Williamson <alex@shazbot.org>
>>> Cc: Cédric Le Goater <clg@redhat.com>
>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
>>> ---
>>> include/hw/vfio/vfio-device.h | 22 +++++++
>>> hw/vfio/device.c | 109 ++++++++++++++++++++++++++++++++++
>>> hw/vfio/dmabuf-stubs.c | 17 ++++++
>>> hw/vfio/meson.build | 1 +
>>> 4 files changed, 149 insertions(+)
>>> create mode 100644 hw/vfio/dmabuf-stubs.c
>>>
>>> diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-
>> device.h
>>> index 8472420d3f..c05430be8a 100644
>>> --- a/include/hw/vfio/vfio-device.h
>>> +++ b/include/hw/vfio/vfio-device.h
>>> @@ -41,6 +41,13 @@ enum {
>>> VFIO_DEVICE_TYPE_AP = 3,
>>> };
>>>
>>> +enum {
>>> + /* The Guest passed addresses stored in IOV are invalid */
>>> + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
>>> + /* Guest or Host may be at fault for this type of error */
>>> + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
>>> +};
>>
>> Nack.
>>
>> As said a few times already : it's a VFIO-specific enum leaking
>> into vfio-device.h to serve virtio-gpu's fallback logic. The
>> cleanest alternative is to use standard -errno returns and
>> make the fd an output parameter.
> It looks like Cedric remains unconvinced about the value or usefulness
> of this error enum. Therefore, to make progress, I intend to adopt his
> suggestion to use standard -errno returns for the next version, considering
> that this series has been stuck for a year.
>
> AFAICS, dropping this error enum means that we would not be able to
> clearly identify and log (or attribute) Guest vs Host errors in virtio-gpu,
> particularly the INVALID_IOV case. I am not sure if this can be considered
> a significant limitation. However, if there is a reasonable middle ground
> solution or an alternative that you can think of that does not involve
> using VFIO error enums in virtio-gpu, then I would like to pursue that
> instead.
Cédric's comment is a reiteration of previous points, but his concrete
code suggestion is new and brings to light some challenges with errno
propagation.
First, errno does not precisely match the required semantics. We need to
distinguish lookup failures from the other errors. However, with your
suggestion, lookup failures become -EINVAL and vfio_device_get_feature()
also returns the same value when the backend lacks the operation, making
it impossible to distinguish them.
Propagating errno also requires extra care to preserve it when
necessary. For patch "[PATCH v13 8/9] virtio-gpu-dmabuf: Improve error
handling with 'Error **' and err enum", you suggested to add the
"saved_errno" variable to save errno before error_setg_errno(). That is
redundant because error_setg_errno() preserves errno. Realizing that
requires careful attention.
While we could spend effort fixing these issues, we can simply avoid the
churn by not using errno.
In any case, I agree keeping this stuck is not ideal while I don't think
I can provide any further insights. So I'm inviting Markus Armbruster to
this discussion. This is an area better handled by him, who maintains
the error reporting facility, including include/qapi/error.h, which
extensively documents codebase-wide error-handling convention.
Markus, could you advise on the appropriate convention for returning
this kind of classification alongside Error **? Your perspective
across the codebase may help us settle on a consistent approach
beyond the individual subsystems involved here. Perhaps you may improve
the documentation according to a design decision made here.
If anyone else has a clean middle-ground solution in the meantime, I
would greatly appreciate your input as well.
Regards,
Akihiko Odaki
>
> Thanks,
> Vivek
>>
>>
>>> typedef struct VFIODeviceOps VFIODeviceOps;
>>> typedef struct VFIODeviceIOOps VFIODeviceIOOps;
>>> typedef struct VFIOMigration VFIOMigration;
>>> @@ -323,6 +330,21 @@ bool vfio_device_has_region_cap(VFIODevice
>> *vbasedev, int region, uint16_t cap_t
>>>
>>> int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
>>> struct vfio_irq_info *info);
>>> +
>>> +/**
>>> + * Create a dmabuf fd by first translating the addresses in the
>>> + * iovec array into VFIO region offsets and then invoking the
>>> + * VFIO_DEVICE_FEATURE_DMA_BUF feature.
>>> + *
>>> + * @iov: array of iovec entries associated with a buffer
>>> + * @iov_cnt: number of entries in the iovec array
>>> + * @errp: pointer to Error*, to store an error if it happens.
>>> + *
>>> + * Returns the created dmabuf fd or either
>> VFIO_DMABUF_CREATE_ERR_UNSPEC
>>> + * or VFIO_DMABUF_CREATE_ERR_INVALID_IOV on error.
>>> + */
>>> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
>> iov_cnt,
>>> + Error **errp);
>>> #endif
>>>
>>> /* Returns 0 on success, or a negative errno. */
>>> diff --git a/hw/vfio/device.c b/hw/vfio/device.c
>>> index 4f11959633..d95503a5f1 100644
>>> --- a/hw/vfio/device.c
>>> +++ b/hw/vfio/device.c
>>> @@ -21,7 +21,9 @@
>>> #include "qemu/osdep.h"
>>> #include <sys/ioctl.h>
>>>
>>> +#include "system/ramblock.h"
>>> #include "hw/vfio/vfio-device.h"
>>> +#include "hw/vfio/vfio-region.h"
>>> #include "hw/vfio/pci.h"
>>> #include "hw/core/iommu.h"
>>> #include "trace.h"
>>> @@ -667,3 +669,110 @@ static VFIODeviceIOOps
>> vfio_device_io_ops_ioctl = {
>>> .region_read = vfio_device_io_region_read,
>>> .region_write = vfio_device_io_region_write,
>>> };
>>> +
>>> +/*
>>> + * This helper looks up the VFIODevice corresponding to the given iov.
>> It
>>> + * can be useful to determinine if a buffer (represented by the iov)
>> belongs
>>> + * to a VFIO device or not. This is mainly invoked when external
>> components
>>> + * such as virtio-gpu request creation of dmabuf fds for buffers that may
>>> + * belong to a VFIO device.
>>> + */
>>> +static bool vfio_device_lookup(struct iovec *iov, VFIODevice
>> **vbasedevp,
>>> + RAMBlock **first_rbp, Error **errp)
>>> +{
>>> + VFIODevice *vbasedev;
>>> + RAMBlock *first_rb;
>>> + ram_addr_t offset;
>>> +
>>> + first_rb = qemu_ram_block_from_host(iov[0].iov_base, false,
>> &offset);
>>> + if (!first_rb) {
>>> + error_setg(errp, "Could not find first ramblock\n");
>>
>> no \n
>>
>>
>>> + return false;
>>> + }
>>> +
>>> + *first_rbp = first_rb;
>>> + QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
>>
>> wrong list : global_next.
>>
>>
>>> + if (vbasedev->dev == first_rb->mr->dev) {
>>> + *vbasedevp = vbasedev;
>>> + return true;
>>> + }
>>> + }
>>> + error_setg(errp, "No VFIO device found to create dmabuf from\n");
>>
>> no \n
>>
>>> + return false;
>>> +}
>>> +
>>> +/*
>>> + * This helper looks up the VFIORegion corresponding to the given
>> address.
>>> + * It also verifies that the RAMBlock associated with the address is the
>>> + * same as the first_rb passed in. This is to ensure that all addresses
>>> + * in the iov belong to the same region.
>>> + */
>>> +static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
>>> + RAMBlock *first_rb, ram_addr_t *offsetp,
>>> + Error **errp)
>>> +{
>>> + VFIORegion *region;
>>> + RAMBlock *rb;
>>> +
>>> + rb = qemu_ram_block_from_host(addr, false, offsetp);
>>> + if (!rb || rb != first_rb) {
>>> + error_setg(errp, "Dmabuf segments must belong to the same
>> region\n");
>>
>> remove \n
>>
>>> + return false;
>>> + }
>>> +
>>> + region = vfio_get_region_from_mr(rb->mr);
>>> + if (region) {
>>> + *regionp = region;
>>> + return true;
>>> + }
>>> + error_setg(errp, "Could not find valid region for dmabuf segment\n");
>>
>> here too.
>>
>>> + return false;
>>> +}
>>> +
>>> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
>> iov_cnt,
>>> + Error **errp)
>>> +{
>>> + g_autofree struct vfio_device_feature *feature = NULL;
>>> + struct vfio_device_feature_dma_buf *dma_buf;
>>> + RAMBlock *first_rb = NULL;
>>> + VFIODevice *vbasedev;
>>> + VFIORegion *region;
>>> + ram_addr_t offset;
>>> + size_t argsz;
>>> + int i, ret;
>>> +
>>> + if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
>>> + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
>>
>> return -EINVAL;
>>
>>> + }
>>> +
>>> + argsz = sizeof(*feature) + sizeof (*dma_buf) +
>>> + sizeof(struct vfio_region_dma_range) * iov_cnt;
>>> + feature = g_malloc0(argsz);
>>> + *feature = (struct vfio_device_feature) {
>>> + .argsz = argsz,
>>> + .flags = VFIO_DEVICE_FEATURE_GET |
>> VFIO_DEVICE_FEATURE_DMA_BUF,
>>> + };
>>> + dma_buf = (struct vfio_device_feature_dma_buf *)feature->data;
>>> +
>>> + for (i = 0; i < iov_cnt; i++) {
>>> + if (!vfio_region_lookup(iov[i].iov_base, ®ion,
>>> + first_rb, &offset, errp)) {
>>> + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
>>
>> return -EINVAL;
>>
>>> + }
>>> +
>>> + dma_buf->region_index = region->nr;
>>> + dma_buf->dma_ranges[i].offset = offset;
>>> + dma_buf->dma_ranges[i].length = iov[i].iov_len;
>>> + }
>>> +
>>> + dma_buf->nr_ranges = iov_cnt;
>>> + dma_buf->open_flags = O_RDONLY | O_CLOEXEC;
>>> +
>>> + ret = vfio_device_get_feature(vbasedev, feature);
>>> + if (ret < 0) {
>>> + error_setg_errno(errp, -ret,
>>> + "Could not create dmabuf fd via VFIO device");
>>> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
>>
>> return ret;
>>
>>> + }
>>> + return ret;
>>> +}
>>> diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
>>> new file mode 100644
>>> index 0000000000..fb5318e929
>>> --- /dev/null
>>> +++ b/hw/vfio/dmabuf-stubs.c
>>
>> Fails to build on MinGW/Windows.
>>
>> hw/vfio/dmabuf-stubs.c:12:5: error: no previous prototype for
>> 'vfio_device_create_dmabuf_fd'
>> hw/vfio/dmabuf-stubs.c:19:7: error: no previous prototype for
>> 'vfio_device_mmap_dmabuf'
>>
>>
>>> @@ -0,0 +1,17 @@
>>> +/*
>>> + * Copyright (c) 2026 Intel and/or its affiliates.
>>> + *
>>> + * SPDX-License-Identifier: GPL-2.0-or-later
>>> + */
>>> +
>>> +#include "qemu/osdep.h"
>>> +#include "qemu/error-report.h"
>>> +#include "qemu/iov.h"
>>> +#include "hw/vfio/vfio-device.h"
>>> +
>>> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
>> iov_cnt,
>>> + Error **errp)
>>> +{
>>> + error_setg(errp, "VFIO dmabuf support is not enabled");
>>> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
>>
>> return -ENOTSUP;
>>
>>
>>> +}
>>> diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build
>>> index c7c31b78f6..aa6f4bc1b4 100644
>>> --- a/hw/vfio/meson.build
>>> +++ b/hw/vfio/meson.build
>>> @@ -38,3 +38,4 @@ stub_ss.add(files('iommufd-stubs.c'))
>>> system_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files(
>>> 'display.c',
>>> ))
>>> +system_ss.add(when: 'CONFIG_VFIO', if_false: files('dmabuf-stubs.c'))
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2026-10-12 14:00 ` Akihiko Odaki
@ 2026-10-13 3:57 ` Kasireddy, Vivek
0 siblings, 0 replies; 36+ messages in thread
From: Kasireddy, Vivek @ 2026-10-13 3:57 UTC (permalink / raw)
To: Akihiko Odaki, qemu-devel@nongnu.org
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
Hi Akihiko,
> Subject: Re: [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for
> blobs associated with VFIO devices
>
> >>>
> >>>>> 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_fd() API which identifies the right
> >>>>> VFIO device and eventually creates a dmabuf fd.
> >>>>>
> >>>>> Note that, for mmapping the dmabuf, we directly call mmap() if
> the
> >>>>> dmabuf fd was created via virtio_gpu_create_udmabuf() since we
> >>>> know
> >>>>> that the udmabuf driver supports mmap(). However, if the
> dmabuf
> >>>> was
> >>>>> created via vfio_device_create_dmabuf_fd(), we use the
> >>>>> vfio_device_mmap_dmabuf() API to get a mapping 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>
> >>>>> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> >>>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> >>>>> ---
> >>>>> hw/display/virtio-gpu-dmabuf.c | 22 +++++++++++++++++++---
> >>>>> 1 file changed, 19 insertions(+), 3 deletions(-)
> >>>>>
> >>>>> diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-
> gpu-
> >>>> dmabuf.c
> >>>>> index c9de8e9ba3..f59a5e76ff 100644
> >>>>> --- a/hw/display/virtio-gpu-dmabuf.c
> >>>>> +++ b/hw/display/virtio-gpu-dmabuf.c
> >>>>> @@ -153,9 +153,25 @@ bool virtio_gpu_init_dmabuf(struct
> >>>> virtio_gpu_simple_resource *res)
> >>>>> if (res->dmabuf_fd ==
> >>>> VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
> >>>>> error_free_or_abort(&local_err);
> >>>>>
> >>>>> - qemu_log_mask(LOG_GUEST_ERROR,
> >>>>> - "Cannot create dmabuf: incompatible
> memory\n");
> >>>>> - return false;
> >>>>> + res->dmabuf_fd = vfio_device_create_dmabuf_fd(res-
> >iov,
> >>>>> + res->iov_cnt,
> >>>>> + &local_err);
> >>>>> + if (res->dmabuf_fd ==
> >>>> VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
> >>>>> + error_free_or_abort(&local_err);
> >>>>> + qemu_log_mask(LOG_GUEST_ERROR,
> >>>>> + "Cannot create dmabuf: incompatible
> memory\n");
> >>>>> + return false;
> >>>>> + }
> >>>>> +
> >>>>> + if (res->dmabuf_fd >= 0) {
> >>>>> + pdata = vfio_device_mmap_dmabuf(res->iov, res-
> >iov_cnt,
> >>>>> + &local_err);
> >>>>
> >>>> This maps the complete IOV size, while virtio_gpu_fini_dmabuf()
> >>>> unmaps
> >>>> only blob_size. Create and attach accept backing larger than the
> blob,
> >>>> so excess pages remain mapped after detach, unref or reset.
> >>> Good catch. I'll add a check in virtio_gpu_fini_dmabuf() to
> determine if
> >>> IOV size > blob_size, then do munmap(res->remapped, IOV size);
> >>> I think this should be safe even if the mapping (created with mmap)
> >>> size is blob_size. Or, is there a better solution you can think of such
> as
> >>> tracking the exact mapping size in res object?
> >>
> >> Unmapping the IOV size is not safe if only blob_size was mapped:
> >> munmap() can also remove unrelated mappings in the excess range.
> > Ok, got it.
> >
> >>
> >> A cleaner fix is to update vfio_device_mmap_dmabuf() to take the
> size to
> >> map (or cap it to blob_size).
> > Currently, vfio_device_mmap_dmabuf() creates an IOV sized mapping,
> so it
> > is going to need extra logic to cap it to blob_size, which needs to be
> explicitly
> > passed in. So, are you ok with this given that you previously did not
> like the
> > idea of passing in blob_size as a parameter?
>
> Yes, I am fine with a mapping-length parameter for this purpose.
> I should have made the distinction clearer.
>
> Previously, total_size was required to equal the IOV size, adding
> blob-specific validation to the VFIO helper. That validation belongs
> in virtio-gpu.
>
> Here, the parameter specifies how much of the IOV to map, which can
> be less than its total size. That is a generic mapping operation;
> the helper does not need to know about blobs. We can name the
> parameter length and have virtio-gpu pass res->blob_size.
>
> The extra logic to stop at that length and shorten the final mapped
> segment as necessary is appropriate. This lets mapping and unmapping
> use the same length without additional tracking.
Ok, I'll make the change to have vfio_device_mmap_dmabuf() accept
a length parameter.
Thanks,
Vivek
>
> Regards,
> Akihiko Odaki
>
> >
> > Thanks,
> > Vivek
> >
> >> This keeps it symmetric with the udmabuf
> >> path and allows virtio_gpu_fini_dmabuf() to continue unmapping
> >> blob_size
> >> without needing extra tracking variables.
> >>
> >> Regards,
> >> Akihiko Odaki
> >>
> >>>
> >>> Thanks,
> >>> Vivek
> >>>>
> >>>> Regards,
> >>>> Akihiko Odaki
> >>>>
> >>>>> + if (!pdata) {
> >>>>> + virtio_gpu_fini_dmabuf(res);
> >>>>> + }
> >>>>> + } else {
> >>>>> + res->dmabuf_fd = -1;
> >>>>> + }
> >>>>> } else if (res->dmabuf_fd >= 0) {
> >>>>> pdata = virtio_gpu_remap_dmabuf(res, &local_err);
> >>>>> if (!pdata) {
> >>>
> >
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-12 14:01 ` Akihiko Odaki
@ 2026-10-13 4:06 ` Kasireddy, Vivek
2026-10-13 16:20 ` Cédric Le Goater
0 siblings, 1 reply; 36+ messages in thread
From: Kasireddy, Vivek @ 2026-10-13 4:06 UTC (permalink / raw)
To: Akihiko Odaki, Cédric Le Goater, qemu-devel@nongnu.org,
Markus Armbruster
Cc: Alex Williamson
Hi Akihiko,
> Subject: Re: [PATCH v13 6/9] vfio/device: Add support for creating
> dmabuf from multiple ranges
>
> >>
> >>> In order to create a dmabuf associated with a buffer that spans
> >>> multiple ranges, we first need to identify the VFIO region and
> >>> index the buffer (represented by iovec) belongs to and then
> >>> translate its addresses to offsets within that region.
> >>>
> >>> The qemu_ram_block_from_host() API gives us both the region and
> >>> the offset info we need to populate the dma ranges so that we can
> >>> invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the
> >> dmabuf.
> >>>
> >>> Also, instead of iterating over all QOM devices to find the
> >>> VFIODevice associated with a memory region, introduce a helper
> >>> to just use the vfio_device_list to lookup the VFIODevice.
> >>> And, introduce another helper to lookup the VFIO region given an
> >>> address.
> >>>
> >>> Lastly, introduce an enum to return the type of error encountered
> >>> while creating the dmabuf fd.
> >>>
> >>> Cc: Alex Williamson <alex@shazbot.org>
> >>> Cc: Cédric Le Goater <clg@redhat.com>
> >>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> >>> ---
> >>> include/hw/vfio/vfio-device.h | 22 +++++++
> >>> hw/vfio/device.c | 109
> ++++++++++++++++++++++++++++++++++
> >>> hw/vfio/dmabuf-stubs.c | 17 ++++++
> >>> hw/vfio/meson.build | 1 +
> >>> 4 files changed, 149 insertions(+)
> >>> create mode 100644 hw/vfio/dmabuf-stubs.c
> >>>
> >>> diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-
> >> device.h
> >>> index 8472420d3f..c05430be8a 100644
> >>> --- a/include/hw/vfio/vfio-device.h
> >>> +++ b/include/hw/vfio/vfio-device.h
> >>> @@ -41,6 +41,13 @@ enum {
> >>> VFIO_DEVICE_TYPE_AP = 3,
> >>> };
> >>>
> >>> +enum {
> >>> + /* The Guest passed addresses stored in IOV are invalid */
> >>> + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
> >>> + /* Guest or Host may be at fault for this type of error */
> >>> + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
> >>> +};
> >>
> >> Nack.
> >>
> >> As said a few times already : it's a VFIO-specific enum leaking
> >> into vfio-device.h to serve virtio-gpu's fallback logic. The
> >> cleanest alternative is to use standard -errno returns and
> >> make the fd an output parameter.
> > It looks like Cedric remains unconvinced about the value or usefulness
> > of this error enum. Therefore, to make progress, I intend to adopt his
> > suggestion to use standard -errno returns for the next version,
> considering
> > that this series has been stuck for a year.
> >
> > AFAICS, dropping this error enum means that we would not be able to
> > clearly identify and log (or attribute) Guest vs Host errors in virtio-gpu,
> > particularly the INVALID_IOV case. I am not sure if this can be
> considered
> > a significant limitation. However, if there is a reasonable middle
> ground
> > solution or an alternative that you can think of that does not involve
> > using VFIO error enums in virtio-gpu, then I would like to pursue that
> > instead.
>
> Cédric's comment is a reiteration of previous points, but his concrete
> code suggestion is new and brings to light some challenges with errno
> propagation.
>
> First, errno does not precisely match the required semantics. We need
> to
> distinguish lookup failures from the other errors. However, with your
> suggestion, lookup failures become -EINVAL and
> vfio_device_get_feature()
> also returns the same value when the backend lacks the operation,
> making
> it impossible to distinguish them.
>
> Propagating errno also requires extra care to preserve it when
> necessary. For patch "[PATCH v13 8/9] virtio-gpu-dmabuf: Improve error
> handling with 'Error **' and err enum", you suggested to add the
> "saved_errno" variable to save errno before error_setg_errno(). That is
> redundant because error_setg_errno() preserves errno. Realizing that
> requires careful attention.
>
> While we could spend effort fixing these issues, we can simply avoid the
> churn by not using errno.
>
> In any case, I agree keeping this stuck is not ideal while I don't think
> I can provide any further insights. So I'm inviting Markus Armbruster to
Looks like you forgot to cc Markus. I have added him now.
> this discussion. This is an area better handled by him, who maintains
> the error reporting facility, including include/qapi/error.h, which
> extensively documents codebase-wide error-handling convention.
>
> Markus, could you advise on the appropriate convention for returning
> this kind of classification alongside Error **? Your perspective
> across the codebase may help us settle on a consistent approach
> beyond the individual subsystems involved here. Perhaps you may
> improve
> the documentation according to a design decision made here.
Markus, here is some additional context from Akihiko as to why there is
a need to introduce an error enum in VFIO:
https://lore.kernel.org/qemu-devel/09f02fe2-63cb-4283-899e-4cffc5f60cf1@rsg.ci.i.u-tokyo.ac.jp/
>
> If anyone else has a clean middle-ground solution in the meantime, I
> would greatly appreciate your input as well.
I am not sure if it can be considered clean or elegant but one middle-ground
solution I can think of is to have (and use) the error enum just in virtio-gpu
only but associate EINVAL (return value of vfio_device_create_dmabuf_fd())
as the equivalent of INVALID_IOV. That is, the relevant code now becomes:
res->dmabuf_fd = virtio_gpu_create_udmabuf(res, &local_err);
if (res->dmabuf_fd == VIRTIO_GPU_DMABUF_CREATE_ERR_INVALID_IOV) {
error_free_or_abort(&local_err);
res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
res->iov_cnt,
&local_err);
if (res->dmabuf_fd == -EINVAL) {
error_free_or_abort(&local_err);
qemu_log_mask(LOG_GUEST_ERROR,
"Cannot create dmabuf: incompatible memory\n");
return false;
}
I think this is reasonable IMO, but is this proposal acceptable to you?
Thanks,
Vivek
>
> Regards,
> Akihiko Odaki
>
> >
> > Thanks,
> > Vivek
> >>
> >>
> >>> typedef struct VFIODeviceOps VFIODeviceOps;
> >>> typedef struct VFIODeviceIOOps VFIODeviceIOOps;
> >>> typedef struct VFIOMigration VFIOMigration;
> >>> @@ -323,6 +330,21 @@ bool
> vfio_device_has_region_cap(VFIODevice
> >> *vbasedev, int region, uint16_t cap_t
> >>>
> >>> int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
> >>> struct vfio_irq_info *info);
> >>> +
> >>> +/**
> >>> + * Create a dmabuf fd by first translating the addresses in the
> >>> + * iovec array into VFIO region offsets and then invoking the
> >>> + * VFIO_DEVICE_FEATURE_DMA_BUF feature.
> >>> + *
> >>> + * @iov: array of iovec entries associated with a buffer
> >>> + * @iov_cnt: number of entries in the iovec array
> >>> + * @errp: pointer to Error*, to store an error if it happens.
> >>> + *
> >>> + * Returns the created dmabuf fd or either
> >> VFIO_DMABUF_CREATE_ERR_UNSPEC
> >>> + * or VFIO_DMABUF_CREATE_ERR_INVALID_IOV on error.
> >>> + */
> >>> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
> >> iov_cnt,
> >>> + Error **errp);
> >>> #endif
> >>>
> >>> /* Returns 0 on success, or a negative errno. */
> >>> diff --git a/hw/vfio/device.c b/hw/vfio/device.c
> >>> index 4f11959633..d95503a5f1 100644
> >>> --- a/hw/vfio/device.c
> >>> +++ b/hw/vfio/device.c
> >>> @@ -21,7 +21,9 @@
> >>> #include "qemu/osdep.h"
> >>> #include <sys/ioctl.h>
> >>>
> >>> +#include "system/ramblock.h"
> >>> #include "hw/vfio/vfio-device.h"
> >>> +#include "hw/vfio/vfio-region.h"
> >>> #include "hw/vfio/pci.h"
> >>> #include "hw/core/iommu.h"
> >>> #include "trace.h"
> >>> @@ -667,3 +669,110 @@ static VFIODeviceIOOps
> >> vfio_device_io_ops_ioctl = {
> >>> .region_read = vfio_device_io_region_read,
> >>> .region_write = vfio_device_io_region_write,
> >>> };
> >>> +
> >>> +/*
> >>> + * This helper looks up the VFIODevice corresponding to the given
> iov.
> >> It
> >>> + * can be useful to determinine if a buffer (represented by the iov)
> >> belongs
> >>> + * to a VFIO device or not. This is mainly invoked when external
> >> components
> >>> + * such as virtio-gpu request creation of dmabuf fds for buffers
> that may
> >>> + * belong to a VFIO device.
> >>> + */
> >>> +static bool vfio_device_lookup(struct iovec *iov, VFIODevice
> >> **vbasedevp,
> >>> + RAMBlock **first_rbp, Error **errp)
> >>> +{
> >>> + VFIODevice *vbasedev;
> >>> + RAMBlock *first_rb;
> >>> + ram_addr_t offset;
> >>> +
> >>> + first_rb = qemu_ram_block_from_host(iov[0].iov_base, false,
> >> &offset);
> >>> + if (!first_rb) {
> >>> + error_setg(errp, "Could not find first ramblock\n");
> >>
> >> no \n
> >>
> >>
> >>> + return false;
> >>> + }
> >>> +
> >>> + *first_rbp = first_rb;
> >>> + QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
> >>
> >> wrong list : global_next.
> >>
> >>
> >>> + if (vbasedev->dev == first_rb->mr->dev) {
> >>> + *vbasedevp = vbasedev;
> >>> + return true;
> >>> + }
> >>> + }
> >>> + error_setg(errp, "No VFIO device found to create dmabuf
> from\n");
> >>
> >> no \n
> >>
> >>> + return false;
> >>> +}
> >>> +
> >>> +/*
> >>> + * This helper looks up the VFIORegion corresponding to the given
> >> address.
> >>> + * It also verifies that the RAMBlock associated with the address is
> the
> >>> + * same as the first_rb passed in. This is to ensure that all
> addresses
> >>> + * in the iov belong to the same region.
> >>> + */
> >>> +static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
> >>> + RAMBlock *first_rb, ram_addr_t *offsetp,
> >>> + Error **errp)
> >>> +{
> >>> + VFIORegion *region;
> >>> + RAMBlock *rb;
> >>> +
> >>> + rb = qemu_ram_block_from_host(addr, false, offsetp);
> >>> + if (!rb || rb != first_rb) {
> >>> + error_setg(errp, "Dmabuf segments must belong to the same
> >> region\n");
> >>
> >> remove \n
> >>
> >>> + return false;
> >>> + }
> >>> +
> >>> + region = vfio_get_region_from_mr(rb->mr);
> >>> + if (region) {
> >>> + *regionp = region;
> >>> + return true;
> >>> + }
> >>> + error_setg(errp, "Could not find valid region for dmabuf
> segment\n");
> >>
> >> here too.
> >>
> >>> + return false;
> >>> +}
> >>> +
> >>> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
> >> iov_cnt,
> >>> + Error **errp)
> >>> +{
> >>> + g_autofree struct vfio_device_feature *feature = NULL;
> >>> + struct vfio_device_feature_dma_buf *dma_buf;
> >>> + RAMBlock *first_rb = NULL;
> >>> + VFIODevice *vbasedev;
> >>> + VFIORegion *region;
> >>> + ram_addr_t offset;
> >>> + size_t argsz;
> >>> + int i, ret;
> >>> +
> >>> + if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
> >>> + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
> >>
> >> return -EINVAL;
> >>
> >>> + }
> >>> +
> >>> + argsz = sizeof(*feature) + sizeof (*dma_buf) +
> >>> + sizeof(struct vfio_region_dma_range) * iov_cnt;
> >>> + feature = g_malloc0(argsz);
> >>> + *feature = (struct vfio_device_feature) {
> >>> + .argsz = argsz,
> >>> + .flags = VFIO_DEVICE_FEATURE_GET |
> >> VFIO_DEVICE_FEATURE_DMA_BUF,
> >>> + };
> >>> + dma_buf = (struct vfio_device_feature_dma_buf *)feature-
> >data;
> >>> +
> >>> + for (i = 0; i < iov_cnt; i++) {
> >>> + if (!vfio_region_lookup(iov[i].iov_base, ®ion,
> >>> + first_rb, &offset, errp)) {
> >>> + return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
> >>
> >> return -EINVAL;
> >>
> >>> + }
> >>> +
> >>> + dma_buf->region_index = region->nr;
> >>> + dma_buf->dma_ranges[i].offset = offset;
> >>> + dma_buf->dma_ranges[i].length = iov[i].iov_len;
> >>> + }
> >>> +
> >>> + dma_buf->nr_ranges = iov_cnt;
> >>> + dma_buf->open_flags = O_RDONLY | O_CLOEXEC;
> >>> +
> >>> + ret = vfio_device_get_feature(vbasedev, feature);
> >>> + if (ret < 0) {
> >>> + error_setg_errno(errp, -ret,
> >>> + "Could not create dmabuf fd via VFIO device");
> >>> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
> >>
> >> return ret;
> >>
> >>> + }
> >>> + return ret;
> >>> +}
> >>> diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
> >>> new file mode 100644
> >>> index 0000000000..fb5318e929
> >>> --- /dev/null
> >>> +++ b/hw/vfio/dmabuf-stubs.c
> >>
> >> Fails to build on MinGW/Windows.
> >>
> >> hw/vfio/dmabuf-stubs.c:12:5: error: no previous prototype for
> >> 'vfio_device_create_dmabuf_fd'
> >> hw/vfio/dmabuf-stubs.c:19:7: error: no previous prototype for
> >> 'vfio_device_mmap_dmabuf'
> >>
> >>
> >>> @@ -0,0 +1,17 @@
> >>> +/*
> >>> + * Copyright (c) 2026 Intel and/or its affiliates.
> >>> + *
> >>> + * SPDX-License-Identifier: GPL-2.0-or-later
> >>> + */
> >>> +
> >>> +#include "qemu/osdep.h"
> >>> +#include "qemu/error-report.h"
> >>> +#include "qemu/iov.h"
> >>> +#include "hw/vfio/vfio-device.h"
> >>> +
> >>> +int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int
> >> iov_cnt,
> >>> + Error **errp)
> >>> +{
> >>> + error_setg(errp, "VFIO dmabuf support is not enabled");
> >>> + return VFIO_DMABUF_CREATE_ERR_UNSPEC;
> >>
> >> return -ENOTSUP;
> >>
> >>
> >>> +}
> >>> diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build
> >>> index c7c31b78f6..aa6f4bc1b4 100644
> >>> --- a/hw/vfio/meson.build
> >>> +++ b/hw/vfio/meson.build
> >>> @@ -38,3 +38,4 @@ stub_ss.add(files('iommufd-stubs.c'))
> >>> system_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files(
> >>> 'display.c',
> >>> ))
> >>> +system_ss.add(when: 'CONFIG_VFIO', if_false: files('dmabuf-
> stubs.c'))
> >
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-13 4:06 ` Kasireddy, Vivek
@ 2026-10-13 16:20 ` Cédric Le Goater
2026-10-14 2:17 ` Akihiko Odaki
2026-10-14 7:03 ` Markus Armbruster
0 siblings, 2 replies; 36+ messages in thread
From: Cédric Le Goater @ 2026-10-13 16:20 UTC (permalink / raw)
To: Kasireddy, Vivek, Akihiko Odaki, qemu-devel@nongnu.org,
Markus Armbruster
Cc: Alex Williamson
On 10/13/26 06:06, Kasireddy, Vivek wrote:
> Hi Akihiko,
>
>> Subject: Re: [PATCH v13 6/9] vfio/device: Add support for creating
>> dmabuf from multiple ranges
>>
>>>>
>>>>> In order to create a dmabuf associated with a buffer that spans
>>>>> multiple ranges, we first need to identify the VFIO region and
>>>>> index the buffer (represented by iovec) belongs to and then
>>>>> translate its addresses to offsets within that region.
>>>>>
>>>>> The qemu_ram_block_from_host() API gives us both the region and
>>>>> the offset info we need to populate the dma ranges so that we can
>>>>> invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the
>>>> dmabuf.
>>>>>
>>>>> Also, instead of iterating over all QOM devices to find the
>>>>> VFIODevice associated with a memory region, introduce a helper
>>>>> to just use the vfio_device_list to lookup the VFIODevice.
>>>>> And, introduce another helper to lookup the VFIO region given an
>>>>> address.
>>>>>
>>>>> Lastly, introduce an enum to return the type of error encountered
>>>>> while creating the dmabuf fd.
>>>>>
>>>>> Cc: Alex Williamson <alex@shazbot.org>
>>>>> Cc: Cédric Le Goater <clg@redhat.com>
>>>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
>>>>> ---
>>>>> include/hw/vfio/vfio-device.h | 22 +++++++
>>>>> hw/vfio/device.c | 109
>> ++++++++++++++++++++++++++++++++++
>>>>> hw/vfio/dmabuf-stubs.c | 17 ++++++
>>>>> hw/vfio/meson.build | 1 +
>>>>> 4 files changed, 149 insertions(+)
>>>>> create mode 100644 hw/vfio/dmabuf-stubs.c
>>>>>
>>>>> diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-
>>>> device.h
>>>>> index 8472420d3f..c05430be8a 100644
>>>>> --- a/include/hw/vfio/vfio-device.h
>>>>> +++ b/include/hw/vfio/vfio-device.h
>>>>> @@ -41,6 +41,13 @@ enum {
>>>>> VFIO_DEVICE_TYPE_AP = 3,
>>>>> };
>>>>>
>>>>> +enum {
>>>>> + /* The Guest passed addresses stored in IOV are invalid */
>>>>> + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
>>>>> + /* Guest or Host may be at fault for this type of error */
>>>>> + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
>>>>> +};
>>>>
>>>> Nack.
>>>>
>>>> As said a few times already : it's a VFIO-specific enum leaking
>>>> into vfio-device.h to serve virtio-gpu's fallback logic. The
>>>> cleanest alternative is to use standard -errno returns and
>>>> make the fd an output parameter.
>>> It looks like Cedric remains unconvinced about the value or usefulness
>>> of this error enum. Therefore, to make progress, I intend to adopt his
>>> suggestion to use standard -errno returns for the next version,
>> considering
>>> that this series has been stuck for a year.
>>>
>>> AFAICS, dropping this error enum means that we would not be able to
>>> clearly identify and log (or attribute) Guest vs Host errors in virtio-gpu,
>>> particularly the INVALID_IOV case. I am not sure if this can be
>> considered
>>> a significant limitation. However, if there is a reasonable middle
>> ground
>>> solution or an alternative that you can think of that does not involve
>>> using VFIO error enums in virtio-gpu, then I would like to pursue that
>>> instead.
>>
>> Cédric's comment is a reiteration of previous points, but his concrete
>> code suggestion is new and brings to light some challenges with errno
>> propagation.
>>
>> First, errno does not precisely match the required semantics. We need
>> to
>> distinguish lookup failures from the other errors. However, with your
>> suggestion, lookup failures become -EINVAL and
>> vfio_device_get_feature()
>> also returns the same value when the backend lacks the operation,
>> making
>> it impossible to distinguish them.
>>
>> Propagating errno also requires extra care to preserve it when
>> necessary. For patch "[PATCH v13 8/9] virtio-gpu-dmabuf: Improve error
>> handling with 'Error **' and err enum", you suggested to add the
>> "saved_errno" variable to save errno before error_setg_errno(). That is
>> redundant because error_setg_errno() preserves errno. Realizing that
>> requires careful attention.
>>
>> While we could spend effort fixing these issues, we can simply avoid the
>> churn by not using errno.
>>
>> In any case, I agree keeping this stuck is not ideal while I don't think
>> I can provide any further insights. So I'm inviting Markus Armbruster to
> Looks like you forgot to cc Markus. I have added him now.
>
>> this discussion. This is an area better handled by him, who maintains
>> the error reporting facility, including include/qapi/error.h, which
>> extensively documents codebase-wide error-handling convention.
>>
>> Markus, could you advise on the appropriate convention for returning
>> this kind of classification alongside Error **? Your perspective
>> across the codebase may help us settle on a consistent approach
>> beyond the individual subsystems involved here. Perhaps you may
>> improve
>> the documentation according to a design decision made here.
> Markus, here is some additional context from Akihiko as to why there is
> a need to introduce an error enum in VFIO:
> https://lore.kernel.org/qemu-devel/09f02fe2-63cb-4283-899e-4cffc5f60cf1@rsg.ci.i.u-tokyo.ac.jp/
>
>>
>> If anyone else has a clean middle-ground solution in the meantime, I
>> would greatly appreciate your input as well.
> I am not sure if it can be considered clean or elegant but one middle-ground
> solution I can think of is to have (and use) the error enum just in virtio-gpu
> only but associate EINVAL (return value of vfio_device_create_dmabuf_fd())
> as the equivalent of INVALID_IOV. That is, the relevant code now becomes:
>
> res->dmabuf_fd = virtio_gpu_create_udmabuf(res, &local_err);
> if (res->dmabuf_fd == VIRTIO_GPU_DMABUF_CREATE_ERR_INVALID_IOV) {
> error_free_or_abort(&local_err);
>
> res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
> res->iov_cnt,
> &local_err);
> if (res->dmabuf_fd == -EINVAL) {
> error_free_or_abort(&local_err);
> qemu_log_mask(LOG_GUEST_ERROR,
> "Cannot create dmabuf: incompatible memory\n");
> return false;
> }
>
> I think this is reasonable IMO, but is this proposal acceptable to you?
The return value drives control flow.
AFAICT, in virtio_gpu_init_dmabuf(), the only distinction that seems
to matter for control flow is : "should I try the next backend ?" and
that's EINVAL, which means "these addresses are incompatible with this
particular backend."
The guest-vs-host attribution for logging/debugging is in the errp
messages :
- "IOV memory address incompatible with udmabuf" : guest gave addresses udmabuf can't handle
- "No VFIO device found to create dmabuf from" : guest addresses don't map to a VFIO device
- "UDMABUF_CREATE_LIST: ioctl failed" + errno : host/kernel issue
The Error* object is designed to encode a human-readable attribution
in a return value. It carries the diagnostic detail and the return
code carries the machine action.
Now the flow,
udmabuf
├─ -EINVAL ──► VFIO
│ ├─ >= 0 ──► vfio_device_mmap_dmabuf ──► success
│ ├─ -EINVAL ──► guest error: incompatible memory
│ └─ other -errno ──► error_report_err ──► host error
│
├─ >= 0 ──► virtio_gpu_remap_dmabuf ──► success
│
├─ -ENODEV ──► error_report_err ──► fail (VFIO NOT tried)
├─ -ENOMEM ──► error_report_err ──► fail (VFIO NOT tried)
└─ other -errno ──► error_report_err ──► fail (VFIO NOT tried)
The fallback trigger should be widen to -EINVAL || -ENODEV.
How's that ?
Thanks,
C.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-12 6:27 ` Kasireddy, Vivek
2026-10-12 14:01 ` Akihiko Odaki
@ 2026-10-13 16:40 ` Cédric Le Goater
1 sibling, 0 replies; 36+ messages in thread
From: Cédric Le Goater @ 2026-10-13 16:40 UTC (permalink / raw)
To: Kasireddy, Vivek, odaki@rsg.ci.i.u-tokyo.ac.jp,
qemu-devel@nongnu.org
Cc: Alex Williamson
On 10/12/26 08:27, Kasireddy, Vivek wrote:
> Hi Akihiko,
>
>> Subject: Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf
>> from multiple ranges
>>
>>> In order to create a dmabuf associated with a buffer that spans
>>> multiple ranges, we first need to identify the VFIO region and
>>> index the buffer (represented by iovec) belongs to and then
>>> translate its addresses to offsets within that region.
>>>
>>> The qemu_ram_block_from_host() API gives us both the region and
>>> the offset info we need to populate the dma ranges so that we can
>>> invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the
>> dmabuf.
>>>
>>> Also, instead of iterating over all QOM devices to find the
>>> VFIODevice associated with a memory region, introduce a helper
>>> to just use the vfio_device_list to lookup the VFIODevice.
>>> And, introduce another helper to lookup the VFIO region given an
>>> address.
>>>
>>> Lastly, introduce an enum to return the type of error encountered
>>> while creating the dmabuf fd.
>>>
>>> Cc: Alex Williamson <alex@shazbot.org>
>>> Cc: Cédric Le Goater <clg@redhat.com>
>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
>>> ---
>>> include/hw/vfio/vfio-device.h | 22 +++++++
>>> hw/vfio/device.c | 109 ++++++++++++++++++++++++++++++++++
>>> hw/vfio/dmabuf-stubs.c | 17 ++++++
>>> hw/vfio/meson.build | 1 +
>>> 4 files changed, 149 insertions(+)
>>> create mode 100644 hw/vfio/dmabuf-stubs.c
>>>
>>> diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-
>> device.h
>>> index 8472420d3f..c05430be8a 100644
>>> --- a/include/hw/vfio/vfio-device.h
>>> +++ b/include/hw/vfio/vfio-device.h
>>> @@ -41,6 +41,13 @@ enum {
>>> VFIO_DEVICE_TYPE_AP = 3,
>>> };
>>>
>>> +enum {
>>> + /* The Guest passed addresses stored in IOV are invalid */
>>> + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
>>> + /* Guest or Host may be at fault for this type of error */
>>> + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
>>> +};
>>
>> Nack.
>>
>> As said a few times already : it's a VFIO-specific enum leaking
>> into vfio-device.h to serve virtio-gpu's fallback logic. The
>> cleanest alternative is to use standard -errno returns and
>> make the fd an output parameter.
> It looks like Cedric remains unconvinced about the value or usefulness
> of this error enum. Therefore, to make progress, I intend to adopt his
> suggestion to use standard -errno returns for the next version, considering
> that this series has been stuck for a year.
Well, v12 was sent in March and v13 in October; that's a 7-month gap.
If you want to make progress on a series, sending updates more than
twice a year helps a lot. Maintainers context-switch between many
series; long gaps mean re-reading everything from scratch each time.
That said, converging on standard -errno is the right pattern IMO.
Widening the fallback trigger to also cover -ENODEV would be a
nice improvement for v14.
Thanks,
C.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-13 16:20 ` Cédric Le Goater
@ 2026-10-14 2:17 ` Akihiko Odaki
2026-10-14 7:41 ` Cédric Le Goater
2026-10-14 7:03 ` Markus Armbruster
1 sibling, 1 reply; 36+ messages in thread
From: Akihiko Odaki @ 2026-10-14 2:17 UTC (permalink / raw)
To: Cédric Le Goater, Kasireddy, Vivek, qemu-devel@nongnu.org,
Markus Armbruster
Cc: Alex Williamson
On 2026/10/14 1:20, Cédric Le Goater wrote:
> On 10/13/26 06:06, Kasireddy, Vivek wrote:
>> Hi Akihiko,
>>
>>> Subject: Re: [PATCH v13 6/9] vfio/device: Add support for creating
>>> dmabuf from multiple ranges
>>>
>>>>>
>>>>>> In order to create a dmabuf associated with a buffer that spans
>>>>>> multiple ranges, we first need to identify the VFIO region and
>>>>>> index the buffer (represented by iovec) belongs to and then
>>>>>> translate its addresses to offsets within that region.
>>>>>>
>>>>>> The qemu_ram_block_from_host() API gives us both the region and
>>>>>> the offset info we need to populate the dma ranges so that we can
>>>>>> invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the
>>>>> dmabuf.
>>>>>>
>>>>>> Also, instead of iterating over all QOM devices to find the
>>>>>> VFIODevice associated with a memory region, introduce a helper
>>>>>> to just use the vfio_device_list to lookup the VFIODevice.
>>>>>> And, introduce another helper to lookup the VFIO region given an
>>>>>> address.
>>>>>>
>>>>>> Lastly, introduce an enum to return the type of error encountered
>>>>>> while creating the dmabuf fd.
>>>>>>
>>>>>> Cc: Alex Williamson <alex@shazbot.org>
>>>>>> Cc: Cédric Le Goater <clg@redhat.com>
>>>>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
>>>>>> ---
>>>>>> include/hw/vfio/vfio-device.h | 22 +++++++
>>>>>> hw/vfio/device.c | 109
>>> ++++++++++++++++++++++++++++++++++
>>>>>> hw/vfio/dmabuf-stubs.c | 17 ++++++
>>>>>> hw/vfio/meson.build | 1 +
>>>>>> 4 files changed, 149 insertions(+)
>>>>>> create mode 100644 hw/vfio/dmabuf-stubs.c
>>>>>>
>>>>>> diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-
>>>>> device.h
>>>>>> index 8472420d3f..c05430be8a 100644
>>>>>> --- a/include/hw/vfio/vfio-device.h
>>>>>> +++ b/include/hw/vfio/vfio-device.h
>>>>>> @@ -41,6 +41,13 @@ enum {
>>>>>> VFIO_DEVICE_TYPE_AP = 3,
>>>>>> };
>>>>>>
>>>>>> +enum {
>>>>>> + /* The Guest passed addresses stored in IOV are invalid */
>>>>>> + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
>>>>>> + /* Guest or Host may be at fault for this type of error */
>>>>>> + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
>>>>>> +};
>>>>>
>>>>> Nack.
>>>>>
>>>>> As said a few times already : it's a VFIO-specific enum leaking
>>>>> into vfio-device.h to serve virtio-gpu's fallback logic. The
>>>>> cleanest alternative is to use standard -errno returns and
>>>>> make the fd an output parameter.
>>>> It looks like Cedric remains unconvinced about the value or usefulness
>>>> of this error enum. Therefore, to make progress, I intend to adopt his
>>>> suggestion to use standard -errno returns for the next version,
>>> considering
>>>> that this series has been stuck for a year.
>>>>
>>>> AFAICS, dropping this error enum means that we would not be able to
>>>> clearly identify and log (or attribute) Guest vs Host errors in
>>>> virtio-gpu,
>>>> particularly the INVALID_IOV case. I am not sure if this can be
>>> considered
>>>> a significant limitation. However, if there is a reasonable middle
>>> ground
>>>> solution or an alternative that you can think of that does not involve
>>>> using VFIO error enums in virtio-gpu, then I would like to pursue that
>>>> instead.
>>>
>>> Cédric's comment is a reiteration of previous points, but his concrete
>>> code suggestion is new and brings to light some challenges with errno
>>> propagation.
>>>
>>> First, errno does not precisely match the required semantics. We need
>>> to
>>> distinguish lookup failures from the other errors. However, with your
>>> suggestion, lookup failures become -EINVAL and
>>> vfio_device_get_feature()
>>> also returns the same value when the backend lacks the operation,
>>> making
>>> it impossible to distinguish them.
>>>
>>> Propagating errno also requires extra care to preserve it when
>>> necessary. For patch "[PATCH v13 8/9] virtio-gpu-dmabuf: Improve error
>>> handling with 'Error **' and err enum", you suggested to add the
>>> "saved_errno" variable to save errno before error_setg_errno(). That is
>>> redundant because error_setg_errno() preserves errno. Realizing that
>>> requires careful attention.
>>>
>>> While we could spend effort fixing these issues, we can simply avoid the
>>> churn by not using errno.
>>>
>>> In any case, I agree keeping this stuck is not ideal while I don't think
>>> I can provide any further insights. So I'm inviting Markus Armbruster to
>> Looks like you forgot to cc Markus. I have added him now.
>>
>>> this discussion. This is an area better handled by him, who maintains
>>> the error reporting facility, including include/qapi/error.h, which
>>> extensively documents codebase-wide error-handling convention.
>>>
>>> Markus, could you advise on the appropriate convention for returning
>>> this kind of classification alongside Error **? Your perspective
>>> across the codebase may help us settle on a consistent approach
>>> beyond the individual subsystems involved here. Perhaps you may
>>> improve
>>> the documentation according to a design decision made here.
>> Markus, here is some additional context from Akihiko as to why there is
>> a need to introduce an error enum in VFIO:
>> https://lore.kernel.org/qemu-
>> devel/09f02fe2-63cb-4283-899e-4cffc5f60cf1@rsg.ci.i.u-tokyo.ac.jp/
>>
>>>
>>> If anyone else has a clean middle-ground solution in the meantime, I
>>> would greatly appreciate your input as well.
>> I am not sure if it can be considered clean or elegant but one middle-
>> ground
>> solution I can think of is to have (and use) the error enum just in
>> virtio-gpu
>> only but associate EINVAL (return value of
>> vfio_device_create_dmabuf_fd())
>> as the equivalent of INVALID_IOV. That is, the relevant code now becomes:
>>
>> res->dmabuf_fd = virtio_gpu_create_udmabuf(res, &local_err);
>> if (res->dmabuf_fd ==
>> VIRTIO_GPU_DMABUF_CREATE_ERR_INVALID_IOV) {
>> error_free_or_abort(&local_err);
>>
>> res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
>> res->iov_cnt,
>> &local_err);
>> if (res->dmabuf_fd == -EINVAL) {
>> error_free_or_abort(&local_err);
>> qemu_log_mask(LOG_GUEST_ERROR,
>> "Cannot create dmabuf: incompatible
>> memory\n");
>> return false;
>> }
>>
>> I think this is reasonable IMO, but is this proposal acceptable to you?
>
> The return value drives control flow.
>
> AFAICT, in virtio_gpu_init_dmabuf(), the only distinction that seems
> to matter for control flow is : "should I try the next backend ?" and
> that's EINVAL, which means "these addresses are incompatible with this
> particular backend."
>
> The guest-vs-host attribution for logging/debugging is in the errp
> messages :
>
> - "IOV memory address incompatible with udmabuf" : guest gave
> addresses udmabuf can't handle
> - "No VFIO device found to create dmabuf from" : guest addresses
> don't map to a VFIO device
> - "UDMABUF_CREATE_LIST: ioctl failed" + errno : host/kernel issue
>
> The Error* object is designed to encode a human-readable attribution
> in a return value. It carries the diagnostic detail and the return
> code carries the machine action.
>
> Now the flow,
>
> udmabuf
> ├─ -EINVAL ──► VFIO
> │ ├─ >= 0 ──► vfio_device_mmap_dmabuf ──► success
> │ ├─ -EINVAL ──► guest error: incompatible memory
> │ └─ other -errno ──► error_report_err ──► host error
> │
> ├─ >= 0 ──► virtio_gpu_remap_dmabuf ──► success
> │
> ├─ -ENODEV ──► error_report_err ──► fail (VFIO NOT tried)
> ├─ -ENOMEM ──► error_report_err ──► fail (VFIO NOT tried)
> └─ other -errno ──► error_report_err ──► fail (VFIO NOT tried)
>
>
> The fallback trigger should be widen to -EINVAL || -ENODEV.
>
> How's that ?
Choosing between qemu_log_mask(LOG_GUEST_ERROR, ...) and
error_report_err() is also a machine decision. The caller needs to
distinguish incompatible backing from other failures to select the
reporting path; human-readable attribution in Error * is insufficient.
The -EINVAL ambiguity therefore remains. vfio_device_get_feature()
also returns -EINVAL when the backend lacks the operation. If we
propagate that unchanged, your diagram classifies it as incompatible
guest memory. Using -EINVAL for that classification requires an
explicit mapping that keeps these other failures distinct.
Regarding -ENODEV, virtio_gpu_device_realize() already requires
virtio_gpu_have_udmabuf() for this blob path. udmabuf_fd() caches the
opened fd, so the availability-related -ENODEV should not occur
after successful realization.
Regards,
Akihiko Odaki
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-13 16:20 ` Cédric Le Goater
2026-10-14 2:17 ` Akihiko Odaki
@ 2026-10-14 7:03 ` Markus Armbruster
2026-10-14 13:07 ` Akihiko Odaki
1 sibling, 1 reply; 36+ messages in thread
From: Markus Armbruster @ 2026-10-14 7:03 UTC (permalink / raw)
To: Cédric Le Goater
Cc: Kasireddy, Vivek, Akihiko Odaki, qemu-devel@nongnu.org,
Alex Williamson
Cédric Le Goater <clg@redhat.com> writes:
> On 10/13/26 06:06, Kasireddy, Vivek wrote:
>> Hi Akihiko,
>>
>>> Subject: Re: [PATCH v13 6/9] vfio/device: Add support for creating
>>> dmabuf from multiple ranges
>>>
>>>>>
>>>>>> In order to create a dmabuf associated with a buffer that spans
>>>>>> multiple ranges, we first need to identify the VFIO region and
>>>>>> index the buffer (represented by iovec) belongs to and then
>>>>>> translate its addresses to offsets within that region.
>>>>>>
>>>>>> The qemu_ram_block_from_host() API gives us both the region and
>>>>>> the offset info we need to populate the dma ranges so that we can
>>>>>> invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the dmabuf.
>>>>>>
>>>>>> Also, instead of iterating over all QOM devices to find the
>>>>>> VFIODevice associated with a memory region, introduce a helper
>>>>>> to just use the vfio_device_list to lookup the VFIODevice.
>>>>>> And, introduce another helper to lookup the VFIO region given an
>>>>>> address.
>>>>>>
>>>>>> Lastly, introduce an enum to return the type of error encountered
>>>>>> while creating the dmabuf fd.
>>>>>>
>>>>>> Cc: Alex Williamson <alex@shazbot.org>
>>>>>> Cc: Cédric Le Goater <clg@redhat.com>
>>>>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
>>>>>> ---
>>>>>> include/hw/vfio/vfio-device.h | 22 +++++++
>>>>>> hw/vfio/device.c | 109 ++++++++++++++++++++++++++++++++++
>>>>>> hw/vfio/dmabuf-stubs.c | 17 ++++++
>>>>>> hw/vfio/meson.build | 1 +
>>>>>> 4 files changed, 149 insertions(+)
>>>>>> create mode 100644 hw/vfio/dmabuf-stubs.c
>>>>>>
>>>>>> diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
>>>>>> index 8472420d3f..c05430be8a 100644
>>>>>> --- a/include/hw/vfio/vfio-device.h
>>>>>> +++ b/include/hw/vfio/vfio-device.h
>>>>>> @@ -41,6 +41,13 @@ enum {
>>>>>> VFIO_DEVICE_TYPE_AP = 3,
>>>>>> };
>>>>>>
>>>>>> +enum {
>>>>>> + /* The Guest passed addresses stored in IOV are invalid */
>>>>>> + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
>>>>>> + /* Guest or Host may be at fault for this type of error */
>>>>>> + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
>>>>>> +};
>>>>>
>>>>> Nack.
>>>>>
>>>>> As said a few times already : it's a VFIO-specific enum leaking
>>>>> into vfio-device.h to serve virtio-gpu's fallback logic. The
>>>>> cleanest alternative is to use standard -errno returns and
>>>>> make the fd an output parameter.
>>>> It looks like Cedric remains unconvinced about the value or usefulness
>>>> of this error enum. Therefore, to make progress, I intend to adopt his
>>>> suggestion to use standard -errno returns for the next version, considering
>>>> that this series has been stuck for a year.
>>>>
>>>> AFAICS, dropping this error enum means that we would not be able to
>>>> clearly identify and log (or attribute) Guest vs Host errors in virtio-gpu,
>>>> particularly the INVALID_IOV case. I am not sure if this can be considered
>>>> a significant limitation. However, if there is a reasonable middle ground
>>>> solution or an alternative that you can think of that does not involve
>>>> using VFIO error enums in virtio-gpu, then I would like to pursue that
>>>> instead.
>>>
>>> Cédric's comment is a reiteration of previous points, but his concrete
>>> code suggestion is new and brings to light some challenges with errno
>>> propagation.
>>>
>>> First, errno does not precisely match the required semantics. We need
>>> to
>>> distinguish lookup failures from the other errors. However, with your
>>> suggestion, lookup failures become -EINVAL and
>>> vfio_device_get_feature()
>>> also returns the same value when the backend lacks the operation,
>>> making
>>> it impossible to distinguish them.
This matters only when something actually needs to distinguish them.
If -EINVAL on lookup failure bothers you, consider -ENOENT.
>>> Propagating errno also requires extra care to preserve it when
>>> necessary. For patch "[PATCH v13 8/9] virtio-gpu-dmabuf: Improve error
>>> handling with 'Error **' and err enum", you suggested to add the
>>> "saved_errno" variable to save errno before error_setg_errno(). That is
>>> redundant because error_setg_errno() preserves errno. Realizing that
>>> requires careful attention.
>>>
>>> While we could spend effort fixing these issues, we can simply avoid the
>>> churn by not using errno.
Two separate styles:
1. Libc commonly sets @errno and returns a single error value. Care may
indeed be necessary to preserve errno when passing errors up the
stack in this style.
2. We commonly use negative errno codes as error values. Preserving
@errno is a non-issue then.
>>> In any case, I agree keeping this stuck is not ideal while I don't think
>>> I can provide any further insights. So I'm inviting Markus Armbruster to
>> Looks like you forgot to cc Markus. I have added him now.
>>
>>> this discussion. This is an area better handled by him, who maintains
>>> the error reporting facility, including include/qapi/error.h, which
>>> extensively documents codebase-wide error-handling convention.
>>>
>>> Markus, could you advise on the appropriate convention for returning
>>> this kind of classification alongside Error **? Your perspective
>>> across the codebase may help us settle on a consistent approach
>>> beyond the individual subsystems involved here. Perhaps you may
>>> improve
>>> the documentation according to a design decision made here.
error.h indeed recommends use of negative integers as error values, but
doesn't recommend any particular encoding. Perhaps it should mention
the common practice of using negative errno codes.
>> Markus, here is some additional context from Akihiko as to why there is
>> a need to introduce an error enum in VFIO:
>> https://lore.kernel.org/qemu-devel/09f02fe2-63cb-4283-899e-4cffc5f60cf1@rsg.ci.i.u-tokyo.ac.jp/
>>
>>>
>>> If anyone else has a clean middle-ground solution in the meantime, I
>>> would greatly appreciate your input as well.
>> I am not sure if it can be considered clean or elegant but one middle-ground
>> solution I can think of is to have (and use) the error enum just in virtio-gpu
>> only but associate EINVAL (return value of vfio_device_create_dmabuf_fd())
>> as the equivalent of INVALID_IOV. That is, the relevant code now becomes:
>> res->dmabuf_fd = virtio_gpu_create_udmabuf(res, &local_err);
>> if (res->dmabuf_fd == VIRTIO_GPU_DMABUF_CREATE_ERR_INVALID_IOV) {
>> error_free_or_abort(&local_err);
>> res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
>> res->iov_cnt,
>> &local_err);
>> if (res->dmabuf_fd == -EINVAL) {
>> error_free_or_abort(&local_err);
>> qemu_log_mask(LOG_GUEST_ERROR,
>> "Cannot create dmabuf: incompatible memory\n");
>> return false;
>> }
>> I think this is reasonable IMO, but is this proposal acceptable to you?
>
> The return value drives control flow.
>
> AFAICT, in virtio_gpu_init_dmabuf(), the only distinction that seems
> to matter for control flow is : "should I try the next backend ?" and
> that's EINVAL, which means "these addresses are incompatible with this
> particular backend."
>
> The guest-vs-host attribution for logging/debugging is in the errp
> messages :
>
> - "IOV memory address incompatible with udmabuf" : guest gave addresses udmabuf can't handle
> - "No VFIO device found to create dmabuf from" : guest addresses don't map to a VFIO device
> - "UDMABUF_CREATE_LIST: ioctl failed" + errno : host/kernel issue
>
> The Error* object is designed to encode a human-readable attribution
> in a return value. It carries the diagnostic detail and the return
> code carries the machine action.
Yes, this is the overwhelmingly common way to do this[*].
When all errors are handled the same, a single return value signifying
failure suffices. When callers need to handle different values
differently, which is rare, we need several error values. Negative
errno is often convenient then. Sometimes, it's a bad fit, so we come
up with some other set of error codes.
Regardless, error values need to be clearly documented.
To decide what error values to use, you should start with how errors are
handled. Design for that. In a library, you may not know. But when
you do, resist the temptation to encode all possible errors perfectly.
KISS. You can always make it more complicated when new callers require
it.
Does this help? If not, try asking pointed questions.
[...]
[*] There's also the ErrorClass carried by Error objects. It was meant
to carry the machine action, but it turned out to be a costly failure.
Use of error classes other than ERROR_CLASS_GENERIC_ERROR is strongly
discouraged.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-14 2:17 ` Akihiko Odaki
@ 2026-10-14 7:41 ` Cédric Le Goater
2026-10-14 16:40 ` Cédric Le Goater
0 siblings, 1 reply; 36+ messages in thread
From: Cédric Le Goater @ 2026-10-14 7:41 UTC (permalink / raw)
To: Akihiko Odaki, Kasireddy, Vivek, qemu-devel@nongnu.org,
Markus Armbruster
Cc: Alex Williamson
Hello !
[ ... ]
> Choosing between qemu_log_mask(LOG_GUEST_ERROR, ...) and
> error_report_err() is also a machine decision. The caller needs to
> distinguish incompatible backing from other failures to select the
> reporting path; human-readable attribution in Error * is insufficient.
>
> The -EINVAL ambiguity therefore remains. vfio_device_get_feature()
> also returns -EINVAL when the backend lacks the operation. If we
> propagate that unchanged, your diagram classifies it as incompatible
> guest memory. Using -EINVAL for that classification requires an
> explicit mapping that keeps these other failures distinct.
>
> Regarding -ENODEV, virtio_gpu_device_realize() already requires
> virtio_gpu_have_udmabuf() for this blob path. udmabuf_fd() caches the
> opened fd, so the availability-related -ENODEV should not occur
> after successful realization.
You raise valid points :
* -EINVAL from vfio_device_get_feature(): You're right. That needs a
remap to avoid the -EINVAL collision.
* -ENODEV: Correct, I'll drop that suggestion.
So, we just need the one-line remap above to avoid the -EINVAL collision.
See a proposal here :
https://github.com/legoater/qemu/commits/virtio-gpu-dmabuf
Fixup patch :
https://github.com/legoater/qemu/commit/653c41e89468f82bbdfcaeafe75473b84f5a1e49
Also below,
Thanks,
C.
From 653c41e89468f82bbdfcaeafe75473b84f5a1e49 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
Date: Wed, 14 Oct 2026 00:00:00 +0200
Subject: [PATCH] vfio, virtio-gpu-dmabuf: Replace custom error enum with
standard -errno
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Drop the VFIO_DMABUF_CREATE_ERR_{INVALID_IOV,UNSPEC} enum from
vfio-device.h and use standard negative errno values instead:
- -EINVAL: iov addresses are incompatible with this dmabuf backend
- -ENODEV: required backend (udmabuf device) is unavailable
- -ENOMEM: allocation failure
- -EIO: VFIO feature call failed
- -ENOTSUP: VFIO not compiled in
- other -errno: forwarded from kernel VFIO ioctl
Remap -EINVAL from vfio_device_get_feature() to -EIO so that a
"feature not supported" error is not misclassified by the caller
as "addresses incompatible with this backend".
The virtio-gpu fallback logic (try udmabuf, then VFIO) can now check
-EINVAL.
Also fix several issues in the same code:
- vfio_device_lookup: use global_next (not next) for vfio_device_list
- Move vfio_device_create_dmabuf_fd/vfio_device_mmap_dmabuf
declarations outside #ifdef CONFIG_VFIO guard so prototypes are
visible to the stubs (fixes MinGW build)
- Remove trailing \n and trailing space from error_setg messages
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
include/hw/vfio/vfio-device.h | 17 +++++++----------
hw/display/virtio-gpu-dmabuf.c | 22 ++++++++++++----------
hw/vfio/device.c | 21 +++++++++++----------
hw/vfio/dmabuf-stubs.c | 2 +-
4 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index 4b8fb6205604..473623240877 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -41,13 +41,6 @@ enum {
VFIO_DEVICE_TYPE_AP = 3,
};
-enum {
- /* The Guest passed addresses stored in IOV are invalid */
- VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
- /* Guest or Host may be at fault for this type of error */
- VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
-};
-
typedef struct VFIODeviceOps VFIODeviceOps;
typedef struct VFIODeviceIOOps VFIODeviceIOOps;
typedef struct VFIOMigration VFIOMigration;
@@ -331,6 +324,8 @@ bool vfio_device_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_t
int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
struct vfio_irq_info *info);
+#endif
+
/**
* Create a dmabuf fd by first translating the addresses in the
* iovec array into VFIO region offsets and then invoking the
@@ -340,8 +335,11 @@ int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
* @iov_cnt: number of entries in the iovec array
* @errp: pointer to Error*, to store an error if it happens.
*
- * Returns the created dmabuf fd or either VFIO_DMABUF_CREATE_ERR_UNSPEC
- * or VFIO_DMABUF_CREATE_ERR_INVALID_IOV on error.
+ * Returns the dmabuf fd (>= 0) on success, or a negative errno:
+ * - -EINVAL: iov addresses do not belong to a VFIO device
+ * - -EIO: VFIO feature call failed
+ * - -ENOTSUP: VFIO not compiled in
+ * - other negative errno from the kernel VFIO ioctl
*/
int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
Error **errp);
@@ -360,7 +358,6 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
*/
void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
Error **errp);
-#endif
/* Returns 0 on success, or a negative errno. */
bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp);
diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
index f59a5e76ff3c..82769eed442a 100644
--- a/hw/display/virtio-gpu-dmabuf.c
+++ b/hw/display/virtio-gpu-dmabuf.c
@@ -39,21 +39,21 @@ static int virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res,
udmabuf = udmabuf_fd();
if (udmabuf < 0) {
error_setg(errp, "udmabuf device not available or enabled");
- return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ return -ENODEV;
}
list = g_try_malloc0(sizeof(struct udmabuf_create_list) +
sizeof(struct udmabuf_create_item) * res->iov_cnt);
if (!list) {
error_setg(errp, "failed to allocate udmabuf create list");
- return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ return -ENOMEM;
}
for (i = 0; i < res->iov_cnt; i++) {
rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
if (!rb || rb->fd < 0) {
- error_setg(errp, "IOV memory address incompatible with udmabuf ");
- return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ error_setg(errp, "IOV memory address incompatible with udmabuf");
+ return -EINVAL;
}
list->list[i].memfd = rb->fd;
@@ -66,11 +66,13 @@ static int virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res,
fd = ioctl(udmabuf, UDMABUF_CREATE_LIST, list);
if (fd < 0) {
- error_setg_errno(errp, errno, "UDMABUF_CREATE_LIST: ioctl failed");
- if (errno == EINVAL || errno == EBADFD) {
- return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ int saved_errno = errno;
+
+ error_setg_errno(errp, saved_errno, "UDMABUF_CREATE_LIST: ioctl failed");
+ if (saved_errno == EINVAL || saved_errno == EBADFD) {
+ return -EINVAL;
}
- return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ return -saved_errno;
}
return fd;
}
@@ -150,13 +152,13 @@ bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
pdata = res->iov[0].iov_base;
} else if (res->blob_size) {
res->dmabuf_fd = virtio_gpu_create_udmabuf(res, &local_err);
- if (res->dmabuf_fd == VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
+ if (res->dmabuf_fd == -EINVAL) {
error_free_or_abort(&local_err);
res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
res->iov_cnt,
&local_err);
- if (res->dmabuf_fd == VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
+ if (res->dmabuf_fd == -EINVAL) {
error_free_or_abort(&local_err);
qemu_log_mask(LOG_GUEST_ERROR,
"Cannot create dmabuf: incompatible memory\n");
diff --git a/hw/vfio/device.c b/hw/vfio/device.c
index 5bc044376441..28cb23f3df6a 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -686,18 +686,18 @@ static bool vfio_device_lookup(struct iovec *iov, VFIODevice **vbasedevp,
first_rb = qemu_ram_block_from_host(iov[0].iov_base, false, &offset);
if (!first_rb) {
- error_setg(errp, "Could not find first ramblock\n");
+ error_setg(errp, "Could not find first ramblock");
return false;
}
*first_rbp = first_rb;
- QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
+ QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) {
if (vbasedev->dev == first_rb->mr->dev) {
*vbasedevp = vbasedev;
return true;
}
}
- error_setg(errp, "No VFIO device found to create dmabuf from\n");
+ error_setg(errp, "No VFIO device found to create dmabuf from");
return false;
}
@@ -716,7 +716,7 @@ static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
rb = qemu_ram_block_from_host(addr, false, offsetp);
if (!rb || rb != first_rb) {
- error_setg(errp, "Dmabuf segments must belong to the same region\n");
+ error_setg(errp, "Dmabuf segments must belong to the same region");
return false;
}
@@ -725,7 +725,7 @@ static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
*regionp = region;
return true;
}
- error_setg(errp, "Could not find valid region for dmabuf segment\n");
+ error_setg(errp, "Could not find valid region for dmabuf segment");
return false;
}
@@ -742,7 +742,7 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
int i, ret;
if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
- return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ return -EINVAL;
}
argsz = sizeof(*feature) + sizeof (*dma_buf) +
@@ -757,7 +757,7 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
for (i = 0; i < iov_cnt; i++) {
if (!vfio_region_lookup(iov[i].iov_base, ®ion,
first_rb, &offset, errp)) {
- return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ return -EINVAL;
}
dma_buf->region_index = region->nr;
@@ -772,7 +772,8 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
if (ret < 0) {
error_setg_errno(errp, -ret,
"Could not create dmabuf fd via VFIO device");
- return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ /* Remap -EINVAL: caller uses it to mean "addresses incompatible" */
+ return (ret == -EINVAL) ? -EIO : ret;
}
return ret;
}
@@ -811,7 +812,7 @@ void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
}
if (vfio_device_get_region_info(vbasedev, region->nr, &info)) {
- error_setg(errp, "Cannot find region info for dmabuf segment\n");
+ error_setg(errp, "Cannot find region info for dmabuf segment");
goto err;
}
@@ -819,7 +820,7 @@ void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
MAP_SHARED | MAP_FIXED, vbasedev->fd,
info->offset + offset);
if (submap == MAP_FAILED) {
- error_setg_errno(errp, errno, "Could not mmap dmabuf segment\n");
+ error_setg_errno(errp, errno, "Could not mmap dmabuf segment");
goto err;
}
len += iov[i].iov_len;
diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
index b9e03a162a75..241a9761ef5e 100644
--- a/hw/vfio/dmabuf-stubs.c
+++ b/hw/vfio/dmabuf-stubs.c
@@ -13,7 +13,7 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
Error **errp)
{
error_setg(errp, "VFIO dmabuf support is not enabled");
- return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ return -ENOTSUP;
}
void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
--
2.56.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-14 7:03 ` Markus Armbruster
@ 2026-10-14 13:07 ` Akihiko Odaki
2026-10-14 16:29 ` Cédric Le Goater
0 siblings, 1 reply; 36+ messages in thread
From: Akihiko Odaki @ 2026-10-14 13:07 UTC (permalink / raw)
To: Markus Armbruster, Cédric Le Goater
Cc: Kasireddy, Vivek, qemu-devel@nongnu.org, Alex Williamson
On 2026/10/14 16:03, Markus Armbruster wrote:
> Cédric Le Goater <clg@redhat.com> writes:
>
>> On 10/13/26 06:06, Kasireddy, Vivek wrote:
>>> Hi Akihiko,
>>>
>>>> Subject: Re: [PATCH v13 6/9] vfio/device: Add support for creating
>>>> dmabuf from multiple ranges
>>>>
>>>>>>
>>>>>>> In order to create a dmabuf associated with a buffer that spans
>>>>>>> multiple ranges, we first need to identify the VFIO region and
>>>>>>> index the buffer (represented by iovec) belongs to and then
>>>>>>> translate its addresses to offsets within that region.
>>>>>>>
>>>>>>> The qemu_ram_block_from_host() API gives us both the region and
>>>>>>> the offset info we need to populate the dma ranges so that we can
>>>>>>> invoke the VFIO_DEVICE_FEATURE_DMA_BUF feature to create the dmabuf.
>>>>>>>
>>>>>>> Also, instead of iterating over all QOM devices to find the
>>>>>>> VFIODevice associated with a memory region, introduce a helper
>>>>>>> to just use the vfio_device_list to lookup the VFIODevice.
>>>>>>> And, introduce another helper to lookup the VFIO region given an
>>>>>>> address.
>>>>>>>
>>>>>>> Lastly, introduce an enum to return the type of error encountered
>>>>>>> while creating the dmabuf fd.
>>>>>>>
>>>>>>> Cc: Alex Williamson <alex@shazbot.org>
>>>>>>> Cc: Cédric Le Goater <clg@redhat.com>
>>>>>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
>>>>>>> ---
>>>>>>> include/hw/vfio/vfio-device.h | 22 +++++++
>>>>>>> hw/vfio/device.c | 109 ++++++++++++++++++++++++++++++++++
>>>>>>> hw/vfio/dmabuf-stubs.c | 17 ++++++
>>>>>>> hw/vfio/meson.build | 1 +
>>>>>>> 4 files changed, 149 insertions(+)
>>>>>>> create mode 100644 hw/vfio/dmabuf-stubs.c
>>>>>>>
>>>>>>> diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
>>>>>>> index 8472420d3f..c05430be8a 100644
>>>>>>> --- a/include/hw/vfio/vfio-device.h
>>>>>>> +++ b/include/hw/vfio/vfio-device.h
>>>>>>> @@ -41,6 +41,13 @@ enum {
>>>>>>> VFIO_DEVICE_TYPE_AP = 3,
>>>>>>> };
>>>>>>>
>>>>>>> +enum {
>>>>>>> + /* The Guest passed addresses stored in IOV are invalid */
>>>>>>> + VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
>>>>>>> + /* Guest or Host may be at fault for this type of error */
>>>>>>> + VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
>>>>>>> +};
>>>>>>
>>>>>> Nack.
>>>>>>
>>>>>> As said a few times already : it's a VFIO-specific enum leaking
>>>>>> into vfio-device.h to serve virtio-gpu's fallback logic. The
>>>>>> cleanest alternative is to use standard -errno returns and
>>>>>> make the fd an output parameter.
>>>>> It looks like Cedric remains unconvinced about the value or usefulness
>>>>> of this error enum. Therefore, to make progress, I intend to adopt his
>>>>> suggestion to use standard -errno returns for the next version, considering
>>>>> that this series has been stuck for a year.
>>>>>
>>>>> AFAICS, dropping this error enum means that we would not be able to
>>>>> clearly identify and log (or attribute) Guest vs Host errors in virtio-gpu,
>>>>> particularly the INVALID_IOV case. I am not sure if this can be considered
>>>>> a significant limitation. However, if there is a reasonable middle ground
>>>>> solution or an alternative that you can think of that does not involve
>>>>> using VFIO error enums in virtio-gpu, then I would like to pursue that
>>>>> instead.
>>>>
>>>> Cédric's comment is a reiteration of previous points, but his concrete
>>>> code suggestion is new and brings to light some challenges with errno
>>>> propagation.
>>>>
>>>> First, errno does not precisely match the required semantics. We need
>>>> to
>>>> distinguish lookup failures from the other errors. However, with your
>>>> suggestion, lookup failures become -EINVAL and
>>>> vfio_device_get_feature()
>>>> also returns the same value when the backend lacks the operation,
>>>> making
>>>> it impossible to distinguish them.
>
> This matters only when something actually needs to distinguish them.
>
> If -EINVAL on lookup failure bothers you, consider -ENOENT.
-EINVAL itself is fine, but the problem is that
vfio_device_get_feature() also returns -EINVAL.
-ENOENT would work, but I'm concerned that it might be fragile, for
example, if called functions start returning different error codes or if
a new function call is added in the future.
>
>>>> Propagating errno also requires extra care to preserve it when
>>>> necessary. For patch "[PATCH v13 8/9] virtio-gpu-dmabuf: Improve error
>>>> handling with 'Error **' and err enum", you suggested to add the
>>>> "saved_errno" variable to save errno before error_setg_errno(). That is
>>>> redundant because error_setg_errno() preserves errno. Realizing that
>>>> requires careful attention.
>>>>
>>>> While we could spend effort fixing these issues, we can simply avoid the
>>>> churn by not using errno.
>
> Two separate styles:
>
> 1. Libc commonly sets @errno and returns a single error value. Care may
> indeed be necessary to preserve errno when passing errors up the
> stack in this style.
>
> 2. We commonly use negative errno codes as error values. Preserving
> @errno is a non-issue then.
It is style 1. As noted above, we actually need no additional code here
since error_setg_errno() preserves errno, but it still requires careful
attention to ensure correctness.
>
>>>> In any case, I agree keeping this stuck is not ideal while I don't think
>>>> I can provide any further insights. So I'm inviting Markus Armbruster to
>>> Looks like you forgot to cc Markus. I have added him now.
>>>
>>>> this discussion. This is an area better handled by him, who maintains
>>>> the error reporting facility, including include/qapi/error.h, which
>>>> extensively documents codebase-wide error-handling convention.
>>>>
>>>> Markus, could you advise on the appropriate convention for returning
>>>> this kind of classification alongside Error **? Your perspective
>>>> across the codebase may help us settle on a consistent approach
>>>> beyond the individual subsystems involved here. Perhaps you may
>>>> improve
>>>> the documentation according to a design decision made here.
>
> error.h indeed recommends use of negative integers as error values, but
> doesn't recommend any particular encoding. Perhaps it should mention
> the common practice of using negative errno codes.
>
>>> Markus, here is some additional context from Akihiko as to why there is
>>> a need to introduce an error enum in VFIO:
>>> https://lore.kernel.org/qemu-devel/09f02fe2-63cb-4283-899e-4cffc5f60cf1@rsg.ci.i.u-tokyo.ac.jp/
>>>
>>>>
>>>> If anyone else has a clean middle-ground solution in the meantime, I
>>>> would greatly appreciate your input as well.
>>> I am not sure if it can be considered clean or elegant but one middle-ground
>>> solution I can think of is to have (and use) the error enum just in virtio-gpu
>>> only but associate EINVAL (return value of vfio_device_create_dmabuf_fd())
>>> as the equivalent of INVALID_IOV. That is, the relevant code now becomes:
>>> res->dmabuf_fd = virtio_gpu_create_udmabuf(res, &local_err);
>>> if (res->dmabuf_fd == VIRTIO_GPU_DMABUF_CREATE_ERR_INVALID_IOV) {
>>> error_free_or_abort(&local_err);
>>> res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
>>> res->iov_cnt,
>>> &local_err);
>>> if (res->dmabuf_fd == -EINVAL) {
>>> error_free_or_abort(&local_err);
>>> qemu_log_mask(LOG_GUEST_ERROR,
>>> "Cannot create dmabuf: incompatible memory\n");
>>> return false;
>>> }
>>> I think this is reasonable IMO, but is this proposal acceptable to you?
>>
>> The return value drives control flow.
>>
>> AFAICT, in virtio_gpu_init_dmabuf(), the only distinction that seems
>> to matter for control flow is : "should I try the next backend ?" and
>> that's EINVAL, which means "these addresses are incompatible with this
>> particular backend."
>>
>> The guest-vs-host attribution for logging/debugging is in the errp
>> messages :
>>
>> - "IOV memory address incompatible with udmabuf" : guest gave addresses udmabuf can't handle
>> - "No VFIO device found to create dmabuf from" : guest addresses don't map to a VFIO device
>> - "UDMABUF_CREATE_LIST: ioctl failed" + errno : host/kernel issue
>>
>> The Error* object is designed to encode a human-readable attribution
>> in a return value. It carries the diagnostic detail and the return
>> code carries the machine action.
>
> Yes, this is the overwhelmingly common way to do this[*].
>
> When all errors are handled the same, a single return value signifying
> failure suffices. When callers need to handle different values
> differently, which is rare, we need several error values. Negative
> errno is often convenient then. Sometimes, it's a bad fit, so we come
> up with some other set of error codes.
>
> Regardless, error values need to be clearly documented.
>
> To decide what error values to use, you should start with how errors are
> handled. Design for that. In a library, you may not know. But when
> you do, resist the temptation to encode all possible errors perfectly.
> KISS. You can always make it more complicated when new callers require
> it.
>
> Does this help? If not, try asking pointed questions.
Thank you for the guidance. Rephrasing your points:
- Negative errno is often convenient, but an alternative set of error
codes are used when it's a bad fit.
- KISS: encode specific error conditions to be distinguished instead
encoding all.
This brings us to a common architectural intersection: How should a
function handle and propagate errors when its callees return overlapping
-errno values that require different treatment by the caller?
Both virtio_gpu_create_udmabuf() and vfio_device_create_dmabuf_fd() face
this challenge. Evaluating the available design options against your
advice yields the following:
1. Use custom error code enum.
Defining an enum is not as convenient as negative errno, but it is KISS;
it encodes specific error conditions we care about:
enum {
VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
};
static int vfio_device_create_dmabuf_fd(..., Error **errp)
{
...
if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
}
...
ret = vfio_device_get_feature(vbasedev, feature);
if (ret < 0) {
error_setg_errno(errp, -ret,
"Could not create dmabuf fd via VFIO device");
return VFIO_DMABUF_CREATE_ERR_UNSPEC;
}
return ret;
}
2. Remap -errno.
This is what Cédric suggested [1].
The negative errno values returned by internal callees do not precisely
represent the error conditions we need to handle, making negative errno
a "bad fit" here. However, the main issue isn't negative errno itself,
but rather that we must handle negative errno values originating from
different function calls. We can remap the values to resolve this:
static int vfio_device_create_dmabuf_fd(..., Error **errp)
{
...
if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
return -EINVAL;
}
...
ret = vfio_device_get_feature(vbasedev, feature);
if (ret < 0) {
error_setg_errno(errp, -ret,
"Could not create dmabuf fd via VFIO device");
/*
* Remap -EINVAL: caller uses it to mean
* "addresses incompatible"
*/
return (ret == -EINVAL) ? -EIO : ret;
}
return ret;
}
The downside is that it is not KISS; the condition to remap errno
encodes more possible errors, but they do not matter to the current
caller (and it coalesces error codes from vfio_device_get_feature(),
though that is also harmless for the caller).
3. Another better idea?
[1]
https://lore.kernel.org/qemu-devel/458252ce-c1b8-4df6-8268-4ae09cd96d56@redhat.com/
Regards,
Akihiko Odaki
>
>
> [...]
>
>
> [*] There's also the ErrorClass carried by Error objects. It was meant
> to carry the machine action, but it turned out to be a costly failure.
> Use of error classes other than ERROR_CLASS_GENERIC_ERROR is strongly
> discouraged.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-14 13:07 ` Akihiko Odaki
@ 2026-10-14 16:29 ` Cédric Le Goater
0 siblings, 0 replies; 36+ messages in thread
From: Cédric Le Goater @ 2026-10-14 16:29 UTC (permalink / raw)
To: Akihiko Odaki, Markus Armbruster
Cc: Kasireddy, Vivek, qemu-devel@nongnu.org, Alex Williamson
On 10/14/26 15:07, Akihiko Odaki wrote:
>>
>
> Thank you for the guidance. Rephrasing your points:
>
> - Negative errno is often convenient, but an alternative set of error
> codes are used when it's a bad fit.
>
> - KISS: encode specific error conditions to be distinguished instead encoding all.
>
> This brings us to a common architectural intersection: How should a function handle and propagate errors when its callees return overlapping -errno values that require different treatment by the caller?
>
> Both virtio_gpu_create_udmabuf() and vfio_device_create_dmabuf_fd() face this challenge. Evaluating the available design options against your advice yields the following:
>
> 1. Use custom error code enum.
>
> Defining an enum is not as convenient as negative errno, but it is KISS; it encodes specific error conditions we care about:
>
> enum {
> VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
> VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
> };
>
> static int vfio_device_create_dmabuf_fd(..., Error **errp)
> {
> ...
>
> if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
> return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
> }
>
> ...
>
> ret = vfio_device_get_feature(vbasedev, feature);
> if (ret < 0) {
> error_setg_errno(errp, -ret,
> "Could not create dmabuf fd via VFIO device");
> return VFIO_DMABUF_CREATE_ERR_UNSPEC;
> }
> return ret;
> }
Works, it's heavy.
This function has a single caller, and the enum values break the
-errno convention that the rest of the fallback chain uses
(virtio_gpu_create_udmabuf returns -errno). The caller would
handle two different return-value conventions in the same fallback
sequence.
A VFIO_DMABUF_CREATE_ERR_* enum defined in a VFIO header that
hw/display/virtio-gpu-dmabuf.c must include and switch on.
That's adding a VFIO-specific error vocabulary to the display
subsystem's control flow. It introduces a layering violation.
What is important is to acknowledge that how the implementation
arrives at "not applicable" (device lookup failed, region lookup
failed) is irrelevant to the caller.
A VFIO-specific error enum in the return type inverts thatrelationship;it makes the caller encode knowledge of the implementation's internal
failure modes. That's the opposite of what a library API should do.
> 2. Remap -errno.
>
> This is what Cédric suggested [1].
>
> The negative errno values returned by internal callees do not precisely represent the error conditions we need to handle, making negative errno a "bad fit" here. However, the main issue isn't negative errno itself, but rather that we must handle negative errno values originating from different function calls. We can remap the values to resolve this:
>
> static int vfio_device_create_dmabuf_fd(..., Error **errp)
> {
> ...
>
> if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
> return -EINVAL;
> }
>
> ...
>
> ret = vfio_device_get_feature(vbasedev, feature);
> if (ret < 0) {
> error_setg_errno(errp, -ret,
> "Could not create dmabuf fd via VFIO device");
> /*
> * Remap -EINVAL: caller uses it to mean
> * "addresses incompatible"
> */
> return (ret == -EINVAL) ? -EIO : ret;
> }
> return ret;
> }
>
> The downside is that it is not KISS; the condition to remap errno encodes more possible errors, but they do not matter to the current caller (and it coalesces error codes from vfio_device_get_feature(), though that is also harmless for the caller).
The KISS argument is a bit thin here. you acknowledge yourself that neither
concern matters to the caller.
> 3. Another better idea?
If the downside is to encode knowledge about what vfio_device_get_feature()
might return (that the caller should not even know about), and future changes
to that function's error codes could silently break the contract, let's use
-ENODEV as a compromise.
int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
Error **errp)
{
...
if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
return -ENODEV; <--------
}
...
for (i = 0; i < iov_cnt; i++) {
if (!vfio_region_lookup(iov[i].iov_base, ®ion,
first_rb, &offset, errp)) {
return -ENODEV; <----------
}
...
}
...
ret = vfio_device_get_feature(vbasedev, feature);
if (ret < 0) {
error_setg_errno(errp, -ret,
"Could not create dmabuf fd via VFIO device");
return ret; /* pass through kernel errno unchanged */
}
return ret;
}
Caller becomes:
res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
res->iov_cnt,
&local_err);
if (res->dmabuf_fd == -ENODEV) {
error_free_or_abort(&local_err);
qemu_log_mask(LOG_GUEST_ERROR,
"Cannot create dmabuf: incompatible memory\n");
return false;
}
Thanks,
C.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges
2026-10-14 7:41 ` Cédric Le Goater
@ 2026-10-14 16:40 ` Cédric Le Goater
0 siblings, 0 replies; 36+ messages in thread
From: Cédric Le Goater @ 2026-10-14 16:40 UTC (permalink / raw)
To: Akihiko Odaki, Kasireddy, Vivek, qemu-devel@nongnu.org,
Markus Armbruster
Cc: Alex Williamson
On 10/14/26 09:41, Cédric Le Goater wrote:
> Hello !
>
> [ ... ]
>
>> Choosing between qemu_log_mask(LOG_GUEST_ERROR, ...) and
>> error_report_err() is also a machine decision. The caller needs to
>> distinguish incompatible backing from other failures to select the
>> reporting path; human-readable attribution in Error * is insufficient.
>>
>> The -EINVAL ambiguity therefore remains. vfio_device_get_feature()
>> also returns -EINVAL when the backend lacks the operation. If we
>> propagate that unchanged, your diagram classifies it as incompatible
>> guest memory. Using -EINVAL for that classification requires an
>> explicit mapping that keeps these other failures distinct.
>>
>> Regarding -ENODEV, virtio_gpu_device_realize() already requires
>> virtio_gpu_have_udmabuf() for this blob path. udmabuf_fd() caches the
>> opened fd, so the availability-related -ENODEV should not occur
>> after successful realization.
> You raise valid points :
>
> * -EINVAL from vfio_device_get_feature(): You're right. That needs a
> remap to avoid the -EINVAL collision.
> * -ENODEV: Correct, I'll drop that suggestion.
>
> So, we just need the one-line remap above to avoid the -EINVAL collision.
> See a proposal here :
>
> https://github.com/legoater/qemu/commits/virtio-gpu-dmabuf
>
> Fixup patch :
>
> https://github.com/legoater/qemu/commit/653c41e89468f82bbdfcaeafe75473b84f5a1e49
>
> Also below,
I updated branch
https://github.com/legoater/qemu/commits/virtio-gpu-dmabuf
with the -ENODEV approach.
Patch below,
C.
From 3b741e23bb9e9bb80b9f2c78d53b3a4bbcefb795 Mon Sep 17 00:00:00 2001From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
Date: Wed, 14 Oct 2026 00:00:00 +0200
Subject: [PATCH] vfio, virtio-gpu-dmabuf: Replace custom error enum with
standard -errno
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Drop the VFIO_DMABUF_CREATE_ERR_{INVALID_IOV,UNSPEC} enum from
vfio-device.h and use standard negative errno values instead:
- -ENODEV: iov addresses do not belong to a VFIO device
- -ENOTSUP: VFIO not compiled in
- other -errno: forwarded from kernel VFIO ioctl
Use -ENODEV (instead of -EINVAL) for the "not applicable" case so
that kernel errno values from vfio_device_get_feature() can pass
through unchanged without collision.
The virtio-gpu fallback logic (try udmabuf, then VFIO) checks -ENODEV
to decide whether to try the next backend.
Also fix several issues in the same code:
- vfio_device_lookup: use global_next (not next) for vfio_device_list
- Move vfio_device_create_dmabuf_fd/vfio_device_mmap_dmabuf
declarations outside #ifdef CONFIG_VFIO guard so prototypes are
visible to the stubs (fixes MinGW build)
- Remove trailing \n and trailing space from error_setg messages
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
include/hw/vfio/vfio-device.h | 16 ++++++----------
hw/display/virtio-gpu-dmabuf.c | 22 ++++++++++++----------
hw/vfio/device.c | 20 ++++++++++----------
hw/vfio/dmabuf-stubs.c | 2 +-
4 files changed, 29 insertions(+), 31 deletions(-)
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index 4b8fb6205604..81bc68b28b41 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -41,13 +41,6 @@ enum {
VFIO_DEVICE_TYPE_AP = 3,
};
-enum {
- /* The Guest passed addresses stored in IOV are invalid */
- VFIO_DMABUF_CREATE_ERR_INVALID_IOV = -1,
- /* Guest or Host may be at fault for this type of error */
- VFIO_DMABUF_CREATE_ERR_UNSPEC = -2,
-};
-
typedef struct VFIODeviceOps VFIODeviceOps;
typedef struct VFIODeviceIOOps VFIODeviceIOOps;
typedef struct VFIOMigration VFIOMigration;
@@ -331,6 +324,8 @@ bool vfio_device_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_t
int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
struct vfio_irq_info *info);
+#endif
+
/**
* Create a dmabuf fd by first translating the addresses in the
* iovec array into VFIO region offsets and then invoking the
@@ -340,8 +335,10 @@ int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
* @iov_cnt: number of entries in the iovec array
* @errp: pointer to Error*, to store an error if it happens.
*
- * Returns the created dmabuf fd or either VFIO_DMABUF_CREATE_ERR_UNSPEC
- * or VFIO_DMABUF_CREATE_ERR_INVALID_IOV on error.
+ * Returns the dmabuf fd (>= 0) on success, or a negative errno:
+ * - -ENODEV: iov addresses do not belong to a VFIO device
+ * - -ENOTSUP: VFIO not compiled in
+ * - other negative errno from the kernel VFIO ioctl
*/
int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
Error **errp);
@@ -360,7 +357,6 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
*/
void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
Error **errp);
-#endif
/* Returns 0 on success, or a negative errno. */
bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp);
diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
index f59a5e76ff3c..8713b97c9c68 100644
--- a/hw/display/virtio-gpu-dmabuf.c
+++ b/hw/display/virtio-gpu-dmabuf.c
@@ -39,21 +39,21 @@ static int virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res,
udmabuf = udmabuf_fd();
if (udmabuf < 0) {
error_setg(errp, "udmabuf device not available or enabled");
- return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ return -ENODEV;
}
list = g_try_malloc0(sizeof(struct udmabuf_create_list) +
sizeof(struct udmabuf_create_item) * res->iov_cnt);
if (!list) {
error_setg(errp, "failed to allocate udmabuf create list");
- return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ return -ENOMEM;
}
for (i = 0; i < res->iov_cnt; i++) {
rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
if (!rb || rb->fd < 0) {
- error_setg(errp, "IOV memory address incompatible with udmabuf ");
- return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ error_setg(errp, "IOV memory address incompatible with udmabuf");
+ return -EINVAL;
}
list->list[i].memfd = rb->fd;
@@ -66,11 +66,13 @@ static int virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res,
fd = ioctl(udmabuf, UDMABUF_CREATE_LIST, list);
if (fd < 0) {
- error_setg_errno(errp, errno, "UDMABUF_CREATE_LIST: ioctl failed");
- if (errno == EINVAL || errno == EBADFD) {
- return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ int saved_errno = errno;
+
+ error_setg_errno(errp, saved_errno, "UDMABUF_CREATE_LIST: ioctl failed");
+ if (saved_errno == EINVAL || saved_errno == EBADFD) {
+ return -EINVAL;
}
- return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ return -saved_errno;
}
return fd;
}
@@ -150,13 +152,13 @@ bool virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
pdata = res->iov[0].iov_base;
} else if (res->blob_size) {
res->dmabuf_fd = virtio_gpu_create_udmabuf(res, &local_err);
- if (res->dmabuf_fd == VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
+ if (res->dmabuf_fd == -EINVAL) {
error_free_or_abort(&local_err);
res->dmabuf_fd = vfio_device_create_dmabuf_fd(res->iov,
res->iov_cnt,
&local_err);
- if (res->dmabuf_fd == VFIO_DMABUF_CREATE_ERR_INVALID_IOV) {
+ if (res->dmabuf_fd == -ENODEV) {
error_free_or_abort(&local_err);
qemu_log_mask(LOG_GUEST_ERROR,
"Cannot create dmabuf: incompatible memory\n");
diff --git a/hw/vfio/device.c b/hw/vfio/device.c
index 5bc044376441..f7b4e40dc119 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -686,18 +686,18 @@ static bool vfio_device_lookup(struct iovec *iov, VFIODevice **vbasedevp,
first_rb = qemu_ram_block_from_host(iov[0].iov_base, false, &offset);
if (!first_rb) {
- error_setg(errp, "Could not find first ramblock\n");
+ error_setg(errp, "Could not find first ramblock");
return false;
}
*first_rbp = first_rb;
- QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
+ QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) {
if (vbasedev->dev == first_rb->mr->dev) {
*vbasedevp = vbasedev;
return true;
}
}
- error_setg(errp, "No VFIO device found to create dmabuf from\n");
+ error_setg(errp, "No VFIO device found to create dmabuf from");
return false;
}
@@ -716,7 +716,7 @@ static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
rb = qemu_ram_block_from_host(addr, false, offsetp);
if (!rb || rb != first_rb) {
- error_setg(errp, "Dmabuf segments must belong to the same region\n");
+ error_setg(errp, "Dmabuf segments must belong to the same region");
return false;
}
@@ -725,7 +725,7 @@ static bool vfio_region_lookup(void *addr, VFIORegion **regionp,
*regionp = region;
return true;
}
- error_setg(errp, "Could not find valid region for dmabuf segment\n");
+ error_setg(errp, "Could not find valid region for dmabuf segment");
return false;
}
@@ -742,7 +742,7 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
int i, ret;
if (!vfio_device_lookup(iov, &vbasedev, &first_rb, errp)) {
- return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ return -ENODEV;
}
argsz = sizeof(*feature) + sizeof (*dma_buf) +
@@ -757,7 +757,7 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
for (i = 0; i < iov_cnt; i++) {
if (!vfio_region_lookup(iov[i].iov_base, ®ion,
first_rb, &offset, errp)) {
- return VFIO_DMABUF_CREATE_ERR_INVALID_IOV;
+ return -ENODEV;
}
dma_buf->region_index = region->nr;
@@ -772,7 +772,7 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
if (ret < 0) {
error_setg_errno(errp, -ret,
"Could not create dmabuf fd via VFIO device");
- return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ return ret;
}
return ret;
}
@@ -811,7 +811,7 @@ void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
}
if (vfio_device_get_region_info(vbasedev, region->nr, &info)) {
- error_setg(errp, "Cannot find region info for dmabuf segment\n");
+ error_setg(errp, "Cannot find region info for dmabuf segment");
goto err;
}
@@ -819,7 +819,7 @@ void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
MAP_SHARED | MAP_FIXED, vbasedev->fd,
info->offset + offset);
if (submap == MAP_FAILED) {
- error_setg_errno(errp, errno, "Could not mmap dmabuf segment\n");
+ error_setg_errno(errp, errno, "Could not mmap dmabuf segment");
goto err;
}
len += iov[i].iov_len;
diff --git a/hw/vfio/dmabuf-stubs.c b/hw/vfio/dmabuf-stubs.c
index b9e03a162a75..241a9761ef5e 100644
--- a/hw/vfio/dmabuf-stubs.c
+++ b/hw/vfio/dmabuf-stubs.c
@@ -13,7 +13,7 @@ int vfio_device_create_dmabuf_fd(struct iovec *iov, unsigned int iov_cnt,
Error **errp)
{
error_setg(errp, "VFIO dmabuf support is not enabled");
- return VFIO_DMABUF_CREATE_ERR_UNSPEC;
+ return -ENOTSUP;
}
void *vfio_device_mmap_dmabuf(struct iovec *iov, unsigned int iov_cnt,
--
2.56.0
^ permalink raw reply related [flat|nested] 36+ messages in thread
end of thread, other threads:[~2026-10-14 16:41 UTC | newest]
Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-07 20:09 [PATCH v13 0/9] vfio: Create dmabuf from multiple VFIO ranges and use it in virtio-gpu Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 1/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device Vivek Kasireddy
2026-10-08 9:02 ` Akihiko Odaki
2026-10-09 4:32 ` Kasireddy, Vivek
2026-10-09 9:26 ` Akihiko Odaki
2026-10-12 6:10 ` Kasireddy, Vivek
2026-10-07 20:09 ` [PATCH v13 2/9] virtio-gpu: Rename udmabuf files and helpers to dmabuf Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 3/9] virtio-gpu-dmabuf: Remove rcu_read_lock/unlock from virtio_gpu_create_udmabuf() Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 4/9] virtio-gpu-dmabuf: Use g_autofree for the list pointer Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 5/9] vfio/region: Add a helper to get VFIO region from memory region Vivek Kasireddy
2026-10-07 20:09 ` [PATCH v13 6/9] vfio/device: Add support for creating dmabuf from multiple ranges Vivek Kasireddy
2026-10-08 9:08 ` Akihiko Odaki
2026-10-09 4:24 ` Kasireddy, Vivek
2026-10-09 8:13 ` Cédric Le Goater
2026-10-12 6:27 ` Kasireddy, Vivek
2026-10-12 14:01 ` Akihiko Odaki
2026-10-13 4:06 ` Kasireddy, Vivek
2026-10-13 16:20 ` Cédric Le Goater
2026-10-14 2:17 ` Akihiko Odaki
2026-10-14 7:41 ` Cédric Le Goater
2026-10-14 16:40 ` Cédric Le Goater
2026-10-14 7:03 ` Markus Armbruster
2026-10-14 13:07 ` Akihiko Odaki
2026-10-14 16:29 ` Cédric Le Goater
2026-10-13 16:40 ` Cédric Le Goater
2026-10-07 20:09 ` [PATCH v13 7/9] vfio/device: Add a helper to mmap a dmabuf Vivek Kasireddy
2026-10-09 8:13 ` Cédric Le Goater
2026-10-07 20:09 ` [PATCH v13 8/9] virtio-gpu-dmabuf: Improve error handling with 'Error **' and err enum Vivek Kasireddy
2026-10-09 8:17 ` Cédric Le Goater
2026-10-07 20:09 ` [PATCH v13 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices Vivek Kasireddy
2026-10-08 9:11 ` Akihiko Odaki
2026-10-09 4:26 ` Kasireddy, Vivek
2026-10-09 9:51 ` Akihiko Odaki
2026-10-12 6:14 ` Kasireddy, Vivek
2026-10-12 14:00 ` Akihiko Odaki
2026-10-13 3:57 ` Kasireddy, Vivek
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.