To setup passthrough for a PCI device, follow these steps:
- Make sure the vfio-pci module is available, e.g. using the modinfo command:
$ modinfo vfio-pci
filename: /lib/modules/4.18.0/kernel/drivers/vfio/pci/vfio-pci.ko
description: VFIO PCI - User Level meta-driver - Verify that the pciutils package, providing the lspci command et al, is available using your distro's package manager
- Determine the PCI device's address using the lspci command:
$ lspci
0002:06:00.0 Ethernet controller: Mellanox Technologies MT27500/MT27520 Family
[ConnectX-3/ConnectX-3 Pro Virtual Function] - Add the following element to the guest domain XML's devices section:
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0002' bus='0x06' slot='0x00' function='0x0'/>
</source>
</hostdev>
Note that if attribute managed is set to no (which is the default), it becomes the user's duty to unbind the PCI device from the respective device driver, and rebind to vfio-pci in the host prior to starting the guest.
It is well worth checking out the expanded domain XML:
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0002' bus='0x06' slot='0x00' function='0x0'/>
</source>
<address type='pci' domain='0x0002' bus='0x00' slot='0x01' function='0x0'>
<zpci uid='0x0001' fid='0x00000000'/>
</address>
</hostdev>
Theoretically, the PCI address in the guest can change between boots. However, the <zpci> element guarantees address persistence inside of the guest. The actual address of the passthrough device is based solely on the uid attribute: The uid becomes the PCI domain, all remaining values of the address (PCI bus, slot and function) are set to zero. Therefore, in this example, the PCI address in the guest would be 0001:00:00:0.
Take note of the fid attribute, whose value is required to hotplug/hotunplug PCI devices within a guest.
Furthermore note that the target PCI address is not visible anywhere (except within the QEMU process) at all. I.e. it is not related to the PCI address as observed within the KVM guest, and could be set to an arbitrary value. However, choosing the "wrong" values might have undesired subtle side effects with QEMU. Therefore, we strongly recommend not to specify a target address, and to rather rely on the auto-assignment. I.e. if the guest's PCI address has to be chosen, at a maximum restrict the target address element to uid (for PCI address definition) and fid (so that e.g. scripts in the guest for hotplugging PCI devices can rely on a specific value) as follows:
<address type='pci'>
<zpci uid='0x0001' fid='0x00000000'/>
</address>
For further (rather technical) details see here and here (git commit).