Skip to main content
RunBook Academy

← All labs in Proxmox VE

Lab · advanced · ~60 min

Pass through a PCIe device and verify it appears inside the guest

A · Physical hardware

Objectives

  • Enable IOMMU in BIOS and kernel command line
  • Bind a PCIe device to vfio-pci
  • Pass through a USB controller or NIC to a VM
  • Verify the device is visible and functional inside the guest

Prerequisites

  • A CPU and motherboard that supports VT-d / AMD-Vi
  • A spare PCIe device (USB controller, NIC, or NVMe)
  • Two PCIe slots (or one with hot-spare) so the host stays functional

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-pci as 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.

Deliverables

  • · dmesg shows "DMAR: IOMMU enabled"
  • · The VM boots and lspci shows the passed-through device
  • · A functional smoke test of the device (USB stick read, NIC ping, etc.)

Verification status

Executed end to end
not yet run on hardware

The commands and configuration here have been reviewed against the verified software versions, but nobody has run this lab start to finish on a system meeting its prerequisites. Treat the Expected Outcome as the intended result rather than an observed one, and keep the Cleanup section to hand.