* [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu
@ 2025-11-22 6:46 Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 1/9] virtio-gpu: Recreate the resource's dmabuf if new backing is attached Vivek Kasireddy
` (8 more replies)
0 siblings, 9 replies; 13+ messages in thread
From: Vivek Kasireddy @ 2025-11-22 6:46 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, Leon Romanovsky, Leon Romanovsky,
Jason Gunthorpe, 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 implement VFIO_DEVICE_FEATURE_DMA_BUF and
leverage it in virtio-gpu.
So, while creating the blobs we use ram_block_is_memfd_backed() to
figure out if the blob is backed by memfd or a vfio-pci device. If
it is determined that the blob is backed by vfio-pci device region,
instead of calling into udmabuf driver to create a dmabuf fd we would
now call into vfio-pci driver to have a dmabuf fd created on the Host.
Changelog:
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 vfio-pci kernel driver series:
https://lore.kernel.org/dri-devel/20251120-dmabuf-vfio-v9-0-d7f71607f371@nvidia.com/
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: Leon Romanovsky <leon@kernel.org>
Cc: Leon Romanovsky <leonro@nvidia.com>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Cc: Dongwon Kim <dongwon.kim@intel.com>
Vivek Kasireddy (9):
virtio-gpu: Recreate the resource's dmabuf if new backing is attached
virtio-gpu: Find hva for Guest's DMA addr associated with a ram device
vfio: Document vfio_device_get_region_info()
vfio/region: Add a helper to get region index from memory region
vfio/device: Add a helper to lookup VFIODevice from memory region
vfio/device: Add support for VFIO_DEVICE_FEATURE_DMA_BUF
virtio-gpu: Rename udmabuf files and helpers to dmabuf
virtio-gpu-dmabuf: Introduce ram_block_is_memfd_backed() helper
virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO
devices
hw/display/Kconfig | 5 +
hw/display/meson.build | 4 +-
...abuf-stubs.c => virtio-gpu-dmabuf-stubs.c} | 4 +-
...rtio-gpu-udmabuf.c => virtio-gpu-dmabuf.c} | 155 +++++++++++++++---
hw/display/virtio-gpu.c | 31 +++-
hw/vfio/device.c | 57 +++++++
hw/vfio/region.c | 14 ++
include/hw/vfio/vfio-device.h | 46 ++++++
include/hw/virtio/virtio-gpu.h | 6 +-
9 files changed, 288 insertions(+), 34 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} (58%)
--
2.50.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 1/9] virtio-gpu: Recreate the resource's dmabuf if new backing is attached
2025-11-22 6:46 [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu Vivek Kasireddy
@ 2025-11-22 6:46 ` Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 2/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device Vivek Kasireddy
` (7 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Vivek Kasireddy @ 2025-11-22 6:46 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 are cases when a blob resource's backing might get detached
and re-attached again such as when the underlying object is getting
migrated in the Guest. In these situations, we need to obtain a new
dmabuf fd, which can be done by calling virtio_gpu_init_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.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 43e88a4daf..199b18c746 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -937,6 +937,10 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
}
+
+ if (res->blob_size) {
+ virtio_gpu_init_udmabuf(res);
+ }
}
static void
--
2.50.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 2/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device
2025-11-22 6:46 [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 1/9] virtio-gpu: Recreate the resource's dmabuf if new backing is attached Vivek Kasireddy
@ 2025-11-22 6:46 ` Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 3/9] vfio: Document vfio_device_get_region_info() Vivek Kasireddy
` (6 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Vivek Kasireddy @ 2025-11-22 6:46 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 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().
This is because the ram device's address space is not accessible
to virtio-gpu directly and hence dma_memory_map() cannot be used.
Therefore, we first need to identify the memory region associated
with the DMA address and add the offset to the pointer returned
from memory_region_get_ram_ptr() to obtain the host address.
Note that we take a reference on the memory region but we would
still eventually call dma_memory_unmap() (to unref the mr).
Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Cc: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Cc: Alex Williamson <alex@shazbot.org>
Cc: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/display/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 199b18c746..d746c5f426 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -798,6 +798,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,
@@ -839,9 +856,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
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.50.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 3/9] vfio: Document vfio_device_get_region_info()
2025-11-22 6:46 [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 1/9] virtio-gpu: Recreate the resource's dmabuf if new backing is attached Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 2/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device Vivek Kasireddy
@ 2025-11-22 6:46 ` Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 4/9] vfio/region: Add a helper to get region index from memory region Vivek Kasireddy
` (5 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Vivek Kasireddy @ 2025-11-22 6:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Vivek Kasireddy, Alex Williamson, Cédric Le Goater
Add documentation for vfio_device_get_region_info() and clarify the
expectations around its usage.
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 | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index 0fe6c60ba2..bb28123faf 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -257,6 +257,19 @@ void vfio_device_prepare(VFIODevice *vbasedev, VFIOContainer *bcontainer,
void vfio_device_unprepare(VFIODevice *vbasedev);
+/**
+ * Return the region info for a given region index. The region info includes
+ * details such as size, offset, and capabilities. Note that the returned
+ * info pointer is either a cached copy or newly allocated by
+ * vfio_device_get_region_info(), so the caller is not expected to allocate
+ * or free it.
+ *
+ * @vbasedev: #VFIODevice to use
+ * @index: region index
+ * @info: pointer to store the region info
+ *
+ * Returns 0 on success or a negative value on error.
+ */
int vfio_device_get_region_info(VFIODevice *vbasedev, int index,
struct vfio_region_info **info);
int vfio_device_get_region_info_type(VFIODevice *vbasedev, uint32_t type,
--
2.50.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 4/9] vfio/region: Add a helper to get region index from memory region
2025-11-22 6:46 [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu Vivek Kasireddy
` (2 preceding siblings ...)
2025-11-22 6:46 ` [PATCH v3 3/9] vfio: Document vfio_device_get_region_info() Vivek Kasireddy
@ 2025-11-22 6:46 ` Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 5/9] vfio/device: Add a helper to lookup VFIODevice " Vivek Kasireddy
` (4 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Vivek Kasireddy @ 2025-11-22 6:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Vivek Kasireddy, Alex Williamson, Cédric Le Goater
Having a way to figure out the region index (or bar) associated
with a memory region is helpful in various scenarios. For example,
this capability can be useful in retrieving the region info 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/region.c | 14 ++++++++++++++
include/hw/vfio/vfio-device.h | 10 ++++++++++
2 files changed, 24 insertions(+)
diff --git a/hw/vfio/region.c b/hw/vfio/region.c
index b165ab0b93..046adfaa2c 100644
--- a/hw/vfio/region.c
+++ b/hw/vfio/region.c
@@ -398,3 +398,17 @@ void vfio_region_mmaps_set_enabled(VFIORegion *region, bool enabled)
trace_vfio_region_mmaps_set_enabled(memory_region_name(region->mem),
enabled);
}
+
+int vfio_get_region_index_from_mr(MemoryRegion *mr)
+{
+ VFIORegion *region;
+
+ while (mr->container) {
+ if (mr->ops == &vfio_region_ops) {
+ region = mr->opaque;
+ return region->nr;
+ }
+ mr = mr->container;
+ }
+ return -1;
+}
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index bb28123faf..44cacd3728 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -290,6 +290,16 @@ 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);
+
+/**
+ * Return the region index associated with a given MemoryRegion. The index
+ * can be useful in retrieving region info.
+ *
+ * @mr: MemoryRegion to use
+ *
+ * Returns the region index or -1 on error.
+ */
+int vfio_get_region_index_from_mr(MemoryRegion *mr);
#endif
/* Returns 0 on success, or a negative errno. */
--
2.50.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 5/9] vfio/device: Add a helper to lookup VFIODevice from memory region
2025-11-22 6:46 [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu Vivek Kasireddy
` (3 preceding siblings ...)
2025-11-22 6:46 ` [PATCH v3 4/9] vfio/region: Add a helper to get region index from memory region Vivek Kasireddy
@ 2025-11-22 6:46 ` Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 6/9] vfio/device: Add support for VFIO_DEVICE_FEATURE_DMA_BUF Vivek Kasireddy
` (3 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Vivek Kasireddy @ 2025-11-22 6:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Vivek Kasireddy, Alex Williamson, Cédric Le Goater
Instead of iterating over all QOM devices to find the VFIODevice
associated with a memory region, it is faster to just use the
vfio_device_list to lookup the VFIODevice.
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/device.c | 12 ++++++++++++
include/hw/vfio/vfio-device.h | 9 +++++++++
2 files changed, 21 insertions(+)
diff --git a/hw/vfio/device.c b/hw/vfio/device.c
index 76869828fc..9ff73f9941 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -603,3 +603,15 @@ static VFIODeviceIOOps vfio_device_io_ops_ioctl = {
.region_read = vfio_device_io_region_read,
.region_write = vfio_device_io_region_write,
};
+
+VFIODevice *vfio_device_lookup(MemoryRegion *mr)
+{
+ VFIODevice *vbasedev;
+
+ QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
+ if (vbasedev->dev == mr->dev) {
+ return vbasedev;
+ }
+ }
+ return NULL;
+}
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index 44cacd3728..2f8087f133 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -300,6 +300,15 @@ int vfio_device_get_irq_info(VFIODevice *vbasedev, int index,
* Returns the region index or -1 on error.
*/
int vfio_get_region_index_from_mr(MemoryRegion *mr);
+
+/**
+ * Return the VFIO device associated with a given MemoryRegion.
+ *
+ * @mr: MemoryRegion to use
+ *
+ * Returns the VFIO device if found or NULL.
+ */
+VFIODevice *vfio_device_lookup(MemoryRegion *mr);
#endif
/* Returns 0 on success, or a negative errno. */
--
2.50.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 6/9] vfio/device: Add support for VFIO_DEVICE_FEATURE_DMA_BUF
2025-11-22 6:46 [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu Vivek Kasireddy
` (4 preceding siblings ...)
2025-11-22 6:46 ` [PATCH v3 5/9] vfio/device: Add a helper to lookup VFIODevice " Vivek Kasireddy
@ 2025-11-22 6:46 ` Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 7/9] virtio-gpu: Rename udmabuf files and helpers to dmabuf Vivek Kasireddy
` (2 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Vivek Kasireddy @ 2025-11-22 6:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Vivek Kasireddy, Alex Williamson, Cédric Le Goater
In order to implement VFIO_DEVICE_FEATURE_DMA_BUF, 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 in order to invoke
this feature.
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/device.c | 45 +++++++++++++++++++++++++++++++++++
include/hw/vfio/vfio-device.h | 14 +++++++++++
2 files changed, 59 insertions(+)
diff --git a/hw/vfio/device.c b/hw/vfio/device.c
index 9ff73f9941..0679e55e8c 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include <sys/ioctl.h>
+#include "system/ramblock.h"
#include "hw/vfio/vfio-device.h"
#include "hw/vfio/pci.h"
#include "hw/hw.h"
@@ -615,3 +616,47 @@ VFIODevice *vfio_device_lookup(MemoryRegion *mr)
}
return NULL;
}
+
+int vfio_device_create_dmabuf_fd(VFIODevice *vbasedev,
+ struct iovec *iov, unsigned int iov_cnt)
+{
+ g_autofree struct vfio_device_feature *feature = NULL;
+ struct vfio_device_feature_dma_buf *dma_buf;
+ RAMBlock *rb, *first_rb;
+ ram_addr_t offset;
+ size_t argsz;
+ int i, index;
+
+ argsz = sizeof(*feature) + sizeof (*dma_buf) +
+ sizeof(struct vfio_region_dma_range) * iov_cnt;
+ feature = g_malloc0(argsz);
+ dma_buf = (struct vfio_device_feature_dma_buf *)feature->data;
+
+ first_rb = qemu_ram_block_from_host(iov[0].iov_base, false, &offset);
+ if (!first_rb) {
+ return -1;
+ }
+
+ for (i = 0; i < iov_cnt; i++) {
+ rb = qemu_ram_block_from_host(iov[i].iov_base, false, &offset);
+ if (rb != first_rb) {
+ return -1;
+ }
+
+ index = vfio_get_region_index_from_mr(rb->mr);
+ if (index < 0) {
+ return -1;
+ }
+
+ dma_buf->region_index = index;
+ 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;
+ feature->argsz = argsz;
+ feature->flags = VFIO_DEVICE_FEATURE_GET | VFIO_DEVICE_FEATURE_DMA_BUF;
+
+ return vbasedev->io_ops->device_feature(vbasedev, feature);
+}
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index 2f8087f133..7fc2912f15 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -309,6 +309,20 @@ int vfio_get_region_index_from_mr(MemoryRegion *mr);
* Returns the VFIO device if found or NULL.
*/
VFIODevice *vfio_device_lookup(MemoryRegion *mr);
+
+/**
+ * Create and return 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.
+ *
+ * @vbasedev: #VFIODevice to use
+ * @iov: array of iovec entries associated with a buffer
+ * @iov_cnt: number of entries in the iovec array
+ *
+ * Returns the newly created dmabuf fd or -1 on error.
+ */
+int vfio_device_create_dmabuf_fd(VFIODevice *vbasedev,
+ struct iovec *iov, unsigned int iov_cnt);
#endif
/* Returns 0 on success, or a negative errno. */
--
2.50.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 7/9] virtio-gpu: Rename udmabuf files and helpers to dmabuf
2025-11-22 6:46 [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu Vivek Kasireddy
` (5 preceding siblings ...)
2025-11-22 6:46 ` [PATCH v3 6/9] vfio/device: Add support for VFIO_DEVICE_FEATURE_DMA_BUF Vivek Kasireddy
@ 2025-11-22 6:46 ` Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 8/9] virtio-gpu-dmabuf: Introduce ram_block_is_memfd_backed() helper Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices Vivek Kasireddy
8 siblings, 0 replies; 13+ messages in thread
From: Vivek Kasireddy @ 2025-11-22 6:46 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>
---
hw/display/meson.build | 4 ++--
...gpu-udmabuf-stubs.c => virtio-gpu-dmabuf-stubs.c} | 4 ++--
.../{virtio-gpu-udmabuf.c => virtio-gpu-dmabuf.c} | 12 ++++++------
hw/display/virtio-gpu.c | 8 ++++----
include/hw/virtio/virtio-gpu.h | 6 +++---
5 files changed, 17 insertions(+), 17 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/hw/display/meson.build b/hw/display/meson.build
index 90e6c041bd..f5f92b1068 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -69,9 +69,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}
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 f692e13510..01067e246d 100644
--- a/hw/display/virtio-gpu-udmabuf-stubs.c
+++ b/hw/display/virtio-gpu-dmabuf-stubs.c
@@ -7,12 +7,12 @@ bool virtio_gpu_have_udmabuf(void)
return false;
}
-void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
+void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
{
/* nothing (stub) */
}
-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 d804f321aa..c34d4c85bc 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-dmabuf.c
@@ -68,7 +68,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);
@@ -79,7 +79,7 @@ static void virtio_gpu_remap_udmabuf(struct virtio_gpu_simple_resource *res)
}
}
-static void virtio_gpu_destroy_udmabuf(struct virtio_gpu_simple_resource *res)
+static void virtio_gpu_destroy_dmabuf(struct virtio_gpu_simple_resource *res)
{
if (res->remapped) {
munmap(res->remapped, res->blob_size);
@@ -128,7 +128,7 @@ bool virtio_gpu_have_udmabuf(void)
return memfd_backend;
}
-void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
+void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
{
void *pdata = NULL;
@@ -141,7 +141,7 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
if (res->dmabuf_fd < 0) {
return;
}
- virtio_gpu_remap_udmabuf(res);
+ virtio_gpu_remap_dmabuf(res);
if (!res->remapped) {
return;
}
@@ -151,10 +151,10 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
res->blob = pdata;
}
-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) {
- virtio_gpu_destroy_udmabuf(res);
+ virtio_gpu_destroy_dmabuf(res);
}
}
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index d746c5f426..681702eea9 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -360,7 +360,7 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
return;
}
- virtio_gpu_init_udmabuf(res);
+ virtio_gpu_init_dmabuf(res);
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
}
@@ -917,7 +917,7 @@ void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
res->addrs = NULL;
if (res->blob) {
- virtio_gpu_fini_udmabuf(res);
+ virtio_gpu_fini_dmabuf(res);
}
}
@@ -954,7 +954,7 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
}
if (res->blob_size) {
- virtio_gpu_init_udmabuf(res);
+ virtio_gpu_init_dmabuf(res);
}
}
@@ -1440,7 +1440,7 @@ static int virtio_gpu_blob_load(QEMUFile *f, void *opaque, size_t size,
return -EINVAL;
}
- virtio_gpu_init_udmabuf(res);
+ virtio_gpu_init_dmabuf(res);
resource_id = qemu_get_be32(f);
}
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 58e0f91fda..e3d351a2d4 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -354,10 +354,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);
-void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
-void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res);
+void 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,
--
2.50.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 8/9] virtio-gpu-dmabuf: Introduce ram_block_is_memfd_backed() helper
2025-11-22 6:46 [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu Vivek Kasireddy
` (6 preceding siblings ...)
2025-11-22 6:46 ` [PATCH v3 7/9] virtio-gpu: Rename udmabuf files and helpers to dmabuf Vivek Kasireddy
@ 2025-11-22 6:46 ` Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices Vivek Kasireddy
8 siblings, 0 replies; 13+ messages in thread
From: Vivek Kasireddy @ 2025-11-22 6:46 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 helper function provides a way to determine if a ram block
is backed by memfd by checking the SEALS on the associated fd.
This is useful in scenarios where we need to quickly verify if
a given memory region is associated with a memfd or not.
Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Cc: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Cc: Alex Williamson <alex@shazbot.org>
Cc: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/display/virtio-gpu-dmabuf.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
index c34d4c85bc..258c48d31b 100644
--- a/hw/display/virtio-gpu-dmabuf.c
+++ b/hw/display/virtio-gpu-dmabuf.c
@@ -27,6 +27,19 @@
#include "standard-headers/linux/udmabuf.h"
#include "standard-headers/drm/drm_fourcc.h"
+static bool ram_block_is_memfd_backed(RAMBlock *rb)
+{
+ int ret;
+
+ if (rb && rb->fd > 0) {
+ ret = fcntl(rb->fd, F_GET_SEALS);
+ if (ret > 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
{
struct udmabuf_create_list *list;
@@ -94,20 +107,14 @@ static void virtio_gpu_destroy_dmabuf(struct virtio_gpu_simple_resource *res)
static int find_memory_backend_type(Object *obj, void *opaque)
{
bool *memfd_backend = opaque;
- int ret;
if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
- RAMBlock *rb = backend->mr.ram_block;
- if (rb && rb->fd > 0) {
- ret = fcntl(rb->fd, F_GET_SEALS);
- if (ret > 0) {
- *memfd_backend = true;
- }
+ if (ram_block_is_memfd_backed(backend->mr.ram_block)) {
+ *memfd_backend = true;
}
}
-
return 0;
}
--
2.50.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2025-11-22 6:46 [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu Vivek Kasireddy
` (7 preceding siblings ...)
2025-11-22 6:46 ` [PATCH v3 8/9] virtio-gpu-dmabuf: Introduce ram_block_is_memfd_backed() helper Vivek Kasireddy
@ 2025-11-22 6:46 ` Vivek Kasireddy
2025-11-22 7:25 ` Akihiko Odaki
8 siblings, 1 reply; 13+ messages in thread
From: Vivek Kasireddy @ 2025-11-22 6:46 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. Therefore, we first need to figure
out if the blob is backed by a VFIO device region or a memfd before
we can call the right API to get a dmabuf fd created.
So, we first call virtio_gpu_create_udmabuf() which further calls
ram_block_is_memfd_backed() to check if the blob's backing storage
is located in a memfd or not. If it is not, we call vfio_create_dmabuf()
which identifies the right VFIO device and eventually invokes the
API vfio_device_create_dmabuf_fd() to have a dmabuf fd created.
Note that in virtio_gpu_remap_dmabuf(), we first try to test if
the VFIO dmabuf exporter supports mmap or not. If it doesn't, we
use the VFIO device fd directly to create the CPU mapping.
While at it, remove the unnecessary rcu_read_lock/rcu_read_unlock
from 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>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/display/Kconfig | 5 ++
hw/display/virtio-gpu-dmabuf.c | 122 ++++++++++++++++++++++++++++++---
2 files changed, 119 insertions(+), 8 deletions(-)
diff --git a/hw/display/Kconfig b/hw/display/Kconfig
index 1e95ab28ef..0d090f25f5 100644
--- a/hw/display/Kconfig
+++ b/hw/display/Kconfig
@@ -106,6 +106,11 @@ config VIRTIO_VGA
depends on VIRTIO_PCI
select VGA
+config VIRTIO_GPU_VFIO_BLOB
+ bool
+ default y
+ depends on VFIO
+
config VHOST_USER_GPU
bool
default y
diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
index 258c48d31b..d121a2c9a7 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"
@@ -40,10 +41,42 @@ static bool ram_block_is_memfd_backed(RAMBlock *rb)
return false;
}
+static void vfio_create_dmabuf(struct virtio_gpu_simple_resource *res)
+{
+#if defined(VIRTIO_GPU_VFIO_BLOB)
+ VFIODevice *vbasedev;
+ RAMBlock *first_rb;
+ ram_addr_t offset;
+
+ first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false, &offset);
+ if (!first_rb) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Could not find ramblock\n", __func__);
+ return;
+ }
+
+ vbasedev = vfio_device_lookup(first_rb->mr);
+ if (!vbasedev) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: No VFIO device found to create dmabuf from\n",
+ __func__);
+ return;
+ }
+
+ res->dmabuf_fd = vfio_device_create_dmabuf_fd(vbasedev,
+ res->iov, res->iov_cnt);
+ if (res->dmabuf_fd < 0) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: VFIO_DEVICE_FEATURE_DMA_BUF: %s\n",
+ __func__, strerror(errno));
+ }
+#endif
+}
+
static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
{
struct udmabuf_create_list *list;
- RAMBlock *rb;
+ RAMBlock *rb, *first_rb;
ram_addr_t offset;
int udmabuf, i;
@@ -52,15 +85,17 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
return;
}
+ first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false, &offset);
+ if (!ram_block_is_memfd_backed(first_rb)) {
+ return;
+ }
+
list = g_malloc0(sizeof(struct udmabuf_create_list) +
sizeof(struct udmabuf_create_item) * res->iov_cnt);
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) {
+ if (rb != first_rb) {
g_free(list);
return;
}
@@ -81,11 +116,77 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
g_free(list);
}
+static void *vfio_dmabuf_mmap(struct virtio_gpu_simple_resource *res)
+{
+ struct vfio_region_info *info = NULL;
+ VFIODevice *vbasedev = NULL;
+ ram_addr_t offset, len = 0;
+ RAMBlock *first_rb, *rb;
+ void *map, *submap;
+ int i, ret = -1;
+
+ first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false, &offset);
+ if (!first_rb) {
+ return MAP_FAILED;
+ }
+#if defined(VIRTIO_GPU_VFIO_BLOB)
+ vbasedev = vfio_device_lookup(first_rb->mr);
+#endif
+ if (!vbasedev) {
+ return MAP_FAILED;
+ }
+
+ /*
+ * 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, res->blob_size, PROT_READ, MAP_SHARED, vbasedev->fd, 0);
+ if (map == MAP_FAILED) {
+ return map;
+ }
+
+ for (i = 0; i < res->iov_cnt; i++) {
+ rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
+ if (rb != first_rb) {
+ goto err;
+ }
+#if defined(VIRTIO_GPU_VFIO_BLOB)
+ ret = vfio_get_region_index_from_mr(rb->mr);
+ if (ret < 0) {
+ goto err;
+ }
+
+ ret = vfio_device_get_region_info(vbasedev, ret, &info);
+#endif
+ if (ret < 0 || !info) {
+ goto err;
+ }
+
+ submap = mmap(map + len, res->iov[i].iov_len, PROT_READ,
+ MAP_SHARED | MAP_FIXED, vbasedev->fd,
+ info->offset + offset);
+ if (submap == MAP_FAILED) {
+ goto err;
+ }
+
+ len += res->iov[i].iov_len;
+ }
+ return map;
+err:
+ munmap(map, res->blob_size);
+ return MAP_FAILED;
+}
+
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);
if (res->remapped == MAP_FAILED) {
+ res->remapped = vfio_dmabuf_mmap(res);
+ if (res->remapped != MAP_FAILED) {
+ return;
+ }
warn_report("%s: dmabuf mmap failed: %s", __func__,
strerror(errno));
res->remapped = NULL;
@@ -146,6 +247,13 @@ void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
} else {
virtio_gpu_create_udmabuf(res);
if (res->dmabuf_fd < 0) {
+ vfio_create_dmabuf(res);
+ }
+
+ if (res->dmabuf_fd < 0) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: memory region cannot be used to create dmabuf\n",
+ __func__);
return;
}
virtio_gpu_remap_dmabuf(res);
@@ -160,9 +268,7 @@ void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res)
{
- if (res->remapped) {
- virtio_gpu_destroy_dmabuf(res);
- }
+ virtio_gpu_destroy_dmabuf(res);
}
static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)
--
2.50.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2025-11-22 6:46 ` [PATCH v3 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices Vivek Kasireddy
@ 2025-11-22 7:25 ` Akihiko Odaki
2025-11-23 6:17 ` Kasireddy, Vivek
0 siblings, 1 reply; 13+ messages in thread
From: Akihiko Odaki @ 2025-11-22 7:25 UTC (permalink / raw)
To: Vivek Kasireddy, qemu-devel
Cc: Marc-André Lureau, Alex Bennée, Dmitry Osipenko,
Alex Williamson, Cédric Le Goater
On 2025/11/22 15:46, Vivek Kasireddy wrote:
> In addition to memfd, a blob resource can also have its backing
> storage in a VFIO device region. Therefore, we first need to figure
> out if the blob is backed by a VFIO device region or a memfd before
> we can call the right API to get a dmabuf fd created.
>
> So, we first call virtio_gpu_create_udmabuf() which further calls
> ram_block_is_memfd_backed() to check if the blob's backing storage
> is located in a memfd or not. If it is not, we call vfio_create_dmabuf()
> which identifies the right VFIO device and eventually invokes the
> API vfio_device_create_dmabuf_fd() to have a dmabuf fd created.
>
> Note that in virtio_gpu_remap_dmabuf(), we first try to test if
> the VFIO dmabuf exporter supports mmap or not. If it doesn't, we
> use the VFIO device fd directly to create the CPU mapping.
>
> While at it, remove the unnecessary rcu_read_lock/rcu_read_unlock
> from 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>
> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> ---
> hw/display/Kconfig | 5 ++
> hw/display/virtio-gpu-dmabuf.c | 122 ++++++++++++++++++++++++++++++---
> 2 files changed, 119 insertions(+), 8 deletions(-)
>
> diff --git a/hw/display/Kconfig b/hw/display/Kconfig
> index 1e95ab28ef..0d090f25f5 100644
> --- a/hw/display/Kconfig
> +++ b/hw/display/Kconfig
> @@ -106,6 +106,11 @@ config VIRTIO_VGA
> depends on VIRTIO_PCI
> select VGA
>
> +config VIRTIO_GPU_VFIO_BLOB
> + bool
> + default y
> + depends on VFIO
> +
> config VHOST_USER_GPU
> bool
> default y
> diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c
> index 258c48d31b..d121a2c9a7 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"
> @@ -40,10 +41,42 @@ static bool ram_block_is_memfd_backed(RAMBlock *rb)
> return false;
> }
>
> +static void vfio_create_dmabuf(struct virtio_gpu_simple_resource *res)
> +{
> +#if defined(VIRTIO_GPU_VFIO_BLOB)
> + VFIODevice *vbasedev;
> + RAMBlock *first_rb;
> + ram_addr_t offset;
> +
> + first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false, &offset);
> + if (!first_rb) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Could not find ramblock\n", __func__);
> + return;
> + }
> +
> + vbasedev = vfio_device_lookup(first_rb->mr);
> + if (!vbasedev) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: No VFIO device found to create dmabuf from\n",
> + __func__);
> + return;
> + }
> +
> + res->dmabuf_fd = vfio_device_create_dmabuf_fd(vbasedev,
> + res->iov, res->iov_cnt);
> + if (res->dmabuf_fd < 0) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: VFIO_DEVICE_FEATURE_DMA_BUF: %s\n",
> + __func__, strerror(errno));
> + }
> +#endif
> +}
> +
> static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
> {
> struct udmabuf_create_list *list;
> - RAMBlock *rb;
> + RAMBlock *rb, *first_rb;
> ram_addr_t offset;
> int udmabuf, i;
>
> @@ -52,15 +85,17 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
> return;
> }
>
> + first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false, &offset);
> + if (!ram_block_is_memfd_backed(first_rb)) {
> + return;
> + }
> +
We had an extensive discussion but I still don't understand the benefit
of this change while I see it adds complexity by having another call of
qemu_ram_block_from_host() and imposing an extra restriction that all
elements need to belong to one RAMBlock.
If anyone else have some opinion on this, I'd like to hear.
Regards,
Akihiko Odaki
> list = g_malloc0(sizeof(struct udmabuf_create_list) +
> sizeof(struct udmabuf_create_item) * res->iov_cnt);
>
> 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) {
> + if (rb != first_rb) {
> g_free(list);
> return;
> }
> @@ -81,11 +116,77 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
> g_free(list);
> }
>
> +static void *vfio_dmabuf_mmap(struct virtio_gpu_simple_resource *res)
> +{
> + struct vfio_region_info *info = NULL;
> + VFIODevice *vbasedev = NULL;
> + ram_addr_t offset, len = 0;
> + RAMBlock *first_rb, *rb;
> + void *map, *submap;
> + int i, ret = -1;
> +
> + first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false, &offset);
> + if (!first_rb) {
> + return MAP_FAILED;
> + }
> +#if defined(VIRTIO_GPU_VFIO_BLOB)
> + vbasedev = vfio_device_lookup(first_rb->mr);
> +#endif
> + if (!vbasedev) {
> + return MAP_FAILED;
> + }
> +
> + /*
> + * 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, res->blob_size, PROT_READ, MAP_SHARED, vbasedev->fd, 0);
> + if (map == MAP_FAILED) {
> + return map;
> + }
> +
> + for (i = 0; i < res->iov_cnt; i++) {
> + rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
> + if (rb != first_rb) {
> + goto err;
> + }
> +#if defined(VIRTIO_GPU_VFIO_BLOB)
> + ret = vfio_get_region_index_from_mr(rb->mr);
> + if (ret < 0) {
> + goto err;
> + }
> +
> + ret = vfio_device_get_region_info(vbasedev, ret, &info);
> +#endif
> + if (ret < 0 || !info) {
> + goto err;
> + }
> +
> + submap = mmap(map + len, res->iov[i].iov_len, PROT_READ,
> + MAP_SHARED | MAP_FIXED, vbasedev->fd,
> + info->offset + offset);
> + if (submap == MAP_FAILED) {
> + goto err;
> + }
> +
> + len += res->iov[i].iov_len;
> + }
> + return map;
> +err:
> + munmap(map, res->blob_size);
> + return MAP_FAILED;
> +}
> +
> 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);
> if (res->remapped == MAP_FAILED) {
> + res->remapped = vfio_dmabuf_mmap(res);
> + if (res->remapped != MAP_FAILED) {
> + return;
> + }
> warn_report("%s: dmabuf mmap failed: %s", __func__,
> strerror(errno));
> res->remapped = NULL;
> @@ -146,6 +247,13 @@ void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
> } else {
> virtio_gpu_create_udmabuf(res);
> if (res->dmabuf_fd < 0) {
> + vfio_create_dmabuf(res);
> + }
> +
> + if (res->dmabuf_fd < 0) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: memory region cannot be used to create dmabuf\n",
> + __func__);
> return;
> }
> virtio_gpu_remap_dmabuf(res);
> @@ -160,9 +268,7 @@ void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_resource *res)
>
> void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res)
> {
> - if (res->remapped) {
> - virtio_gpu_destroy_dmabuf(res);
> - }
> + virtio_gpu_destroy_dmabuf(res);
> }
>
> static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH v3 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2025-11-22 7:25 ` Akihiko Odaki
@ 2025-11-23 6:17 ` Kasireddy, Vivek
2025-11-23 8:36 ` Akihiko Odaki
0 siblings, 1 reply; 13+ messages in thread
From: Kasireddy, Vivek @ 2025-11-23 6:17 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 v3 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs
> associated with VFIO devices
>
> On 2025/11/22 15:46, Vivek Kasireddy wrote:
> > In addition to memfd, a blob resource can also have its backing
> > storage in a VFIO device region. Therefore, we first need to figure
> > out if the blob is backed by a VFIO device region or a memfd before
> > we can call the right API to get a dmabuf fd created.
> >
> > So, we first call virtio_gpu_create_udmabuf() which further calls
> > ram_block_is_memfd_backed() to check if the blob's backing storage
> > is located in a memfd or not. If it is not, we call vfio_create_dmabuf()
> > which identifies the right VFIO device and eventually invokes the
> > API vfio_device_create_dmabuf_fd() to have a dmabuf fd created.
> >
> > Note that in virtio_gpu_remap_dmabuf(), we first try to test if
> > the VFIO dmabuf exporter supports mmap or not. If it doesn't, we
> > use the VFIO device fd directly to create the CPU mapping.
> >
> > While at it, remove the unnecessary rcu_read_lock/rcu_read_unlock
> > from 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>
> > Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> > ---
> > hw/display/Kconfig | 5 ++
> > hw/display/virtio-gpu-dmabuf.c | 122
> ++++++++++++++++++++++++++++++---
> > 2 files changed, 119 insertions(+), 8 deletions(-)
> >
> > diff --git a/hw/display/Kconfig b/hw/display/Kconfig
> > index 1e95ab28ef..0d090f25f5 100644
> > --- a/hw/display/Kconfig
> > +++ b/hw/display/Kconfig
> > @@ -106,6 +106,11 @@ config VIRTIO_VGA
> > depends on VIRTIO_PCI
> > select VGA
> >
> > +config VIRTIO_GPU_VFIO_BLOB
> > + bool
> > + default y
> > + depends on VFIO
> > +
> > config VHOST_USER_GPU
> > bool
> > default y
> > diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-
> dmabuf.c
> > index 258c48d31b..d121a2c9a7 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"
> > @@ -40,10 +41,42 @@ static bool ram_block_is_memfd_backed(RAMBlock
> *rb)
> > return false;
> > }
> >
> > +static void vfio_create_dmabuf(struct virtio_gpu_simple_resource *res)
> > +{
> > +#if defined(VIRTIO_GPU_VFIO_BLOB)
> > + VFIODevice *vbasedev;
> > + RAMBlock *first_rb;
> > + ram_addr_t offset;
> > +
> > + first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false,
> &offset);
> > + if (!first_rb) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: Could not find ramblock\n", __func__);
> > + return;
> > + }
> > +
> > + vbasedev = vfio_device_lookup(first_rb->mr);
> > + if (!vbasedev) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: No VFIO device found to create dmabuf from\n",
> > + __func__);
> > + return;
> > + }
> > +
> > + res->dmabuf_fd = vfio_device_create_dmabuf_fd(vbasedev,
> > + res->iov, res->iov_cnt);
> > + if (res->dmabuf_fd < 0) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: VFIO_DEVICE_FEATURE_DMA_BUF: %s\n",
> > + __func__, strerror(errno));
> > + }
> > +#endif
> > +}
> > +
> > static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource
> *res)
> > {
> > struct udmabuf_create_list *list;
> > - RAMBlock *rb;
> > + RAMBlock *rb, *first_rb;
> > ram_addr_t offset;
> > int udmabuf, i;
> >
> > @@ -52,15 +85,17 @@ static void virtio_gpu_create_udmabuf(struct
> virtio_gpu_simple_resource *res)
> > return;
> > }
> >
> > + first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false,
> &offset);
> > + if (!ram_block_is_memfd_backed(first_rb)) {
> > + return;
> > + }
> > +
>
> We had an extensive discussion but I still don't understand the benefit
> of this change while I see it adds complexity by having another call of
I'll get rid of the extra call to qemu_ram_block_from_host() in the next version.
> qemu_ram_block_from_host() and imposing an extra restriction that all
> elements need to belong to one RAMBlock.
I thought you suggested that we need to ensure all entries (need to be
validated and) are associated with the same memory region? As
virtio_gpu_create_udmabuf() was not doing that, I thought this
change/restriction needs to be added.
And, since calling ram_block_is_memfd_backed() for each entry would
incur extra overhead (as there can be thousands of entries and fcntl needs
to check with the kernel), I figured calling it once for the first ram block
and comparing all the other ram blocks against it made sense.
Also, rethinking this whole situation again, I don't think we should try to create
a dmabuf for a buffer that might have mixed/different memory regions or
memfds (as this is most likely an invalid scenario that could lead to undefined
behavior) so this change is meant to prevent such scenario.
Thanks,
Vivek
>
> If anyone else have some opinion on this, I'd like to hear.
>
> Regards,
> Akihiko Odaki
>
> > list = g_malloc0(sizeof(struct udmabuf_create_list) +
> > sizeof(struct udmabuf_create_item) * res->iov_cnt);
> >
> > 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) {
> > + if (rb != first_rb) {
> > g_free(list);
> > return;
> > }
> > @@ -81,11 +116,77 @@ static void virtio_gpu_create_udmabuf(struct
> virtio_gpu_simple_resource *res)
> > g_free(list);
> > }
> >
> > +static void *vfio_dmabuf_mmap(struct virtio_gpu_simple_resource *res)
> > +{
> > + struct vfio_region_info *info = NULL;
> > + VFIODevice *vbasedev = NULL;
> > + ram_addr_t offset, len = 0;
> > + RAMBlock *first_rb, *rb;
> > + void *map, *submap;
> > + int i, ret = -1;
> > +
> > + first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false,
> &offset);
> > + if (!first_rb) {
> > + return MAP_FAILED;
> > + }
> > +#if defined(VIRTIO_GPU_VFIO_BLOB)
> > + vbasedev = vfio_device_lookup(first_rb->mr);
> > +#endif
> > + if (!vbasedev) {
> > + return MAP_FAILED;
> > + }
> > +
> > + /*
> > + * 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, res->blob_size, PROT_READ, MAP_SHARED,
> vbasedev->fd, 0);
> > + if (map == MAP_FAILED) {
> > + return map;
> > + }
> > +
> > + for (i = 0; i < res->iov_cnt; i++) {
> > + rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
> > + if (rb != first_rb) {
> > + goto err;
> > + }
> > +#if defined(VIRTIO_GPU_VFIO_BLOB)
> > + ret = vfio_get_region_index_from_mr(rb->mr);
> > + if (ret < 0) {
> > + goto err;
> > + }
> > +
> > + ret = vfio_device_get_region_info(vbasedev, ret, &info);
> > +#endif
> > + if (ret < 0 || !info) {
> > + goto err;
> > + }
> > +
> > + submap = mmap(map + len, res->iov[i].iov_len, PROT_READ,
> > + MAP_SHARED | MAP_FIXED, vbasedev->fd,
> > + info->offset + offset);
> > + if (submap == MAP_FAILED) {
> > + goto err;
> > + }
> > +
> > + len += res->iov[i].iov_len;
> > + }
> > + return map;
> > +err:
> > + munmap(map, res->blob_size);
> > + return MAP_FAILED;
> > +}
> > +
> > 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);
> > if (res->remapped == MAP_FAILED) {
> > + res->remapped = vfio_dmabuf_mmap(res);
> > + if (res->remapped != MAP_FAILED) {
> > + return;
> > + }
> > warn_report("%s: dmabuf mmap failed: %s", __func__,
> > strerror(errno));
> > res->remapped = NULL;
> > @@ -146,6 +247,13 @@ void virtio_gpu_init_dmabuf(struct
> virtio_gpu_simple_resource *res)
> > } else {
> > virtio_gpu_create_udmabuf(res);
> > if (res->dmabuf_fd < 0) {
> > + vfio_create_dmabuf(res);
> > + }
> > +
> > + if (res->dmabuf_fd < 0) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: memory region cannot be used to create dmabuf\n",
> > + __func__);
> > return;
> > }
> > virtio_gpu_remap_dmabuf(res);
> > @@ -160,9 +268,7 @@ void virtio_gpu_init_dmabuf(struct
> virtio_gpu_simple_resource *res)
> >
> > void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res)
> > {
> > - if (res->remapped) {
> > - virtio_gpu_destroy_dmabuf(res);
> > - }
> > + virtio_gpu_destroy_dmabuf(res);
> > }
> >
> > static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices
2025-11-23 6:17 ` Kasireddy, Vivek
@ 2025-11-23 8:36 ` Akihiko Odaki
0 siblings, 0 replies; 13+ messages in thread
From: Akihiko Odaki @ 2025-11-23 8:36 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 2025/11/23 15:17, Kasireddy, Vivek wrote:
> Hi Akihiko,
>
>> Subject: Re: [PATCH v3 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs
>> associated with VFIO devices
>>
>> On 2025/11/22 15:46, Vivek Kasireddy wrote:
>>> In addition to memfd, a blob resource can also have its backing
>>> storage in a VFIO device region. Therefore, we first need to figure
>>> out if the blob is backed by a VFIO device region or a memfd before
>>> we can call the right API to get a dmabuf fd created.
>>>
>>> So, we first call virtio_gpu_create_udmabuf() which further calls
>>> ram_block_is_memfd_backed() to check if the blob's backing storage
>>> is located in a memfd or not. If it is not, we call vfio_create_dmabuf()
>>> which identifies the right VFIO device and eventually invokes the
>>> API vfio_device_create_dmabuf_fd() to have a dmabuf fd created.
>>>
>>> Note that in virtio_gpu_remap_dmabuf(), we first try to test if
>>> the VFIO dmabuf exporter supports mmap or not. If it doesn't, we
>>> use the VFIO device fd directly to create the CPU mapping.
>>>
>>> While at it, remove the unnecessary rcu_read_lock/rcu_read_unlock
>>> from 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>
>>> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
>>> ---
>>> hw/display/Kconfig | 5 ++
>>> hw/display/virtio-gpu-dmabuf.c | 122
>> ++++++++++++++++++++++++++++++---
>>> 2 files changed, 119 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/hw/display/Kconfig b/hw/display/Kconfig
>>> index 1e95ab28ef..0d090f25f5 100644
>>> --- a/hw/display/Kconfig
>>> +++ b/hw/display/Kconfig
>>> @@ -106,6 +106,11 @@ config VIRTIO_VGA
>>> depends on VIRTIO_PCI
>>> select VGA
>>>
>>> +config VIRTIO_GPU_VFIO_BLOB
>>> + bool
>>> + default y
>>> + depends on VFIO
>>> +
>>> config VHOST_USER_GPU
>>> bool
>>> default y
>>> diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-
>> dmabuf.c
>>> index 258c48d31b..d121a2c9a7 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"
>>> @@ -40,10 +41,42 @@ static bool ram_block_is_memfd_backed(RAMBlock
>> *rb)
>>> return false;
>>> }
>>>
>>> +static void vfio_create_dmabuf(struct virtio_gpu_simple_resource *res)
>>> +{
>>> +#if defined(VIRTIO_GPU_VFIO_BLOB)
>>> + VFIODevice *vbasedev;
>>> + RAMBlock *first_rb;
>>> + ram_addr_t offset;
>>> +
>>> + first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false,
>> &offset);
>>> + if (!first_rb) {
>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>> + "%s: Could not find ramblock\n", __func__);
>>> + return;
>>> + }
>>> +
>>> + vbasedev = vfio_device_lookup(first_rb->mr);
>>> + if (!vbasedev) {
>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>> + "%s: No VFIO device found to create dmabuf from\n",
>>> + __func__);
>>> + return;
>>> + }
>>> +
>>> + res->dmabuf_fd = vfio_device_create_dmabuf_fd(vbasedev,
>>> + res->iov, res->iov_cnt);
>>> + if (res->dmabuf_fd < 0) {
>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>> + "%s: VFIO_DEVICE_FEATURE_DMA_BUF: %s\n",
>>> + __func__, strerror(errno));
>>> + }
>>> +#endif
>>> +}
>>> +
>>> static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource
>> *res)
>>> {
>>> struct udmabuf_create_list *list;
>>> - RAMBlock *rb;
>>> + RAMBlock *rb, *first_rb;
>>> ram_addr_t offset;
>>> int udmabuf, i;
>>>
>>> @@ -52,15 +85,17 @@ static void virtio_gpu_create_udmabuf(struct
>> virtio_gpu_simple_resource *res)
>>> return;
>>> }
>>>
>>> + first_rb = qemu_ram_block_from_host(res->iov[0].iov_base, false,
>> &offset);
>>> + if (!ram_block_is_memfd_backed(first_rb)) {
>>> + return;
>>> + }
>>> +
>>
>> We had an extensive discussion but I still don't understand the benefit
>> of this change while I see it adds complexity by having another call of
> I'll get rid of the extra call to qemu_ram_block_from_host() in the next version.
It is possible to reduce the number of the execution of
qemu_ram_block_from_host() calls, but the code complexity remains unless
you keep the original code.
>
>> qemu_ram_block_from_host() and imposing an extra restriction that all
>> elements need to belong to one RAMBlock.
> I thought you suggested that we need to ensure all entries (need to be
> validated and) are associated with the same memory region? As
> virtio_gpu_create_udmabuf() was not doing that, I thought this
> change/restriction needs to be added.
My first comment I raised for "[PATCH v2 09/10] virtio-gpu-dmabuf:
Introduce qemu_iovec_same_memory_regions()" was that it complicates the
codebase without necessity.
https://lore.kernel.org/qemu-devel/83274ca7-dd37-4856-b198-f334bf630835@rsg.ci.i.u-tokyo.ac.jp/
>
> And, since calling ram_block_is_memfd_backed() for each entry would
> incur extra overhead (as there can be thousands of entries and fcntl needs
> to check with the kernel), I figured calling it once for the first ram block
> and comparing all the other ram blocks against it made sense.
I don't think the change is irrelevant with adding support of VFIO, and
I doubt its necessity either; the UDMABUF_CREATE_LIST ioctl will catch it.
>
> Also, rethinking this whole situation again, I don't think we should try to create
> a dmabuf for a buffer that might have mixed/different memory regions or
> memfds (as this is most likely an invalid scenario that could lead to undefined
> behavior) so this change is meant to prevent such scenario.
In the email thread I cited I only said the check is unnecessary, but it
can be also problematic.
For example, if you hotplug some memory, the memory can be backed by
another memfd, and the kernel may use both the existing memory and the
hotplugged one to back a virtually contiguous region allocated for a
virtio-gpu resource. You may look at drm_gem_get_pages() in Linux and
find out that it allocates on a per-page basis.
Regards,
Akihiko Odaki
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-11-23 8:41 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-22 6:46 [PATCH v3 0/9] vfio: Implement VFIO_DEVICE_FEATURE_DMA_BUF and use it in virtio-gpu Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 1/9] virtio-gpu: Recreate the resource's dmabuf if new backing is attached Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 2/9] virtio-gpu: Find hva for Guest's DMA addr associated with a ram device Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 3/9] vfio: Document vfio_device_get_region_info() Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 4/9] vfio/region: Add a helper to get region index from memory region Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 5/9] vfio/device: Add a helper to lookup VFIODevice " Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 6/9] vfio/device: Add support for VFIO_DEVICE_FEATURE_DMA_BUF Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 7/9] virtio-gpu: Rename udmabuf files and helpers to dmabuf Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 8/9] virtio-gpu-dmabuf: Introduce ram_block_is_memfd_backed() helper Vivek Kasireddy
2025-11-22 6:46 ` [PATCH v3 9/9] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices Vivek Kasireddy
2025-11-22 7:25 ` Akihiko Odaki
2025-11-23 6:17 ` Kasireddy, Vivek
2025-11-23 8:36 ` Akihiko Odaki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).