R4: virtio-gpu driver (virgl, scanout, cursor), guest verification pending #7
Loading…
Reference in a new issue
No description provided.
Delete branch "r4-virtio-gpu"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Anima work item: WI-456
01a0e388-0729-7da2-9fac-747b889a2020Stacked on #6 (
r2-sync). Pins illumos-ddir4-virtiobe78455670(illumos-ddi #6, stacked on its #5).Status: code complete and verified in a QEMU guest (Hephaistos, QEMU 6.2,
-device virtio-gpu-gl-pci -display egl-headless, virglrenderer 0.9.1 on the host's AMD GPU), including Mesa's virgl driver rendering throughvirtio_gputo the screen. The guest runs found three bugs and the final review of their evidence a fourth, all fixed here and re-run on the device (see Fixes from the guest runs). This PR was first opened while the test host was down, with the verification marked pending; that original section is kept at the end under History.What was built
drivers/virtio-gpu(modulevirtio_gpu, PCI1af4:1050), on illumos-ddi'sddi::private::virtio:VIRGL,EDID,RESOURCE_BLOBandCONTEXT_INITwhen offered. The control queue carries every request and the cursor queue carries cursor updates.virtio_gpu_ctrl_hdrand complete in thread context on the framework's task queue, and waiters also poll. Fenced requests (SUBMIT_3D, the 3D transfers) take their fence id under the submission lock and signal R2Fences in the device's per-context order.SysMembound for DMA against the device's node, and their cookies are theATTACH_BACKING(or blob) memory entries:BLOB_MEM_GUEST,BLOB_MEM_HOST3D_GUEST).RESOURCE_UNREFbefore freeing its memory, and leaks the memory if the device never answers.MAP;EXECBUFFER(32-, 40- and 64-byte layouts;FENCE_FD_IN/OUTthrough R2 sync files; in and out sync-object arrays including timelines andSYNCOBJ_RESET; rings withRING_IDX);GETPARAM(3D_FEATURES,CAPSET_QUERY_FIX=1,RESOURCE_BLOB,HOST_VISIBLE=0,CROSS_DEVICE=0,CONTEXT_INIT,SUPPORTED_CAPSET_IDs,EXPLICIT_DEBUG_NAME);RESOURCE_CREATE;RESOURCE_INFO;TRANSFER_FROM_HOSTandTRANSFER_TO_HOST(also in the 36-byte layout);WAIT;GET_CAPS;RESOURCE_CREATE_BLOB;CONTEXT_INIT. The driver reports version 0.1.0, which Mesa's virgl winsys requires.SET_SCANOUT, withTRANSFER_TO_HOST_2Dfor dumb buffers andRESOURCE_FLUSH. The cursor uses the cursor queue.DIRTYFBsends one transfer and flush of the damage's bounding box.pci:0000:BB:DD.F, which Xorg's modesetting driver matches.GemObject::handle_opened,handle_closedandrelease;Driver::file_closeandDriver::dumb_object;KmsDriver::dirty_fb(the default is stillENOSYS);SyncCore::sync_file_fencemade public;Plainfor the virtgpu uAPI structures.drm-uapiis regenerated withvirtgpu_drm.hfrom Linux v6.12. The header is MIT-licensed; its source URL and SHA-256 are intools/uapi/include/README. libdrm 2.4.109's copy lacksRESOURCE_CREATE_BLOB,CONTEXT_INIT, the later parameters and the sync-object arrays.virtgpu_compat.rsdeclares the older layouts:EXECBUFFERat 32 bytes (libdrm 2.4.109) and 40 bytes (Mesa 21.3), and the 36-byte transfers.tools/uapi/virtgpu_compat_layout.cchecks those layouts against the original headers, andabi.rspins every virtio-gpu ioctl number.packaging/virtio-gpu.p5mdelivers the module with adriveraction (alias=pci1af4,1050,perms="* 0666 root sys", and adevlinkfor/dev/dri).packaging/xorg.conf.d/20-virtio-gpu.confconfigures modesetting withkmsdev/dev/dri/card0and glamor.devlink.tabgets the virtio_gpu line.tools/test/drm_r4_test.ccovers the parameters, capsets and dumb buffers. With virgl, it also sends a minimal virgl command stream (surface, framebuffer, clear) throughEXECBUFFERand checks the pixels read back withTRANSFER_FROM_HOST; chains fences across the three layouts; covers sync objects and a timeline wait that times out; imports a buffer into the render node's context with PRIME; creates blobs and runsCONTEXT_INIT; checks every refusal; and runs 2000 submissions in a row plus 8 threads at once.tools/test/run-r4-test.shlinks, checks symbols, runsadd_drv, runs the test and modetest, checks that detach is refused while a file is open and while only a dma-buf is left, then unloads and checks that/etcand/devicesare restored.cargo test -p virtio_gpu --no-default-features.-N misc/virtio -N fs/specfs.Decisions
rdrmnull, with-N misc/virtio -N fs/specfs.Driver::fence_priorityisNone, and no driver lock has an interrupt priority.RESOURCE_UNREFis therefore never awaited on the completing thread.Mesa: oi-userlandhephaistos/virgl-gallium(d69854c287) was built on oibuild in/ws/toastywith-j2, and published asx11/library/mesa@21.3.9-2025.0.0.90withCOMPONENT_REVISION=90so that it outranks the installed 21.3.9. No packages were installed on oibuild andenv-prepwas not run. The worktree-local repo was created withpkgrepo create. The guest run showed that revision 90 crashes invirgl_disk_cache_create(it reads a GNU build ID that illumos' link-editor does not emit), so the oibuild worktree gainedpatches/09-virgl-disk-cache-build-id.patch(commit4aa9a85809, usesdisk_cache_get_function_identifier, which falls back to the library's mtime) and was republished as revision 91 (mesa-virgl-r4-91.p5p, SHA-2561fb443ad…). Revision 91 was published from the worktree's local branchr4/xorg-glamorat4aa9a85809, which isd69854c287plus five xorg-server test commits (the abandoned glamor build) plus the Mesa patch; only the patch touches Mesa. Nothing was pushed upstream. The crash itself was seen in the guest but its stack was not saved; the static evidence (the unpatchedbuild_id_length(note)on a NULL note with the assert compiled out, and no note section in the builtvirtio_gpu_dri.so) is inlogs/oibuild/mesa-virgl-r4/build-id-evidence.log.Deviations
HOST_VISIBLEis 0 andBLOB_MEM_HOST3Dblobs are refused withEINVAL: the gate framework has no shared-memory regions, as the work item expected.CROSS_DEVICEis 0 (no resource UUIDs).POLL_RINGS_MASKisEINVAL, because the core has no per-file event queue outside KMS.SET_SCANOUT_BLOBis not implemented. WithHOST_VISIBLE=0, Mesa does not use them.EXECBUFFERcommand stream is limited to 1 MiB (Mesa 21.3 sends at most 266,240 bytes).EXECBUFFERis queued, adding its fence to the reservations, the out sync objects or a new sync file can still fail for lack of memory. The ioctl then reports an error for work that runs anyway. Linux reserves these first.pid N, because the DDI has no process name.CONTEXT_INITisEINVALwithoutVIRTIO_GPU_F_CONTEXT_INIT, which QEMU 6.2 does not offer. On such a host only that path can be exercised.Verification (counts and logs)
Done:
--lockedon the pinned illumos-ddi: check, clippy-D warnings(also withrdrmnull/panic-drill), fmt, rustdoc-D warnings. Tests:drm109,drm-uapi1,virtio_gpu5, and the host tests caught a real bug in response checking.xtask uapi-check: 111 sizes, 497 offsets, 121 ioctl numbers identical to gcc 14.3.0 on illumos (tools/uapi/drm_layout.oibldofgate.out, which now includes the compat layouts). The kernel archives ofvirtio_gpuandrdrmnullbuild with nightly-2026-04-16. Log:logs/r4-host-checks-illumos-drm.log.cda5b9a49f, the golden guest's kernel), with nothing loaded:virtio_gpulinks withNEEDED misc/virtio, fs/specfsand all 127 of its undefined symbols are exported by the running kernel;rdrmnullhas 106 of 106. Log:logs/oibldofgate/20260930-r4-kmod-link.log.kernel-checkof the virtio crate against that kernel: 48/48 symbols fromvirtio. Log:logs/oibldofgate/20260930-r4-virtio-kernel-check.log.pkglintclean, published and received as a p5p. Log:logs/oibuild/20260930-r4-virtio-gpu-package.log; artifactartifacts/r4-virtio-gpu/package/.gmake install(1558 ninja steps,virtio_gpu_dri.soin the proto area) andgmake publishboth exit 0. Logs:logs/oibuild/mesa-virgl-r4/; artifactartifacts/r4-virtio-gpu/mesa/mesa-virgl-r4.p5p.drm_r4_test.ccompiles withgcc -Wall -Wextraon illumos.Guest runs on Hephaistos (2026-09-30; fresh overlays of the golden Hipster image, illumos
cda5b9a49f, 2 vCPUs, 3 GiB, private user networking, bounded lifetime; ports 2360-2364; all overlays deleted afterwards, nothing left running). Logs are in the workspace underlogs/hephaistos/illumos-drm/, screenshots underartifacts/r4-virtio-gpu/screens/, the results note isnotes/r4-virtio-gpu-verification.md. No run panicked.virtio-gpu-gl-pci,virtio-gpu-pciandegl-headless; libvirglrenderer 0.9.1;/dev/dri/renderD128on the host. Log20260930-r4-host-preflight.log.addr=0x10; and at illumoscda5b9a49fthe virtio framework caches the BAR register number of the first modern device (illumos bug 18358, fixed upstream in36d8c52c14), sovirtio_initfor the GPU failed with "Failed to map CAP 1 @ BAR4" behind the transitional vioblk. The runs attach the disk withdisable-modern=oninstead. Logs20260930-r4-run2-driver.log,20260930-r4-run2-bar-cache.log; documented in illumos-ddi #6 (docs/DESIGN.md).dmesg):virtio_gpu0: virtio-gpu: 1 scanout(s), features 0x110000003 of 0x130000003 (virgl true, edid true, blob false, context_init false), 2 capset(s) 0x6, modern interface.run-r4-test.sh: PASS, 74 checks, 0 failures (r4-run5, driver fromc4318271eb, whose code is that of7dda62f; the rebase only movedvirgl_egl_test.cinto its own commit;virtio_gpu.aSHA-256c909e777…f7e6). Log20260930-r4-run5-driver.log.drm_r4_test63/63, including the minimal virgl command stream (surface, framebuffer, clear) read back from the host renderer withTRANSFER_FROM_HOST, fences across the 32/40/64-byteEXECBUFFERlayouts, binary and timeline sync objects, PRIME into another file's context, 2000 submissions in a row, and 8 threads creating, clearing, fencing, reading back and closing 800 textures at once.EXECBUFFERflagsEINVAL; a timeline wait times out withETIMEafter 100 ms;CONTEXT_INIT-only rings refused; unknown handles and sync objects, bad strides, oversized and unreadable streams refused.20260930-r4-run3-modetest-vsync-gpu0.png(SMPTE bars).modunloadrefused while a process holds a file, a dumb buffer and a dma-buf, and while only a dma-buf is left; the device works again afterwards; then it unloads, and/etcand/devicesare as before. At detach: 19,543 requests, 7,224 fenced, 0 failed, 5 queue-full waits, 0 timeouts, 2,011 resources created, 0 left.rdrmnullin the same boot:run-r1-test: fail=0(R0, R1 and R2 suites, 0 failures each) andrun-r3-test: fail=0. Logs20260930-r4-run5-regression-r1.log,20260930-r4-run5-regression-r3.log.x11/server/xorg@1.19.7-2026.0.0.14andx11/demo/mesa-demos@8.5.0installed from the openindiana.org publisher into the overlay (20260930-r4-run5-x-install.log) withpackaging/xorg.conf.d/20-virtio-gpu.conf: modesetting opens card0, reads the EDID, runs 1024x768 with damage throughDIRTYFB(20260930-r4-run5-Xorg.1-stock.log, screenshot20260930-r4-run5-xorg-stock-gpu0.png). OpenIndiana's Xorg is built without glamor ("No glamor support in the X Server", "AIGLX: Screen 0 is not DRI2 capable"), soglxinfo -Breports softpipe, not virgl (20260930-r4-run5-glxinfo-stock-xorg.log), andglxgearsruns at about 180 FPS in software, shown on the virtio-gpu scanout (20260930-r4-run5-glxgears-softpipe.log,20260930-r4-run5-glxgears-softpipe-gpu0.png). A glamor rebuild of Xorg on oibuild failed (xtrans 1.6 and gcc 14 errors; the last attempt's log islogs/oibuild/mesa-virgl-r4/xorg-glamor-publish.log, failing inXtranssock.conmsghdr.msg_control) and was abandoned. The stock-Xorg screenshot20260930-r4-run5-xorg-stock-gpu0.pngis black (an empty root window); the scanout of X's damage is shown by the glxgears screenshot.pkg installof the p5p in the guest is impossible (it depends on osnet 23293, the golden image has 23197), so its payload (tar SHA-256be86a844…65b4, 104 files, each listed in20260930-r4-run5-mesa-overlay.log;virtio_gpu_dri.soSHA-256c300f510…) was extracted over the stock Mesa 21.3.9 in the overlay only, never the golden image. OpenIndiana's libdrm 2.4.109 only enumerates device nodes nameddisplay, so without help EGL fails with "DRI2: failed to find EGLDevice" (20260930-r4-run5-virgl-egl.log); the tests loadtools/test/drm_devshim.cwithLD_PRELOAD_64to answerdrmGetDevice2for the device.tools/test/virgl_egl_test.c(EGL on GBM, render node):GL_RENDERER: virgl,GL_VERSION: 3.1 Mesa 21.3.9, a cleared 256x256 FBO reads back exactly, 600 clear-and-read-back frames at about 1,300 per second, 0 failures (20260930-r4-run5-virgl-egl-shim.log).tools/test/virgl_kms_gears.c(GBM scanout surface on card0, page flip per frame, waiting for each flip event): renderer virgl, 600 frames at 74.8 fps on the 75 Hz mode, 0 failures; QMP screendump of the virgl-rendered frame20260930-r4-run5-virgl-kms-gears-gpu0.png. Afterwardsmodunloadsucceeded: 18,762 requests, 3,011 fenced, 0 failed, 8 resources created, 0 left (20260930-r4-run5-virgl-kms-gears.log).xf86CloseConsole(VT_ACTIVATE) holding card0, and needed SIGKILL before the unload.8e15c99b50(after the final review round's fix below;virtio_gpu.aSHA-2563f6d912c…3519,rdrmnull.afrom the same commit), port 2365:run-r4-test.sh: PASS, 74 checks, including its/dev/dricleanup (20260930-r4-run6-driver.log). Detach: 19,522 requests, 7,224 fenced, 0 failed, 4 queue-full waits, 0 timeouts, 2,011 resources, 0 left.modunloadsucceeds (20260930-r4-run6-cursor-close.log, program20260930-r4-run6-cursor_close.c).run-r1-test: fail=0,run-r3-test: fail=0(20260930-r4-run6-regression-r1.log,-r3.log).x11/library/mesaandx11/library/libdrmfrom the publisher, rev 91 payload over it,20260930-r4-run6-mesa-overlay.log):virgl_egl_test0 failed withGL_RENDERER: virgl;virgl_kms_gears600 page-flipped frames at 75.0 fps; screendump20260930-r4-run6-virgl-kms-gears-gpu0.png; cleanmodunloadafterwards (20260930-r4-run6-virgl.log). Xorg was not rerun.logs/hephaistos/illumos-drm/r4-console/.55d8e6011d: check, clippy-D warnings(also withrdrmnull/panic-drill), fmt, rustdoc, tests (drm111,drm-uapi1,virtio_gpu5),uapi-check0 differences. Loglogs/20260930-r4-host-checks-final-illumos-drm.log.Fixes from the guest runs
a1d0785kms (core): a CRTC turned off by a close orRMFBnow takes its other planes with it.modetest -Cleft a legacy cursor framebuffer (owned by no file) on the dark CRTC, so detach was refused with no file open. New host testclose_turns_off_the_cursor_of_the_crtc_it_turns_offfails without the fix.7dda62fvirtio_gpu: the driver no longer keeps aKArc<FenceDomain>; it takes the domain from the device's sync core per submission. Holding it meant the core's "fences or sync objects remain" check refused every unload.4ad90da, and the rate check ina1d0785, run-r4-test.sh: the page-flip rate is compared with the mode's refresh rate (QEMU's EDID prefers 75 Hz), and the script removesvirtio_gpu's/dev/drilinks at the end so later suites start clean.8e15c99kms (core), from the final review round: a file's close also turns off the legacy cursors it set.add_fbtakes anFbOwner(FileorCursor), and the internal cursor framebuffer records the file whoseCURSORcall made it. Without this, a cursor set on a CRTC that is off (or left bySETCRTCturning the CRTC off) outlived its master and keptvirtio_gpu's detach refused. Linux leaves such cursors on; the README explains the difference. New host testclose_turns_off_the_legacy_cursors_the_file_set, which fails without the change; verified on the device in r4-run6.72256f3tools/test:virgl_egl_test.c,virgl_kms_gears.c,drm_devshim.c.7dd280a,03f8109,55d8e60README;d02a5bcthe Xorg snippet documents the no-glamor case.Local review rounds
8e15c99, re-run in r4-run6); two claims without logs (the rev-90 crash, now backed by static evidence and marked as such; the Xorg glamor failure, log added); and the Mesa branch name (corrected above). Notes: the driver package p5p in the workspace was built from an earlier commit (72397ee39e; onlypkglintand publishing were claimed, and it should be rebuilt from the merged head before any publication); the run3 SMPTE screenshot predates the fixes (r4-run6's virgl screendump is at the final head).Open issues
ddi_display:drminstead of the node namedisplay(and fix the PCI path parsing); until then Mesa needsdrm_devshim.cfor virtio-gpu. Workspace notenotes/mesa-component.md, libdrm item 6.cda5b9a49f): a second modern virtio device fails; the runs use a transitional disk.hephaistos/virgl-galliumbranch, local) and a Mesa package whose dependencies match the installed osnet.SET_SCANOUT_BLOB, host-visible blobs (they need shared-memory regions in the gate's virtio framework), resource UUIDs, and polled-ring fence events.EXECBUFFER's fence slots, chains and fd before queueing.mainonce the stacked branches merge.History
The first version of this PR (head
298fec2438) was opened while Hephaistos was down. Its verification section read:Found by the R4 run: the driver kept a counted reference to the DRM device's fence domain for its fenced requests, so the core's detach check always found the domain in use ("fences or sync objects remain" with every count at zero) and the module never unloaded. The driver now keeps only its fence context number and the ioctls pass the domain in. run-r4-test.sh: modetest prints the mode after the rates; compare in END.