From 1e947cf7d864b97d45764c6dfaaf9f6837e3a55e Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Wed, 30 Apr 2014 14:32:19 +0300 Subject: [PATCH] qemu: specify domain in host-side PCI addresses when needed/supported This uses the new QEMU_CAPS_HOST_PCI_MULTIDOMAIN capability when present, for -devivce pci-assign, -device vfio-pci, and -pcidevice. While creating tests for this new functionality, I noticed that the xmls for two existing tests had erroneously specified an until-now-ignored domain="0x0002", so I corrected those two tests, and also added two failure tests to be sure that we alert users who attempt to use a non-zero domain with a qemu that doesn't support it. --- src/qemu/qemu_command.c | 42 +++++++++++++++---- src/qemu/qemu_command.h | 3 +- src/qemu/qemu_hotplug.c | 17 +++++--- src/qemu/qemu_monitor_text.c | 18 ++++++-- ...qemuxml2argv-hostdev-vfio-multidomain.args | 6 +++ .../qemuxml2argv-hostdev-vfio-multidomain.xml | 33 +++++++++++++++ .../qemuxml2argv-net-hostdev-multidomain.args | 7 ++++ .../qemuxml2argv-net-hostdev-multidomain.xml | 40 ++++++++++++++++++ ...xml2argv-net-hostdev-vfio-multidomain.args | 7 ++++ ...uxml2argv-net-hostdev-vfio-multidomain.xml | 41 ++++++++++++++++++ .../qemuxml2argv-net-hostdev-vfio.xml | 2 +- .../qemuxml2argv-net-hostdev.xml | 2 +- tests/qemuxml2argvtest.c | 18 ++++++++ 13 files changed, 217 insertions(+), 19 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-vfio-multidomain.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-vfio-multidomain.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-multidomain.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-multidomain.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio-multidomain.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio-multidomain.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 6c1e17d283..29ae8e4b1a 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5522,7 +5522,18 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def, break; } - virBufferAsprintf(&buf, ",host=%.2x:%.2x.%.1x", + virBufferAddLit(&buf, ",host="); + if (dev->source.subsys.u.pci.addr.domain) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_HOST_PCI_MULTIDOMAIN)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("non-zero domain='%.4x' in host device PCI address " + "not supported in this QEMU binary"), + dev->source.subsys.u.pci.addr.domain); + goto error; + } + virBufferAsprintf(&buf, "%.4x:", dev->source.subsys.u.pci.addr.domain); + } + virBufferAsprintf(&buf, "%.2x:%.2x.%.1x", dev->source.subsys.u.pci.addr.bus, dev->source.subsys.u.pci.addr.slot, dev->source.subsys.u.pci.addr.function); @@ -5548,14 +5559,31 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def, char * -qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev) +qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps) { char *ret = NULL; - ignore_value(virAsprintf(&ret, "host=%.2x:%.2x.%.1x", - dev->source.subsys.u.pci.addr.bus, - dev->source.subsys.u.pci.addr.slot, - dev->source.subsys.u.pci.addr.function)); + if (dev->source.subsys.u.pci.addr.domain) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_HOST_PCI_MULTIDOMAIN)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("non-zero domain='%.4x' in host device PCI address " + "not supported in this QEMU binary"), + dev->source.subsys.u.pci.addr.domain); + goto cleanup; + } + ignore_value(virAsprintf(&ret, "host=%.4x:%.2x:%.2x.%.1x", + dev->source.subsys.u.pci.addr.domain, + dev->source.subsys.u.pci.addr.bus, + dev->source.subsys.u.pci.addr.slot, + dev->source.subsys.u.pci.addr.function)); + } else { + ignore_value(virAsprintf(&ret, "host=%.2x:%.2x.%.1x", + dev->source.subsys.u.pci.addr.bus, + dev->source.subsys.u.pci.addr.slot, + dev->source.subsys.u.pci.addr.function)); + } + cleanup: return ret; } @@ -9493,7 +9521,7 @@ qemuBuildCommandLine(virConnectPtr conn, VIR_FREE(devstr); } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCIDEVICE)) { virCommandAddArg(cmd, "-pcidevice"); - if (!(devstr = qemuBuildPCIHostdevPCIDevStr(hostdev))) + if (!(devstr = qemuBuildPCIHostdevPCIDevStr(hostdev, qemuCaps))) goto error; virCommandAddArg(cmd, devstr); VIR_FREE(devstr); diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index ecd1d45818..45f29a0917 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -152,7 +152,8 @@ char * qemuBuildSoundDevStr(virDomainDefPtr domainDef, virQEMUCapsPtr qemuCaps); /* Legacy, pre device support */ -char * qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev); +char * qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps); /* Current, best practice */ char * qemuBuildPCIHostdevDevStr(virDomainDefPtr def, virDomainHostdevDefPtr dev, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index cdf9eacd94..7c8830ef24 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1258,16 +1258,23 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, configfd, configfd_name); qemuDomainObjExitMonitor(driver, vm); } else { - virDevicePCIAddress guestAddr = hostdev->info->addr.pci; + virDevicePCIAddressPtr guestAddr = &hostdev->info->addr.pci; + virDevicePCIAddressPtr hostAddr = &hostdev->source.subsys.u.pci.addr; + + if (hostAddr->domain && + !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_HOST_PCI_MULTIDOMAIN)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("non-zero domain='%.4x' in host device " + "PCI address not supported in this QEMU binary"), + hostAddr->domain); + goto error; + } qemuDomainObjEnterMonitor(driver, vm); - ret = qemuMonitorAddPCIHostDevice(priv->mon, - &hostdev->source.subsys.u.pci.addr, - &guestAddr); + ret = qemuMonitorAddPCIHostDevice(priv->mon, hostAddr, guestAddr); qemuDomainObjExitMonitor(driver, vm); hostdev->info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; - memcpy(&hostdev->info->addr.pci, &guestAddr, sizeof(guestAddr)); } virDomainAuditHostdev(vm, hostdev, "attach", ret == 0); if (ret < 0) diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index bd604f0b53..008795c93e 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1826,10 +1826,20 @@ int qemuMonitorTextAddPCIHostDevice(qemuMonitorPtr mon, memset(guestAddr, 0, sizeof(*guestAddr)); - /* XXX hostAddr->domain */ - if (virAsprintf(&cmd, "pci_add pci_addr=auto host host=%.2x:%.2x.%.1x", - hostAddr->bus, hostAddr->slot, hostAddr->function) < 0) - goto cleanup; + if (hostAddr->domain) { + /* if domain > 0, the caller has already verified that this qemu + * supports specifying domain in pci_add command + */ + if (virAsprintf(&cmd, + "pci_add pci_addr=auto host host=%.4x:%.2x:%.2x.%.1x", + hostAddr->domain, hostAddr->bus, + hostAddr->slot, hostAddr->function) < 0) + goto cleanup; + } else { + if (virAsprintf(&cmd, "pci_add pci_addr=auto host host=%.2x:%.2x.%.1x", + hostAddr->bus, hostAddr->slot, hostAddr->function) < 0) + goto cleanup; + } if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0) goto cleanup; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-vfio-multidomain.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-vfio-multidomain.args new file mode 100644 index 0000000000..2761543500 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-vfio-multidomain.args @@ -0,0 +1,6 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ +/usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb -hda \ +/dev/HostVG/QEMUGuest2 -device vfio-pci,host=55aa:20:0f.3,id=hostdev0,\ +bus=pci.0,addr=0x3 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-vfio-multidomain.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-vfio-multidomain.xml new file mode 100644 index 0000000000..efbff3845c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-vfio-multidomain.xml @@ -0,0 +1,33 @@ + + QEMUGuest2 + c7a5fdbd-edaf-9466-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + +
+ + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-multidomain.args b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-multidomain.args new file mode 100644 index 0000000000..5c8f0a70d5 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-multidomain.args @@ -0,0 +1,7 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ +/usr/bin/qemu -S \ +-M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \ +-usb -hda /dev/HostVG/QEMUGuest1 \ +-device pci-assign,host=2424:21:1c.6,id=hostdev0,bus=pci.0,addr=0x3 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-multidomain.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-multidomain.xml new file mode 100644 index 0000000000..14b9515216 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-multidomain.xml @@ -0,0 +1,40 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + +
+ + + + + + + + + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio-multidomain.args b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio-multidomain.args new file mode 100644 index 0000000000..201c8eaee1 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio-multidomain.args @@ -0,0 +1,7 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ +/usr/bin/qemu -S \ +-M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \ +-usb -hda /dev/HostVG/QEMUGuest1 \ +-device vfio-pci,host=0021:de:1f.1,id=hostdev0,bus=pci.0,addr=0x3 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio-multidomain.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio-multidomain.xml new file mode 100644 index 0000000000..5e834ad718 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio-multidomain.xml @@ -0,0 +1,41 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + + +
+ + + + + + + + + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio.xml index 90419a435b..b4f5e72ee5 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev-vfio.xml @@ -26,7 +26,7 @@ -
+
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev.xml index d65ef874e8..f88eefc9e9 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev.xml @@ -25,7 +25,7 @@ -
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 14482fd639..ad5e2cd6bd 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -942,9 +942,21 @@ mymain(void) DO_TEST("net-mcast", NONE); DO_TEST("net-hostdev", QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); + DO_TEST("net-hostdev-multidomain", + QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN); + DO_TEST_FAILURE("net-hostdev-multidomain", + QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, + QEMU_CAPS_NODEFCONFIG); DO_TEST("net-hostdev-vfio", QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("net-hostdev-vfio-multidomain", + QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_VFIO_PCI, QEMU_CAPS_HOST_PCI_MULTIDOMAIN); + DO_TEST_FAILURE("net-hostdev-vfio-multidomain", + QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_VFIO_PCI); DO_TEST("serial-vc", NONE); DO_TEST("serial-pty", NONE); @@ -1121,6 +1133,12 @@ mymain(void) DO_TEST("hostdev-vfio", QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("hostdev-vfio-multidomain", + QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_VFIO_PCI, QEMU_CAPS_HOST_PCI_MULTIDOMAIN); + DO_TEST_FAILURE("hostdev-vfio-multidomain", + QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_VFIO_PCI); DO_TEST("pci-rom", QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_PCI_ROMBAR); -- GitLab