15.4. Attaching PCI devices to virtual machines by using the command line
When using a virtual machine (VM), you can access and control a PCI device, such as a storage or network controller, that is attached to the host system. In this scenario, the host system passes control of the device to the VM. This is also known as a PCI device assignment, or PCI passthrough.
To use a PCI hardware device attached to your host in a virtual machine (VM), you can detach the device from the host and assign it to the VM.
This procedure describes generic PCI device assignment. For instructions on assigning specific types of PCI devices, see the relevant procedures:
Prerequisites
If your host is using the IBM Z architecture, the
vfiokernel modules must be loaded on the host. To verify, use the following command:# lsmod | grep vfioThe output must contain the following modules:
-
vfio_pci -
vfio_pci_core -
vfio_iommu_type1
-
Procedure
Obtain the PCI address identifier of the device that you want to use. For example, if you want to use a NVME disk attached to the host, the following output showss it as device
0000:65:00.0.# lspci -nkD 0000:00:00.0 0600: 8086:a708 (rev 01) Subsystem: 17aa:230e Kernel driver in use: igen6_edac Kernel modules: igen6_edac 0000:00:02.0 0300: 8086:a7a1 (rev 04) Subsystem: 17aa:230e Kernel driver in use: i915 Kernel modules: i915, xe 0000:00:04.0 1180: 8086:a71d (rev 01) Subsystem: 17aa:230e Kernel driver in use: thermal_pci Kernel modules: processor_thermal_device_pci 0000:00:05.0 0604: 8086:a74d (rev 01) Subsystem: 17aa:230e Kernel driver in use: pcieport 0000:00:07.0 0604: 8086:a76e (rev 01) Subsystem: 17aa:230e Kernel driver in use: pcieport 0000:65:00.0 0108: 144d:a822 (rev 01) DeviceName: PCIe SSD in Slot 0 Bay 2 Subsystem: 1028:1fd9 Kernel driver in use: nvme Kernel modules: nvme 0000:6a:00.0 0108: 1179:0110 (rev 01) DeviceName: PCIe SSD in Slot 11 Bay 2 Subsystem: 1028:1ffb Kernel driver in use: nvme Kernel modules: nvmeOpen the XML configuration of the VM to which you want to attach the PCI device.
# virsh edit vm-nameAdd the following
<hostdev>configuration to the<devices>section of the XML file.Replace the values on the
addressline with the PCI address of your device. Optionally, to change the PCI address that the device will use in the VM, you can configure a different address on the<address type="pci">line.For example, if the device address on the host is
0000:65:00.0, and you want it to use0000:02:00.0in the guest, use the following configuration:<hostdev mode="subsystem" type="pci" managed="yes"> <driver name="vfio"/> <source> <address domain="0x0000" bus="0x65" slot="0x00" function="0x0"/> </source> <address type="pci" domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> </hostdev>Optional: On IBM Z hosts, you can modify how the guest operating system will detect the PCI device. To do this, add a
<zpci>sub-element to the<address>element. In the<zpci>line, you can adjust theuidandfidvalues, which modifies the PCI address and function ID of the device in the guest operating system.<hostdev mode="subsystem" type="pci" managed="yes"> <driver name="vfio"/> <source> <address domain="0x0000" bus="0x65" slot="0x00" function="0x0"/> </source> <address type="pci" domain='0x0000' bus='0x02' slot='0x00' function='0x0'> <zpci uid="0x0008" fid="0x001807"/> </address> </hostdev>In this example:
-
uid="0x0008"sets the domain PCI address of the device in the VM to0008:00:00.0. fid="0x001807"sets the slot value of the device to0x001807. As a result, the device configuration in the file system of the VM is saved to/sys/bus/pci/slots/00001087/address.If these values are not specified,
libvirtconfigures them automatically.
-
- Save the XML configuration.
If the VM is running, shut it down.
# virsh shutdown vm-name
Verification
- Start the VM and log in to its guest operating system.
In the guest operating system, confirm that the PCI device is listed.
For example, if you configured guest device address as
0000:02:00.0, use the following command in PowerShell:# Get-PnpDevice -PresentOnly | % { $loc=(Get-PnpDeviceProperty -InstanceId $.InstanceId -KeyName 'DEVPKEY_Device_LocationInfo' -EA SilentlyContinue).Data; if($loc -eq 'PCI bus 2, device 0, function 0'){ $ | Select Status,Class,FriendlyName,InstanceId,@{n='Location';e={$loc}} } } Status : OK Class : System FriendlyName : Intel(R) 100 Series/C230 Series Chipset Family PCI Express Root Port #1 - A110 InstanceId : PCI\VEN_8086&DEV_A110&SUBSYS_86941043&REV_F1\3&11583659&0&00 Location : PCI bus 2, device 0, function 0