We do this in 2 passes: before PCI addresses are about to be collected, we convert type=pci auto_allocate=true to type=none auto_allocate=true, since the existing code is already expecting type=none here. After all PCI allocation should be complete, we do another pass of the device addresses converting type=pci auto_allocate=true to auto_allocate=false, so we don't trigger the unallocated address validation check in generic domain code. --- src/qemu/qemu_domain_address.c | 47 ++++++++++++++++++++++ .../qemuxml2argv-pci-autofill-addr.args | 25 ++++++++++++ .../qemuxml2argv-pci-autofill-addr.xml | 35 ++++++++++++++++ tests/qemuxml2argvtest.c | 1 + .../qemuxml2xmlout-pci-autofill-addr.xml | 41 +++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 6 files changed, 150 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-autofill-addr.xml diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 9d09b3a..90050ec 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1456,6 +1456,45 @@ qemuDomainAddressFindNewBusNr(virDomainDefPtr def) static int +qemuDomainPrepPCIAutoAllocate(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr device ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void *opaque ATTRIBUTE_UNUSED) +{ + /* If PCI auto_allocate requested, set type to NONE since the rest + of the code expects it. */ + if (info->auto_allocate && + info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE; + + return 0; +} + + +static int +qemuDomainFinishPCIAutoAllocate(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr device ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void *opaque ATTRIBUTE_UNUSED) +{ + /* A PCI device was allocated as requested, unset auto_allocate so + we don't trip the domain error about unallocated addresses */ + if (info->auto_allocate && + info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + info->auto_allocate = false; + + /* We wanted to allocate a PCI address but it was never filled in... + this is likely an XML error. Re-set type=PCI to give a correct + error from domain conf */ + if (info->auto_allocate && + info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) + info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; + + return 0; +} + + +static int qemuDomainAssignPCIAddresses(virDomainDefPtr def, virQEMUCapsPtr qemuCaps, virDomainObjPtr obj) @@ -1471,6 +1510,10 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + if (virDomainDeviceInfoIterate(def, qemuDomainPrepPCIAutoAllocate, + NULL) < 0) + goto cleanup; + for (i = 0; i < def->ncontrollers; i++) { if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { if ((int) def->controllers[i]->idx > max_idx) @@ -1616,6 +1659,10 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, } } + if (virDomainDeviceInfoIterate(def, qemuDomainFinishPCIAutoAllocate, + NULL) < 0) + goto cleanup; + if (obj && obj->privateData) { priv = obj->privateData; if (addrs) { diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.args b/tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.args new file mode 100644 index 0000000..ddb8c8d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.args @@ -0,0 +1,25 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/libexec/qemu-kvm \ +-name fdr-br \ +-S \ +-M pc-1.2 \ +-m 2048 \ +-smp 2 \ +-uuid 3ec6cbe1-b5a2-4515-b800-31a61855df41 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-fdr-br/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-usb \ +-drive file=/var/iso/f18kde.iso,format=raw,if=none,media=cdrom,\ +id=drive-virtio-disk0 \ +-device virtio-blk-pci,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,\ +id=virtio-disk0 \ +-vga cirrus \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.xml new file mode 100644 index 0000000..e5256fe --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.xml @@ -0,0 +1,35 @@ +<domain type='qemu'> + <name>fdr-br</name> + <uuid>3ec6cbe1-b5a2-4515-b800-31a61855df41</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='pc-1.2'>hvm</type> + <boot dev='hd'/> + </os> + <devices> + <emulator>/usr/libexec/qemu-kvm</emulator> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/var/iso/f18kde.iso'/> + <target dev='vda' bus='virtio'/> + <readonly/> + <address type='pci'/> + </disk> + <controller type='usb' index='0'> + <address type='pci'/> + </controller> + <controller type='ide' index='0'> + <address type='pci'/> + </controller> + <input type='mouse' bus='ps2'/> + <video> + <model type='cirrus' vram='16384' heads='1'/> + <address type='pci'/> + </video> + <memballoon model='virtio'> + <address type='pci'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index a83102d..7ab0f31 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1501,6 +1501,7 @@ mymain(void) DO_TEST("pci-autoadd-addr", QEMU_CAPS_DEVICE_PCI_BRIDGE); DO_TEST("pci-autoadd-idx", QEMU_CAPS_DEVICE_PCI_BRIDGE); + DO_TEST("pci-autofill-addr", NONE); DO_TEST("pci-many", QEMU_CAPS_DEVICE_PCI_BRIDGE); DO_TEST("pci-bridge-many-disks", diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-autofill-addr.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-autofill-addr.xml new file mode 100644 index 0000000..6259044 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-autofill-addr.xml @@ -0,0 +1,41 @@ +<domain type='qemu'> + <name>fdr-br</name> + <uuid>3ec6cbe1-b5a2-4515-b800-31a61855df41</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='pc-1.2'>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='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/var/iso/f18kde.iso'/> + <target dev='vda' bus='virtio'/> + <readonly/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 9eb2625..6f39ca9 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -587,6 +587,7 @@ mymain(void) QEMU_CAPS_DEVICE_PCI_BRIDGE); DO_TEST_FULL("pci-autoadd-idx", WHEN_ACTIVE, QEMU_CAPS_DEVICE_PCI_BRIDGE); + DO_TEST("pci-autofill-addr"); DO_TEST_FULL("q35", WHEN_ACTIVE, QEMU_CAPS_DEVICE_PCI_BRIDGE, -- 2.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list