virtio-pci is the way forward for aarch64 guests: it's faster and less alien to people coming from other architectures. Now that guest support is finally getting there, we'd like to start using it by default instead of virtio-mmio. Users and applications can already opt-in by explicitly using <address type='pci'/> inside the relevant elements, but that's kinda cumbersome and requires all users and management applications to adapt, which we'd really like to avoid. What we can do instead is use virtio-mmio only if the guest already has at least one virtio-mmio device, and use virtio-pci in all other situations. That means existing virtio-mmio guests will keep using the old addressing scheme, and new guests will automatically be created using virtio-pci instead. Users can still override the default in either direction. --- Sending this as an RFC for the time being because it clearly needs some more polish, but I wanted to get the idea out there sooner rather than later. It needs to be applied on top of Laine's PCI series[1]. [1] https://www.redhat.com/archives/libvir-list/2016-October/msg00699.html src/qemu/qemu_domain_address.c | 128 ++++++++++++++++++++- ...l2argv-aarch64-virt-2.6-virtio-pci-default.args | 14 ++- .../qemuxml2argv-aarch64-virtio-pci-default.args | 14 ++- .../qemuxml2xmlout-aarch64-virtio-pci-default.xml | 24 +++- 4 files changed, 162 insertions(+), 18 deletions(-) diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index f27d1e3..7f07764 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -265,6 +265,118 @@ qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def, } +static bool +qemuDomainAnyDeviceHasAddressOfType(virDomainDefPtr def, + virDomainDeviceAddressType type) +{ + size_t i; + + for (i = 0; i < def->ndisks; i++) { + if (def->disks[i]->info.type == type) + return true; + } + + for (i = 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nfss; i++) { + if (def->fss[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nnets; i++) { + if (def->nets[i]->info.type == type) + return true; + } + + for (i = 0; i < def->ninputs; i++) { + if (def->inputs[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nsounds; i++) { + if (def->sounds[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nvideos; i++) { + if (def->videos[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nhostdevs; i++) { + if (def->hostdevs[i]->info->type == type) + return true; + } + + for (i = 0; i < def->nredirdevs; i++) { + if (def->redirdevs[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nsmartcards; i++) { + if (def->smartcards[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nserials; i++) { + if (def->serials[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nparallels; i++) { + if (def->parallels[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nchannels; i++) { + if (def->channels[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nconsoles; i++) { + if (def->consoles[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nhubs; i++) { + if (def->hubs[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nrngs; i++) { + if (def->rngs[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nshmems; i++) { + if (def->shmems[i]->info.type == type) + return true; + } + + for (i = 0; i < def->nmems; i++) { + if (def->mems[i]->info.type == type) + return true; + } + + if (def->memballoon && def->memballoon->info.type == type) + return true; + + if (def->watchdog && def->watchdog->info.type == type) + return true; + + if (def->nvram && def->nvram->info.type == type) + return true; + + if (def->tpm && def->tpm->info.type == type) + return true; + + return false; +} + + static void qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def, virDomainDeviceAddressType type) @@ -390,6 +502,8 @@ static void qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) { + bool usesMMIO; + if (def->os.arch != VIR_ARCH_ARMV7L && def->os.arch != VIR_ARCH_AARCH64) return; @@ -398,9 +512,17 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def, qemuDomainMachineIsVirt(def))) return; - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO)) { - qemuDomainPrimeVirtioDeviceAddresses( - def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO); + /* We use virtio-mmio by default on mach-virt guests only if they already + * have at least one virtio-mmio device: in all other cases, we prefer + * virtio-pci */ + usesMMIO = qemuDomainAnyDeviceHasAddressOfType(def, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO); + if (qemuDomainMachineHasPCIeRoot(def) && !usesMMIO) { + qemuDomainPrimeVirtioDeviceAddresses(def, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI); + } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO)) { + qemuDomainPrimeVirtioDeviceAddresses(def, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO); } } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virt-2.6-virtio-pci-default.args b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virt-2.6-virtio-pci-default.args index 75db1a4..df03c6e 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virt-2.6-virtio-pci-default.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virt-2.6-virtio-pci-default.args @@ -21,14 +21,18 @@ QEMU_AUDIO_DRV=none \ -initrd /aarch64.initrd \ -append 'earlyprintk console=ttyAMA0,115200n8 rw root=/dev/vda rootwait' \ -dtb /aarch64.dtb \ --device virtio-serial-device,id=virtio-serial0 \ +-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ +-device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \ +-device virtio-serial-pci,id=virtio-serial0,bus=pci.2,addr=0x2 \ -drive file=/aarch64.raw,format=raw,if=none,id=drive-virtio-disk0 \ --device virtio-blk-device,drive=drive-virtio-disk0,id=virtio-disk0 \ --device virtio-net-device,vlan=0,id=net0,mac=52:54:00:09:a4:37 \ +-device virtio-blk-pci,bus=pci.2,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=pci.2,addr=0x1 \ -net user,vlan=0,name=hostnet0 \ -serial pty \ -chardev pty,id=charconsole1 \ -device virtconsole,chardev=charconsole1,id=console1 \ --device virtio-balloon-device,id=balloon0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x4 \ -object rng-random,id=objrng0,filename=/dev/random \ --device virtio-rng-device,rng=objrng0,id=rng0 +-device virtio-rng-pci,rng=objrng0,id=rng0,bus=pci.2,addr=0x5 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-default.args b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-default.args index b5b010c..f205d9a 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-default.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-default.args @@ -21,14 +21,18 @@ QEMU_AUDIO_DRV=none \ -initrd /aarch64.initrd \ -append 'earlyprintk console=ttyAMA0,115200n8 rw root=/dev/vda rootwait' \ -dtb /aarch64.dtb \ --device virtio-serial-device,id=virtio-serial0 \ +-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ +-device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \ +-device virtio-serial-pci,id=virtio-serial0,bus=pci.2,addr=0x2 \ -drive file=/aarch64.raw,format=raw,if=none,id=drive-virtio-disk0 \ --device virtio-blk-device,drive=drive-virtio-disk0,id=virtio-disk0 \ --device virtio-net-device,vlan=0,id=net0,mac=52:54:00:09:a4:37 \ +-device virtio-blk-pci,bus=pci.2,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=pci.2,addr=0x1 \ -net user,vlan=0,name=hostnet0 \ -serial pty \ -chardev pty,id=charconsole1 \ -device virtconsole,chardev=charconsole1,id=console1 \ --device virtio-balloon-device,id=balloon0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x4 \ -object rng-random,id=objrng0,filename=/dev/random \ --device virtio-rng-device,rng=objrng0,id=rng0 +-device virtio-rng-pci,rng=objrng0,id=rng0,bus=pci.2,addr=0x5 diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-default.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-default.xml index 7c3fc19..90659a1 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-default.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-default.xml @@ -30,16 +30,30 @@ <disk type='file' device='disk'> <source file='/aarch64.raw'/> <target dev='vda' bus='virtio'/> - <address type='virtio-mmio'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x03' function='0x0'/> </disk> <controller type='pci' index='0' model='pcie-root'/> <controller type='virtio-serial' index='0'> - <address type='virtio-mmio'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x02' function='0x0'/> + </controller> + <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='0x00' function='0x0'/> + </controller> + <controller type='pci' index='3' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='3' port='0x10'/> + <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='virtio-mmio'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> </interface> <serial type='pty'> <target port='0'/> @@ -51,11 +65,11 @@ <target type='virtio' port='1'/> </console> <memballoon model='virtio'> - <address type='virtio-mmio'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x04' function='0x0'/> </memballoon> <rng model='virtio'> <backend model='random'>/dev/random</backend> - <address type='virtio-mmio'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x05' function='0x0'/> </rng> </devices> </domain> -- 2.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list