Starting with qemu 1.6, the qemu-system-arm vexpress-a9 model has a hardcoded virtio-mmio transport which enables attaching all virtio devices. On the command line, we have to use virtio-XXX-device rather than virtio-XXX-pci, thankfully s390 already set the precedent here so it's fairly straight forward. At the XML level, this adds a new device address type virtio-mmio. The controller and addressing don't have any subelements at the moment because we they aren't needed for this usecase, but could be added later if needed. Add a test case for an ARM guest with one of every virtio device enabled. --- src/conf/domain_conf.c | 12 +++- src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 16 ++++-- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 65 +++++++++++++++++----- .../qemuxml2argv-arm-vexpressa9-virtio.args | 1 + .../qemuxml2argv-arm-vexpressa9-virtio.xml | 45 +++++++++++++++ tests/qemuxml2argvtest.c | 4 ++ 8 files changed, 124 insertions(+), 21 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.xml diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5e423cc..25d356b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -210,7 +210,8 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, "usb", "spapr-vio", "virtio-s390", - "ccw") + "ccw", + "virtio-mmio") VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, "block", @@ -2386,6 +2387,7 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, return 1; case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO: return 1; case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: @@ -3027,6 +3029,9 @@ virDomainDeviceInfoFormat(virBufferPtr buf, info->addr.ccw.devno); break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO: + break; + default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unknown address type '%d'"), info->type); @@ -3491,6 +3496,9 @@ virDomainDeviceInfoParseXML(xmlNodePtr node, goto cleanup; break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO: + break; + default: /* Should not happen */ virReportError(VIR_ERR_INTERNAL_ERROR, @@ -5738,6 +5746,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 && + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Controllers must use the 'pci' address type")); @@ -6349,6 +6358,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 && + def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Network interfaces must use 'pci' address type")); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 978be16..4d90f84 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -207,6 +207,7 @@ enum virDomainDeviceAddressType { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST }; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 51064e8..2b0e9fc 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -234,6 +234,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "vnc-share-policy", /* 150 */ "device-del-event", + "virtio-mmio", ); struct _virQEMUCaps { @@ -1381,6 +1382,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "pci-bridge", QEMU_CAPS_DEVICE_PCI_BRIDGE }, { "vfio-pci", QEMU_CAPS_DEVICE_VFIO_PCI }, { "scsi-generic", QEMU_CAPS_DEVICE_SCSI_GENERIC }, + { "virtio-mmio", QEMU_CAPS_DEVICE_VIRTIO_MMIO }, }; static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBlk[] = { @@ -2814,17 +2816,19 @@ virQEMUCapsUsedQMP(virQEMUCapsPtr qemuCaps) bool virQEMUCapsSupportsChardev(virDomainDefPtr def, virQEMUCapsPtr qemuCaps, - virDomainChrDefPtr chr ATTRIBUTE_UNUSED) + virDomainChrDefPtr chr) { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV) || !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) return false; - /* This may not be true for all machine types, but at least - * the only supported serial devices of vexpress-a9 and versatilepb - * don't have the chardev property wired up */ if (def->os.arch != VIR_ARCH_ARMV7L) - return false; + return true; - return true; + /* This may not be true for all ARM machine types, but at least + * the non-virtio serial devices of vexpress-a9 and versatilepb + * don't have the chardev property wired up */ + return (chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO || + (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE && + chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO)); } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 56f8405..fdb61b0 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -190,6 +190,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_MLOCK = 149, /* -realtime mlock=on|off */ QEMU_CAPS_VNC_SHARE_POLICY = 150, /* set display sharing policy */ QEMU_CAPS_DEVICE_DEL_EVENT = 151, /* DEVICE_DELETED event */ + QEMU_CAPS_DEVICE_VIRTIO_MMIO = 152, /* -device virtio-mmio */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f611940..9b037f5 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -418,22 +418,27 @@ cleanup: } static bool -qemuDomainSupportsNicdev(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) +qemuDomainSupportsNicdev(virDomainDefPtr def, + virQEMUCapsPtr qemuCaps, + virDomainNetDefPtr net) { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) return false; - /* arm boards require legacy -net nic */ - if (def->os.arch == VIR_ARCH_ARMV7L) + /* non-virtio ARM nics require legacy -net nic */ + if (def->os.arch == VIR_ARCH_ARMV7L && + net->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO) return false; return true; } static bool -qemuDomainSupportsNetdev(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) +qemuDomainSupportsNetdev(virDomainDefPtr def, + virQEMUCapsPtr qemuCaps, + virDomainNetDefPtr net) { - if (!qemuDomainSupportsNicdev(def, qemuCaps)) + if (!qemuDomainSupportsNicdev(def, qemuCaps, net)) return false; return virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV); } @@ -474,7 +479,7 @@ qemuOpenVhostNet(virDomainDefPtr def, * option), don't try to open the device. */ if (!(virQEMUCapsGet(qemuCaps, QEMU_CAPS_VHOST_NET) && - qemuDomainSupportsNetdev(def, qemuCaps))) { + qemuDomainSupportsNetdev(def, qemuCaps, net))) { if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("vhost-net is not supported with " @@ -1146,8 +1151,8 @@ cleanup: } static void -qemuDomainPrimeS390VirtioDevices(virDomainDefPtr def, - enum virDomainDeviceAddressType type) +qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def, + enum virDomainDeviceAddressType type) { /* declare address-less virtio devices to be of address type 'type' @@ -1281,7 +1286,7 @@ qemuDomainAssignS390Addresses(virDomainDefPtr def, if (STREQLEN(def->os.machine, "s390-ccw", 8) && virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_CCW)) { - qemuDomainPrimeS390VirtioDevices( + qemuDomainPrimeVirtioDeviceAddresses( def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW); if (!(addrs = qemuDomainCCWAddressSetCreate())) @@ -1296,7 +1301,7 @@ qemuDomainAssignS390Addresses(virDomainDefPtr def, goto cleanup; } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_S390)) { /* deal with legacy virtio-s390 */ - qemuDomainPrimeS390VirtioDevices( + qemuDomainPrimeVirtioDeviceAddresses( def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390); } @@ -1319,6 +1324,18 @@ cleanup: return ret; } +static int +qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def, + virQEMUCapsPtr qemuCaps) +{ + if (def->os.arch == VIR_ARCH_ARMV7L && + STREQ(def->os.machine, "vexpress-a9") && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO)) { + qemuDomainPrimeVirtioDeviceAddresses( + def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO); + } + return 0; +} static int qemuSpaprVIOFindByReg(virDomainDefPtr def ATTRIBUTE_UNUSED, @@ -1833,6 +1850,10 @@ int qemuDomainAssignAddresses(virDomainDefPtr def, if (rc) return rc; + rc = qemuDomainAssignARMVirtioMMIOAddresses(def, qemuCaps); + if (rc) + return rc; + return qemuDomainAssignPCIAddresses(def, qemuCaps, obj); } @@ -3939,6 +3960,9 @@ qemuBuildDriveDevStr(virDomainDefPtr def, } else if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) { virBufferAddLit(&opt, "virtio-blk-s390"); + } else if (disk->info.type == + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO) { + virBufferAddLit(&opt, "virtio-blk-device"); } else { virBufferAddLit(&opt, "virtio-blk-pci"); } @@ -4216,6 +4240,9 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, else if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) virBufferAddLit(&buf, "virtio-scsi-s390"); + else if (def->info.type == + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO) + virBufferAddLit(&buf, "virtio-scsi-device"); else virBufferAddLit(&buf, "virtio-scsi-pci"); break; @@ -4245,6 +4272,9 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, } else if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) { virBufferAddLit(&buf, "virtio-serial-s390"); + } else if (def->info.type == + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO) { + virBufferAddLit(&buf, "virtio-serial-device"); } else { virBufferAddLit(&buf, "virtio-serial"); } @@ -4360,6 +4390,8 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, nic = "virtio-net-ccw"; else if (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) nic = "virtio-net-s390"; + else if (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO) + nic = "virtio-net-device"; else nic = "virtio-net-pci"; @@ -4604,6 +4636,9 @@ qemuBuildMemballoonDevStr(virDomainMemballoonDefPtr dev, case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: virBufferAddLit(&buf, "virtio-balloon-ccw"); break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO: + virBufferAddLit(&buf, "virtio-balloon-device"); + break; default: virReportError(VIR_ERR_XML_ERROR, _("memballoon unsupported with address type '%s'"), @@ -5597,6 +5632,8 @@ qemuBuildRNGDeviceArgs(virCommandPtr cmd, virBufferAsprintf(&buf, "virtio-rng-ccw,rng=%s", dev->info.alias); else if (dev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) virBufferAsprintf(&buf, "virtio-rng-s390,rng=%s", dev->info.alias); + else if (dev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO) + virBufferAsprintf(&buf, "virtio-rng-device,rng=%s", dev->info.alias); else virBufferAsprintf(&buf, "virtio-rng-pci,rng=%s", dev->info.alias); @@ -6873,7 +6910,7 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd, * * NB, no support for -netdev without use of -device */ - if (qemuDomainSupportsNetdev(def, qemuCaps)) { + if (qemuDomainSupportsNetdev(def, qemuCaps, net)) { if (!(host = qemuBuildHostNetStr(net, driver, ',', vlan, tapfdName, tapfdSize, @@ -6881,7 +6918,7 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd, goto cleanup; virCommandAddArgList(cmd, "-netdev", host, NULL); } - if (qemuDomainSupportsNicdev(def, qemuCaps)) { + if (qemuDomainSupportsNicdev(def, qemuCaps, net)) { if (!(nic = qemuBuildNicDevStr(net, vlan, bootindex, qemuCaps))) goto cleanup; virCommandAddArgList(cmd, "-device", nic, NULL); @@ -6890,7 +6927,7 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd, goto cleanup; virCommandAddArgList(cmd, "-net", nic, NULL); } - if (!qemuDomainSupportsNetdev(def, qemuCaps)) { + if (!qemuDomainSupportsNetdev(def, qemuCaps, net)) { if (!(host = qemuBuildHostNetStr(net, driver, ',', vlan, tapfdName, tapfdSize, @@ -7883,7 +7920,7 @@ qemuBuildCommandLine(virConnectPtr conn, int vlan; /* VLANs are not used with -netdev, so don't record them */ - if (qemuDomainSupportsNetdev(def, qemuCaps)) + if (qemuDomainSupportsNetdev(def, qemuCaps, net)) vlan = -1; else vlan = i; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.args new file mode 100644 index 0000000..349c758 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu-system-arm -S -M vexpress-a9 -m 1024 -smp 1 -nographic -nodefconfig -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -boot c -kernel /arm-kernel -initrd /arm-initrd -append 'console=ttyAMA0,115200n8 rw root=/dev/vda3 rootwait physmap.enabled=0' -dtb /f19-arm.dtb -device virtio-serial-device,id=virtio-serial0 -drive file=/mnt/data/devel/images/f19-arm.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 -net user,vlan=0,name=hostnet0 -serial pty -chardev pty,id=charconsole1 -device virtconsole,chardev=charconsole1,id=console1 -device virtio-balloon-device,id=balloon0 -object rng-random,id=rng0,filename=/dev/random -device virtio-rng-device,rng=rng0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.xml b/tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.xml new file mode 100644 index 0000000..7709db9 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.xml @@ -0,0 +1,45 @@ +<domain type="qemu"> + <name>armtest</name> + <uuid>496d7ea8-9739-544b-4ebd-ef08be936e6a</uuid> + <memory>1048576</memory> + <currentMemory>1048576</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch="armv7l" machine="vexpress-a9">hvm</type> + <kernel>/arm-kernel</kernel> + <initrd>/arm-initrd</initrd> + <dtb>/f19-arm.dtb</dtb> + <cmdline>console=ttyAMA0,115200n8 rw root=/dev/vda3 rootwait physmap.enabled=0</cmdline> + </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/bin/qemu-system-arm</emulator> + <disk type='file' device='disk'> + <source file='/mnt/data/devel/images/f19-arm.raw'/> + <target dev='vda' bus='virtio'/> + </disk> + <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 0bf2724..2bdd18e 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1032,6 +1032,10 @@ mymain(void) DO_TEST("arm-vexpressa9-basic", QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DTB, QEMU_CAPS_DRIVE); + DO_TEST("arm-vexpressa9-virtio", + QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DTB, + QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE_VIRTIO_MMIO, + QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM); virObjectUnref(driver.config); virObjectUnref(driver.caps); -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list