Skip to content

Commit 0fc3760

Browse files
author
Adam Ford
committed
virtio/gpu: mmap dma-buf blob fds into the guest shm region
resource_map_blob() in the virgl_resource_map2/Linux variant only mmaps SHM (memfd) blob fds into the guest's virtio shm region directly. DMABUF blob fds are delegated to Rutabaga::resource_map -> virgl_renderer_resource_map2, which is designed for virglrenderer-allocated GPU memory and has no machinery to mmap an external dma-buf fd into a host VA range. For dma-bufs that are not virglrenderer-managed (V4L2 capture buffers exported via VIDIOC_EXPBUF, dma-bufs forwarded to the guest by a host PipeWire daemon, etc.) it silently no-ops and the guest's blob is left backed by zero pages. The user-visible symptom is camera capture across the muvm PipeWire bridge delivering all-zero frames even though every layer reports success: SCM_RIGHTS forwards the dma-buf fd, libkrun classifies it correctly as DMABUF, the guest issues DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB which succeeds, and multifilesink writes plausible-sized files that turn out to be 0x00 bytes from offset 0 to EOF. A V4L2 EXPBUF dma-buf wraps regular kernel pages allocated via VIDIOC_REQBUFS/V4L2_MEMORY_MMAP and is CPU-mappable. It can be mmap'd into the guest's pre-reserved shm region with MAP_FIXED exactly the same way SHM (memfd) blobs are. Extending the existing SHM branch to also accept DMABUF gives the guest live pages and fixes camera capture without changes to the bridge, PipeWire, or the v4l2 userspace stack. If the dma-buf is GPU-only and not CPU-mappable, mmap returns MAP_FAILED and we surface ErrUnspec, no worse than the prior silent no-op. The handle_type is now included in the error log to help diagnose mismatches. The fd lifetime is fine: Rutabaga::export_blob returns a try_clone() of the descriptor, and the mapping persists past the temporary's drop because the original fd is retained in the resource's persistent handle slot. Signed-off-by: Adam Ford <[email protected]>
1 parent a3b7ae2 commit 0fc3760

1 file changed

Lines changed: 20 additions & 2 deletions

File tree

src/devices/src/virtio/gpu/virtio_gpu.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use krun_display::{
2020
use libc::c_void;
2121
#[cfg(target_os = "macos")]
2222
use rutabaga_gfx::RUTABAGA_MEM_HANDLE_TYPE_APPLE;
23+
#[cfg(all(feature = "virgl_resource_map2", target_os = "linux"))]
24+
use rutabaga_gfx::RUTABAGA_MEM_HANDLE_TYPE_DMABUF;
2325
#[cfg(all(not(feature = "virgl_resource_map2"), target_os = "linux"))]
2426
use rutabaga_gfx::RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_FD;
2527
#[cfg(all(feature = "virgl_resource_map2", target_os = "linux"))]
@@ -837,7 +839,20 @@ impl VirtioGpu {
837839
let addr = shm_region.host_addr + offset;
838840

839841
if let Ok(export) = self.rutabaga.export_blob(resource_id) {
840-
if export.handle_type == RUTABAGA_MEM_HANDLE_TYPE_SHM {
842+
// SHM and DMABUF are both regular host fds whose pages can be exposed
843+
// to the guest by mmap'ing them directly into the virtio shm region.
844+
// For SHM (memfd) this has always worked. For DMABUF it had been
845+
// delegated to virgl_renderer_resource_map2, which only handles
846+
// virglrenderer-allocated GPU memory and silently no-ops for external
847+
// dma-bufs — leaving the guest blob backed by zero pages. That broke
848+
// muvm camera capture, where the v4l2 source exports kernel buffers
849+
// via VIDIOC_EXPBUF as dma-bufs, the muvm bridge forwards the fd
850+
// across SCM_RIGHTS, libkrun classifies it as DMABUF, and the guest's
851+
// CREATE_BLOB allocates a host-backed-by-nothing blob. Mapping the
852+
// dma-buf fd directly here gives the guest real, live pages.
853+
if export.handle_type == RUTABAGA_MEM_HANDLE_TYPE_SHM
854+
|| export.handle_type == RUTABAGA_MEM_HANDLE_TYPE_DMABUF
855+
{
841856
let ret = unsafe {
842857
libc::mmap(
843858
addr as *mut libc::c_void,
@@ -849,7 +864,10 @@ impl VirtioGpu {
849864
)
850865
};
851866
if ret == libc::MAP_FAILED {
852-
error!("failed to mmap resource in shm region");
867+
error!(
868+
"failed to mmap resource in shm region (handle_type={:#x})",
869+
export.handle_type
870+
);
853871
return Err(ErrUnspec);
854872
}
855873
} else {

0 commit comments

Comments
 (0)