[libvirt] [PATCH 2/2] HACK: qemu: aarch64: Use virtio-pci if user specifies PCI controller

Cole Robinson crobinso at redhat.com
Thu Jan 28 21:14:21 UTC 2016


If a user manually specifies this XML snippet for aarch64 machvirt:

  <controller type='pci' index='0' model='pci-root'/>

Libvirt will interpret this to mean that the OS supports virtio-pci,
and will allocate PCI addresses (instead of virtio-mmio) for virtio
devices.

This is a giant hack. Trying to improve it led me into the maze of PCI
address code and I gave up for now. Here are the issues:

* I'd prefer that to be model='pcie-root' which matches what
qemu-system-aarch64 -M virt actually provides by default... however
libvirt isn't happy with a single pcie-root specified by the user, it
will error with:

error: unsupported configuration: failed to create PCI bridge on bus 1: too many devices with fixed addresses

Instead this patch uses hacks to make pci-root use the pcie.0 bus for
aarch64, since that code path already works.

* It may even be nice to make specifying <controller type='pci'/> map to
'give me the recommended PCI setup for this VM'... then we could adjust
what that default means in the future, maybe switching to something like
what q35 uses. This would make apps lives easier.

But presently that violates the XML schema, and libvirt can't handle lack
of model= anyways:

error: internal error: Invalid PCI controller model -1
---
 src/qemu/qemu_command.c                            | 34 ++++++++----
 ...l2argv-aarch64-pci-manual-nocontroller-fail.xml | 43 ++++++++++++++++
 ...l2argv-aarch64-virtio-pci-manual-addresses.args |  2 -
 ...ml2argv-aarch64-virtio-pci-manual-addresses.xml |  1 +
 ...2argv-aarch64-virtio-pci-manual-controller.args | 36 +++++++++++++
 ...l2argv-aarch64-virtio-pci-manual-controller.xml | 50 ++++++++++++++++++
 tests/qemuxml2argvtest.c                           | 20 ++++++--
 ...2xmlout-aarch64-virtio-pci-manual-addresses.xml | 11 +---
 ...xmlout-aarch64-virtio-pci-manual-controller.xml | 60 ++++++++++++++++++++++
 tests/qemuxml2xmltest.c                            |  8 ++-
 10 files changed, 239 insertions(+), 26 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-aarch64-pci-manual-nocontroller-fail.xml
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-controller.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-controller.xml
 create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-controller.xml

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8943270..4b0f070 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1064,7 +1064,10 @@ qemuAssignDeviceControllerAlias(virDomainDefPtr domainDef,
          * (including the hardcoded pci-root controller on
          * multibus-capable qemus).
          */
-        return virAsprintf(&controller->info.alias, "pci.%d", controller->idx);
+        if (domainDef->os.arch == VIR_ARCH_AARCH64)
+            return virAsprintf(&controller->info.alias, "pcie.%d", controller->idx);
+        else
+            return virAsprintf(&controller->info.alias, "pci.%d", controller->idx);
     } else if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE) {
         /* for any machine based on e.g. I440FX or G3Beige, the
          * first (and currently only) IDE controller is an integrated
@@ -1393,15 +1396,28 @@ static int
 qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def,
                                        virQEMUCapsPtr qemuCaps)
 {
-    if (((def->os.arch == VIR_ARCH_ARMV7L) ||
-        (def->os.arch == VIR_ARCH_AARCH64)) &&
-        (STRPREFIX(def->os.machine, "vexpress-") ||
-            STREQ(def->os.machine, "virt") ||
-            STRPREFIX(def->os.machine, "virt-")) &&
-        virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO)) {
-        qemuDomainPrimeVirtioDeviceAddresses(
-            def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO);
+    size_t i;
+
+    if ((def->os.arch != VIR_ARCH_ARMV7L) &&
+        (def->os.arch != VIR_ARCH_AARCH64))
+        return 0;
+
+    if (!(STRPREFIX(def->os.machine, "vexpress-") ||
+          STREQ(def->os.machine, "virt") ||
+          STRPREFIX(def->os.machine, "virt-")))
+        return 0;
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO))
+        return 0;
+
+    /* If there's a PCIe controller in the XML, we will use PCI virtio */
+    for (i = 0; i < def->ncontrollers; i++) {
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI)
+            return 0;
     }
+
+    qemuDomainPrimeVirtioDeviceAddresses(
+        def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO);
     return 0;
 }
 
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-pci-manual-nocontroller-fail.xml b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-pci-manual-nocontroller-fail.xml
new file mode 100644
index 0000000..6a44f19
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-pci-manual-nocontroller-fail.xml
@@ -0,0 +1,43 @@
+<domain type='qemu'>
+  <name>aarch64test</name>
+  <uuid>496d7ea8-9739-544b-4ebd-ef08be936e8b</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='aarch64' machine='virt'>hvm</type>
+    <kernel>/aarch64.kernel</kernel>
+    <initrd>/aarch64.initrd</initrd>
+    <cmdline>earlyprintk console=ttyAMA0,115200n8 rw root=/dev/vda rootwait</cmdline>
+    <dtb>/aarch64.dtb</dtb>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <acpi/>
+    <apic/>
+    <pae/>
+  </features>
+  <cpu mode='custom' match='exact'>
+    <model fallback='allow'>cortex-a53</model>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-aarch64</emulator>
+    <disk type='file' device='disk'>
+      <source file='/aarch64.raw'/>
+      <target dev='sda' bus='scsi'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='scsi' index='0' model='virtio-scsi'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+    </controller>
+    <interface type='user'>
+      <mac address='52:54:00:09:a4:37'/>
+      <model type='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+    </interface>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.args b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.args
index 142fd5b..f091c89 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.args
@@ -21,8 +21,6 @@ QEMU_AUDIO_DRV=none \
 -initrd /aarch64.initrd \
 -append 'earlyprintk console=ttyAMA0,115200n8 rw root=/dev/vda rootwait' \
 -dtb /aarch64.dtb \
--device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1 \
--device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \
 -device virtio-scsi-pci,id=scsi0,bus=pcie.0,addr=0x3 \
 -usb \
 -drive file=/aarch64.raw,format=raw,if=none,id=drive-scsi0-0-0-0 \
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.xml b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.xml
index 6a44f19..80a6592 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.xml
@@ -31,6 +31,7 @@
       <target dev='sda' bus='scsi'/>
       <address type='drive' controller='0' bus='0' target='0' unit='0'/>
     </disk>
+    <controller type='pci' index='0' model='pci-root'/>
     <controller type='scsi' index='0' model='virtio-scsi'>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
     </controller>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-controller.args b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-controller.args
new file mode 100644
index 0000000..dfa07da
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-controller.args
@@ -0,0 +1,36 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-aarch64 \
+-name aarch64test \
+-S \
+-M virt \
+-cpu cortex-a53 \
+-m 1024 \
+-smp 1 \
+-uuid 496d7ea8-9739-544b-4ebd-ef08be936e8b \
+-nographic \
+-nodefconfig \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-boot c \
+-kernel /aarch64.kernel \
+-initrd /aarch64.initrd \
+-append 'earlyprintk console=ttyAMA0,115200n8 rw root=/dev/vda rootwait' \
+-dtb /aarch64.dtb \
+-device virtio-serial-pci,id=virtio-serial0,bus=pcie.0,addr=0x2 \
+-usb \
+-drive file=/aarch64.raw,format=raw,if=none,id=drive-virtio-disk0 \
+-device virtio-blk-pci,bus=pcie.0,addr=0x3,drive=drive-virtio-disk0,\
+id=virtio-disk0 \
+-device virtio-net-pci,vlan=0,id=net0,mac=52:54:00:09:a4:37,bus=pcie.0,addr=0x1 \
+-net user,vlan=0,name=hostnet0 \
+-serial pty \
+-chardev pty,id=charconsole1 \
+-device virtconsole,chardev=charconsole1,id=console1 \
+-device virtio-balloon-pci,id=balloon0,bus=pcie.0,addr=0x4 \
+-object rng-random,id=objrng0,filename=/dev/random \
+-device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0,addr=0x5
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-controller.xml b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-controller.xml
new file mode 100644
index 0000000..c5ea728
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-controller.xml
@@ -0,0 +1,50 @@
+<domain type='qemu'>
+  <name>aarch64test</name>
+  <uuid>496d7ea8-9739-544b-4ebd-ef08be936e8b</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='aarch64' machine='virt'>hvm</type>
+    <kernel>/aarch64.kernel</kernel>
+    <initrd>/aarch64.initrd</initrd>
+    <cmdline>earlyprintk console=ttyAMA0,115200n8 rw root=/dev/vda rootwait</cmdline>
+    <dtb>/aarch64.dtb</dtb>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <acpi/>
+    <apic/>
+    <pae/>
+  </features>
+  <cpu mode='custom' match='exact'>
+    <model fallback='allow'>cortex-a53</model>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-aarch64</emulator>
+    <disk type='file' device='disk'>
+      <source file='/aarch64.raw'/>
+      <target dev='vda' bus='virtio'/>
+    </disk>
+    <controller type='pci' index='0' model='pci-root'/>
+    <interface type='user'>
+      <mac address='52:54:00:09:a4:37'/>
+      <model type='virtio'/>
+    </interface>
+    <console type='pty'/>
+    <console type='pty'>
+      <target type='virtio' port='0'/>
+    </console>
+    <memballoon model='virtio'/>
+    <!--
+      This actually doesn't work in practice because vexpress only has
+      4 virtio slots available, rng makes 5 -->
+    <rng model='virtio'>
+      <backend model='random'>/dev/random</backend>
+    </rng>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index b2f636e..6c5a8ab 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1649,9 +1649,23 @@ mymain(void)
             QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM,
             QEMU_CAPS_OBJECT_GPEX, QEMU_CAPS_DEVICE_PCI_BRIDGE,
             QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE);
-    /* Example of using virtio-pci with no explicit PCI controller
-       but with manual PCI addresses */
-    DO_TEST_PARSE_ERROR("aarch64-virtio-pci-manual-addresses",
+    /* Example of using virtio-pci with manual PCIe controller and auto
+       allocated addresses */
+    DO_TEST("aarch64-virtio-pci-manual-controller",
+            QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DTB,
+            QEMU_CAPS_DEVICE_VIRTIO_MMIO,
+            QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM,
+            QEMU_CAPS_OBJECT_GPEX, QEMU_CAPS_DEVICE_PCI_BRIDGE,
+            QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI);
+    /* Example of using virtio-pci with manual PCIe controller and
+       manual PCI addresses */
+    DO_TEST("aarch64-virtio-pci-manual-addresses",
+            QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DTB,
+            QEMU_CAPS_DEVICE_VIRTIO_MMIO,
+            QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM,
+            QEMU_CAPS_OBJECT_GPEX, QEMU_CAPS_DEVICE_PCI_BRIDGE,
+            QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI);
+    DO_TEST_PARSE_ERROR("aarch64-pci-manual-nocontroller-fail",
             QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DTB,
             QEMU_CAPS_DEVICE_VIRTIO_MMIO,
             QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM,
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-addresses.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-addresses.xml
index 4add271..80a6592 100644
--- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-addresses.xml
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-addresses.xml
@@ -31,19 +31,10 @@
       <target dev='sda' bus='scsi'/>
       <address type='drive' controller='0' bus='0' target='0' unit='0'/>
     </disk>
+    <controller type='pci' index='0' model='pci-root'/>
     <controller type='scsi' index='0' model='virtio-scsi'>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
     </controller>
-    <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='0x01' 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='0x01' function='0x0'/>
-    </controller>
     <interface type='user'>
       <mac address='52:54:00:09:a4:37'/>
       <model type='virtio'/>
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-controller.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-controller.xml
new file mode 100644
index 0000000..7be2cbd
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-controller.xml
@@ -0,0 +1,60 @@
+<domain type='qemu'>
+  <name>aarch64test</name>
+  <uuid>496d7ea8-9739-544b-4ebd-ef08be936e8b</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='aarch64' machine='virt'>hvm</type>
+    <kernel>/aarch64.kernel</kernel>
+    <initrd>/aarch64.initrd</initrd>
+    <cmdline>earlyprintk console=ttyAMA0,115200n8 rw root=/dev/vda rootwait</cmdline>
+    <dtb>/aarch64.dtb</dtb>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <acpi/>
+    <apic/>
+    <pae/>
+  </features>
+  <cpu mode='custom' match='exact'>
+    <model fallback='allow'>cortex-a53</model>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-aarch64</emulator>
+    <disk type='file' device='disk'>
+      <source file='/aarch64.raw'/>
+      <target dev='vda' bus='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+    </disk>
+    <controller type='pci' index='0' model='pci-root'/>
+    <controller type='virtio-serial' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+    </controller>
+    <interface type='user'>
+      <mac address='52:54:00:09:a4:37'/>
+      <model type='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
+    </interface>
+    <serial type='pty'>
+      <target port='0'/>
+    </serial>
+    <console type='pty'>
+      <target type='serial' port='0'/>
+    </console>
+    <console type='pty'>
+      <target type='virtio' port='1'/>
+    </console>
+    <memballoon model='virtio'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+    </memballoon>
+    <rng model='virtio'>
+      <backend model='random'>/dev/random</backend>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
+    </rng>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index cac401c..e7f8845 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -731,14 +731,18 @@ mymain(void)
             QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM,
             QEMU_CAPS_OBJECT_GPEX, QEMU_CAPS_DEVICE_PCI_BRIDGE,
             QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI);
-    /*
+    DO_TEST_FULL("aarch64-virtio-pci-manual-controller", WHEN_ACTIVE,
+            QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DTB,
+            QEMU_CAPS_DEVICE_VIRTIO_MMIO,
+            QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM,
+            QEMU_CAPS_OBJECT_GPEX, QEMU_CAPS_DEVICE_PCI_BRIDGE,
+            QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI);
     DO_TEST_FULL("aarch64-virtio-pci-manual-addresses", WHEN_ACTIVE,
             QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DTB,
             QEMU_CAPS_DEVICE_VIRTIO_MMIO,
             QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM,
             QEMU_CAPS_OBJECT_GPEX, QEMU_CAPS_DEVICE_PCI_BRIDGE,
             QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI);
-    */
     DO_TEST("aarch64-gic");
     DO_TEST("aarch64-gicv3");
 
-- 
2.5.0




More information about the libvir-list mailing list