PCIe passthrough lab
This lab walks through the steps to enable PCIe passthrough and verify a device is fully accessible from inside a VM. We use a USB controller as the example — the safest device to lose from the host.
Steps
1. Enable IOMMU in BIOS
Reboot, enter BIOS setup. Enable:
- Intel: VT-d (under CPU / Security)
- AMD: AMD-Vi / IOMMU
Save and boot.
2. Configure the kernel command line
nano /etc/default/grub
# For Intel:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"
# For AMD:
# GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt"
update-grub
3. Load VFIO modules
cat >> /etc/modules << 'EOF'
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
EOF
update-initramfs -u -k all
reboot
4. Verify IOMMU is active
dmesg | grep -e DMAR -e IOMMU
# Expected: "Intel-IOMMU: enabled" or "AMD-Vi: IOMMU performance counters supported"
find /sys/kernel/iommu_groups/ -type l | wc -l
# Expected: many IOMMU groups
5. Identify the device to pass through
For a USB controller:
lspci | grep -i usb
# 00:14.0 USB controller: ...
# 00:14.1 USB controller: ...
# Pick the one that won't take your keyboard with it
Get the vendor:device IDs:
lspci -n -s 00:14
# 00:14.0 0c03: 8086:a1af (rev 20)
# 00:14.1 0c03: 8086:a1af (rev 20)
6. Bind to vfio-pci
cat > /etc/modprobe.d/vfio.conf << EOF
options vfio-pci ids=8086:a1af
EOF
update-initramfs -u -k all
reboot
# Verify
lspci -nn -d 8086:a1af
# Expected: device shows "Kernel driver in use: vfio-pci"
7. Pass through to the VM
qm create 906 --name passthrough-test --memory 2048 --cores 2 \
--net0 virtio,bridge=vmbr0 --ostype l26 \
--machine q35 --bios ovmf \
--efidisk0 local-lvm:1,efitype=4m,pre-enrolled-keys=1 \
--scsi0 local-lvm:32,iothread=1 \
--hostpci0 00:14,pcie=1
Boot and install Linux in the VM.
8. Verify inside the guest
# Inside the VM
lspci | grep -i usb
# Expected: the passed-through controller appears
lsusb
# Expected: any USB devices plugged in show up here
9. Functional test
If you passed through a NIC:
# Inside the VM
ip link show
# Expected: the passed-through NIC appears
ping -c 3 8.8.8.8
If you passed through a USB controller, plug in a USB stick and verify it appears.
Verification
- IOMMU is enabled in BIOS and kernel
- The device shows
vfio-pcias its kernel driver - The VM boots and the guest sees the device via lspci
- The device functions correctly inside the guest
Cleanup
qm stop 906 && qm destroy 906
# The device is still bound to vfio-pci; rebind to the host driver if needed:
echo "0000:00:14.0" > /sys/bus/pci/drivers/vfio-pci/unbind
echo "0000:00:14.0" > /sys/bus/pci/drivers/xhci_hcd/bind
Notes
For complex passthrough (full GPUs), see the home-lab GPU passthrough lesson. This lab deliberately uses a USB controller for safety.