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