Skip to content

virtio/gpu: mmap dma-buf blob fds into the guest shm region#644

Open
aford173 wants to merge 1 commit intocontainers:mainfrom
aford173:pipewire
Open

virtio/gpu: mmap dma-buf blob fds into the guest shm region#644
aford173 wants to merge 1 commit intocontainers:mainfrom
aford173:pipewire

Conversation

@aford173
Copy link
Copy Markdown

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.

Requires: AsahiLinux/muvm#223

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 <adam.ford@anodize.com>
@slp
Copy link
Copy Markdown
Collaborator

slp commented Apr 21, 2026

The change looks good to me, but can't get it to work here after enabling the virgl_renderer_map2 feature. Does it require any other changes apart from AsahiLinux/muvm#223 ?

@aford173
Copy link
Copy Markdown
Author

@slp - From what I can tell,I only needed the libkrun and muvm patches to stream video from guest to host via Pipewire. I setup pipewire to run as a user service and the user that runs muvm is added to the groups for seat,tty,video,render,audio,pipewire, and input. I only have one camera configured with pipewire, so it uses that one camera by default. My host runs Xwayland.

I run "muvm -- bash" to get my virtual machine, then I run gstreamer to capture video inside the virtual machine

gst-launch0-1.0 pipewiresrc ! videoconvert ! ximagesink

The video streams from my laptop's built-in USB Camera to a window.

I haven't tried updating libkrunfw, but the version I have checked out is from December 2025.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants