Assigning a GPU to a virtual machine turns the host into a chassis, the hypervisor into wiring, and the guest into the workstation, the machine that trains models, transcodes video or drives the displays while sitting in a rack with its siblings. PCI passthrough is the mechanism, the same direct-assignment machinery as the SR-IOV article but pointed at a bigger device class, and the GPU case adds its own chapters to the story: the IOMMU group discipline that decides whether the card is assignable at all, the vfio driver that holds the device for the guest, the UEFI firmware requirement that trips every first setup, and the vendor-specific realities of the two GPU families that dominate the hardware. This article walks the complete path from bare host to a guest driving a real GPU.

The use case and what the architecture demands

The three workloads that pull GPUs into virtual machines have different shapes and the same requirement, near-native access to the card's silicon. Machine learning inference and small-scale training wants the card's compute on a machine that also serves the application around it. Media transcoding wants the encode and decode blocks of a modern GPU applied to a stream pipeline. The virtual workstation wants everything, displays included, for a user working on the guest's desktop remotely. All three accept the same trade that SR-IOV's article stated: the assigned device is physically in the host, the guest cannot live-migrate while holding it, and the availability story is rapid provisioning rather than motion.

The demands the architecture places on the host are three. The IOMMU must be active, the same firmware and kernel ceremony from the SR-IOV article, because GPU DMA is the heaviest DMA there is and the assignment guarantees are not optional. The GPU must sit in an assignable IOMMU group, clean or with only its expected siblings. And the host must relinquish the card completely, which is the vfio driver's job and the next section's topic, because a GPU initialized by the host's own driver cannot be handed over without the vendor's reset behaving, the single flakiest promise in this entire field.

IOMMU groups and the preflight that saves the evening

The IOMMU group discipline from the SR-IOV article applies unchanged and matters more for GPUs, because a card with its own audio controller, the HDMI audio function that every modern GPU carries, must be assignable as a pair or not at all. The preflight is the group listing, and the readable form on a modern kernel is a short shell walk:

#!/bin/bash
for g in /sys/kernel/iommu_groups/*; do
echo "IOMMU group ${g##*/}:"
for d in $g/devices/*; do
echo " $(lspci -n -s ${d##*/})"
done
done

A typical healthy listing shows the GPU and its audio function together in one group with nothing else, the topology the hardware engineers designed for exactly this use. A group that carries the GPU alongside an NVMe controller or a USB controller is the problem listing, the card that cannot be assigned without pulling its neighbors, and the remedies are the ACS-capable processor root ports that server platforms carry, the specific slot choices that isolate devices, or the vfio multi-function assignment that takes the whole group, in that order of preference.

Binding the GPU to the vfio driver

The host kernel must not initialize the card it is about to give away, and the vfio-pci driver exists as the placeholder owner, the module that binds to the device, claims it for the virtualization machinery, and does nothing else. The binding is configured through the modprobe mechanism, a file that names the vendor and device IDs, the identifiers lspci -n printed in the preflight:

/etc/modprobe.d/vfio.conf options vfio-pci ids=10de:2684,10de:22ba softdep nvidia pre: vfio-pci

where the two IDs name the GPU and its audio function of the example card, and the softdep line orders the module loading so that vfio-pci wins the race against the vendor driver on every boot. The initramfs rebuild that makes the arrangement stick, dracut --force on the RHEL family or update-initramfs -u on the Debian side, followed by the reboot, and the confirmation reads:

lspci -nnk -s 01:00.0 01:00.0 VGA compatible controller: NVIDIA (rev a1) Kernel driver in use: vfio-pci

the line that means the card now belongs to the assignment machinery and no longer to the host's graphics stack, including the host's console, which moved to another adapter or to the serial console that this series installed on every machine from the start.

Attaching the GPU to the guest

The libvirt declaration for a passed-through PCI device is the hostdev block, the same shape as the SR-IOV interface with the audio function added as its sibling:

<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x1'/>
</source>
</hostdev>

The managed flag hands the device to the guest at start and returns it at shutdown, both functions moving as a pair, and the guest boots to find a real GPU on its PCI bus, enumerates it with its real vendor driver, and behaves from that moment like a machine with the card soldered in. The memory side deserves its line: GPU workloads pin large amounts of host memory for DMA, the vfio mechanism's locked-memory accounting, and the libvirt memlock limit is raised accordingly, either through the machine's XML or through the hugepages configuration that the virtio article already motivated for the latency-sensitive tier and that the GPU tier inherits for the same reason.

Guest UEFI boot and the firmware requirement

Every modern GPU initializes through the card's own option ROM, and current cards ship that ROM in UEFI form only, which makes a legacy BIOS guest unable to POST the card, the failure that greets the first setup with a black screen and a wrong conclusion. The guest must boot through OVMF, the open-source UEFI firmware for virtual machines, and current libvirt declares it in one attribute:

<os firmware='efi'>

