From 8f4008713a49873b4bf354321f94b3fdeee14231 Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Tue, 10 Jan 2017 00:20:11 -0500 Subject: [PATCH] qemu: use virDomainPCIAddressSetAllMulti() to set multi when needed If there are multiple devices assigned to the different functions of a single PCI slot, they will not work properly if the device at function 0 doesn't have its "multi" attribute turned on, so it makes sense for libvirt to turn it on during PCI address assignment. Setting multi then assures that the new setting is stored in the config (so it will be used next time the domain is started), preventing any potential problems in the case that a future change in the configuration eliminates the devices on all non-0 functions (multi will still be set for function 0 even though it is the only function in use on the slot, which has no useful purpose, but also doesn't cause any problems). (NB: If we were to instead just decide on the setting for multifunction at runtime, a later removal of the non-0 functions of a slot would result in a silent change in the guest ABI for the remaining device on function 0 (although it may seem like an inconsequential guest ABI change, it *is* a guest ABI change to turn off the multi bit).) --- src/qemu/qemu_domain_address.c | 5 + .../qemuxml2argv-q35-multifunction.args | 42 ++++++ .../qemuxml2argv-q35-multifunction.xml | 51 ++++++++ tests/qemuxml2argvtest.c | 23 ++++ .../qemuxml2xmlout-q35-multifunction.xml | 120 ++++++++++++++++++ tests/qemuxml2xmltest.c | 23 ++++ 6 files changed, 264 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 4575d368f9..27861d2152 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -2133,6 +2133,11 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0) goto cleanup; + /* set multi attribute for devices at function 0 of + * any slot that has multiple functions in use + */ + virDomainPCIAddressSetAllMulti(def); + for (i = 0; i < def->ncontrollers; i++) { virDomainControllerDefPtr cont = def->controllers[i]; int idx = cont->idx; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args new file mode 100644 index 0000000000..6c4e9b211f --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args @@ -0,0 +1,42 @@ +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 ioh3420,port=0x10,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\ +addr=0x2 \ +-device ioh3420,port=0x11,chassis=2,id=pci.2,bus=pcie.0,addr=0x2.0x1 \ +-device ioh3420,port=0x12,chassis=3,id=pci.3,bus=pcie.0,addr=0x2.0x2 \ +-device ioh3420,port=0x18,chassis=4,id=pci.4,bus=pcie.0,multifunction=on,\ +addr=0x3 \ +-device ioh3420,port=0x19,chassis=5,id=pci.5,bus=pcie.0,multifunction=on,\ +addr=0x3.0x1 \ +-device ioh3420,port=0x20,chassis=6,id=pci.6,bus=pcie.0,multifunction=off,\ +addr=0x4 \ +-device ioh3420,port=0x21,chassis=7,id=pci.7,bus=pcie.0,addr=0x4.0x1 \ +-device ioh3420,port=0x8,chassis=8,id=pci.8,bus=pcie.0,addr=0x1 \ +-device ioh3420,port=0x28,chassis=9,id=pci.9,bus=pcie.0,addr=0x5 \ +-device ioh3420,port=0x30,chassis=10,id=pci.10,bus=pcie.0,addr=0x6 \ +-device ioh3420,port=0x38,chassis=11,id=pci.11,bus=pcie.0,addr=0x7 \ +-device ioh3420,port=0x40,chassis=12,id=pci.12,bus=pcie.0,addr=0x8 \ +-device ioh3420,port=0x48,chassis=13,id=pci.13,bus=pcie.0,addr=0x9 \ +-device ioh3420,port=0x50,chassis=14,id=pci.14,bus=pcie.0,addr=0xa \ +-device ioh3420,port=0x58,chassis=15,id=pci.15,bus=pcie.0,addr=0xb \ +-device ioh3420,port=0x60,chassis=16,id=pci.16,bus=pcie.0,addr=0xc \ +-device ioh3420,port=0x68,chassis=17,id=pci.17,bus=pcie.0,addr=0xd \ +-device ioh3420,port=0x70,chassis=18,id=pci.18,bus=pcie.0,addr=0xe \ +-device nec-usb-xhci,id=usb,bus=pci.1,addr=0x0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml new file mode 100644 index 0000000000..c1edca1eea --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml @@ -0,0 +1,51 @@ + + q35-test + 11dbdcdd-4c3b-482b-8903-9bdb8c0a2774 + 2097152 + 2097152 + 2 + + hvm + + + + destroy + restart + destroy + + /usr/libexec/qemu-kvm + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + + + + + + + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 82af287a5a..c965e80dd5 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1938,6 +1938,29 @@ mymain(void) QEMU_CAPS_ICH9_USB_EHCI1, QEMU_CAPS_NEC_USB_XHCI, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); + DO_TEST("q35-multifunction", + QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY, + QEMU_CAPS_DEVICE_VIRTIO_RNG, + QEMU_CAPS_OBJECT_RNG_RANDOM, + QEMU_CAPS_NETDEV, + QEMU_CAPS_DEVICE_VIRTIO_NET, + QEMU_CAPS_DEVICE_VIRTIO_GPU, + QEMU_CAPS_VIRTIO_GPU_VIRGL, + QEMU_CAPS_VIRTIO_KEYBOARD, + QEMU_CAPS_VIRTIO_MOUSE, + QEMU_CAPS_VIRTIO_TABLET, + QEMU_CAPS_VIRTIO_INPUT_HOST, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_FSDEV, + QEMU_CAPS_FSDEV_WRITEOUT, + 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_NEC_USB_XHCI, + QEMU_CAPS_DEVICE_VIDEO_PRIMARY); DO_TEST("q35-virt-manager-basic", QEMU_CAPS_KVM, QEMU_CAPS_RTC, diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml new file mode 100644 index 0000000000..7da78a55ae --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml @@ -0,0 +1,120 @@ + + q35-test + 11dbdcdd-4c3b-482b-8903-9bdb8c0a2774 + 2097152 + 2097152 + 2 + + hvm + + + + destroy + restart + destroy + + /usr/libexec/qemu-kvm + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + +
+ + +
+ + + + +
+ + + diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index bbd4687336..50b4500f87 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -795,6 +795,29 @@ mymain(void) QEMU_CAPS_ICH9_USB_EHCI1, QEMU_CAPS_NEC_USB_XHCI, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); + DO_TEST("q35-multifunction", + QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY, + QEMU_CAPS_DEVICE_VIRTIO_RNG, + QEMU_CAPS_OBJECT_RNG_RANDOM, + QEMU_CAPS_NETDEV, + QEMU_CAPS_DEVICE_VIRTIO_NET, + QEMU_CAPS_DEVICE_VIRTIO_GPU, + QEMU_CAPS_VIRTIO_GPU_VIRGL, + QEMU_CAPS_VIRTIO_KEYBOARD, + QEMU_CAPS_VIRTIO_MOUSE, + QEMU_CAPS_VIRTIO_TABLET, + QEMU_CAPS_VIRTIO_INPUT_HOST, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_FSDEV, + QEMU_CAPS_FSDEV_WRITEOUT, + 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_NEC_USB_XHCI, + QEMU_CAPS_DEVICE_VIDEO_PRIMARY); DO_TEST("q35-virt-manager-basic", QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY, QEMU_CAPS_DEVICE_VIRTIO_RNG,