Skip to content

Support vendor VFIO vGPU devices - #321

Draft
yummybomb wants to merge 3 commits into
hypeship/generalize-vgpu-devicefrom
hypeship/vendor-vfio-vgpu
Draft

Support vendor VFIO vGPU devices#321
yummybomb wants to merge 3 commits into
hypeship/generalize-vgpu-devicefrom
hypeship/vendor-vfio-vgpu

Conversation

@yummybomb

@yummybomb yummybomb commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

background

The NVIDIA driver exposes vGPUs through the mdev framework only on host kernels < 6.8. On kernels >= 6.8 the same driver builds NVIDIA's vendor-specific VFIO framework instead, where each SR-IOV VF is assigned a profile directly through its nvidia/ sysfs attributes and the VF itself is passed to the VM (no mdev UUIDs). Supporting this framework is the prerequisite for moving GPU hosts to newer host OS/kernel versions. Hosts migrate one at a time, so both frameworks must coexist: hypeman detects the host's framework at runtime and the mdev path stays intact.

Note that /sys/class/mdev_bus/ itself may still be present on a vendor VFIO host, because nvidia_vgpu_vfio pulls in the mdev module. It just never gains parent entries, so detection keys off discovered mdev VFs rather than the directory existing.

summary

  • detect NVIDIA's mdev and vendor-specific VFIO frameworks at runtime
  • discover vendor VFIO virtual functions and parse creatable_vgpu_types
  • assign and release profiles through current_vgpu_type with least-loaded-GPU placement
  • preserve active assignments and clear orphaned assignments by checking open VFIO handles — both iommufd cdevs (/dev/vfio/devices/*) and the legacy /dev/vfio/<group> node QEMU holds when iommufd is not configured
  • document both frameworks and verify that vendor VFIO vGPUs retain the existing standby rejection

Stacked on #322, which contains the framework-neutral lifecycle refactor.

creatable_vgpu_types format

The driver emits a table with a header row and the type ID first:

ID    : vGPU Name
1145  : NVIDIA L40S-1B
1147  : NVIDIA L40S-1Q

Parsing splits on the : separator and skips the header row. An earlier revision expected the name first and the type ID last, which failed on every line (parse vGPU type ID "Name"), and because getVGPUStatus discards profile errors the host advertised vGPU mode with all its slots and no profiles at all — no placement could succeed.

Once a profile consumes a GPU's entire framebuffer, the remaining VFs on that GPU print the header and nothing else. That is a legitimately empty list rather than a malformed file, so it yields zero profiles instead of an error; otherwise one 48Q allocation would remove the whole GPU from the status response.

host validation

Validated on an L40S host running vGPU Manager 580.159.01 on Ubuntu 24.04 / kernel 6.8.0-136, where the driver reports Host VGPU Mode: SR-IOV and /sys/class/mdev_bus/ has no parents:

  • framework detection returns vendor VFIO; 64 VFs discovered across two L40S
  • 30 profiles enumerated with correct framebuffer sizes
  • availability drops from 64 to 32 slots after assigning NVIDIA L40S-48Q on one GPU, and returns to 64 after release. Assigning a smaller profile instead clamps that GPU's remaining VFs to the same framebuffer size class (2B/2Q/2A after a 2Q), matching how the mdev driver reports available_instances

Availability counts free VFs that can currently accept a profile, not how many of that profile fit — the driver enforces the framebuffer limit at assignment time. That is the pre-existing mdev behavior and this PR keeps it; tightening the count is separate work.

  • assigning current_vgpu_type and booting QEMU with -device vfio-pci,sysfsdev=<VF> produces a live NVIDIA L40S-1Q in nvidia-smi vgpu, released by writing 0
  • that QEMU process held the legacy /dev/vfio/<group> node, not an iommufd cdev, even with /dev/iommu present — so the legacy group fd check is the one that keeps assignments alive on this host
  • ran this branch as the systemd service and booted both existing and Ubuntu 24.04 kernel-browser GPU images with NVIDIA L40S-2Q; guest GRID loaded, CDP and kernel-images-api started, hardware OpenGL reported the L40S through ANGLE, and NVENC completed an encode
  • stop released the VF, start reacquired it, and standby returned the expected 409
  • restarting hypeman with a live VM preserved its assignment; killing QEMU and restarting hypeman cleared the orphaned current_vgpu_type
  • after the host provisioning role installed persistent SR-IOV ordering, a reboot restored 64 VFs and hypeman rediscovered all 30 profiles

tests

  • go test -race ./lib/devices ./lib/instances -run 'VendorVFIO|CreatableVGPU|StoredVGPU|StandbyRejectsVendorVFIO' -count=1
  • go test ./lib/devices ./lib/hypervisor/qemu ./lib/resources -count=1
  • go test ./cmd/api ./cmd/api/api ./lib/instances ./integration -run '^$' -count=1
  • go vet ./cmd/api ./lib/devices ./lib/hypervisor/qemu ./lib/instances ./lib/resources

@yummybomb
yummybomb force-pushed the hypeship/vendor-vfio-vgpu branch from 199b1d1 to a93d009 Compare July 28, 2026 21:32
@yummybomb
yummybomb changed the base branch from main to hypeship/generalize-vgpu-device July 28, 2026 21:32
@yummybomb
yummybomb force-pushed the hypeship/vendor-vfio-vgpu branch 4 times, most recently from d893fce to de4742a Compare July 29, 2026 15:15
@yummybomb
yummybomb force-pushed the hypeship/vendor-vfio-vgpu branch from de4742a to 18e047f Compare July 29, 2026 16:09
The reconcile in-use check only matched iommufd cdev paths
(/dev/vfio/devices/*), but QEMU holds the legacy /dev/vfio/<group> node
unless iommufd is configured, so a hypeman restart under a live vGPU VM
relied on the driver rejecting the release of an active VF. Resolve the
VF's iommu group and match the legacy node as well.
The driver prints an "ID : vGPU Name" table, so the previous
name-then-ID parse rejected every line and no profiles were
enumerated. A GPU with no framebuffer left prints only the header,
which now yields zero profiles instead of an error.
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