Skip to content

feat: MSI interrupt-driven VirtIO GPU + VirGL fixes#243

Merged
ryanbreen merged 1 commit intomainfrom
feat/virgl-msi-interrupt-gpu
Mar 3, 2026
Merged

feat: MSI interrupt-driven VirtIO GPU + VirGL fixes#243
ryanbreen merged 1 commit intomainfrom
feat/virgl-msi-interrupt-gpu

Conversation

@ryanbreen
Copy link
Owner

Summary

  • Replace busy-polling with MSI interrupt + WFI completion for VirtIO GPU commands (10 FPS → 2000-3000 FPS)
  • SPI allocation infrastructure so GPU and xHCI don't collide on GICv2m SPIs
  • Cached queue notify addresses (single write_volatile vs 3 MMIO ops)
  • Fix 4 VirGL command encoding bugs: rasterizer fill mode, vertex buffer protocol, fragment shader constant, shader compilation flag
  • Add VirGL command encoder module (virgl.rs) and Linux reference implementations

Test plan

  • Kernel builds with zero warnings
  • Parallels VM boots successfully with MSI configured
  • xHCI keyboard still works (no SPI collision)
  • VirGL SUBMIT_3D commands succeed at 2000-3000 FPS
  • Boot tests pass (all 5 fork+exit iterations complete)

🤖 Generated with Claude Code

Replace busy-polling with MSI interrupt + WFI completion for VirtIO GPU
commands. Each VirGL frame previously burned ~50ms spinning in a tight
poll loop with SeqCst fences. Now the guest halts with WFI, Parallels
processes the command immediately, and delivers an MSI interrupt to wake
the vCPU. Result: 10 FPS → 2000-3000 FPS.

Key changes:
- SPI allocation infrastructure (allocate_msi_spi) so GPU and xHCI
  don't collide on the same GICv2m SPI
- Cached queue notify addresses — single write_volatile instead of
  3 MMIO ops per notification
- MSI setup + interrupt handler with WFI completion loop
- GPU MSI dispatch in aarch64 exception handler

VirGL command encoding fixes:
- Rasterizer fill mode was POINT (2) instead of FILL (0) — all
  triangles rendered as invisible 1-pixel dots
- SET_VERTEX_BUFFERS had spurious start_slot DWORD making length%3!=0,
  causing silent EINVAL from host (vertex buffers never bound)
- SHADER_FRAGMENT constant was 4 (TESS_EVAL) instead of 1
- Shader compilation never triggered (bit 31 not set in offset field)

Also adds VirGL command encoder module (virgl.rs), Linux reference
implementations for Parallels VirGL benchmarking, and minor cleanups.

Co-Authored-By: Ryan Breen <rbreen@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ryanbreen ryanbreen merged commit b48a0db into main Mar 3, 2026
2 of 4 checks passed
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.

1 participant