Proxmox Deep Dive Part 11: PCI and GPU Passthrough
Part 10 covered backups. This part covers a subsystem that looks unrelated to everything so far but depends on it in one specific way: handing a physical PCI device, most often a GPU, directly to a VM rather than sharing it through the host.
IOMMU and VFIO, in outline.
PCI passthrough works through VFIO (Virtual Function I/O), a Linux kernel framework that safely exposes a hardware device to a VM without the host’s own driver ever claiming it. That safety depends on IOMMU (Intel VT-d or AMD-Vi, present on most CPUs from roughly the last five to six years), which lets the hypervisor remap a device’s DMA addresses so the VM can talk to the device directly without being able to read or write arbitrary host memory. Getting a passthrough working means, in order: enabling IOMMU in the BIOS/UEFI and the bootloader, loading the VFIO kernel modules, confirming the target device is actually bound to vfio-pci rather than its normal driver, and then adding it to a VM’s configuration as a raw PCI device.
IOMMU groups: the part that catches most first attempts.
A device can only be passed through cleanly if it sits in its own IOMMU group, or if every other device sharing that group is passed through alongside it, since the IOMMU’s isolation guarantee applies at the group level, not the individual device level. Consumer motherboards, especially ones without server-grade chipsets, often group a GPU together with unrelated devices (USB controllers, other PCIe slots) that have no business being handed to a VM, and there’s often no way to split that grouping without ACS override patches or different hardware entirely, which themselves carry a real isolation weakening the passthrough model is otherwise trying to guarantee. Checking IOMMU grouping before buying hardware specifically for passthrough saves a lot of after-the-fact troubleshooting.
Verifying it actually worked.
lspci -k shows the kernel driver currently bound to each PCI device. For a GPU intended for passthrough, that field needs to read vfio-pci, not nvidia, nouveau, or amdgpu, if the host’s own driver still shows up there, VFIO never got the device and the VM will fail to start or fail to see the card correctly. This single check is the fastest way to confirm the setup steps actually took effect before troubleshooting anything further downstream.
Common failure modes worth knowing about before hitting them.
NVIDIA consumer GPUs historically detect they’re running inside a VM and refuse to initialize properly, surfacing as the well-known “Code 43” error in a Windows guest, worked around by hiding specific hypervisor-identifying CPU flags from the guest. ROM-BAR issues, where a GPU’s video BIOS doesn’t initialize correctly inside a VM, sometimes need a manually dumped and supplied ROM file rather than relying on the one Proxmox reads automatically. Neither of these is a Proxmox-specific problem exactly, they’re artifacts of consumer GPU vendors not officially supporting virtualized use, but they’re common enough that expecting a first attempt to need one of these workarounds is more realistic than expecting a completely clean pass.
What actually justifies the setup effort.
Media transcoding for something like Plex or Jellyfin benefits from a passed-through GPU’s hardware encoder for far better power efficiency and throughput than CPU-based transcoding, without needing the whole host dedicated to just that one workload. AI/ML workloads that need CUDA or ROCm directly often can’t get acceptable performance any other way inside a VM. Gaming VMs are the use case most home lab passthrough guides are actually written for, a Windows VM with a passed-through GPU behaving close enough to bare metal for real-time gaming. None of these are justified by “it would be neat,” the setup and troubleshooting cost is real enough that the workload should actually need dedicated hardware access rather than settle for it as a nice-to-have.
Part 12 moves back to software: the user, permission, and API model that governs everything covered so far, and the automation tooling (Terraform, Ansible) that builds on top of it.