or through the explicit loader path to the distribution's OVMF image for the installations that predate the attribute. The UEFI choice carries its guest-side obligations, the disk partitioned GPT rather than MBR, the bootloader installed for UEFI, and the guest OS itself UEFI-aware, every current Linux and Windows release qualifying, and the combination of vfio binding from the host side with OVMF from the guest side is the pair that makes the card light up on the first boot rather than the third.

Vendor realities, the driver handshake and the reset question

The two GPU families each carry one piece of history worth knowing. On the NVIDIA side, the consumer-line drivers historically refused to initialize on a hypervisor-detected machine, the famous error 43, and the workaround era of vendor-id spoofing has ended, with current drivers from the vendor initializing on virtualized machines openly, which converts the setup from a trick into a supported configuration and the runbook note from a hack into a version requirement, keep the guest driver current. On the AMD side, the card-specific reset behavior is the piece, certain models of previous generations failing to reinitialize cleanly after a guest shutdown, the card needing a host reboot before the next assignment, and the vendor's current generations have left the issue behind, but the specific model's behavior in a passthrough loop belongs in the test protocol before the fleet commits.

The test protocol itself is short and non-negotiable: boot the guest with the card, exercise the workload, shut down, boot again, exercise again, three times, and the third clean cycle is the evidence that the specific card in the specific host resets reliably, the property that production depends on and that no specification sheet guarantees.

Troubleshooting file and the checklist

The failure modes of a GPU passthrough setup number roughly five, and the file reads fast. The guest boots without seeing the card, the host still owns it, lspci -nnk on the host showing the vendor driver in use means the vfio binding lost the race and the modprobe ordering needs the softdep. The card appears but the driver fails to start, the UEFI question, the guest still on legacy firmware while the card demands the option ROM. The guest boots, the card initializes, and the second boot hangs, the reset behavior from the vendor section, and the fix is the model's documented workaround or the model change. The machine fails to start with a memory lock error, the memlock limit from the attachment section. And the performance that lands below the card's bare numbers, the vendor tools inside the guest reporting clocks and utilization that name the bottleneck, the interrupt and pinning story from the virtio article applying to the assigned card with its real tunables.

The checklist in working order: firmware virtualization flags on, kernel IOMMU parameter active, groups preflighted with the GPU clean. VFIO binding configured with both function IDs, initramfs rebuilt, lspci confirming the placeholder driver. Guest on OVMF firmware, GPT disk, the vendor's current driver inside. Memlock or hugepages sized for the GPU's DMA appetite. The reset loop tested three times, the workload benchmarked inside the guest against the card's known numbers. A setup that passes this list is a workstation in the rack, and the host that holds several of them is a chassis in every sense except the sheet metal.
Headless operation and the display question

A rack guest with a GPU does not necessarily have a monitor, and the display path deserves its own decision. The physical display scenario passes the card's own video outputs through to real screens, the workstation under the desk model, and the guest's desktop appears where the cables lead. The headless scenario, the compute and transcode tier, has no cable at all, and the guest drives its GPU for off-screen work, the ML inference that never paints a pixel and the transcode that reads and writes frames over the bus.

The headless pattern's detail is the card's display engine idling while the compute blocks work, and some vendor drivers require a display-connected or virtual display configuration for full performance, the fake monitor plug or the vendor's virtual display mode being the two standard answers, each documented per vendor and worth one test in the benchmarking pass. The remote desktop scenario sits between the two, the guest with a GPU driving its own framebuffer and the desktop delivered over the network, and the performance question there is the transport, the compression in the remote protocol doing to the GPU's output what the network carries, the topic with its own tooling ecosystem and the runbook note that the passthrough article's scope ends at the framebuffer.

Multi-GPU hosts and the sharing patterns

A host that carries two or more GPUs extends the pattern with the sharing question, and the two answers are both honest. The partition pattern assigns each card to a different guest, one GPU per machine, the arrangement that keeps every passthrough simple and the accounting legible, and a two-card host serving two guests with one card each is the shape that most compute tiers settle into, the host's IOMMU preflight run once per card and the boot ordering configured per assignment.

The time-slicing pattern, one card shared by multiple guests in sequence, exists in the vendor and ecosystem tooling but belongs to the container and orchestration world rather than the passthrough model, because the assignment machinery here is whole-card and exclusive by design. The honest architecture statement for the KVM host is that passthrough partitions the GPUs, and the fleet that needs sharing graduates to the orchestration layers built for it, the same two-tier honesty the SR-IOV article applied to the network tier, each capability in its place and the boundary written down.

The closing perspective on the whole device-assignment arc

SR-IOV and PCI passthrough are the two halves of the same capability, the network card splitting into virtual functions and the GPU moving whole, and together with the virtio baseline from the earlier article they complete the performance spectrum of the KVM host. The spectrum reads as a menu: virtio for the elastic tier that migrates and multiplies, virtual functions for the network-hungry machines, whole-device assignment for the compute-heavy few, and the fleet that assigns each workload to its right place on the menu is the fleet whose hardware earns its keep in every tier simultaneously, which is the quiet definition of a well-run virtualization platform.