Until now libvirt has always assumed that virtio devices were legacy PCI, so they would never be assigned to a PCIe slot. This patch looks for QEMU_CAPS_VIRTIO_NET_DISABLE_MODERN as an indicator that all the virtio devices in a qemu binary are capable of operating as PCIe, and if so it changes the connect flags to place them on a PCIe slot rather than legacy PCI. One problem that this could lead to with current libvirt - there isn't yet any provision for auto-adding any other kind of PCI controller except pci-bridge, and there are no PCIe controllers that support hotplug in the default configuration of machinetypes that have a pcie-root (Q35 and aarch64/virt). This means that if you add a virtio device to a configuration with no extra pci controllers, libvirt will fail to find an address for it (unless you add "<hotplug require='no'/> to the device - then it will be assigned to pcie-root). I'm hoping that the controller-auto-add will soon be refactored to auto-add pcie-*-port controllers, which will solve this problem. In the meantime, it's simple enough to just add a few lines like this (one for each hotpluggable virtio device) to the config: <controller type='pci' model='pcie-root-port'/> --- src/qemu/qemu_domain_address.c | 43 +++++-- .../qemuxml2argv-q35-virtio-pcie.args | 54 +++++++++ .../qemuxml2argv-q35-virtio-pcie.xml | 69 ++++++++++++ tests/qemuxml2argvtest.c | 10 ++ .../qemuxml2xmlout-q35-virtio-pcie.xml | 123 +++++++++++++++++++++ tests/qemuxml2xmltest.c | 10 ++ 6 files changed, 300 insertions(+), 9 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pcie.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pcie.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virtio-pcie.xml diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 87a1268..4dfd6be 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -998,14 +998,23 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, size_t i, j; virDomainPCIConnectFlags flags = 0; /* initialize to quiet gcc warning */ virPCIDeviceAddress tmp_addr; + bool virtioPCIe = false; /* PCI controllers */ for (i = 0; i < def->ncontrollers; i++) { if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { virDomainControllerModelPCI model = def->controllers[i]->model; + if (model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) { + /* if qemu has the disable-modern option for virtio-net, + * then its virtio devices will present themselves as PCIe devices + * when plugged into a PCIe slot + */ + virtioPCIe = virQEMUCapsGet(qemuCaps, + QEMU_CAPS_VIRTIO_NET_DISABLE_MODERN); + continue; + } if (model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || - model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT || !virDeviceInfoPCIAddressWanted(&def->controllers[i]->info)) continue; @@ -1046,8 +1055,13 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, !virDeviceInfoPCIAddressWanted(&def->nets[i]->info)) { continue; } - /* most <interface> devices are hotpluggable, legacy PCI */ - flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + + /* use PCIe for virtio-net if the machinetype supports it */ + if (virtioPCIe && STREQ(def->nets[i]->model, "virtio")) + flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; + else + flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + flags |= VIR_PCI_CONNECT_HOTPLUGGABLE; if (virDomainPCIAddressReserveNextSlot(addrs, &def->nets[i]->info, flags) < 0) @@ -1203,8 +1217,12 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, goto error; } - /* <disk> devices are hotpluggable, legacy PCI */ - flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + /* use PCIe if the machinetype supports it */ + if (virtioPCIe) + flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; + else + flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + flags |= VIR_PCI_CONNECT_HOTPLUGGABLE; if (virDomainPCIAddressReserveNextSlot(addrs, &def->disks[i]->info, flags) < 0) @@ -1233,8 +1251,11 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO && virDeviceInfoPCIAddressWanted(&def->memballoon->info)) { - /* <balloon> devices are NOT hotpluggable, legacy PCI */ - flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + /* <balloon> devices are NOT hotpluggable, suport PCIe in newer qemus */ + if (virtioPCIe) + flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; + else + flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; if (virDomainPCIAddressReserveNextSlot(addrs, &def->memballoon->info, @@ -1248,8 +1269,12 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, !virDeviceInfoPCIAddressWanted(&def->rngs[i]->info)) continue; - /* <rng> devices are hotpluggable, legacy PCI */ - flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + /* <rng> devices are hotpluggable, might be legacy PCI or PCIe */ + if (virtioPCIe) + flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; + else + flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + flags |= VIR_PCI_CONNECT_HOTPLUGGABLE; if (virDomainPCIAddressReserveNextSlot(addrs, &def->rngs[i]->info, flags) < 0) diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pcie.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pcie.args new file mode 100644 index 0000000..9cb150c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pcie.args @@ -0,0 +1,54 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/libexec/qemu-kvm \ +-name q35-test \ +-S \ +-M q35 \ +-m 2048 \ +-smp 2,sockets=2,cores=1,threads=1 \ +-uuid 11dbdcdd-4c3b-482b-8903-9bdb8c0a2774 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-q35-test/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ +-device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \ +-device ioh3420,port=0x18,chassis=4,id=pci.4,bus=pcie.0,addr=0x3 \ +-device ioh3420,port=0x20,chassis=5,id=pci.5,bus=pcie.0,addr=0x4 \ +-device ioh3420,port=0x28,chassis=6,id=pci.6,bus=pcie.0,addr=0x5 \ +-device ich9-usb-ehci1,id=usb,bus=pcie.0,addr=0x1d.0x7 \ +-device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pcie.0,multifunction=on,\ +addr=0x1d \ +-device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pcie.0,addr=0x1d.0x1 \ +-device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pcie.0,addr=0x1d.0x2 \ +-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-sata0-0-0 \ +-device ide-drive,bus=ide.0,drive=drive-sata0-0-0,id=sata0-0-0 \ +-drive file=/dev/HostVG/QEMUGuest2,format=raw,if=none,id=drive-virtio-disk1 \ +-device virtio-blk-pci,bus=pci.4,addr=0x0,drive=drive-virtio-disk1,\ +id=virtio-disk1 \ +-drive file=/dev/HostVG/QEMUGuest2,format=raw,if=none,id=drive-virtio-disk2 \ +-device virtio-blk-pci,bus=pcie.0,addr=0x8,drive=drive-virtio-disk2,\ +id=virtio-disk2 \ +-device rtl8139,vlan=0,id=net0,mac=00:11:22:33:44:55,bus=pci.2,addr=0x1 \ +-net user,vlan=0,name=hostnet0 \ +-device rtl8139,vlan=1,id=net1,mac=00:11:22:33:44:55,bus=pcie.0,addr=0x6 \ +-net user,vlan=1,name=hostnet1 \ +-device virtio-net-pci,vlan=2,id=net2,mac=00:11:22:33:44:55,bus=pci.3,addr=0x0 \ +-net user,vlan=2,name=hostnet2 \ +-device virtio-net-pci,vlan=3,id=net3,mac=00:11:22:33:44:55,bus=pcie.0,\ +addr=0x7 \ +-net user,vlan=3,name=hostnet3 \ +-vga qxl \ +-global qxl-vga.ram_size=67108864 \ +-global qxl-vga.vram_size=33554432 \ +-device virtio-balloon-pci,id=balloon0,bus=pcie.0,addr=0x9 \ +-object rng-random,id=objrng0,filename=/dev/random \ +-device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0,addr=0xa \ +-object rng-random,id=objrng1,filename=/dev/random \ +-device virtio-rng-pci,rng=objrng1,id=rng1,bus=pci.5,addr=0x0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pcie.xml b/tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pcie.xml new file mode 100644 index 0000000..d3c7c05 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pcie.xml @@ -0,0 +1,69 @@ +<domain type='qemu'> + <name>q35-test</name> + <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>2097152</currentMemory> + <vcpu placement='static' cpuset='0-1'>2</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/libexec/qemu-kvm</emulator> + <controller type='pci' model='pcie-root'/> + <controller type='pci' model='dmi-to-pci-bridge'/> + <controller type='pci' model='pci-bridge'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='sda' bus='sata'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='vdb' bus='virtio'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='vdc' bus='virtio'/> + <hotplug require='no'/> + </disk> + <video> + <model type='qxl' ram='65536' vram='32768' vgamem='8192' heads='1'/> + </video> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='rtl8139'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='rtl8139'/> + <hotplug require='no'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='virtio'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='virtio'/> + <hotplug require='no'/> + </interface> + <rng model='virtio'> + <hotplug require='no'/> + <backend model='random'>/dev/random</backend> + </rng> + <rng model='virtio'> + <hotplug require='yes'/> + <backend model='random'>/dev/random</backend> + </rng> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 2be634c..ce0158d 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1685,6 +1685,16 @@ mymain(void) QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL, QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM); + DO_TEST("q35-virtio-pcie", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_ICH9_AHCI, + QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1, + QEMU_CAPS_DEVICE_VIDEO_PRIMARY, + QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL, + QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM, + QEMU_CAPS_VIRTIO_NET_DISABLE_MODERN); DO_TEST("pcie-root-port", QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virtio-pcie.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virtio-pcie.xml new file mode 100644 index 0000000..70d0cd2 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virtio-pcie.xml @@ -0,0 +1,123 @@ +<domain type='qemu'> + <name>q35-test</name> + <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>2097152</currentMemory> + <vcpu placement='static' cpuset='0-1'>2</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/libexec/qemu-kvm</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='sda' bus='sata'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='vdb' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='vdc' bus='virtio'/> + <hotplug require='no'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + </disk> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='dmi-to-pci-bridge'> + <model name='i82801b11-bridge'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/> + </controller> + <controller type='pci' index='2' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='2'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </controller> + <controller type='pci' index='3' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='3' port='0x10'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </controller> + <controller type='pci' index='4' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='4' port='0x18'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='5' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='5' port='0x20'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <controller type='pci' index='6' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='6' port='0x28'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </controller> + <controller type='usb' index='0' model='ich9-ehci1'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x7'/> + </controller> + <controller type='usb' index='0' model='ich9-uhci1'> + <master startport='0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0' multifunction='on'/> + </controller> + <controller type='usb' index='0' model='ich9-uhci2'> + <master startport='2'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x1'/> + </controller> + <controller type='usb' index='0' model='ich9-uhci3'> + <master startport='4'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x2'/> + </controller> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='rtl8139'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='rtl8139'/> + <hotplug require='no'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='virtio'/> + <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='virtio'/> + <hotplug require='no'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <video> + <model type='qxl' ram='65536' vram='32768' vgamem='8192' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> + </memballoon> + <rng model='virtio'> + <backend model='random'>/dev/random</backend> + <hotplug require='no'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </rng> + <rng model='virtio'> + <backend model='random'>/dev/random</backend> + <hotplug require='yes'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/> + </rng> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 2d8145b..40c284d 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -696,6 +696,16 @@ mymain(void) QEMU_CAPS_ICH9_AHCI, QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL); + DO_TEST("q35-virtio-pcie", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_ICH9_AHCI, + QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1, + QEMU_CAPS_DEVICE_VIDEO_PRIMARY, + QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL, + QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM, + QEMU_CAPS_VIRTIO_NET_DISABLE_MODERN); DO_TEST("pcie-root", QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, -- 2.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list