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 | 24 +++++++++++
.../qemuxml2argv-pci-autofill-addr.xml | 44 ++++++++++++++++++++
tests/qemuxml2argvtest.c | 1 +
.../qemuxml2xmlout-pci-autofill-addr.xml | 46 +++++++++++++++++++++
tests/qemuxml2xmltest.c | 1 +
6 files changed, 163 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 eff33fc..74d13b6 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -1399,6 +1399,45 @@ qemuDomainSupportsPCI(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)
@@ -1423,6 +1462,10 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
}
}
+ if (virDomainDeviceInfoIterate(def, qemuDomainPrepPCIAutoAllocate,
+ NULL) < 0)
+ goto cleanup;
+
nbuses = max_idx + 1;
if (nbuses > 0 &&
@@ -1553,6 +1596,10 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
}
}
}
+
+ if (virDomainDeviceInfoIterate(def, qemuDomainFinishPCIAutoAllocate,
+ NULL) < 0)
+ goto cleanup;
}
if (obj && obj->privateData) {
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.args
b/tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.args
new file mode 100644
index 0000000..2ab305e
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.args
@@ -0,0 +1,24 @@
+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 \
+-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..8e7b6ab
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-autofill-addr.xml
@@ -0,0 +1,44 @@
+<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>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</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'/>
+ </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 aaec9de..79339c8 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1524,6 +1524,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..0f32c23
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-autofill-addr.xml
@@ -0,0 +1,46 @@
+<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>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</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 b3568df..d43ca13 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -580,6 +580,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.5.0