Signed-off-by: Shivaprasad G Bhat <sbhat@xxxxxxxxxxxxxxxxxx> --- src/qemu/qemu_domain.c | 2 src/qemu/qemu_domain_address.c | 68 +++++++++++++++++ src/qemu/qemu_domain_address.h | 5 + src/qemu/qemu_driver.c | 66 ++++++++++------ src/qemu/qemu_hotplug.c | 82 ++++++++++++++++++++ src/qemu/qemu_hotplug.h | 4 + tests/qemuhotplugtest.c | 39 ++++++++-- .../qemuhotplug-multifunction-hostdev-pci-2.xml | 14 +++ .../qemuhotplug-multifunction-hostdev-pci.xml | 20 +++++ ...hotplug-base-live+multifunction-hostdev-pci.xml | 76 +++++++++++++++++++ ...eries-base-live+multifunction-hostdev-pci-2.xml | 61 +++++++++++++++ ...pseries-base-live+multifunction-hostdev-pci.xml | 69 +++++++++++++++++ 12 files changed, 475 insertions(+), 31 deletions(-) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci-2.xml create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+multifunction-hostdev-pci.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+multifunction-hostdev-pci-2.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+multifunction-hostdev-pci.xml diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index c0a0af525f..1cfaf01540 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -33,6 +33,8 @@ #include "qemu_capabilities.h" #include "qemu_migration.h" #include "qemu_security.h" +#include "qemu_hotplug.h" +#include "qemu_hostdev.h" #include "viralloc.h" #include "virlog.h" #include "virerror.h" diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 7bee4fb937..ee743321dd 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -25,6 +25,7 @@ #include "qemu_domain_address.h" #include "qemu_domain.h" +#include "domain_conf.h" #include "viralloc.h" #include "virhostdev.h" #include "virerror.h" @@ -3206,6 +3207,73 @@ qemuDomainEnsurePCIAddress(virDomainObjPtr obj, info->pciConnectFlags); } + +int +qemuDomainPCIMultifunctionHostdevEnsurePCIAddresses(virDomainObjPtr vm, + virDomainDeviceDefListPtr devlist, + virQEMUDriverPtr driver) +{ + int ret = -1, aggrslotidx = 0; + virBitmapPtr slotmap = NULL; + size_t i; + qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainPCIMultifunctionAddressInfoPtr devinfos = NULL; + + if (devlist->count > VIR_PCI_MAX_FUNCTIONS) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("More devices per slot found")); + return -1; + } + + for (i = 0; i < devlist->count; i++) + qemuDomainFillDevicePCIConnectFlags(vm->def, devlist->devs[i], priv->qemuCaps, driver); + + if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + devlist->count) < 0) + return -1; + + /* Temporarily add the devices to the domain def to get the + * next aggregateIdx */ + for (i = 0; i < devlist->count; i++) + vm->def->hostdevs[vm->def->nhostdevs++] = devlist->devs[i]->data.hostdev; + + for (i = 0; i < devlist->count; i++) { + if (qemuDomainIsPSeries(vm->def)) { + /* Isolation groups are only relevant for pSeries guests */ + if (qemuDomainFillDeviceIsolationGroup(vm->def, devlist->devs[i]) < 0) + return -1; + } + qemuDomainSetDeviceSlotAggregateIdx(vm->def, devlist->devs[i]); + aggrslotidx = aggrslotidx ? aggrslotidx : devlist->devs[i]->data.hostdev->info->aggregateSlotIdx; + if (aggrslotidx != devlist->devs[i]->data.hostdev->info->aggregateSlotIdx) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Devices belong to different PCI slots")); + return -1; + } + } + + for (i = 0; i < devlist->count; i++) + vm->def->hostdevs[--(vm->def->nhostdevs)] = NULL; + + slotmap = virDomainDefHostdevGetPCIOnlineFunctionMap(vm->def, aggrslotidx); + if (!virBitmapIsAllClear(slotmap)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("Device already assigned to guest")); + return -1; + } + + if (VIR_ALLOC(devinfos) < 0) + return -1; + + for (i = 0; i < devlist->count; i++) { + virPCIDeviceAddress addr = devlist->devs[i]->data.hostdev->source.subsys.u.pci.addr; + devinfos->infos[addr.function] = devlist->devs[i]->data.hostdev->info; + } + + ret = virDomainPCIAddressEnsureMultifunctionAddress(priv->pciaddrs, devinfos); + VIR_FREE(devinfos); + return ret; +} + void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm, virDomainDeviceInfoPtr info, diff --git a/src/qemu/qemu_domain_address.h b/src/qemu/qemu_domain_address.h index e1cc467714..43d1de889e 100644 --- a/src/qemu/qemu_domain_address.h +++ b/src/qemu/qemu_domain_address.h @@ -51,6 +51,11 @@ int qemuDomainEnsurePCIAddress(virDomainObjPtr obj, virQEMUDriverPtr driver) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +int +qemuDomainPCIMultifunctionHostdevEnsurePCIAddresses(virDomainObjPtr obj, + virDomainDeviceDefListPtr devlist, + virQEMUDriverPtr driver); + int qemuDomainFillDeviceIsolationGroup(virDomainDefPtr def, virDomainDeviceDefPtr dev) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d2e10082ea..fb14475d8c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7744,15 +7744,26 @@ qemuDomainAttachDeviceLiveInternal(virDomainObjPtr vm, static int qemuDomainAttachDeviceLive(virDomainObjPtr vm, - virDomainDeviceDefPtr dev, + virDomainDeviceDefListPtr devlist, virQEMUDriverPtr driver) { int ret = -1; + size_t i; - if (virDomainDefCompatibleDevice(vm->def, dev, NULL) < 0) - return -1; + for (i = 0; i < devlist->count; i++) + if (virDomainDefCompatibleDevice(vm->def, devlist->devs[i], NULL) < 0) + return ret; + + if (devlist->count > 1) { + ret = qemuDomainAttachMultifunctionDevice(vm, devlist, driver); + if (ret == 0) { + for (i = 0; i < devlist->count; i++) + devlist->devs[i]->data.hostdev = NULL; + } + } else if (devlist->count == 1) { + ret = qemuDomainAttachDeviceLiveInternal(vm, devlist->devs[0], driver); + } - ret = qemuDomainAttachDeviceLiveInternal(vm, dev, driver); if (ret == 0) ret = qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE); @@ -8178,16 +8189,22 @@ qemuDomainAttachDeviceConfigInternal(virDomainDefPtr vmdef, static int qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, - virDomainDeviceDefPtr dev, + virDomainDeviceDefListPtr devlist, virCapsPtr caps, unsigned int parse_flags, virDomainXMLOptionPtr xmlopt) { - if (virDomainDefCompatibleDevice(vmdef, dev, NULL) < 0) - return -1; + size_t i; - if (qemuDomainAttachDeviceConfigInternal(vmdef, dev)) - return -1; + for (i = 0; i < devlist->count; i++) { + if (virDomainDefCompatibleDevice(vmdef, devlist->devs[i], NULL) < 0) + return -1; + } + + for (i = 0; i < devlist->count; i++) { + if (qemuDomainAttachDeviceConfigInternal(vmdef, devlist->devs[i])) + return -1; + } if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0) return -1; @@ -8493,9 +8510,11 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, const char *xml, unsigned int flags) { + size_t i; virDomainDefPtr vmdef = NULL; virQEMUDriverConfigPtr cfg = NULL; - virDomainDeviceDefPtr dev = NULL, dev_copy = NULL; + virDomainDeviceDefListPtr devlist = NULL, devcopylist = NULL; + virDomainDeviceDefListData data = {.def = vm->def, .xmlopt = driver->xmlopt, .caps = NULL}; int ret = -1; virCapsPtr caps = NULL; unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE | @@ -8508,15 +8527,16 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; + data.caps = caps; - dev = dev_copy = virDomainDeviceDefParse(xml, vm->def, - caps, driver->xmlopt, - parse_flags); - if (dev == NULL) + devlist = qemuDomainDeviceParseXMLMany(xml, &data, parse_flags); + if (!devlist) goto cleanup; + devcopylist = devlist; - if (virDomainDeviceValidateAliasForHotplug(vm, dev, flags) < 0) - goto cleanup; + for (i = 0; i < devlist->count; i++) + if (virDomainDeviceValidateAliasForHotplug(vm, devlist->devs[i], flags) < 0) + goto cleanup; if (flags & VIR_DOMAIN_AFFECT_CONFIG && flags & VIR_DOMAIN_AFFECT_LIVE) { @@ -8524,8 +8544,8 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, * create a deep copy of device as adding * to CONFIG takes one instance. */ - dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt); - if (!dev_copy) + devcopylist = virDomainDeviceDefListCopy(devlist, &data); + if (!devcopylist) goto cleanup; } @@ -8535,14 +8555,14 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, if (!vmdef) goto cleanup; - if ((ret = qemuDomainAttachDeviceConfig(vmdef, dev, caps, + if ((ret = qemuDomainAttachDeviceConfig(vmdef, devlist, caps, parse_flags, driver->xmlopt)) < 0) goto cleanup; } if (flags & VIR_DOMAIN_AFFECT_LIVE) { - if ((ret = qemuDomainAttachDeviceLive(vm, dev_copy, driver)) < 0) + if ((ret = qemuDomainAttachDeviceLive(vm, devcopylist, driver)) < 0) goto cleanup; /* * update domain status forcibly because the domain status may be @@ -8566,9 +8586,9 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, cleanup: virDomainDefFree(vmdef); - if (dev != dev_copy) - virDomainDeviceDefFree(dev_copy); - virDomainDeviceDefFree(dev); + if (devlist != devcopylist) + virDomainDeviceDefListFree(devcopylist); + virDomainDeviceDefListFree(devlist); virObjectUnref(cfg); virObjectUnref(caps); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 7dffaf9502..a339e92bfa 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1402,6 +1402,88 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, } +static int +qemuiHostdevPCIMultifunctionDevicesListSort(const void *p1, + const void *p2) +{ + virDomainDeviceDefPtr a = *(virDomainDeviceDefPtr *) p1; + virDomainDeviceDefPtr b = *(virDomainDeviceDefPtr *) p2; + virPCIDeviceAddressPtr addr1 = &a->data.hostdev->source.subsys.u.pci.addr; + virPCIDeviceAddressPtr addr2 = &b->data.hostdev->source.subsys.u.pci.addr; + + return addr1->function - addr2->function; +} + + +int +qemuDomainAttachMultifunctionDevice(virDomainObjPtr vm, + virDomainDeviceDefListPtr devlist, + virQEMUDriverPtr driver) +{ + size_t i, d, h = devlist->count; + int ret = -1; + char *alias; + virObjectEventPtr event; + virQEMUCapsPtr qemuCaps = NULL; + virDomainHostdevDefPtr hostdev = NULL; + + if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, + vm->def->emulator))) + return -1; + + qsort(devlist->devs, devlist->count, sizeof(*devlist->devs), qemuiHostdevPCIMultifunctionDevicesListSort); + + if (qemuDomainPCIMultifunctionHostdevEnsurePCIAddresses(vm, devlist, driver) < 0) + return -1; + + for (d = 0; d < devlist->count; d++) + if (qemuDomainAttachPCIHostDevicePrepare(driver, vm->def, devlist->devs[d]->data.hostdev, qemuCaps) < 0) + goto cleanup; + + /* Hotplug all functions, and Primary at last */ + for (h = devlist->count; h > 0; h--) { + /* The functions need not be contiguous, as a card may be sold with + * minimal functionality and then install the additional functions on + * purchase into any of the daughter-card connectors. + */ + hostdev = devlist->devs[h-1]->data.hostdev; + ret = qemuDomainAttachHostPCIDevice(driver, vm, hostdev); + if (ret) + goto release; + + alias = hostdev->info->alias; + hostdev = NULL; + + event = virDomainEventDeviceAddedNewFromObj(vm, alias); + qemuDomainEventQueue(driver, event); + } + + release: + /* Release addresses for the device which are not hotplugged. + */ + for (i = 0; i < h; i++) + qemuDomainReleaseDeviceAddress(vm, devlist->devs[i]->data.hostdev->info, NULL); + + cleanup: + /* If none are actually hotplugged and just detached from the + * host driver reattach the devices to host driver. + * + * If one of the hotplug failed, those which are already hotplugged cannot + * be unplugged as they are released by qemu only on guest reboot even + * if we issue device_del on them. + * So, dont attempt to reattach any of them. + * NB: Let them be in the guest as they are not used anyway without + * function-zero? + */ + if (d > 0 && h == devlist->count) { + for (i = 0; i < d; i++) + qemuHostdevReAttachPCIDevices(driver, vm->def->name, &devlist->devs[i]->data.hostdev, 1); + } + + return ret; +} + + void qemuDomainDelTLSObjects(virQEMUDriverPtr driver, virDomainObjPtr vm, diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index db0e1df79a..7a6e2dfb60 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -158,6 +158,10 @@ int qemuDomainAttachPCIHostDevicePrepare(virQEMUDriverPtr driver, virDomainDefPtr def, virDomainHostdevDefPtr dev, virQEMUCapsPtr qemuCaps); +int +qemuDomainAttachMultifunctionDevice(virDomainObjPtr vm, + virDomainDeviceDefListPtr devlist, + virQEMUDriverPtr driver); int qemuDomainChrInsert(virDomainDefPtr vmdef, diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index b5dca5e5c9..39f122e083 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -82,6 +82,8 @@ qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt, virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI); virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY); + virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_HOST_PCI_MULTIDOMAIN); + virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION); if (event) virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT); @@ -115,9 +117,14 @@ qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt, static int testQemuHotplugAttach(virDomainObjPtr vm, - virDomainDeviceDefPtr dev) + virDomainDeviceDefListPtr devlist) { int ret = -1; + virDomainDeviceDefPtr dev; + + if (devlist->count > 1) + return qemuDomainAttachMultifunctionDevice(vm, devlist, &driver); + dev = devlist->devs[0]; switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -249,7 +256,9 @@ testQemuHotplug(const void *data) bool keep = test->keep; unsigned int device_parse_flags = 0; virDomainObjPtr vm = NULL; - virDomainDeviceDefPtr dev = NULL; + virDomainDeviceDefPtr dev = NULL; /*temperory */ + virDomainDeviceDefListPtr devlist = NULL; + virDomainDeviceDefListData listdata; virCapsPtr caps = NULL; qemuMonitorTestPtr test_mon = NULL; qemuDomainObjPrivatePtr priv = NULL; @@ -286,10 +295,13 @@ testQemuHotplug(const void *data) if (test->action == ATTACH) device_parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE; - if (!(dev = virDomainDeviceDefParse(device_xml, vm->def, - caps, driver.xmlopt, - device_parse_flags))) + listdata.def = vm->def; + listdata.xmlopt = driver.xmlopt; + listdata.caps = caps; + devlist = qemuDomainDeviceParseXMLMany(device_xml, &listdata, device_parse_flags); + if (!devlist) goto cleanup; + dev = devlist->devs[0]; /* temporary */ /* Now is the best time to feed the spoofed monitor with predefined * replies. */ @@ -319,11 +331,11 @@ testQemuHotplug(const void *data) switch (test->action) { case ATTACH: - ret = testQemuHotplugAttach(vm, dev); + ret = testQemuHotplugAttach(vm, devlist); if (ret == 0) { /* vm->def stolen dev->data.* so we just need to free the dev * envelope */ - VIR_FREE(dev); + virDomainDeviceDefListFreeShallow(devlist); } if (ret == 0 || fail) ret = testQemuHotplugCheckResult(vm, result_xml, @@ -357,7 +369,7 @@ testQemuHotplug(const void *data) virObjectUnref(vm); test->vm = NULL; } - virDomainDeviceDefFree(dev); + virDomainDeviceDefListFree(devlist); virObjectUnref(caps); qemuMonitorTestFree(test_mon); return ((ret < 0 && fail) || (!ret && !fail)) ? 0 : -1; @@ -856,6 +868,17 @@ mymain(void) "device_add", QMP_OK); DO_TEST_DETACH("pseries-base-live", "hostdev-pci", false, false, "device_del", QMP_DEVICE_DELETED("hostdev0") QMP_OK); + DO_TEST_ATTACH("base-live", "multifunction-hostdev-pci", false, false, + "device_add", QMP_OK, + "device_add", QMP_OK, + "device_add", QMP_OK); + + qemuTestSetHostArch(driver.caps, VIR_ARCH_PPC64); + DO_TEST_ATTACH("pseries-base-live", "multifunction-hostdev-pci-2", false, false, + "device_add", QMP_OK, + "device_add", QMP_OK, + "device_add", QMP_OK); + qemuTestSetHostArch(driver.caps, VIR_ARCH_X86_64); DO_TEST_ATTACH("base-live", "watchdog", false, true, "watchdog-set-action", QMP_OK, diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci-2.xml b/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci-2.xml new file mode 100644 index 0000000000..02e2236e5d --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci-2.xml @@ -0,0 +1,14 @@ +<devices> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> + </source> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + </hostdev> +</devices> diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci.xml b/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci.xml new file mode 100644 index 0000000000..54bb627e30 --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci.xml @@ -0,0 +1,20 @@ +<devices> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x1'/> + </source> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x2'/> + </source> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + </hostdev> +</devices> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+multifunction-hostdev-pci.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+multifunction-hostdev-pci.xml new file mode 100644 index 0000000000..f53fe7601b --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+multifunction-hostdev-pci.xml @@ -0,0 +1,76 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </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-x86_64</emulator> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <alias name='ide'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='scsi' index='0' model='virtio-scsi'> + <alias name='scsi0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci'/> + </controller> + <controller type='virtio-serial' index='0'> + <alias name='virtio-serial0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x2'/> + </source> + <alias name='hostdev0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x2'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x1'/> + </source> + <alias name='hostdev1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x1'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + <alias name='hostdev2'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0' multifunction='on'/> + </hostdev> + <memballoon model='none'> + <alias name='balloon0'/> + </memballoon> + </devices> + <seclabel type='none' model='none'/> +</domain> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+multifunction-hostdev-pci-2.xml b/tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+multifunction-hostdev-pci-2.xml new file mode 100644 index 0000000000..85dc48fdb8 --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+multifunction-hostdev-pci-2.xml @@ -0,0 +1,61 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='ppc64' machine='pseries'>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/bin/qemu-system-ppc64</emulator> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + <alias name='pci.0'/> + </controller> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> + <alias name='pci.1'/> + </controller> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <input type='keyboard' bus='usb'> + <alias name='input0'/> + <address type='usb' bus='0' port='1'/> + </input> + <input type='mouse' bus='usb'> + <alias name='input1'/> + <address type='usb' bus='0' port='2'/> + </input> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> + </source> + <alias name='hostdev0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x1'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <alias name='hostdev1'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0' multifunction='on'/> + </hostdev> + <memballoon model='none'> + <alias name='balloon0'/> + </memballoon> + <panic model='pseries'/> + </devices> + <seclabel type='none' model='none'/> +</domain> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+multifunction-hostdev-pci.xml b/tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+multifunction-hostdev-pci.xml new file mode 100644 index 0000000000..9338d42e2e --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+multifunction-hostdev-pci.xml @@ -0,0 +1,69 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='ppc64' machine='pseries'>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/bin/qemu-system-ppc64</emulator> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + <alias name='pci.0'/> + </controller> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> + <alias name='pci.1'/> + </controller> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <input type='keyboard' bus='usb'> + <alias name='input0'/> + <address type='usb' bus='0' port='1'/> + </input> + <input type='mouse' bus='usb'> + <alias name='input1'/> + <address type='usb' bus='0' port='2'/> + </input> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x2'/> + </source> + <alias name='hostdev0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x2'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x1'/> + </source> + <alias name='hostdev1'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x1'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + <alias name='hostdev2'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0' multifunction='on'/> + </hostdev> + <memballoon model='none'> + <alias name='balloon0'/> + </memballoon> + <panic model='pseries'/> + </devices> + <seclabel type='none' model='none'/> +</domain> -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list