[libvirt] [PATCH v3 00/26] Multiple PHBs and hostdev isolation for pSeries guests

Changes from [v2]: * support hot(un)plug properly; * add documentation. Changes from [v1]: * address review comments; * implement a much better isolation algorithm that doesn't require parsing and formatting the isolation group and can handle more dynamic scenarios, such as empty PHBs changing their isolation groups to accomodate hotplugged hostdevs; * add more test cases. Known limitations: * hostdevs in IOMMU group 0 are not handled properly - the default isolation group is currently 0, which means hostdevs in IOMMU group 0 will be assigned addresses as if they were emulated devices and will not be isolated properly. Fixing this will be a lot of work because it requires cleaning up the the code that instantiates pretty much anything embedding a virDomainDeviceInfo, which is... A lot of things. Luckily, IOMMU group 0 will probably not contain any devices that are actually usable as hostdevs, so it should be okay to fix this in a follow-up series rather than upfront. Reviewed-by tags have been collected, so figuring out which patches are still in need of reviewing is pretty easy. [v1] https://www.redhat.com/archives/libvir-list/2017-June/msg00110.html [v2] https://www.redhat.com/archives/libvir-list/2017-June/msg00695.html Andrea Bolognani (26): conf: Remove obsolete comment conf: Make virDomainPCIAddressSetGrow() private conf: Make virDomainPCIAddressFlagsCompatible() private conf: Tweak virDomainPCIAddressGetNextAddr() signature qemu: Clean up qemuDomainAttachHostPCIDevice() tests: Update qemumemlock data tests: Mock IOMMU groups conf: Simplify slot allocation qemu: Allow qemuBuildControllerDevStr() to return NULL qemu: Tweak index number checking conf: Move index number checking to drivers qemu: Relax pci-root index requirement for pSeries guests conf: Parse and format <target index='...'/> conf: Add 'spapr-pci-host-bridge' controller model qemu: Automatically pick target index and model for pci-root controllers qemu: Introduce QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE qemu: Deal with PHB naming conventions qemu: Use multiple PHBs for pSeries guests tests: Add tests for pSeries guests with multiple PHBs tests: Add baseline tests for automatic PHB usage qemu: Use PHBs to fill holes in PCI bus numbering qemu: Use PHBs when extending the guest PCI topology conf: Introduce isolation groups conf: Implement isolation rules qemu: Isolate hostdevs on pSeries guests news: Update for multiple PHBs and hostdev isolation docs/formatdomain.html.in | 5 + docs/news.xml | 21 ++ docs/schemas/domaincommon.rng | 7 + src/bhyve/bhyve_device.c | 4 +- src/bhyve/bhyve_domain.c | 15 ++ src/conf/device_conf.h | 14 +- src/conf/domain_addr.c | 222 ++++++++++++------ src/conf/domain_addr.h | 38 ++- src/conf/domain_conf.c | 31 ++- src/conf/domain_conf.h | 2 + src/libvirt_private.syms | 2 - src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 148 ++++++++++-- src/qemu/qemu_command.h | 9 +- src/qemu/qemu_domain.c | 14 ++ src/qemu/qemu_domain_address.c | 261 +++++++++++++++++++-- src/qemu/qemu_hotplug.c | 23 +- .../qemuargv2xmldata/qemuargv2xml-pseries-disk.xml | 5 +- .../qemuargv2xml-pseries-nvram.xml | 5 +- tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 1 + .../qemumemlock-pc-hardlimit+hostdev.xml | 2 +- .../qemumemlock-pc-hardlimit+locked+hostdev.xml | 2 +- tests/qemumemlockdata/qemumemlock-pc-hostdev.xml | 2 +- .../qemumemlock-pc-locked+hostdev.xml | 2 +- .../qemumemlock-pseries-hardlimit+hostdev.xml | 2 +- ...emumemlock-pseries-hardlimit+locked+hostdev.xml | 2 +- .../qemumemlock-pseries-hostdev.xml | 2 +- .../qemumemlock-pseries-locked+hostdev.xml | 2 +- tests/qemumemlocktest.c | 21 +- .../qemuxml2argv-pseries-hostdevs-1.args | 25 ++ .../qemuxml2argv-pseries-hostdevs-1.xml | 38 +++ .../qemuxml2argv-pseries-hostdevs-2.args | 25 ++ .../qemuxml2argv-pseries-hostdevs-2.xml | 37 +++ .../qemuxml2argv-pseries-hostdevs-3.args | 24 ++ .../qemuxml2argv-pseries-hostdevs-3.xml | 31 +++ .../qemuxml2argv-pseries-many-buses-1.args | 22 ++ .../qemuxml2argv-pseries-many-buses-1.xml | 19 ++ .../qemuxml2argv-pseries-many-buses-2.args | 22 ++ .../qemuxml2argv-pseries-many-buses-2.xml | 18 ++ .../qemuxml2argv-pseries-many-devices.args | 53 +++++ .../qemuxml2argv-pseries-many-devices.xml | 48 ++++ .../qemuxml2argv-pseries-phb-default-missing.args | 22 ++ .../qemuxml2argv-pseries-phb-default-missing.xml | 16 ++ .../qemuxml2argv-pseries-phb-simple.args | 22 ++ .../qemuxml2argv-pseries-phb-simple.xml | 17 ++ tests/qemuxml2argvtest.c | 64 ++++- .../qemuxml2xmlout-panic-pseries.xml | 5 +- .../qemuxml2xmlout-ppc64-usb-controller-legacy.xml | 5 +- .../qemuxml2xmlout-ppc64-usb-controller.xml | 5 +- .../qemuxml2xmlout-pseries-hostdevs-1.xml | 54 +++++ .../qemuxml2xmlout-pseries-hostdevs-2.xml | 50 ++++ .../qemuxml2xmlout-pseries-hostdevs-3.xml | 47 ++++ ...xml => qemuxml2xmlout-pseries-many-buses-1.xml} | 19 +- ...xml => qemuxml2xmlout-pseries-many-buses-2.xml} | 20 +- .../qemuxml2xmlout-pseries-many-devices.xml | 125 ++++++++++ .../qemuxml2xmlout-pseries-nvram.xml | 5 +- .../qemuxml2xmlout-pseries-panic-missing.xml | 5 +- .../qemuxml2xmlout-pseries-panic-no-address.xml | 5 +- ...qemuxml2xmlout-pseries-phb-default-missing.xml} | 18 +- ...m.xml => qemuxml2xmlout-pseries-phb-simple.xml} | 18 +- tests/qemuxml2xmltest.c | 59 ++++- tests/virpcimock.c | 43 +++- 63 files changed, 1637 insertions(+), 216 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml copy tests/qemuxml2xmloutdata/{qemuxml2xmlout-pseries-nvram.xml => qemuxml2xmlout-pseries-many-buses-1.xml} (55%) copy tests/qemuxml2xmloutdata/{qemuxml2xmlout-pseries-nvram.xml => qemuxml2xmlout-pseries-many-buses-2.xml} (54%) create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml copy tests/qemuxml2xmloutdata/{qemuxml2xmlout-pseries-nvram.xml => qemuxml2xmlout-pseries-phb-default-missing.xml} (56%) copy tests/qemuxml2xmloutdata/{qemuxml2xmlout-pseries-nvram.xml => qemuxml2xmlout-pseries-phb-simple.xml} (56%) -- 2.7.5

The virDomainDeviceInfoIsSet() function no longer exists. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/conf/device_conf.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index 48782be..14be2e3 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -134,10 +134,6 @@ struct _virDomainDeviceDimmAddress { typedef struct _virDomainDeviceInfo virDomainDeviceInfo; typedef virDomainDeviceInfo *virDomainDeviceInfoPtr; struct _virDomainDeviceInfo { - /* If adding to this struct, ensure that - * virDomainDeviceInfoIsSet() is updated - * to consider the new fields - */ char *alias; int type; /* virDomainDeviceAddressType */ union { -- 2.7.5

There are no external users. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/conf/domain_addr.c | 2 +- src/conf/domain_addr.h | 5 ----- src/libvirt_private.syms | 1 - 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 639168e..9c809e8 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -362,7 +362,7 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus, * 0 = no action performed * >0 = number of buses added */ -int +static int virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, virDomainPCIConnectFlags flags) diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index f884b8a..efa97ca 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -145,11 +145,6 @@ bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -int virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs, - virPCIDeviceAddressPtr addr, - virDomainPCIConnectFlags flags) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, virDomainPCIConnectFlags flags) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c1e9471..175370e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -115,7 +115,6 @@ virDomainPCIAddressReserveNextAddr; virDomainPCIAddressSetAllMulti; virDomainPCIAddressSetAlloc; virDomainPCIAddressSetFree; -virDomainPCIAddressSetGrow; virDomainPCIAddressSlotInUse; virDomainPCIAddressValidate; virDomainPCIControllerModelToConnectType; -- 2.7.5

There are no external users. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/domain_addr.c | 2 +- src/conf/domain_addr.h | 8 -------- src/libvirt_private.syms | 1 - 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 9c809e8..0a7cb00 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -103,7 +103,7 @@ virDomainPCIControllerConnectTypeToModel(virDomainPCIConnectFlags flags) } -bool +static bool virDomainPCIAddressFlagsCompatible(virPCIDeviceAddressPtr addr, const char *addrStr, virDomainPCIConnectFlags busFlags, diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index efa97ca..0c7905b 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -121,14 +121,6 @@ virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses); void virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs); -bool virDomainPCIAddressFlagsCompatible(virPCIDeviceAddressPtr addr, - const char *addrStr, - virDomainPCIConnectFlags busFlags, - virDomainPCIConnectFlags devFlags, - bool reportError, - bool fromConfig) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - bool virDomainPCIAddressValidate(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, const char *addrStr, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 175370e..c8862a2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -108,7 +108,6 @@ virDomainGetBlkioParametersAssignFromDef; virDomainPCIAddressAsString; virDomainPCIAddressBusSetModel; virDomainPCIAddressEnsureAddr; -virDomainPCIAddressFlagsCompatible; virDomainPCIAddressReleaseAddr; virDomainPCIAddressReserveAddr; virDomainPCIAddressReserveNextAddr; -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
There are no external users.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Laine Stump <laine@laine.org>
--- src/conf/domain_addr.c | 2 +- src/conf/domain_addr.h | 8 -------- src/libvirt_private.syms | 1 - 3 files changed, 1 insertion(+), 10 deletions(-)
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 9c809e8..0a7cb00 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -103,7 +103,7 @@ virDomainPCIControllerConnectTypeToModel(virDomainPCIConnectFlags flags) }
-bool +static bool virDomainPCIAddressFlagsCompatible(virPCIDeviceAddressPtr addr, const char *addrStr, virDomainPCIConnectFlags busFlags, diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index efa97ca..0c7905b 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -121,14 +121,6 @@ virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses);
void virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs);
-bool virDomainPCIAddressFlagsCompatible(virPCIDeviceAddressPtr addr, - const char *addrStr, - virDomainPCIConnectFlags busFlags, - virDomainPCIConnectFlags devFlags, - bool reportError, - bool fromConfig) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - bool virDomainPCIAddressValidate(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, const char *addrStr, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 175370e..c8862a2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -108,7 +108,6 @@ virDomainGetBlkioParametersAssignFromDef; virDomainPCIAddressAsString; virDomainPCIAddressBusSetModel; virDomainPCIAddressEnsureAddr; -virDomainPCIAddressFlagsCompatible; virDomainPCIAddressReleaseAddr; virDomainPCIAddressReserveAddr; virDomainPCIAddressReserveNextAddr;

Move @function after @flags to match other functions in the same module like virDomainPCIAddressReserveNextAddr(). Also move virDomainPCIAddressReserveNextAddr() closer to virDomainPCIAddressReserveAddr() in the header file. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/conf/domain_addr.c | 6 +++--- src/conf/domain_addr.h | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 0a7cb00..b588b36 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -738,8 +738,8 @@ virDomainPCIAddressFindUnusedFunctionOnBus(virDomainPCIAddressBusPtr bus, static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr next_addr, - int function, - virDomainPCIConnectFlags flags) + virDomainPCIConnectFlags flags, + int function) { /* default to starting the search for a free slot from * the first slot of domain 0 bus 0... @@ -845,7 +845,7 @@ virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, { virPCIDeviceAddress addr; - if (virDomainPCIAddressGetNextAddr(addrs, &addr, function, flags) < 0) + if (virDomainPCIAddressGetNextAddr(addrs, &addr, flags, function) < 0) return -1; if (virDomainPCIAddressReserveAddrInternal(addrs, &addr, flags, false) < 0) diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 0c7905b..dbef4b1 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -142,6 +142,12 @@ int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, virDomainPCIConnectFlags flags) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, + virDomainDeviceInfoPtr dev, + virDomainPCIConnectFlags flags, + int function) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + int virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs, virDomainDeviceInfoPtr dev, virDomainPCIConnectFlags flags) @@ -151,12 +157,6 @@ int virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -int virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, - virDomainDeviceInfoPtr dev, - virDomainPCIConnectFlags flags, - int function) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - void virDomainPCIAddressSetAllMulti(virDomainDefPtr def) ATTRIBUTE_NONNULL(1); -- 2.7.5

We use hostdev->info frequently enough that having a shorter name for it makes the code more readable. We will also be adding even more uses later on. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_hotplug.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index a486fb4..d9259ab 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1390,6 +1390,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, qemuDomainObjPrivatePtr priv = vm->privateData; virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV, { .hostdev = hostdev } }; + virDomainDeviceInfoPtr info = hostdev->info; int ret; char *devstr = NULL; int configfd = -1; @@ -1462,7 +1463,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) teardownlabel = true; - if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0) + if (qemuAssignDeviceHostdevAlias(vm->def, &info->alias, -1) < 0) goto error; if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0) goto error; @@ -1471,8 +1472,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_PCI_CONFIGFD)) { configfd = qemuOpenPCIConfig(hostdev); if (configfd >= 0) { - if (virAsprintf(&configfd_name, "fd-%s", - hostdev->info->alias) < 0) + if (virAsprintf(&configfd_name, "fd-%s", info->alias) < 0) goto error; } } @@ -1517,7 +1517,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, VIR_WARN("Unable to remove host device from /dev"); if (releaseaddr) - qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL); + qemuDomainReleaseDeviceAddress(vm, info, NULL); qemuHostdevReAttachPCIDevices(driver, vm->def->name, &hostdev, 1); -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
We use hostdev->info frequently enough that having a shorter name for it makes the code more readable. We will also be adding even more uses later on.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Laine Stump <laine@laine.org>
--- src/qemu/qemu_hotplug.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index a486fb4..d9259ab 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1390,6 +1390,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, qemuDomainObjPrivatePtr priv = vm->privateData; virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV, { .hostdev = hostdev } }; + virDomainDeviceInfoPtr info = hostdev->info; int ret; char *devstr = NULL; int configfd = -1; @@ -1462,7 +1463,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) teardownlabel = true;
- if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0) + if (qemuAssignDeviceHostdevAlias(vm->def, &info->alias, -1) < 0) goto error; if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0) goto error; @@ -1471,8 +1472,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_PCI_CONFIGFD)) { configfd = qemuOpenPCIConfig(hostdev); if (configfd >= 0) { - if (virAsprintf(&configfd_name, "fd-%s", - hostdev->info->alias) < 0) + if (virAsprintf(&configfd_name, "fd-%s", info->alias) < 0) goto error; } } @@ -1517,7 +1517,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, VIR_WARN("Unable to remove host device from /dev");
if (releaseaddr) - qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL); + qemuDomainReleaseDeviceAddress(vm, info, NULL);
qemuHostdevReAttachPCIDevices(driver, vm->def->name, &hostdev, 1);

Use 0001:01:00.0 instead of 0000:04:02.0 as the source address for the host device. This doesn't change anything at the moment, but it will make a difference later on. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml | 2 +- tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml | 2 +- tests/qemumemlockdata/qemumemlock-pc-hostdev.xml | 2 +- tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml | 2 +- tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml | 2 +- tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml | 2 +- tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml | 2 +- tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml index 5443145..e03f5a5 100644 --- a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+hostdev.xml @@ -13,7 +13,7 @@ <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> - <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> </hostdev> </devices> diff --git a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml index 8184eef..7070e5a 100644 --- a/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pc-hardlimit+locked+hostdev.xml @@ -16,7 +16,7 @@ <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> - <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> </hostdev> </devices> diff --git a/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml index 6c058a9..cd517ee 100644 --- a/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pc-hostdev.xml @@ -10,7 +10,7 @@ <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> - <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> </hostdev> </devices> diff --git a/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml index fbc1dc3..da79cb5 100644 --- a/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pc-locked+hostdev.xml @@ -13,7 +13,7 @@ <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> - <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> </hostdev> </devices> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml index ddd3b47..baf0649 100644 --- a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+hostdev.xml @@ -13,7 +13,7 @@ <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> - <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> </hostdev> </devices> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml index 73c28c1..04ae4e9 100644 --- a/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pseries-hardlimit+locked+hostdev.xml @@ -16,7 +16,7 @@ <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> - <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> </hostdev> </devices> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml index daf70a4..a52768c 100644 --- a/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pseries-hostdev.xml @@ -10,7 +10,7 @@ <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> - <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> </hostdev> </devices> diff --git a/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml b/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml index 74212f1..f5abef0 100644 --- a/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml +++ b/tests/qemumemlockdata/qemumemlock-pseries-locked+hostdev.xml @@ -13,7 +13,7 @@ <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> - <address domain='0x0000' bus='0x04' slot='0x02' function='0x0'/> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> </hostdev> </devices> -- 2.7.5

Later on we're going to need access to information about IOMMU groups for host devices. Implement the support in virpcimock, and start using that mock library in a few QEMU test cases. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- tests/qemumemlocktest.c | 21 ++++++++++++++++++++- tests/qemuxml2argvtest.c | 25 ++++++++++++++++++++++--- tests/qemuxml2xmltest.c | 21 ++++++++++++++++++++- tests/virpcimock.c | 43 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 99 insertions(+), 11 deletions(-) diff --git a/tests/qemumemlocktest.c b/tests/qemumemlocktest.c index 6cf17a4..c0f1dc3 100644 --- a/tests/qemumemlocktest.c +++ b/tests/qemumemlocktest.c @@ -56,11 +56,25 @@ testCompareMemLock(const void *data) return ret; } +# define FAKEROOTDIRTEMPLATE abs_builddir "/fakerootdir-XXXXXX" static int mymain(void) { int ret = 0; + char *fakerootdir; + + if (VIR_STRDUP_QUIET(fakerootdir, FAKEROOTDIRTEMPLATE) < 0) { + fprintf(stderr, "Out of memory\n"); + abort(); + } + + if (!mkdtemp(fakerootdir)) { + fprintf(stderr, "Cannot create fakerootdir"); + abort(); + } + + setenv("LIBVIRT_FAKE_ROOT_DIR", fakerootdir, 1); abs_top_srcdir = getenv("abs_top_srcdir"); if (!abs_top_srcdir) @@ -124,12 +138,17 @@ mymain(void) DO_TEST("pseries-hardlimit+locked+hostdev", 2147483648); DO_TEST("pseries-locked+hostdev", VIR_DOMAIN_MEMORY_PARAM_UNLIMITED); + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) + virFileDeleteTree(fakerootdir); + qemuTestDriverFree(&driver); + VIR_FREE(fakerootdir); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -VIR_TEST_MAIN(mymain) +VIR_TEST_MAIN_PRELOAD(mymain, + abs_builddir "/.libs/virpcimock.so") #else diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 27eea70..01c0a65 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -534,13 +534,27 @@ testCompareXMLToArgv(const void *data) return ret; } +# define FAKEROOTDIRTEMPLATE abs_builddir "/fakerootdir-XXXXXX" static int mymain(void) { int ret = 0; + char *fakerootdir; bool skipLegacyCPUs = false; + if (VIR_STRDUP_QUIET(fakerootdir, FAKEROOTDIRTEMPLATE) < 0) { + fprintf(stderr, "Out of memory\n"); + abort(); + } + + if (!mkdtemp(fakerootdir)) { + fprintf(stderr, "Cannot create fakerootdir"); + abort(); + } + + setenv("LIBVIRT_FAKE_ROOT_DIR", fakerootdir, 1); + abs_top_srcdir = getenv("abs_top_srcdir"); if (!abs_top_srcdir) abs_top_srcdir = abs_srcdir "/.."; @@ -2621,15 +2635,20 @@ mymain(void) DO_TEST_PARSE_ERROR("cpu-cache-passthrough3", QEMU_CAPS_KVM); DO_TEST_PARSE_ERROR("cpu-cache-passthrough-l3", QEMU_CAPS_KVM); + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) + virFileDeleteTree(fakerootdir); + qemuTestDriverFree(&driver); + VIR_FREE(fakerootdir); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } VIR_TEST_MAIN_PRELOAD(mymain, - abs_builddir "/.libs/qemuxml2argvmock.so", - abs_builddir "/.libs/virrandommock.so", - abs_builddir "/.libs/qemucpumock.so") + abs_builddir "/.libs/qemuxml2argvmock.so", + abs_builddir "/.libs/virrandommock.so", + abs_builddir "/.libs/qemucpumock.so", + abs_builddir "/.libs/virpcimock.so") #else diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 1307299..c74614c 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -303,14 +303,28 @@ testInfoSet(struct testInfo *info, return -1; } +# define FAKEROOTDIRTEMPLATE abs_builddir "/fakerootdir-XXXXXX" static int mymain(void) { int ret = 0; + char *fakerootdir; struct testInfo info; virQEMUDriverConfigPtr cfg = NULL; + if (VIR_STRDUP_QUIET(fakerootdir, FAKEROOTDIRTEMPLATE) < 0) { + fprintf(stderr, "Out of memory\n"); + abort(); + } + + if (!mkdtemp(fakerootdir)) { + fprintf(stderr, "Cannot create fakerootdir"); + abort(); + } + + setenv("LIBVIRT_FAKE_ROOT_DIR", fakerootdir, 1); + memset(&info, 0, sizeof(info)); if (qemuTestDriverInit(&driver) < 0) @@ -1145,12 +1159,17 @@ mymain(void) DO_TEST("cpu-check-default-partial", NONE); DO_TEST("cpu-check-default-partial2", NONE); + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) + virFileDeleteTree(fakerootdir); + qemuTestDriverFree(&driver); + VIR_FREE(fakerootdir); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -VIR_TEST_MAIN(mymain) +VIR_TEST_MAIN_PRELOAD(mymain, + abs_builddir "/.libs/virpcimock.so") #else diff --git a/tests/virpcimock.c b/tests/virpcimock.c index e9408aa..19b10f4 100644 --- a/tests/virpcimock.c +++ b/tests/virpcimock.c @@ -127,6 +127,7 @@ struct pciDevice { int vendor; int device; int class; + int iommuGroup; struct pciDriver *driver; /* Driver attached. NULL if attached to no driver */ }; @@ -190,6 +191,22 @@ make_file(const char *path, VIR_FREE(filepath); } +static void +make_symlink(const char *path, + const char *name, + const char *target) +{ + char *filepath = NULL; + + if (virAsprintfQuiet(&filepath, "%s/%s", path, name) < 0) + ABORT_OOM(); + + if (symlink(target, filepath) < 0) + ABORT("Unable to create symlink filepath -> target"); + + VIR_FREE(filepath); +} + static int pci_read_file(const char *path, char *buf, @@ -322,7 +339,7 @@ pci_device_new_from_stub(const struct pciDevice *data) char *id; char *c; char *configSrc; - char tmp[32]; + char tmp[256]; struct stat sb; if (VIR_STRDUP_QUIET(id, data->id) < 0) @@ -386,6 +403,20 @@ pci_device_new_from_stub(const struct pciDevice *data) ABORT("@tmp overflow"); make_file(devpath, "class", tmp, -1); + if (snprintf(tmp, sizeof(tmp), + "%s/../../../kernel/iommu_groups/%d", + devpath, dev->iommuGroup) < 0) { + ABORT("@tmp overflow"); + } + if (virFileMakePath(tmp) < 0) + ABORT("Unable to create %s", tmp); + + if (snprintf(tmp, sizeof(tmp), + "../../../kernel/iommu_groups/%d", dev->iommuGroup) < 0) { + ABORT("@tmp overflow"); + } + make_symlink(devpath, "iommu_group", tmp); + if (pci_device_autobind(dev) < 0) ABORT("Unable to bind: %s", data->id); @@ -821,12 +852,12 @@ init_env(void) MAKE_PCI_DEVICE("0000:00:02.0", 0x8086, 0x0046); MAKE_PCI_DEVICE("0000:00:03.0", 0x8086, 0x0048); MAKE_PCI_DEVICE("0001:00:00.0", 0x1014, 0x03b9, .class = 0x060400); - MAKE_PCI_DEVICE("0001:01:00.0", 0x8086, 0x105e); - MAKE_PCI_DEVICE("0001:01:00.1", 0x8086, 0x105e); + MAKE_PCI_DEVICE("0001:01:00.0", 0x8086, 0x105e, .iommuGroup = 2); + MAKE_PCI_DEVICE("0001:01:00.1", 0x8086, 0x105e, .iommuGroup = 2); MAKE_PCI_DEVICE("0005:80:00.0", 0x10b5, 0x8112, .class = 0x060400); - MAKE_PCI_DEVICE("0005:90:01.0", 0x1033, 0x0035); - MAKE_PCI_DEVICE("0005:90:01.1", 0x1033, 0x0035); - MAKE_PCI_DEVICE("0005:90:01.2", 0x1033, 0x00e0); + MAKE_PCI_DEVICE("0005:90:01.0", 0x1033, 0x0035, .iommuGroup = 3); + MAKE_PCI_DEVICE("0005:90:01.1", 0x1033, 0x0035, .iommuGroup = 3); + MAKE_PCI_DEVICE("0005:90:01.2", 0x1033, 0x00e0, .iommuGroup = 3); MAKE_PCI_DEVICE("0000:0a:01.0", 0x8086, 0x0047); MAKE_PCI_DEVICE("0000:0a:02.0", 0x8286, 0x0048); MAKE_PCI_DEVICE("0000:0a:03.0", 0x8386, 0x0048); -- 2.7.5

The current algorithm for slot allocation tries to be clever and avoid looking at buses / slots more than once unless it's necessary. Unfortunately that makes the code more complex, and it will cause problem later on in some situations unless even more complex code is added. Since the performance gains are going to be pretty modest anyway, we can just get rid of the extra complexity and use a completely straighforward implementation instead. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/conf/domain_addr.c | 47 +++++++++-------------------------------------- src/conf/domain_addr.h | 2 -- 2 files changed, 9 insertions(+), 40 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index b588b36..86b1367 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -741,46 +741,34 @@ virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, virDomainPCIConnectFlags flags, int function) { - /* default to starting the search for a free slot from - * the first slot of domain 0 bus 0... - */ virPCIDeviceAddress a = { 0 }; - bool found = false; if (addrs->nbuses == 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available")); goto error; } - /* ...unless this search is for the exact same type of device as - * last time, then continue the search from the slot where we - * found the previous match (it's possible there will still be a - * function available on that slot). - */ - if (flags == addrs->lastFlags) - a = addrs->lastaddr; - else - a.slot = addrs->buses[0].minSlot; - /* if the caller asks for "any function", give them function 0 */ if (function == -1) a.function = 0; else a.function = function; - while (a.bus < addrs->nbuses) { - if (virDomainPCIAddressFindUnusedFunctionOnBus(&addrs->buses[a.bus], - &a, function, + /* "Begin at the beginning," the King said, very gravely, "and go on + * till you come to the end: then stop." */ + for (a.bus = 0; a.bus < addrs->nbuses; a.bus++) { + virDomainPCIAddressBusPtr bus = &addrs->buses[a.bus]; + bool found = false; + + a.slot = bus->minSlot; + + if (virDomainPCIAddressFindUnusedFunctionOnBus(bus, &a, function, flags, &found) < 0) { goto error; } if (found) goto success; - - /* nothing on this bus, go to the next bus */ - if (++a.bus < addrs->nbuses) - a.slot = addrs->buses[a.bus].minSlot; } /* There were no free slots after the last used one */ @@ -791,20 +779,6 @@ virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, /* this device will use the first slot of the new bus */ a.slot = addrs->buses[a.bus].minSlot; goto success; - } else if (flags == addrs->lastFlags) { - /* Check the buses from 0 up to the last used one */ - for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) { - a.slot = addrs->buses[a.bus].minSlot; - - if (virDomainPCIAddressFindUnusedFunctionOnBus(&addrs->buses[a.bus], - &a, function, - flags, &found) < 0) { - goto error; - } - - if (found) - goto success; - } } virReportError(VIR_ERR_INTERNAL_ERROR, @@ -851,9 +825,6 @@ virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, if (virDomainPCIAddressReserveAddrInternal(addrs, &addr, flags, false) < 0) return -1; - addrs->lastaddr = addr; - addrs->lastFlags = flags; - if (!addrs->dryRun) { dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; dev->addr.pci = addr; diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index dbef4b1..c98a228 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -106,8 +106,6 @@ typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr; struct _virDomainPCIAddressSet { virDomainPCIAddressBus *buses; size_t nbuses; - virPCIDeviceAddress lastaddr; - virDomainPCIConnectFlags lastFlags; bool dryRun; /* on a dry run, new buses are auto-added and addresses aren't saved in device infos */ }; -- 2.7.5

We will soon need to be able to return a NULL pointer without the caller considering that an error: to make it possible, change the return type to int and use an out parameter for the string instead. Add some documentation for the function as well. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_command.c | 55 ++++++++++++++++++++++++++++++++++++------------- src/qemu/qemu_command.h | 9 ++++---- src/qemu/qemu_hotplug.c | 5 ++++- 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c53ab97..ea2e63b 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2704,23 +2704,46 @@ qemuCheckSCSIControllerIOThreads(const virDomainDef *domainDef, } -char * +/** + * qemuBuildControllerDevStr: + * @domainDef: domain definition + * @def: controller definition + * @qemuCaps: QEMU binary capabilities + * @devstr: device string + * @nusbcontroller: number of USB controllers + * + * Turn @def into a description of the controller that QEMU will understand, + * to be used either on the command line or through the monitor. + * + * The description will be returned in @devstr and can be NULL, eg. when + * passing in one of the built-in controllers. The returned string must be + * freed by the caller. + * + * The number pointed to by @nusbcontroller will be increased by one every + * time the description for a USB controller has been generated successfully. + * + * Returns: 0 on success, <0 on failure + */ +int qemuBuildControllerDevStr(const virDomainDef *domainDef, virDomainControllerDefPtr def, virQEMUCapsPtr qemuCaps, + char **devstr, int *nusbcontroller) { virBuffer buf = VIR_BUFFER_INITIALIZER; int model = def->model; const char *modelName = NULL; + *devstr = NULL; + if (!qemuCheckCCWS390AddressSupport(domainDef, def->info, qemuCaps, "controller")) - return NULL; + return -1; if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { if ((qemuDomainSetSCSIControllerModel(domainDef, qemuCaps, &model)) < 0) - return NULL; + return -1; } if (!(def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI && @@ -2728,22 +2751,22 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, if (def->queues) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("'queues' is only supported by virtio-scsi controller")); - return NULL; + return -1; } if (def->cmd_per_lun) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("'cmd_per_lun' is only supported by virtio-scsi controller")); - return NULL; + return -1; } if (def->max_sectors) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("'max_sectors' is only supported by virtio-scsi controller")); - return NULL; + return -1; } if (def->ioeventfd) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("'ioeventfd' is only supported by virtio-scsi controller")); - return NULL; + return -1; } } @@ -3158,11 +3181,12 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, if (virBufferCheckError(&buf) < 0) goto error; - return virBufferContentAndReset(&buf); + *devstr = virBufferContentAndReset(&buf); + return 0; error: virBufferFreeAndReset(&buf); - return NULL; + return -1; } @@ -3257,12 +3281,15 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd, continue; } - virCommandAddArg(cmd, "-device"); - if (!(devstr = qemuBuildControllerDevStr(def, cont, qemuCaps, - &usbcontroller))) + if (qemuBuildControllerDevStr(def, cont, qemuCaps, + &devstr, &usbcontroller) < 0) return -1; - virCommandAddArg(cmd, devstr); - VIR_FREE(devstr); + + if (devstr) { + virCommandAddArg(cmd, "-device"); + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); + } } } diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index f5e3e5f..6fbfb3e 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -119,10 +119,11 @@ char *qemuBuildDriveDevStr(const virDomainDef *def, virQEMUCapsPtr qemuCaps); /* Current, best practice */ -char *qemuBuildControllerDevStr(const virDomainDef *domainDef, - virDomainControllerDefPtr def, - virQEMUCapsPtr qemuCaps, - int *nusbcontroller); +int qemuBuildControllerDevStr(const virDomainDef *domainDef, + virDomainControllerDefPtr def, + virQEMUCapsPtr qemuCaps, + char **devstr, + int *nusbcontroller); int qemuBuildMemoryBackendStr(virJSONValuePtr *backendProps, const char **backendType, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index d9259ab..8ca5054 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -523,7 +523,10 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, if (qemuAssignDeviceControllerAlias(vm->def, priv->qemuCaps, controller) < 0) goto cleanup; - if (!(devstr = qemuBuildControllerDevStr(vm->def, controller, priv->qemuCaps, NULL))) + if (qemuBuildControllerDevStr(vm->def, controller, priv->qemuCaps, &devstr, NULL) < 0) + goto cleanup; + + if (!devstr) goto cleanup; if (VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers+1) < 0) -- 2.7.5

Moving the check and rewriting it this way doesn't alter the current behavior, but will allow us to special-case pci-root down the line. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_command.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index ea2e63b..f79fbfc 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2874,6 +2874,26 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, case VIR_DOMAIN_CONTROLLER_TYPE_PCI: switch ((virDomainControllerModelPCI) def->model) { case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: + case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + if (def->idx == 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("index for pci controllers of model '%s' must be > 0"), + virDomainControllerModelPCITypeToString(def->model)); + goto error; + } + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + break; + } + switch ((virDomainControllerModelPCI) def->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: if (def->opts.pciopts.modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE || def->opts.pciopts.chassisNr == -1) { @@ -3132,12 +3152,6 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, _("wrong function called")); goto error; } - if (def->idx == 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("index for pci controllers of model '%s' must be > 0"), - virDomainControllerModelPCITypeToString(def->model)); - goto error; - } break; case VIR_DOMAIN_CONTROLLER_TYPE_IDE: -- 2.7.5

pSeries guests will soon be allowed to have multiple PHBs (pci-root controllers), which of course means that all but one of them will have a non-zero index; hence, we'll need to relax the current check. However, right now the check is performed in the conf module, which is generic rather than tied to the QEMU driver, and where we don't have information such as the guest machine type available. To make this change of behavior possible down the line, we need to move the check from the XML parser to the drivers. Luckily, only QEMU and bhyve are using PCI controllers, so this doesn't result in much duplication. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/bhyve/bhyve_domain.c | 15 +++++++++++++++ src/conf/domain_conf.c | 6 ------ src/qemu/qemu_domain.c | 9 +++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c index 20c8293..7176455 100644 --- a/src/bhyve/bhyve_domain.c +++ b/src/bhyve/bhyve_domain.c @@ -122,6 +122,21 @@ bhyveDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, bhyveDomainDiskDefAssignAddress(driver, disk, def) < 0) return -1; } + + if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) { + virDomainControllerDefPtr cont = dev->data.controller; + + if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && + (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) && + cont->idx != 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("pci-root and pcie-root controllers " + "should have index 0")); + return -1; + } + } + return 0; } diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index fdf85d5..29268a9 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9252,12 +9252,6 @@ virDomainControllerDefParseXML(xmlNodePtr node, "have an address")); goto error; } - if (def->idx > 0) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("pci-root and pcie-root controllers " - "should have index 0")); - goto error; - } if ((rc = virDomainParseScaledValue("./pcihole64", NULL, ctxt, &bytes, 1024, 1024ULL * ULONG_MAX, false)) < 0) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 8e7404d..928f121 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3425,6 +3425,15 @@ qemuDomainControllerDefPostParse(virDomainControllerDefPtr cont, break; case VIR_DOMAIN_CONTROLLER_TYPE_PCI: + if ((cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) && + cont->idx != 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("pci-root and pcie-root controllers " + "should have index 0")); + return -1; + } + if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS && !qemuDomainIsI440FX(def)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", -- 2.7.5

pSeries guests will soon be allowed to have multiple PHBs (pci-root controllers), meaning the current check on the controller index no longer applies to them. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_domain.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 928f121..a3ce10a 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3425,9 +3425,14 @@ qemuDomainControllerDefPostParse(virDomainControllerDefPtr cont, break; case VIR_DOMAIN_CONTROLLER_TYPE_PCI: - if ((cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || - cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) && - cont->idx != 0) { + + /* pSeries guests can have multiple pci-root controllers, + * but other machine types only support a single one */ + if (!qemuDomainIsPSeries(def) && + cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && + (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) && + cont->idx != 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("pci-root and pcie-root controllers " "should have index 0")); -- 2.7.5

Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatdomain.html.in | 5 +++++ docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 24 ++++++++++++++++++++++++ src/conf/domain_conf.h | 1 + 4 files changed, 35 insertions(+) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index a55a9e1..159c243 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3768,6 +3768,11 @@ libvirt API to attach host devices to the correct pci-expander-bus when assigning them to the domain). </dd> + <dt><code>index</code></dt> + <dd> + pci-root controllers for pSeries guests will use this attribute to + record the order they will show up in the guest. + </dd> </dl> <p> For machine types which provide an implicit PCI bus, the pci-root diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e259e3e..39eff46 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1997,6 +1997,11 @@ </attribute> </optional> <optional> + <attribute name='index'> + <ref name='uint8'/> + </attribute> + </optional> + <optional> <element name='node'> <ref name='unsignedInt'/> </element> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 29268a9..1538747 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1866,6 +1866,7 @@ virDomainControllerDefNew(virDomainControllerType type) def->opts.pciopts.chassis = -1; def->opts.pciopts.port = -1; def->opts.pciopts.busNr = -1; + def->opts.pciopts.idx = -1; def->opts.pciopts.numaNode = -1; break; case VIR_DOMAIN_CONTROLLER_TYPE_IDE: @@ -9099,6 +9100,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } def->idx = idxVal; + VIR_FREE(idx); } cur = node->children; @@ -9130,6 +9132,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, chassis = virXMLPropString(cur, "chassis"); port = virXMLPropString(cur, "port"); busNr = virXMLPropString(cur, "busNr"); + idx = virXMLPropString(cur, "index"); processedTarget = true; } } @@ -9348,6 +9351,23 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } } + if (idx) { + if (virStrToLong_i(idx, NULL, 0, + &def->opts.pciopts.idx) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid target index '%s' in PCI controller"), + idx); + goto error; + } + if (def->opts.pciopts.idx < 0 || + def->opts.pciopts.idx > 31) { + virReportError(VIR_ERR_XML_ERROR, + _("PCI controller target index '%s' out of " + "range - must be 0-31"), + idx); + goto error; + } + } if (numaNode >= 0) def->opts.pciopts.numaNode = numaNode; break; @@ -21748,6 +21768,7 @@ virDomainControllerDefFormat(virBufferPtr buf, def->opts.pciopts.chassis != -1 || def->opts.pciopts.port != -1 || def->opts.pciopts.busNr != -1 || + def->opts.pciopts.idx != -1 || def->opts.pciopts.numaNode != -1) { virBufferAddLit(&childBuf, "<target"); if (def->opts.pciopts.chassisNr != -1) @@ -21762,6 +21783,9 @@ virDomainControllerDefFormat(virBufferPtr buf, if (def->opts.pciopts.busNr != -1) virBufferAsprintf(&childBuf, " busNr='%d'", def->opts.pciopts.busNr); + if (def->opts.pciopts.idx != -1) + virBufferAsprintf(&childBuf, " index='%d'", + def->opts.pciopts.idx); if (def->opts.pciopts.numaNode == -1) { virBufferAddLit(&childBuf, "/>\n"); } else { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6d9ee97..53a10db 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -785,6 +785,7 @@ struct _virDomainPCIControllerOpts { int chassis; int port; int busNr; /* used by pci-expander-bus, -1 == unspecified */ + int idx; /* used by spapr-pci-host-bridge, -1 == unspecified */ /* numaNode is a *subelement* of target (to match existing * item in memory target config) -1 == unspecified */ -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatdomain.html.in | 5 +++++ docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 24 ++++++++++++++++++++++++ src/conf/domain_conf.h | 1 + 4 files changed, 35 insertions(+)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index a55a9e1..159c243 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3768,6 +3768,11 @@ libvirt API to attach host devices to the correct pci-expander-bus when assigning them to the domain). </dd> + <dt><code>index</code></dt> + <dd> + pci-root controllers for pSeries guests will use this attribute to + record the order they will show up in the guest.
I don't think you need the first occurence of the word "will" here - documentation should always read as if this is the way things are now, it's the way things have always been, and the way they always will be in the future (except the "Since x.y.z" tags). Aside from this, I'm still uncomfortable about the lack of new tests here, because my own experience is that new code is alsmot always incorrect until it's been run through some tests. But since you're remedying this problem in a later patch in the series, I'm okay with it. Reviewed-by: Laine Stump <laine@laine.org>
+ </dd> </dl> <p> For machine types which provide an implicit PCI bus, the pci-root diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e259e3e..39eff46 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1997,6 +1997,11 @@ </attribute> </optional> <optional> + <attribute name='index'> + <ref name='uint8'/> + </attribute> + </optional> + <optional> <element name='node'> <ref name='unsignedInt'/> </element> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 29268a9..1538747 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1866,6 +1866,7 @@ virDomainControllerDefNew(virDomainControllerType type) def->opts.pciopts.chassis = -1; def->opts.pciopts.port = -1; def->opts.pciopts.busNr = -1; + def->opts.pciopts.idx = -1; def->opts.pciopts.numaNode = -1; break; case VIR_DOMAIN_CONTROLLER_TYPE_IDE: @@ -9099,6 +9100,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } def->idx = idxVal; + VIR_FREE(idx); }
cur = node->children; @@ -9130,6 +9132,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, chassis = virXMLPropString(cur, "chassis"); port = virXMLPropString(cur, "port"); busNr = virXMLPropString(cur, "busNr"); + idx = virXMLPropString(cur, "index"); processedTarget = true; } } @@ -9348,6 +9351,23 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } } + if (idx) { + if (virStrToLong_i(idx, NULL, 0, + &def->opts.pciopts.idx) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid target index '%s' in PCI controller"), + idx); + goto error; + } + if (def->opts.pciopts.idx < 0 || + def->opts.pciopts.idx > 31) { + virReportError(VIR_ERR_XML_ERROR, + _("PCI controller target index '%s' out of " + "range - must be 0-31"), + idx); + goto error; + } + } if (numaNode >= 0) def->opts.pciopts.numaNode = numaNode; break; @@ -21748,6 +21768,7 @@ virDomainControllerDefFormat(virBufferPtr buf, def->opts.pciopts.chassis != -1 || def->opts.pciopts.port != -1 || def->opts.pciopts.busNr != -1 || + def->opts.pciopts.idx != -1 || def->opts.pciopts.numaNode != -1) { virBufferAddLit(&childBuf, "<target"); if (def->opts.pciopts.chassisNr != -1) @@ -21762,6 +21783,9 @@ virDomainControllerDefFormat(virBufferPtr buf, if (def->opts.pciopts.busNr != -1) virBufferAsprintf(&childBuf, " busNr='%d'", def->opts.pciopts.busNr); + if (def->opts.pciopts.idx != -1) + virBufferAsprintf(&childBuf, " index='%d'", + def->opts.pciopts.idx); if (def->opts.pciopts.numaNode == -1) { virBufferAddLit(&childBuf, "/>\n"); } else { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6d9ee97..53a10db 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -785,6 +785,7 @@ struct _virDomainPCIControllerOpts { int chassis; int port; int busNr; /* used by pci-expander-bus, -1 == unspecified */ + int idx; /* used by spapr-pci-host-bridge, -1 == unspecified */ /* numaNode is a *subelement* of target (to match existing * item in memory target config) -1 == unspecified */

On Fri, 2017-06-23 at 12:45 -0400, Laine Stump wrote:
+ <dt><code>index</code></dt> + <dd> + pci-root controllers for pSeries guests will use this attribute to + record the order they will show up in the guest. I don't think you need the first occurence of the word "will" here - documentation should always read as if this is the way things are now, it's the way things have always been, and the way they always will be in the future
It was not meant to indicate that the feature is not currently available or anything like that. It sounded good in my head and I still can't convince myself that's wrong, but you're the native speaker here :) Consider it gone.
(except the "Since x.y.z" tags).
Good point, I'd forgotten to include "Since 3.5.0" but I've added it now. -- Andrea Bolognani / Red Hat / Virtualization

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatdomain.html.in | 5 +++++ docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 24 ++++++++++++++++++++++++ src/conf/domain_conf.h | 1 + 4 files changed, 35 insertions(+)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index a55a9e1..159c243 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3768,6 +3768,11 @@ libvirt API to attach host devices to the correct pci-expander-bus when assigning them to the domain). </dd> + <dt><code>index</code></dt> + <dd> + pci-root controllers for pSeries guests will use this attribute to + record the order they will show up in the guest. + </dd> </dl> <p> For machine types which provide an implicit PCI bus, the pci-root diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e259e3e..39eff46 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1997,6 +1997,11 @@ </attribute> </optional> <optional> + <attribute name='index'> + <ref name='uint8'/> + </attribute> + </optional> + <optional> <element name='node'> <ref name='unsignedInt'/> </element> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 29268a9..1538747 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1866,6 +1866,7 @@ virDomainControllerDefNew(virDomainControllerType type) def->opts.pciopts.chassis = -1; def->opts.pciopts.port = -1; def->opts.pciopts.busNr = -1; + def->opts.pciopts.idx = -1; def->opts.pciopts.numaNode = -1; break; case VIR_DOMAIN_CONTROLLER_TYPE_IDE: @@ -9099,6 +9100,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } def->idx = idxVal; + VIR_FREE(idx); }
cur = node->children; @@ -9130,6 +9132,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, chassis = virXMLPropString(cur, "chassis"); port = virXMLPropString(cur, "port"); busNr = virXMLPropString(cur, "busNr"); + idx = virXMLPropString(cur, "index"); processedTarget = true; } } @@ -9348,6 +9351,23 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } } + if (idx) {
Oh wait - I thought you were going to rename this to targetIdx (both the locals and the member of the struct) to avoid confusion. So make my ACK conditional on that.
+ if (virStrToLong_i(idx, NULL, 0, + &def->opts.pciopts.idx) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid target index '%s' in PCI controller"), + idx); + goto error; + } + if (def->opts.pciopts.idx < 0 || + def->opts.pciopts.idx > 31) { + virReportError(VIR_ERR_XML_ERROR, + _("PCI controller target index '%s' out of " + "range - must be 0-31"), + idx); + goto error; + } + } if (numaNode >= 0) def->opts.pciopts.numaNode = numaNode; break; @@ -21748,6 +21768,7 @@ virDomainControllerDefFormat(virBufferPtr buf, def->opts.pciopts.chassis != -1 || def->opts.pciopts.port != -1 || def->opts.pciopts.busNr != -1 || + def->opts.pciopts.idx != -1 || def->opts.pciopts.numaNode != -1) { virBufferAddLit(&childBuf, "<target"); if (def->opts.pciopts.chassisNr != -1) @@ -21762,6 +21783,9 @@ virDomainControllerDefFormat(virBufferPtr buf, if (def->opts.pciopts.busNr != -1) virBufferAsprintf(&childBuf, " busNr='%d'", def->opts.pciopts.busNr); + if (def->opts.pciopts.idx != -1) + virBufferAsprintf(&childBuf, " index='%d'", + def->opts.pciopts.idx); if (def->opts.pciopts.numaNode == -1) { virBufferAddLit(&childBuf, "/>\n"); } else { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6d9ee97..53a10db 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -785,6 +785,7 @@ struct _virDomainPCIControllerOpts { int chassis; int port; int busNr; /* used by pci-expander-bus, -1 == unspecified */ + int idx; /* used by spapr-pci-host-bridge, -1 == unspecified */ /* numaNode is a *subelement* of target (to match existing * item in memory target config) -1 == unspecified */

On Sun, 2017-06-25 at 15:57 -0400, Laine Stump wrote:
@@ -9348,6 +9351,23 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } } + if (idx) { Oh wait - I thought you were going to rename this to targetIdx (both the locals and the member of the struct) to avoid confusion. So make my ACK conditional on that.
Yeah, that's a good idea. Consider it done. -- Andrea Bolognani / Red Hat / Virtualization

On Fri, Jun 23, 2017 at 8:33 PM, Andrea Bolognani <abologna@redhat.com> wrote:
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/formatdomain.html.in | 5 +++++ docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 24 ++++++++++++++++++++++++ src/conf/domain_conf.h | 1 + 4 files changed, 35 insertions(+)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index a55a9e1..159c243 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3768,6 +3768,11 @@ libvirt API to attach host devices to the correct pci-expander-bus when assigning them to the domain). </dd> + <dt><code>index</code></dt> + <dd> + pci-root controllers for pSeries guests will use this attribute to + record the order they will show up in the guest. + </dd> </dl> <p> For machine types which provide an implicit PCI bus, the pci-root diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e259e3e..39eff46 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1997,6 +1997,11 @@ </attribute> </optional> <optional> + <attribute name='index'> + <ref name='uint8'/> + </attribute> + </optional> + <optional> <element name='node'> <ref name='unsignedInt'/> </element> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 29268a9..1538747 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1866,6 +1866,7 @@ virDomainControllerDefNew(virDomainControllerType type) def->opts.pciopts.chassis = -1; def->opts.pciopts.port = -1; def->opts.pciopts.busNr = -1; + def->opts.pciopts.idx = -1; def->opts.pciopts.numaNode = -1; break; case VIR_DOMAIN_CONTROLLER_TYPE_IDE: @@ -9099,6 +9100,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } def->idx = idxVal; + VIR_FREE(idx); }
cur = node->children; @@ -9130,6 +9132,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, chassis = virXMLPropString(cur, "chassis"); port = virXMLPropString(cur, "port"); busNr = virXMLPropString(cur, "busNr"); + idx = virXMLPropString(cur, "index"); processedTarget = true; } } @@ -9348,6 +9351,23 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } } + if (idx) { + if (virStrToLong_i(idx, NULL, 0, + &def->opts.pciopts.idx) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid target index '%s' in PCI controller"), + idx); + goto error; + } + if (def->opts.pciopts.idx < 0 || + def->opts.pciopts.idx > 31) { + virReportError(VIR_ERR_XML_ERROR, + _("PCI controller target index '%s' out of " + "range - must be 0-31"), + idx); + goto error; + } + }
Better to enforce def->idx == 0 to have def->opts.pciopts.idx as 0 ? That would always assure def->idx == 0 as the implicit PHB. Qemu today allows "-device spapr-pci-host-bridge,index=X,id=pci.0" when X != 0, and we will generate it for implcit phb(which we normally dont) when def->opts.pciopts.idx != 0 in Patch 18. Not sure what all problems/confusions could come because of this inconsistency. if (numaNode >= 0)
def->opts.pciopts.numaNode = numaNode; break; @@ -21748,6 +21768,7 @@ virDomainControllerDefFormat(virBufferPtr buf, def->opts.pciopts.chassis != -1 || def->opts.pciopts.port != -1 || def->opts.pciopts.busNr != -1 || + def->opts.pciopts.idx != -1 || def->opts.pciopts.numaNode != -1) { virBufferAddLit(&childBuf, "<target"); if (def->opts.pciopts.chassisNr != -1) @@ -21762,6 +21783,9 @@ virDomainControllerDefFormat(virBufferPtr buf, if (def->opts.pciopts.busNr != -1) virBufferAsprintf(&childBuf, " busNr='%d'", def->opts.pciopts.busNr); + if (def->opts.pciopts.idx != -1) + virBufferAsprintf(&childBuf, " index='%d'", + def->opts.pciopts.idx); if (def->opts.pciopts.numaNode == -1) { virBufferAddLit(&childBuf, "/>\n"); } else { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6d9ee97..53a10db 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -785,6 +785,7 @@ struct _virDomainPCIControllerOpts { int chassis; int port; int busNr; /* used by pci-expander-bus, -1 == unspecified */ + int idx; /* used by spapr-pci-host-bridge, -1 == unspecified */ /* numaNode is a *subelement* of target (to match existing * item in memory target config) -1 == unspecified */ -- 2.7.5
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On Fri, 2017-06-30 at 17:10 +0530, Shivaprasad bhat wrote:
@@ -9348,6 +9351,23 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } } + if (idx) { + if (virStrToLong_i(idx, NULL, 0, + &def->opts.pciopts.idx) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid target index '%s' in PCI controller"), + idx); + goto error; + } + if (def->opts.pciopts.idx < 0 || + def->opts.pciopts.idx > 31) { + virReportError(VIR_ERR_XML_ERROR, + _("PCI controller target index '%s' out of " + "range - must be 0-31"), + idx); + goto error; + } + } Better to enforce def->idx == 0 to have def->opts.pciopts.idx as 0 ? That would always assure def->idx == 0 as the implicit PHB. Qemu today allows "-device spapr-pci-host-bridge,index=X,id=pci.0" when X != 0, and we will generate it for implcit phb(which we normally dont) when def->opts.pciopts.idx != 0 in Patch 18. Not sure what all problems/confusions could come because of this inconsistency.
Agreed. The attached patch should be squashed into this commit to prevent such a configuration from being accepted. I'm also working on a test case for this specific configuration. Laine, are you okay with me squashing this in and keeping the Reviewed-by? -- Andrea Bolognani / Red Hat / Virtualization

On 07/04/2017 07:32 AM, Andrea Bolognani wrote:
On Fri, 2017-06-30 at 17:10 +0530, Shivaprasad bhat wrote:
@@ -9348,6 +9351,23 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } } + if (idx) { + if (virStrToLong_i(idx, NULL, 0, + &def->opts.pciopts.idx) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid target index '%s' in PCI controller"), + idx); + goto error; + } + if (def->opts.pciopts.idx < 0 || + def->opts.pciopts.idx > 31) { + virReportError(VIR_ERR_XML_ERROR, + _("PCI controller target index '%s' out of " + "range - must be 0-31"), + idx); + goto error; + } + }
Better to enforce def->idx == 0 to have def->opts.pciopts.idx as 0 ? That would always assure def->idx == 0 as the implicit PHB.
Qemu today allows "-device spapr-pci-host-bridge,index=X,id=pci.0" when X != 0, and we will generate it for implcit phb(which we normally dont) when def->opts.pciopts.idx != 0 in Patch 18. Not sure what all problems/confusions could come because of this inconsistency.
Agreed.
The attached patch should be squashed into this commit to prevent such a configuration from being accepted. I'm also working on a test case for this specific configuration.
Laine, are you okay with me squashing this in and keeping the Reviewed-by?
Sure, that's fine with me.

Adding it to the virDomainControllerPCIModelName enumeration is enough for existing code to handle it, so parsing and formatting will work without further tweaking. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/schemas/domaincommon.rng | 2 ++ src/conf/domain_conf.c | 1 + src/conf/domain_conf.h | 1 + 3 files changed, 4 insertions(+) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 39eff46..73343a5 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1954,6 +1954,8 @@ <element name="model"> <attribute name="name"> <choice> + <!-- implementations of 'pci-root' --> + <value>spapr-pci-host-bridge</value> <!-- implementations of 'pci-bridge' --> <value>pci-bridge</value> <!-- implementations of 'dmi-to-pci-bridge' --> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1538747..6afcbe7 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -349,6 +349,7 @@ VIR_ENUM_IMPL(virDomainControllerPCIModelName, "pxb", "pxb-pcie", "pcie-root-port", + "spapr-pci-host-bridge", ); VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 53a10db..b3699e7 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -710,6 +710,7 @@ typedef enum { VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCIE_ROOT_PORT, + VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST } virDomainControllerPCIModelName; -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
Adding it to the virDomainControllerPCIModelName enumeration is enough for existing code to handle it, so parsing and formatting will work without further tweaking.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Laine Stump <laine@laine.org> (assuming you document it in one of these other patches)
--- docs/schemas/domaincommon.rng | 2 ++ src/conf/domain_conf.c | 1 + src/conf/domain_conf.h | 1 + 3 files changed, 4 insertions(+)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 39eff46..73343a5 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1954,6 +1954,8 @@ <element name="model"> <attribute name="name"> <choice> + <!-- implementations of 'pci-root' --> + <value>spapr-pci-host-bridge</value> <!-- implementations of 'pci-bridge' --> <value>pci-bridge</value> <!-- implementations of 'dmi-to-pci-bridge' --> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1538747..6afcbe7 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -349,6 +349,7 @@ VIR_ENUM_IMPL(virDomainControllerPCIModelName, "pxb", "pxb-pcie", "pcie-root-port", + "spapr-pci-host-bridge", );
VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 53a10db..b3699e7 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -710,6 +710,7 @@ typedef enum { VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCIE_ROOT_PORT, + VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE,
VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST } virDomainControllerPCIModelName;

On Sun, 2017-06-25 at 09:55 -0400, Laine Stump wrote:
Adding it to the virDomainControllerPCIModelName enumeration is enough for existing code to handle it, so parsing and formatting will work without further tweaking. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> (assuming you document it in one of these other patches)
How exactly would you like it to be documented? I looked into it before sending out v3 and found out that formatdomain.html already contains the following text: PCI controllers also have an optional subelement <model> with an attribute name. The name attribute holds the name of the specific device that qemu is emulating (e.g. "i82801b11-bridge") rather than simply the class of device ("dmi-to-pci-bridge", "pci-bridge"), which is set in the controller element's model attribute. In almost all cases, you should not manually add a <model> subelement to a controller, nor should you modify one that is automatically generated by libvirt. Since 1.2.19 (QEMU only). So that about covers it, doesn't it? In fact, other existing concrete controller models such as ioh3240 are not mentioned at all. -- Andrea Bolognani / Red Hat / Virtualization

On 06/26/2017 01:25 AM, Andrea Bolognani wrote:
On Sun, 2017-06-25 at 09:55 -0400, Laine Stump wrote:
Adding it to the virDomainControllerPCIModelName enumeration is enough for existing code to handle it, so parsing and formatting will work without further tweaking.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Laine Stump <laine@laine.org>
(assuming you document it in one of these other patches)
How exactly would you like it to be documented?
I looked into it before sending out v3 and found out that formatdomain.html already contains the following text:
PCI controllers also have an optional subelement <model> with an attribute name. The name attribute holds the name of the specific device that qemu is emulating (e.g. "i82801b11-bridge") rather than simply the class of device ("dmi-to-pci-bridge", "pci-bridge"), which is set in the controller element's model attribute. In almost all cases, you should not manually add a <model> subelement to a controller, nor should you modify one that is automatically generated by libvirt. Since 1.2.19 (QEMU only).
So that about covers it, doesn't it? In fact, other existing concrete controller models such as ioh3240 are not mentioned at all.
Hmm. I guess I must have decided not to document the exact model names because 1) they are hypervisor-specific, and 2) nobody should ever need to modify them. Since the others aren't documented, I guess you shouldn't document this one either. (Maybe someone will decide they should all be documented and post a patch for that).

pSeries guests will soon need the new information; luckily, we can figure it out automatically most of the time, so users won't have to worry about it. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_domain_address.c | 88 +++++++++++++++++++++- .../qemuargv2xmldata/qemuargv2xml-pseries-disk.xml | 5 +- .../qemuargv2xml-pseries-nvram.xml | 5 +- .../qemuxml2xmlout-panic-pseries.xml | 5 +- .../qemuxml2xmlout-ppc64-usb-controller-legacy.xml | 5 +- .../qemuxml2xmlout-ppc64-usb-controller.xml | 5 +- .../qemuxml2xmlout-pseries-nvram.xml | 5 +- .../qemuxml2xmlout-pseries-panic-missing.xml | 5 +- .../qemuxml2xmlout-pseries-panic-no-address.xml | 5 +- 9 files changed, 118 insertions(+), 10 deletions(-) diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index b5b863f..960ea04 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1861,6 +1861,7 @@ qemuDomainSupportsPCI(virDomainDefPtr def, static void qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont, + virDomainDefPtr def, virQEMUCapsPtr qemuCaps) { int *modelName = &cont->opts.pciopts.modelName; @@ -1897,6 +1898,9 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont, *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + if (qemuDomainIsPSeries(def)) + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE; + break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: break; @@ -1904,6 +1908,63 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont, } +/** + * qemuDomainAddressFindNewTargetIndex: + * @def: domain definition + * + * Find a target index that can be used for a PCI controller. + * + * Returns: an unused target index, or -1 if all available target + * indexes are already taken. + */ +static int +qemuDomainAddressFindNewTargetIndex(virDomainDefPtr def) +{ + int idx; + int ret = -1; + + /* Try all indexes between 1 and 31 - QEMU only supports 32 + * PHBs, and 0 is reserved for the default, implicit one */ + for (idx = 1; idx <= 31; idx++) { + bool found = false; + size_t i; + + for (i = 0; i < def->ncontrollers; i++) { + virDomainControllerDefPtr cont = def->controllers[i]; + virDomainPCIControllerOptsPtr opts; + + /* We only care about pci-root controllers */ + if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI || + cont->model != VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) { + continue; + } + + opts = &cont->opts.pciopts; + + /* More specifically, we only care about PHBs */ + if (opts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) + continue; + + /* Stop looking as soon as we find a PHB that's + * already using this specific target index */ + if (opts->idx == idx) { + found = true; + break; + } + } + + /* If no existing PCI controller uses this index, great, + * it means it's free and we can return it to the caller */ + if (!found) { + ret = idx; + break; + } + } + + return ret; +} + + static int qemuDomainAddressFindNewBusNr(virDomainDefPtr def) { @@ -2164,7 +2225,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, * device in qemu) for any controller that doesn't yet * have it set. */ - qemuDomainPCIControllerSetDefaultModelName(cont, qemuCaps); + qemuDomainPCIControllerSetDefaultModelName(cont, def, qemuCaps); /* set defaults for any other auto-generated config * options for this controller that haven't been @@ -2201,9 +2262,32 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, goto cleanup; } break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + if (!qemuDomainIsPSeries(def)) + break; + if (options->idx == -1) { + if (cont->idx == 0) { + /* The pci-root controller with controller index 0 + * must always be assigned target index 0, because + * it represents the implicit PHB which is treated + * differently than all other PHBs */ + options->idx = 0; + } else { + /* For all other PHBs the target index doesn't need + * to match the controller index or have any + * particular value, really */ + options->idx = qemuDomainAddressFindNewTargetIndex(def); + } + } + if (options->idx == -1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("No usable target index found for %d"), + addr->bus); + goto cleanup; + } + break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: break; diff --git a/tests/qemuargv2xmldata/qemuargv2xml-pseries-disk.xml b/tests/qemuargv2xmldata/qemuargv2xml-pseries-disk.xml index 1bad8ee..601d0f7 100644 --- a/tests/qemuargv2xmldata/qemuargv2xml-pseries-disk.xml +++ b/tests/qemuargv2xmldata/qemuargv2xml-pseries-disk.xml @@ -30,7 +30,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <controller type='scsi' index='0'> <address type='spapr-vio' reg='0x2000'/> </controller> diff --git a/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml b/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml index 7e9f864..7787847 100644 --- a/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml +++ b/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml @@ -17,7 +17,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <memballoon model='none'/> <nvram> <address type='spapr-vio' reg='0x4000'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml index 1ed11ce..7fb49fe 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml @@ -17,7 +17,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <serial type='pty'> <target port='0'/> <address type='spapr-vio' reg='0x30000000'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml index b7bde24..673b81d 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml @@ -22,7 +22,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <memballoon model='virtio'> <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </memballoon> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml index 82aaaca..68995a9 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml @@ -22,7 +22,10 @@ <controller type='usb' index='0' model='pci-ohci'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <memballoon model='virtio'> <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </memballoon> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml index 713f31c..f89b23b 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml @@ -17,7 +17,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <memballoon model='none'/> <nvram> <address type='spapr-vio' reg='0x4000'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml index 1ed11ce..7fb49fe 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml @@ -17,7 +17,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <serial type='pty'> <target port='0'/> <address type='spapr-vio' reg='0x30000000'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml index 1ed11ce..7fb49fe 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml @@ -17,7 +17,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <serial type='pty'> <target port='0'/> <address type='spapr-vio' reg='0x30000000'/> -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
pSeries guests will soon need the new information; luckily, we can figure it out automatically most of the time, so users won't have to worry about it.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Laine Stump <laine@laine.org> (assuming name change from idx to targetIdx in all appropriate places)
--- src/qemu/qemu_domain_address.c | 88 +++++++++++++++++++++- .../qemuargv2xmldata/qemuargv2xml-pseries-disk.xml | 5 +- .../qemuargv2xml-pseries-nvram.xml | 5 +- .../qemuxml2xmlout-panic-pseries.xml | 5 +- .../qemuxml2xmlout-ppc64-usb-controller-legacy.xml | 5 +- .../qemuxml2xmlout-ppc64-usb-controller.xml | 5 +- .../qemuxml2xmlout-pseries-nvram.xml | 5 +- .../qemuxml2xmlout-pseries-panic-missing.xml | 5 +- .../qemuxml2xmlout-pseries-panic-no-address.xml | 5 +- 9 files changed, 118 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index b5b863f..960ea04 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1861,6 +1861,7 @@ qemuDomainSupportsPCI(virDomainDefPtr def,
static void qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont, + virDomainDefPtr def, virQEMUCapsPtr qemuCaps) { int *modelName = &cont->opts.pciopts.modelName; @@ -1897,6 +1898,9 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont, *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + if (qemuDomainIsPSeries(def)) + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE; + break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: break; @@ -1904,6 +1908,63 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont, }
+/** + * qemuDomainAddressFindNewTargetIndex: + * @def: domain definition + * + * Find a target index that can be used for a PCI controller. + * + * Returns: an unused target index, or -1 if all available target + * indexes are already taken. + */ +static int +qemuDomainAddressFindNewTargetIndex(virDomainDefPtr def) +{ + int idx; + int ret = -1; + + /* Try all indexes between 1 and 31 - QEMU only supports 32 + * PHBs, and 0 is reserved for the default, implicit one */ + for (idx = 1; idx <= 31; idx++) { + bool found = false; + size_t i; + + for (i = 0; i < def->ncontrollers; i++) { + virDomainControllerDefPtr cont = def->controllers[i]; + virDomainPCIControllerOptsPtr opts; + + /* We only care about pci-root controllers */ + if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI || + cont->model != VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) { + continue; + } + + opts = &cont->opts.pciopts; + + /* More specifically, we only care about PHBs */ + if (opts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) + continue; + + /* Stop looking as soon as we find a PHB that's + * already using this specific target index */ + if (opts->idx == idx) { + found = true; + break; + } + } + + /* If no existing PCI controller uses this index, great, + * it means it's free and we can return it to the caller */ + if (!found) { + ret = idx; + break; + } + } + + return ret; +} + + static int qemuDomainAddressFindNewBusNr(virDomainDefPtr def) { @@ -2164,7 +2225,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, * device in qemu) for any controller that doesn't yet * have it set. */ - qemuDomainPCIControllerSetDefaultModelName(cont, qemuCaps); + qemuDomainPCIControllerSetDefaultModelName(cont, def, qemuCaps);
/* set defaults for any other auto-generated config * options for this controller that haven't been @@ -2201,9 +2262,32 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, goto cleanup; } break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + if (!qemuDomainIsPSeries(def)) + break; + if (options->idx == -1) { + if (cont->idx == 0) { + /* The pci-root controller with controller index 0 + * must always be assigned target index 0, because + * it represents the implicit PHB which is treated + * differently than all other PHBs */ + options->idx = 0; + } else { + /* For all other PHBs the target index doesn't need + * to match the controller index or have any + * particular value, really */ + options->idx = qemuDomainAddressFindNewTargetIndex(def); + } + } + if (options->idx == -1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("No usable target index found for %d"), + addr->bus); + goto cleanup; + } + break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: break; diff --git a/tests/qemuargv2xmldata/qemuargv2xml-pseries-disk.xml b/tests/qemuargv2xmldata/qemuargv2xml-pseries-disk.xml index 1bad8ee..601d0f7 100644 --- a/tests/qemuargv2xmldata/qemuargv2xml-pseries-disk.xml +++ b/tests/qemuargv2xmldata/qemuargv2xml-pseries-disk.xml @@ -30,7 +30,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <controller type='scsi' index='0'> <address type='spapr-vio' reg='0x2000'/> </controller> diff --git a/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml b/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml index 7e9f864..7787847 100644 --- a/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml +++ b/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml @@ -17,7 +17,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <memballoon model='none'/> <nvram> <address type='spapr-vio' reg='0x4000'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml index 1ed11ce..7fb49fe 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml @@ -17,7 +17,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <serial type='pty'> <target port='0'/> <address type='spapr-vio' reg='0x30000000'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml index b7bde24..673b81d 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml @@ -22,7 +22,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <memballoon model='virtio'> <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </memballoon> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml index 82aaaca..68995a9 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml @@ -22,7 +22,10 @@ <controller type='usb' index='0' model='pci-ohci'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <memballoon model='virtio'> <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </memballoon> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml index 713f31c..f89b23b 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml @@ -17,7 +17,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <memballoon model='none'/> <nvram> <address type='spapr-vio' reg='0x4000'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml index 1ed11ce..7fb49fe 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml @@ -17,7 +17,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <serial type='pty'> <target port='0'/> <address type='spapr-vio' reg='0x30000000'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml index 1ed11ce..7fb49fe 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml @@ -17,7 +17,10 @@ <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> - <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> <serial type='pty'> <target port='0'/> <address type='spapr-vio' reg='0x30000000'/>

On Sun, 2017-06-25 at 16:00 -0400, Laine Stump wrote:
Reviewed-by: Laine Stump <laine@laine.org> (assuming name change from idx to targetIdx in all appropriate places)
I used 'targetIndex' instead, hopefully that doesn't invalidate the R-b :) -- Andrea Bolognani / Red Hat / Virtualization

+/** + * qemuDomainAddressFindNewTargetIndex: + * @def: domain definition + * + * Find a target index that can be used for a PCI controller. + * + * Returns: an unused target index, or -1 if all available target + * indexes are already taken. + */ +static int +qemuDomainAddressFindNewTargetIndex(virDomainDefPtr def)
May be rename to qemuDomainAddressFindNewPCIRootTargetIndex ? +{
+ int idx; + int ret = -1; + + /* Try all indexes between 1 and 31 - QEMU only supports 32 + * PHBs, and 0 is reserved for the default, implicit one */ + for (idx = 1; idx <= 31; idx++) { + bool found = false; + size_t i;

On Mon, 2017-06-26 at 14:19 +0530, Shivaprasad bhat wrote:
+/** + * qemuDomainAddressFindNewTargetIndex: + * @def: domain definition + * + * Find a target index that can be used for a PCI controller. + * + * Returns: an unused target index, or -1 if all available target + * indexes are already taken. + */ +static int +qemuDomainAddressFindNewTargetIndex(virDomainDefPtr def) May be rename to qemuDomainAddressFindNewPCIRootTargetIndex ?
The name's pretty long as it is, but you're right that the function is only called for PCI Root controllers and embeds knowledge about spapr-pci-host-bridge. I'll think about it. -- Andrea Bolognani / Red Hat / Virtualization

This new capability can be used to detect whether a QEMU binary supports the spapr-pci-host-bridge controller. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 1 + 3 files changed, 4 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 61c9a10..dc87b5d 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -430,6 +430,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "virtio.iommu_platform", "virtio.ats", "loadparm", + "spapr-pci-host-bridge", ); @@ -1679,6 +1680,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "nvdimm", QEMU_CAPS_DEVICE_NVDIMM }, { "pcie-root-port", QEMU_CAPS_DEVICE_PCIE_ROOT_PORT }, { "qemu-xhci", QEMU_CAPS_DEVICE_QEMU_XHCI }, + { "spapr-pci-host-bridge", QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE }, }; static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 6e95876..fd6de28 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -416,6 +416,7 @@ typedef enum { QEMU_CAPS_VIRTIO_PCI_IOMMU_PLATFORM, /* virtio-*-pci.iommu_platform */ QEMU_CAPS_VIRTIO_PCI_ATS, /* virtio-*-pci.ats */ QEMU_CAPS_LOADPARM, /* -machine loadparm */ + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, /* -device spapr-pci-host-bridge */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml index 425992f..7fa652a 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml @@ -164,6 +164,7 @@ <flag name='query-named-block-nodes'/> <flag name='kernel-irqchip'/> <flag name='kernel-irqchip.split'/> + <flag name='spapr-pci-host-bridge'/> <version>2006000</version> <kvmVersion>0</kvmVersion> <package></package> -- 2.7.5

Usually, a controller with alias 'x' will create a bus with the same name; however, the bus created by a PHBs with alias 'x' will be named 'x.0' instead, so we need to account for that. As an exception to the exception, the implicit PHB that's added automatically to every pSeries guest creates the 'pci.0' bus. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_command.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f79fbfc..dba2519 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -302,6 +302,9 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, int ret = -1; char *devStr = NULL; const char *contAlias = NULL; + virDomainControllerModelPCI contModel; + virDomainControllerPCIModelName contModelName; + int contIndex; if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { size_t i; @@ -314,6 +317,9 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && cont->idx == info->addr.pci.bus) { contAlias = cont->info.alias; + contModel = cont->model; + contModelName = cont->opts.pciopts.modelName; + contIndex = cont->opts.pciopts.idx; if (!contAlias) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Device alias was not set for PCI " @@ -349,7 +355,19 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, } } - virBufferAsprintf(buf, ",bus=%s", contAlias); + if (contModel == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT && + contModelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE && + contIndex > 0) { + /* The PCI bus created by a spapr-pci-host-bridge device with + * alias 'x' will be called 'x.0' rather than 'x'; however, + * this does not apply to the implicit PHB in a pSeries guest, + * which always has the hardcoded name 'pci.0' */ + virBufferAsprintf(buf, ",bus=%s.0", contAlias); + } else { + /* For all other controllers, the bus name matches the alias + * of the corresponding controller */ + virBufferAsprintf(buf, ",bus=%s", contAlias); + } if (info->addr.pci.multi == VIR_TRISTATE_SWITCH_ON) virBufferAddLit(buf, ",multifunction=on"); -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
Usually, a controller with alias 'x' will create a bus with the same name; however, the bus created by a PHBs with alias 'x' will be named 'x.0' instead, so we need to account for that.
As an exception to the exception, the implicit PHB that's added automatically to every pSeries guest creates the 'pci.0' bus.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Sigh. Words can't even describe my feelings. Nothing else you can do about it though. Reviewed-by: Laine Stump <laine@laine.org>
--- src/qemu/qemu_command.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f79fbfc..dba2519 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -302,6 +302,9 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, int ret = -1; char *devStr = NULL; const char *contAlias = NULL; + virDomainControllerModelPCI contModel; + virDomainControllerPCIModelName contModelName; + int contIndex;
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { size_t i; @@ -314,6 +317,9 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && cont->idx == info->addr.pci.bus) { contAlias = cont->info.alias; + contModel = cont->model; + contModelName = cont->opts.pciopts.modelName; + contIndex = cont->opts.pciopts.idx; if (!contAlias) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Device alias was not set for PCI " @@ -349,7 +355,19 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, } }
- virBufferAsprintf(buf, ",bus=%s", contAlias); + if (contModel == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT && + contModelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE && + contIndex > 0) { + /* The PCI bus created by a spapr-pci-host-bridge device with + * alias 'x' will be called 'x.0' rather than 'x'; however, + * this does not apply to the implicit PHB in a pSeries guest, + * which always has the hardcoded name 'pci.0' */ + virBufferAsprintf(buf, ",bus=%s.0", contAlias); + } else { + /* For all other controllers, the bus name matches the alias + * of the corresponding controller */ + virBufferAsprintf(buf, ",bus=%s", contAlias); + }
if (info->addr.pci.multi == VIR_TRISTATE_SWITCH_ON) virBufferAddLit(buf, ",multifunction=on");

Additional PHBs (pci-root controllers) will be created for the guest using the spapr-pci-host-bridge QEMU device, if available; the implicit default PHB, while present in the guest configuration, will be skipped. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1431193 Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_command.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index dba2519..fb0beed 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3164,6 +3164,40 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, def->opts.pciopts.numaNode); break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + if (def->opts.pciopts.modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE || + def->opts.pciopts.idx == -1) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("autogenerated pci-root options not set")); + goto error; + } + + /* Skip the implicit one */ + if (def->opts.pciopts.idx == 0) + goto done; + + modelName = virDomainControllerPCIModelNameTypeToString(def->opts.pciopts.modelName); + if (!modelName) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown pci-root model name value %d"), + def->opts.pciopts.modelName); + goto error; + } + if (def->opts.pciopts.modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("PCI controller model name '%s' is not valid for a pci-root"), + modelName); + goto error; + } + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("the spapr-pci-host-bridge controller " + "is not supported in this QEMU binary")); + goto error; + } + virBufferAsprintf(&buf, "%s,index=%d,id=%s", + modelName, def->opts.pciopts.idx, + def->info.alias); + break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -3213,6 +3247,7 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, if (virBufferCheckError(&buf) < 0) goto error; + done: *devstr = virBufferContentAndReset(&buf); return 0; @@ -3270,10 +3305,16 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd, continue; } - /* skip pci-root/pcie-root */ + /* skip pcie-root */ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && - (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || - cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)) + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) + continue; + + /* Skip pci-root, except for pSeries guests (which actually + * support more than one PCI Host Bridge per guest) */ + if (!qemuDomainIsPSeries(def) && + cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) continue; /* first SATA controller on Q35 machines is implicit */ -- 2.7.5

The subject line implies (to me) that this patch somehow automagically creates multiple PHBs for the domain. It looks like what it does is to add the proper commandline args to the qemu command when multiple PHBs have already been added to the config. As for the functionality: Reviewed-by: Laine Stump <laine@laine.org> On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
Additional PHBs (pci-root controllers) will be created for the guest using the spapr-pci-host-bridge QEMU device, if available; the implicit default PHB, while present in the guest configuration, will be skipped.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1431193
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_command.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index dba2519..fb0beed 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3164,6 +3164,40 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, def->opts.pciopts.numaNode); break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + if (def->opts.pciopts.modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE || + def->opts.pciopts.idx == -1) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("autogenerated pci-root options not set")); + goto error; + } + + /* Skip the implicit one */ + if (def->opts.pciopts.idx == 0) + goto done; + + modelName = virDomainControllerPCIModelNameTypeToString(def->opts.pciopts.modelName); + if (!modelName) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown pci-root model name value %d"), + def->opts.pciopts.modelName); + goto error; + } + if (def->opts.pciopts.modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("PCI controller model name '%s' is not valid for a pci-root"), + modelName); + goto error; + } + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("the spapr-pci-host-bridge controller " + "is not supported in this QEMU binary")); + goto error; + } + virBufferAsprintf(&buf, "%s,index=%d,id=%s", + modelName, def->opts.pciopts.idx, + def->info.alias); + break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -3213,6 +3247,7 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, if (virBufferCheckError(&buf) < 0) goto error;
+ done: *devstr = virBufferContentAndReset(&buf); return 0;
@@ -3270,10 +3305,16 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd, continue; }
- /* skip pci-root/pcie-root */ + /* skip pcie-root */ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && - (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || - cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)) + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) + continue; + + /* Skip pci-root, except for pSeries guests (which actually + * support more than one PCI Host Bridge per guest) */ + if (!qemuDomainIsPSeries(def) && + cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) continue;
/* first SATA controller on Q35 machines is implicit */

On Mon, 2017-06-26 at 22:00 -0400, Laine Stump wrote:
The subject line implies (to me) that this patch somehow automagically creates multiple PHBs for the domain. It looks like what it does is to add the proper commandline args to the qemu command when multiple PHBs have already been added to the config.
Would qemu: Format PHBs on the command line be better? -- Andrea Bolognani / Red Hat / Virtualization

Hi Andrea, We need to also adjust the memlock limits along with this patch. I have the changes here if you want to append to this patch. https://paste.fedoraproject.org/paste/JrI4stQTIYiaecuXPyXh8g Thanks, Shivaprasad On Fri, Jun 23, 2017 at 8:33 PM, Andrea Bolognani <abologna@redhat.com> wrote:
Additional PHBs (pci-root controllers) will be created for the guest using the spapr-pci-host-bridge QEMU device, if available; the implicit default PHB, while present in the guest configuration, will be skipped.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1431193
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_command.c | 47 ++++++++++++++++++++++++++++++ ++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index dba2519..fb0beed 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3164,6 +3164,40 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, def->opts.pciopts.numaNode); break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + if (def->opts.pciopts.modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE || + def->opts.pciopts.idx == -1) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("autogenerated pci-root options not set")); + goto error; + } + + /* Skip the implicit one */ + if (def->opts.pciopts.idx == 0) + goto done; + + modelName = virDomainControllerPCIModelNam eTypeToString(def->opts.pciopts.modelName); + if (!modelName) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown pci-root model name value %d"), + def->opts.pciopts.modelName); + goto error; + } + if (def->opts.pciopts.modelName != VIR_DOMAIN_CONTROLLER_PCI_ MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("PCI controller model name '%s' is not valid for a pci-root"), + modelName); + goto error; + } + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("the spapr-pci-host-bridge controller " + "is not supported in this QEMU binary")); + goto error; + } + virBufferAsprintf(&buf, "%s,index=%d,id=%s", + modelName, def->opts.pciopts.idx, + def->info.alias); + break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -3213,6 +3247,7 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, if (virBufferCheckError(&buf) < 0) goto error;
+ done: *devstr = virBufferContentAndReset(&buf); return 0;
@@ -3270,10 +3305,16 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd, continue; }
- /* skip pci-root/pcie-root */ + /* skip pcie-root */ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && - (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || - cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)) + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) + continue; + + /* Skip pci-root, except for pSeries guests (which actually + * support more than one PCI Host Bridge per guest) */ + if (!qemuDomainIsPSeries(def) && + cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) continue;
/* first SATA controller on Q35 machines is implicit */ -- 2.7.5
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On Tue, 2017-06-27 at 13:53 +0530, Shivaprasad bhat wrote:
Hi Andrea, We need to also adjust the memlock limits along with this patch.
Good point. I must have remembered about that at least five during development of the feature - and then promptly forgotten just as many times :/
I have the changes here if you want to append to this patch. https://paste.fedoraproject.org/paste/JrI4stQTIYiaecuXPyXh8g
Please send this as a proper patch, mentioning that it's meant to be applied on top of my series. -- Andrea Bolognani / Red Hat / Virtualization

On Thu, Jun 29, 2017 at 1:03 PM, Andrea Bolognani <abologna@redhat.com> wrote:
On Tue, 2017-06-27 at 13:53 +0530, Shivaprasad bhat wrote:
Hi Andrea,
We need to also adjust the memlock limits along with this patch.
Good point. I must have remembered about that at least five during development of the feature - and then promptly forgotten just as many times :/
I guessed so.. :)
I have the changes here if you want to append to this patch.
https://paste.fedoraproject.org/paste/JrI4stQTIYiaecuXPyXh8g
Please send this as a proper patch, mentioning that it's meant to be applied on top of my series.
Just sent the patch. Thanks, Shivaprasad --
Andrea Bolognani / Red Hat / Virtualization

Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- .../qemuxml2argv-pseries-phb-default-missing.args | 22 +++++++++++++++ .../qemuxml2argv-pseries-phb-default-missing.xml | 16 +++++++++++ .../qemuxml2argv-pseries-phb-simple.args | 22 +++++++++++++++ .../qemuxml2argv-pseries-phb-simple.xml | 17 +++++++++++ tests/qemuxml2argvtest.c | 8 ++++++ .../qemuxml2xmlout-pseries-phb-default-missing.xml | 33 ++++++++++++++++++++++ .../qemuxml2xmlout-pseries-phb-simple.xml | 33 ++++++++++++++++++++++ tests/qemuxml2xmltest.c | 7 +++++ 8 files changed, 158 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-default-missing.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-simple.xml diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args new file mode 100644 index 0000000..009f5a8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args @@ -0,0 +1,22 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name QEMUGuest1 \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device spapr-pci-host-bridge,index=2,id=pci.2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml new file mode 100644 index 0000000..d0b45bf --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml @@ -0,0 +1,16 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <controller type='pci' index='1' model='pci-root'/> + <controller type='pci' index='2' model='pci-root'/> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args new file mode 100644 index 0000000..009f5a8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args @@ -0,0 +1,22 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name QEMUGuest1 \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device spapr-pci-host-bridge,index=2,id=pci.2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml new file mode 100644 index 0000000..b1c6ff3 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml @@ -0,0 +1,17 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <controller type='pci' model='pci-root'/> + <controller type='pci' model='pci-root'/> + <controller type='pci' model='pci-root'/> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 01c0a65..ff68884 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1709,6 +1709,14 @@ mymain(void) QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST_FAILURE("pseries-panic-address", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); + + DO_TEST("pseries-phb-simple", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); + DO_TEST("pseries-phb-default-missing", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); + DO_TEST("disk-ide-drive-split", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_IDE_CD); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-default-missing.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-default-missing.xml new file mode 100644 index 0000000..62708b4 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-default-missing.xml @@ -0,0 +1,33 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> + </controller> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-simple.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-simple.xml new file mode 100644 index 0000000..2c1e64e --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-simple.xml @@ -0,0 +1,33 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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'/> + </controller> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> + </controller> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> + </controller> + <controller type='usb' index='0' model='none'/> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index c74614c..a0a846c 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -676,6 +676,13 @@ mymain(void) DO_TEST("pseries-panic-missing", NONE); DO_TEST("pseries-panic-no-address", NONE); + DO_TEST("pseries-phb-simple", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); + DO_TEST("pseries-phb-default-missing", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); + DO_TEST("balloon-device-auto", NONE); DO_TEST("balloon-device-period", NONE); DO_TEST("channel-virtio-auto", NONE); -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- .../qemuxml2argv-pseries-phb-default-missing.args | 22 +++++++++++++++ .../qemuxml2argv-pseries-phb-default-missing.xml | 16 +++++++++++ .../qemuxml2argv-pseries-phb-simple.args | 22 +++++++++++++++ .../qemuxml2argv-pseries-phb-simple.xml | 17 +++++++++++ tests/qemuxml2argvtest.c | 8 ++++++ .../qemuxml2xmlout-pseries-phb-default-missing.xml | 33 ++++++++++++++++++++++ .../qemuxml2xmlout-pseries-phb-simple.xml | 33 ++++++++++++++++++++++ tests/qemuxml2xmltest.c | 7 +++++ 8 files changed, 158 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-default-missing.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-simple.xml
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args new file mode 100644 index 0000000..009f5a8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args @@ -0,0 +1,22 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name QEMUGuest1 \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device spapr-pci-host-bridge,index=2,id=pci.2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml new file mode 100644 index 0000000..d0b45bf --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml @@ -0,0 +1,16 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <controller type='pci' index='1' model='pci-root'/> + <controller type='pci' index='2' model='pci-root'/> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args new file mode 100644 index 0000000..009f5a8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args @@ -0,0 +1,22 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name QEMUGuest1 \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device spapr-pci-host-bridge,index=2,id=pci.2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml new file mode 100644 index 0000000..b1c6ff3 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml @@ -0,0 +1,17 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <controller type='pci' model='pci-root'/> + <controller type='pci' model='pci-root'/> + <controller type='pci' model='pci-root'/> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 01c0a65..ff68884 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1709,6 +1709,14 @@ mymain(void) QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST_FAILURE("pseries-panic-address", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); + + DO_TEST("pseries-phb-simple", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); + DO_TEST("pseries-phb-default-missing", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); + DO_TEST("disk-ide-drive-split", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_IDE_CD); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-default-missing.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-default-missing.xml new file mode 100644 index 0000000..62708b4 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-default-missing.xml @@ -0,0 +1,33 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> + </controller> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-simple.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-simple.xml new file mode 100644 index 0000000..2c1e64e --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-simple.xml @@ -0,0 +1,33 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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'/> + </controller> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> + </controller> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> + </controller> + <controller type='usb' index='0' model='none'/> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index c74614c..a0a846c 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -676,6 +676,13 @@ mymain(void) DO_TEST("pseries-panic-missing", NONE); DO_TEST("pseries-panic-no-address", NONE);
+ DO_TEST("pseries-phb-simple", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); + DO_TEST("pseries-phb-default-missing", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); +
It's a constant source of annoyance that identical tests are copy-pasted between qemuxml2argvtest.c and qemuxml2xmltest.c. But that's not your problem. Reviewed-by: Laine Stump <laine@laine.org>
DO_TEST("balloon-device-auto", NONE); DO_TEST("balloon-device-period", NONE); DO_TEST("channel-virtio-auto", NONE);

On Fri, 2017-06-23 at 23:03 +0800, Andrea Bolognani wrote:
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- .../qemuxml2argv-pseries-phb-default-missing.args | 22 +++++++++++++++ .../qemuxml2argv-pseries-phb-default-missing.xml | 16 +++++++++++ .../qemuxml2argv-pseries-phb-simple.args | 22 +++++++++++++++ .../qemuxml2argv-pseries-phb-simple.xml | 17 +++++++++++ tests/qemuxml2argvtest.c | 8 ++++++ .../qemuxml2xmlout-pseries-phb-default-missing.xml | 33 ++++++++++++++++++++++ .../qemuxml2xmlout-pseries-phb-simple.xml | 33 ++++++++++++++++++++++ tests/qemuxml2xmltest.c | 7 +++++ 8 files changed, 158 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-default-missing.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-simple.xml
The attached patch should be squashed in to make sure the new test implemented in [1] works correctly. In order for the test case to work, [2] will need to be merged first - I plan to squeeze it in between patches 07 and 08 before pushing. Does that sound reasonable? [1] https://www.redhat.com/archives/libvir-list/2017-July/msg00069.html [2] https://www.redhat.com/archives/libvir-list/2017-July/msg00070.html -- Andrea Bolognani / Red Hat / Virtualization

On 07/04/2017 09:19 AM, Andrea Bolognani wrote:
On Fri, 2017-06-23 at 23:03 +0800, Andrea Bolognani wrote:
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- .../qemuxml2argv-pseries-phb-default-missing.args | 22 +++++++++++++++ .../qemuxml2argv-pseries-phb-default-missing.xml | 16 +++++++++++ .../qemuxml2argv-pseries-phb-simple.args | 22 +++++++++++++++ .../qemuxml2argv-pseries-phb-simple.xml | 17 +++++++++++ tests/qemuxml2argvtest.c | 8 ++++++ .../qemuxml2xmlout-pseries-phb-default-missing.xml | 33 ++++++++++++++++++++++ .../qemuxml2xmlout-pseries-phb-simple.xml | 33 ++++++++++++++++++++++ tests/qemuxml2xmltest.c | 7 +++++ 8 files changed, 158 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-default-missing.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-simple.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-default-missing.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-simple.xml
The attached patch should be squashed in to make sure the new test implemented in [1] works correctly. In order for the test case to work, [2] will need to be merged first - I plan to squeeze it in between patches 07 and 08 before pushing.
Does that sound reasonable?
Yep.

On Wed, 2017-07-05 at 21:14 -0400, Laine Stump wrote:
The attached patch should be squashed in to make sure the new test implemented in [1] works correctly. In order for the test case to work, [2] will need to be merged first - I plan to squeeze it in between patches 07 and 08 before pushing.
Does that sound reasonable?
Yep.
Someone will have to review [1] then... *wink wink* [1] https://www.redhat.com/archives/libvir-list/2017-July/msg00070.html -- Andrea Bolognani / Red Hat / Virtualization

These tests demonstrate that, while it's now possible for the user to create PHB explicitly and manually assign devices to them, libvirt still defaults to extending the guest PCI topology using PCI bridges and making suboptimal device placement choices. The next few commits will improve on these behaviors and the tests outputs will automatically be updated to reflect this. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- .../qemuxml2argv-pseries-hostdevs-1.args | 23 ++++ .../qemuxml2argv-pseries-hostdevs-1.xml | 38 +++++++ .../qemuxml2argv-pseries-hostdevs-2.args | 24 ++++ .../qemuxml2argv-pseries-hostdevs-2.xml | 37 ++++++ .../qemuxml2argv-pseries-hostdevs-3.args | 24 ++++ .../qemuxml2argv-pseries-hostdevs-3.xml | 31 +++++ .../qemuxml2argv-pseries-many-buses-1.args | 22 ++++ .../qemuxml2argv-pseries-many-buses-1.xml | 19 ++++ .../qemuxml2argv-pseries-many-buses-2.args | 22 ++++ .../qemuxml2argv-pseries-many-buses-2.xml | 18 +++ .../qemuxml2argv-pseries-many-devices.args | 53 +++++++++ .../qemuxml2argv-pseries-many-devices.xml | 48 ++++++++ tests/qemuxml2argvtest.c | 36 ++++++ .../qemuxml2xmlout-pseries-hostdevs-1.xml | 46 ++++++++ .../qemuxml2xmlout-pseries-hostdevs-2.xml | 47 ++++++++ .../qemuxml2xmlout-pseries-hostdevs-3.xml | 49 ++++++++ .../qemuxml2xmlout-pseries-many-buses-1.xml | 33 ++++++ .../qemuxml2xmlout-pseries-many-buses-2.xml | 34 ++++++ .../qemuxml2xmlout-pseries-many-devices.xml | 126 +++++++++++++++++++++ tests/qemuxml2xmltest.c | 36 ++++++ 20 files changed, 766 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args new file mode 100644 index 0000000..88eb081 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args @@ -0,0 +1,23 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.0,addr=0x1 \ +-device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x2 \ +-device vfio-pci,host=0001:01:00.1,id=hostdev2,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.xml new file mode 100644 index 0000000..87fe145 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.xml @@ -0,0 +1,38 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- This hostdev will cause a new PHB to be created because its + isolation group is 2 --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + </hostdev> + <!-- This hostdev can't share the PHB that was just created, because + its isolation group is 3 --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + </hostdev> + <!-- This hostdev will be placed on the first PHB, since its isolation + group is 2 just like the first hostdev --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> + </source> + </hostdev> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args new file mode 100644 index 0000000..c43e15d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args @@ -0,0 +1,24 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.1,addr=0x1 \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.1,addr=0x2 \ +-device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.xml new file mode 100644 index 0000000..551b588 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.xml @@ -0,0 +1,37 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- This device will cause a new PHB to be created because of its + address --> + <controller type='scsi' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + </controller> + <!-- This hostdev will share the same PHB as the SCSI controller + despite being in a separate isolation group, because the + address has been requested explicitly by the user --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> + </hostdev> + <!-- This hostdev can use neither the PHB that was just created, nor + the default one, because its isolation group is 3 --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + </hostdev> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args new file mode 100644 index 0000000..99df2e7 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args @@ -0,0 +1,24 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.0,addr=0x2 \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.2,addr=0x1 \ +-device vfio-pci,host=0001:01:00.1,id=hostdev1,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.xml new file mode 100644 index 0000000..0e61a17 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.xml @@ -0,0 +1,31 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- This hostdev will cause a new PHB to be created because its + isolation group is 2. It will be PHB 2 due to the address --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> + </hostdev> + <!-- This hostdev will be placed on the same PHB, since its isolation + group is also 2 --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> + </source> + </hostdev> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args new file mode 100644 index 0000000..bf78fc1 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args @@ -0,0 +1,22 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.1,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.xml new file mode 100644 index 0000000..c52349d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.xml @@ -0,0 +1,19 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- The SCSI controller is plugged into PCI bus 1, but since said bus + is not present in the configuration libvirt will have to add it --> + <controller type='scsi' model='virtio-scsi'> + <address type='pci' bus='1' slot='1'/> + </controller> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args new file mode 100644 index 0000000..1cb5831 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args @@ -0,0 +1,22 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device spapr-pci-host-bridge,index=1,id=pci.2 \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.xml new file mode 100644 index 0000000..7065626 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.xml @@ -0,0 +1,18 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- PCI buses 0 and 2 are present in the configuration, libvirt will + have to fill in the blanks and add bus 1 --> + <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='2' model='pci-root'/> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args new file mode 100644 index 0000000..1db4533 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args @@ -0,0 +1,53 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x2 \ +-device virtio-scsi-pci,id=scsi1,bus=pci.0,addr=0x3 \ +-device virtio-scsi-pci,id=scsi2,bus=pci.0,addr=0x4 \ +-device virtio-scsi-pci,id=scsi3,bus=pci.0,addr=0x5 \ +-device virtio-scsi-pci,id=scsi4,bus=pci.0,addr=0x6 \ +-device virtio-scsi-pci,id=scsi5,bus=pci.0,addr=0x7 \ +-device virtio-scsi-pci,id=scsi6,bus=pci.0,addr=0x8 \ +-device virtio-scsi-pci,id=scsi7,bus=pci.0,addr=0x9 \ +-device virtio-scsi-pci,id=scsi8,bus=pci.0,addr=0xa \ +-device virtio-scsi-pci,id=scsi9,bus=pci.0,addr=0xb \ +-device virtio-scsi-pci,id=scsi10,bus=pci.0,addr=0xc \ +-device virtio-scsi-pci,id=scsi11,bus=pci.0,addr=0xd \ +-device virtio-scsi-pci,id=scsi12,bus=pci.0,addr=0xe \ +-device virtio-scsi-pci,id=scsi13,bus=pci.0,addr=0xf \ +-device virtio-scsi-pci,id=scsi14,bus=pci.0,addr=0x10 \ +-device virtio-scsi-pci,id=scsi15,bus=pci.0,addr=0x11 \ +-device virtio-scsi-pci,id=scsi16,bus=pci.0,addr=0x12 \ +-device virtio-scsi-pci,id=scsi17,bus=pci.0,addr=0x13 \ +-device virtio-scsi-pci,id=scsi18,bus=pci.0,addr=0x14 \ +-device virtio-scsi-pci,id=scsi19,bus=pci.0,addr=0x15 \ +-device virtio-scsi-pci,id=scsi20,bus=pci.0,addr=0x16 \ +-device virtio-scsi-pci,id=scsi21,bus=pci.0,addr=0x17 \ +-device virtio-scsi-pci,id=scsi22,bus=pci.0,addr=0x18 \ +-device virtio-scsi-pci,id=scsi23,bus=pci.0,addr=0x19 \ +-device virtio-scsi-pci,id=scsi24,bus=pci.0,addr=0x1a \ +-device virtio-scsi-pci,id=scsi25,bus=pci.0,addr=0x1b \ +-device virtio-scsi-pci,id=scsi26,bus=pci.0,addr=0x1c \ +-device virtio-scsi-pci,id=scsi27,bus=pci.0,addr=0x1d \ +-device virtio-scsi-pci,id=scsi28,bus=pci.0,addr=0x1e \ +-device virtio-scsi-pci,id=scsi29,bus=pci.0,addr=0x1f \ +-device virtio-scsi-pci,id=scsi30,bus=pci.1,addr=0x1 \ +-device virtio-scsi-pci,id=scsi31,bus=pci.1,addr=0x2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.xml new file mode 100644 index 0000000..f3daba4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.xml @@ -0,0 +1,48 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- pci-root has 31 slots and there are 32 SCSI controllers here, so + libvirt will automatically add at least one more PCI controller --> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index ff68884..137f59a 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1717,6 +1717,42 @@ mymain(void) QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); + DO_TEST("pseries-many-devices", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-many-buses-1", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-many-buses-2", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-hostdevs-1", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("pseries-hostdevs-2", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("pseries-hostdevs-3", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("disk-ide-drive-split", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_IDE_CD); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml new file mode 100644 index 0000000..34defea --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml @@ -0,0 +1,46 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </hostdev> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml new file mode 100644 index 0000000..62bead5 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml @@ -0,0 +1,47 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='scsi' index='0' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <controller type='pci' index='1' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </hostdev> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml new file mode 100644 index 0000000..77c0909 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml @@ -0,0 +1,49 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <controller type='pci' index='1' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='1'/> + <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='0x00' slot='0x02' function='0x0'/> + </controller> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </hostdev> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml new file mode 100644 index 0000000..9044936 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml @@ -0,0 +1,33 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='scsi' index='0' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <controller type='pci' index='1' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml new file mode 100644 index 0000000..75dfabf --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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'/> + </controller> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='1' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml new file mode 100644 index 0000000..b596fe6 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml @@ -0,0 +1,126 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='scsi' index='0' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </controller> + <controller type='scsi' index='1' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='scsi' index='2' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <controller type='scsi' index='3' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </controller> + <controller type='scsi' index='4' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </controller> + <controller type='scsi' index='5' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + </controller> + <controller type='scsi' index='6' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + </controller> + <controller type='scsi' index='7' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> + </controller> + <controller type='scsi' index='8' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <controller type='scsi' index='9' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> + </controller> + <controller type='scsi' index='10' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> + </controller> + <controller type='scsi' index='11' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/> + </controller> + <controller type='scsi' index='12' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/> + </controller> + <controller type='scsi' index='13' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/> + </controller> + <controller type='scsi' index='14' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x10' function='0x0'/> + </controller> + <controller type='scsi' index='15' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x11' function='0x0'/> + </controller> + <controller type='scsi' index='16' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x12' function='0x0'/> + </controller> + <controller type='scsi' index='17' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x13' function='0x0'/> + </controller> + <controller type='scsi' index='18' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x14' function='0x0'/> + </controller> + <controller type='scsi' index='19' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x15' function='0x0'/> + </controller> + <controller type='scsi' index='20' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x16' function='0x0'/> + </controller> + <controller type='scsi' index='21' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x17' function='0x0'/> + </controller> + <controller type='scsi' index='22' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x18' function='0x0'/> + </controller> + <controller type='scsi' index='23' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x19' function='0x0'/> + </controller> + <controller type='scsi' index='24' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1a' function='0x0'/> + </controller> + <controller type='scsi' index='25' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/> + </controller> + <controller type='scsi' index='26' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1c' function='0x0'/> + </controller> + <controller type='scsi' index='27' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0'/> + </controller> + <controller type='scsi' index='28' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/> + </controller> + <controller type='scsi' index='29' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x0'/> + </controller> + <controller type='scsi' index='30' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + </controller> + <controller type='scsi' index='31' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <controller type='pci' index='1' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index a0a846c..312e2b1 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -683,6 +683,42 @@ mymain(void) QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); + DO_TEST("pseries-many-devices", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-many-buses-1", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-many-buses-2", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-hostdevs-1", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("pseries-hostdevs-2", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("pseries-hostdevs-3", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("balloon-device-auto", NONE); DO_TEST("balloon-device-period", NONE); DO_TEST("channel-virtio-auto", NONE); -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
These tests demonstrate that, while it's now possible for the user to create PHB explicitly and manually assign devices to them, libvirt still defaults to extending the guest PCI topology using PCI bridges and making suboptimal device placement choices.
The next few commits will improve on these behaviors and the tests outputs will automatically be updated to reflect this.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- .../qemuxml2argv-pseries-hostdevs-1.args | 23 ++++ .../qemuxml2argv-pseries-hostdevs-1.xml | 38 +++++++ .../qemuxml2argv-pseries-hostdevs-2.args | 24 ++++ .../qemuxml2argv-pseries-hostdevs-2.xml | 37 ++++++ .../qemuxml2argv-pseries-hostdevs-3.args | 24 ++++ .../qemuxml2argv-pseries-hostdevs-3.xml | 31 +++++ .../qemuxml2argv-pseries-many-buses-1.args | 22 ++++ .../qemuxml2argv-pseries-many-buses-1.xml | 19 ++++ .../qemuxml2argv-pseries-many-buses-2.args | 22 ++++ .../qemuxml2argv-pseries-many-buses-2.xml | 18 +++ .../qemuxml2argv-pseries-many-devices.args | 53 +++++++++ .../qemuxml2argv-pseries-many-devices.xml | 48 ++++++++ tests/qemuxml2argvtest.c | 36 ++++++ .../qemuxml2xmlout-pseries-hostdevs-1.xml | 46 ++++++++ .../qemuxml2xmlout-pseries-hostdevs-2.xml | 47 ++++++++ .../qemuxml2xmlout-pseries-hostdevs-3.xml | 49 ++++++++ .../qemuxml2xmlout-pseries-many-buses-1.xml | 33 ++++++ .../qemuxml2xmlout-pseries-many-buses-2.xml | 34 ++++++ .../qemuxml2xmlout-pseries-many-devices.xml | 126 +++++++++++++++++++++ tests/qemuxml2xmltest.c | 36 ++++++ 20 files changed, 766 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args new file mode 100644 index 0000000..88eb081 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args @@ -0,0 +1,23 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.0,addr=0x1 \ +-device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x2 \ +-device vfio-pci,host=0001:01:00.1,id=hostdev2,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.xml new file mode 100644 index 0000000..87fe145 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.xml @@ -0,0 +1,38 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- This hostdev will cause a new PHB to be created because its + isolation group is 2 --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + </hostdev> + <!-- This hostdev can't share the PHB that was just created, because + its isolation group is 3 -->
I like the idea of putting comments in the test XML indicating exactly what we're testing for! Reviewed-by: Laine Stump <laine@laine.org>
+ <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + </hostdev> + <!-- This hostdev will be placed on the first PHB, since its isolation + group is 2 just like the first hostdev --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> + </source> + </hostdev> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args new file mode 100644 index 0000000..c43e15d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args @@ -0,0 +1,24 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.1,addr=0x1 \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.1,addr=0x2 \ +-device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.xml new file mode 100644 index 0000000..551b588 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.xml @@ -0,0 +1,37 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- This device will cause a new PHB to be created because of its + address --> + <controller type='scsi' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + </controller> + <!-- This hostdev will share the same PHB as the SCSI controller + despite being in a separate isolation group, because the + address has been requested explicitly by the user --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> + </hostdev> + <!-- This hostdev can use neither the PHB that was just created, nor + the default one, because its isolation group is 3 --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + </hostdev> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args new file mode 100644 index 0000000..99df2e7 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args @@ -0,0 +1,24 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.0,addr=0x2 \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.2,addr=0x1 \ +-device vfio-pci,host=0001:01:00.1,id=hostdev1,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.xml new file mode 100644 index 0000000..0e61a17 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.xml @@ -0,0 +1,31 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- This hostdev will cause a new PHB to be created because its + isolation group is 2. It will be PHB 2 due to the address --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> + </hostdev> + <!-- This hostdev will be placed on the same PHB, since its isolation + group is also 2 --> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> + </source> + </hostdev> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args new file mode 100644 index 0000000..bf78fc1 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args @@ -0,0 +1,22 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.1,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.xml new file mode 100644 index 0000000..c52349d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.xml @@ -0,0 +1,19 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- The SCSI controller is plugged into PCI bus 1, but since said bus + is not present in the configuration libvirt will have to add it --> + <controller type='scsi' model='virtio-scsi'> + <address type='pci' bus='1' slot='1'/> + </controller> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args new file mode 100644 index 0000000..1cb5831 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args @@ -0,0 +1,22 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device spapr-pci-host-bridge,index=1,id=pci.2 \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.xml new file mode 100644 index 0000000..7065626 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.xml @@ -0,0 +1,18 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- PCI buses 0 and 2 are present in the configuration, libvirt will + have to fill in the blanks and add bus 1 --> + <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='2' model='pci-root'/> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args new file mode 100644 index 0000000..1db4533 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args @@ -0,0 +1,53 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name guest \ +-S \ +-M pseries \ +-m 512 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-boot c \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x2 \ +-device virtio-scsi-pci,id=scsi1,bus=pci.0,addr=0x3 \ +-device virtio-scsi-pci,id=scsi2,bus=pci.0,addr=0x4 \ +-device virtio-scsi-pci,id=scsi3,bus=pci.0,addr=0x5 \ +-device virtio-scsi-pci,id=scsi4,bus=pci.0,addr=0x6 \ +-device virtio-scsi-pci,id=scsi5,bus=pci.0,addr=0x7 \ +-device virtio-scsi-pci,id=scsi6,bus=pci.0,addr=0x8 \ +-device virtio-scsi-pci,id=scsi7,bus=pci.0,addr=0x9 \ +-device virtio-scsi-pci,id=scsi8,bus=pci.0,addr=0xa \ +-device virtio-scsi-pci,id=scsi9,bus=pci.0,addr=0xb \ +-device virtio-scsi-pci,id=scsi10,bus=pci.0,addr=0xc \ +-device virtio-scsi-pci,id=scsi11,bus=pci.0,addr=0xd \ +-device virtio-scsi-pci,id=scsi12,bus=pci.0,addr=0xe \ +-device virtio-scsi-pci,id=scsi13,bus=pci.0,addr=0xf \ +-device virtio-scsi-pci,id=scsi14,bus=pci.0,addr=0x10 \ +-device virtio-scsi-pci,id=scsi15,bus=pci.0,addr=0x11 \ +-device virtio-scsi-pci,id=scsi16,bus=pci.0,addr=0x12 \ +-device virtio-scsi-pci,id=scsi17,bus=pci.0,addr=0x13 \ +-device virtio-scsi-pci,id=scsi18,bus=pci.0,addr=0x14 \ +-device virtio-scsi-pci,id=scsi19,bus=pci.0,addr=0x15 \ +-device virtio-scsi-pci,id=scsi20,bus=pci.0,addr=0x16 \ +-device virtio-scsi-pci,id=scsi21,bus=pci.0,addr=0x17 \ +-device virtio-scsi-pci,id=scsi22,bus=pci.0,addr=0x18 \ +-device virtio-scsi-pci,id=scsi23,bus=pci.0,addr=0x19 \ +-device virtio-scsi-pci,id=scsi24,bus=pci.0,addr=0x1a \ +-device virtio-scsi-pci,id=scsi25,bus=pci.0,addr=0x1b \ +-device virtio-scsi-pci,id=scsi26,bus=pci.0,addr=0x1c \ +-device virtio-scsi-pci,id=scsi27,bus=pci.0,addr=0x1d \ +-device virtio-scsi-pci,id=scsi28,bus=pci.0,addr=0x1e \ +-device virtio-scsi-pci,id=scsi29,bus=pci.0,addr=0x1f \ +-device virtio-scsi-pci,id=scsi30,bus=pci.1,addr=0x1 \ +-device virtio-scsi-pci,id=scsi31,bus=pci.1,addr=0x2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.xml new file mode 100644 index 0000000..f3daba4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.xml @@ -0,0 +1,48 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <!-- pci-root has 31 slots and there are 32 SCSI controllers here, so + libvirt will automatically add at least one more PCI controller --> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='scsi' model='virtio-scsi'/> + <controller type='usb' model='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index ff68884..137f59a 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1717,6 +1717,42 @@ mymain(void) QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE);
+ DO_TEST("pseries-many-devices", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-many-buses-1", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-many-buses-2", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-hostdevs-1", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("pseries-hostdevs-2", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("pseries-hostdevs-3", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("disk-ide-drive-split", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_IDE_CD); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml new file mode 100644 index 0000000..34defea --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml @@ -0,0 +1,46 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </hostdev> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml new file mode 100644 index 0000000..62bead5 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml @@ -0,0 +1,47 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='scsi' index='0' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <controller type='pci' index='1' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </hostdev> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml new file mode 100644 index 0000000..77c0909 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml @@ -0,0 +1,49 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <controller type='pci' index='1' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='1'/> + <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='0x00' slot='0x02' function='0x0'/> + </controller> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> + </source> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> + </source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </hostdev> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml new file mode 100644 index 0000000..9044936 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml @@ -0,0 +1,33 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='scsi' index='0' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <controller type='pci' index='1' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml new file mode 100644 index 0000000..75dfabf --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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'/> + </controller> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='1' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml new file mode 100644 index 0000000..b596fe6 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml @@ -0,0 +1,126 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</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='scsi' index='0' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </controller> + <controller type='scsi' index='1' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='scsi' index='2' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <controller type='scsi' index='3' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </controller> + <controller type='scsi' index='4' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </controller> + <controller type='scsi' index='5' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + </controller> + <controller type='scsi' index='6' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + </controller> + <controller type='scsi' index='7' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> + </controller> + <controller type='scsi' index='8' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <controller type='scsi' index='9' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> + </controller> + <controller type='scsi' index='10' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> + </controller> + <controller type='scsi' index='11' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/> + </controller> + <controller type='scsi' index='12' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/> + </controller> + <controller type='scsi' index='13' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/> + </controller> + <controller type='scsi' index='14' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x10' function='0x0'/> + </controller> + <controller type='scsi' index='15' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x11' function='0x0'/> + </controller> + <controller type='scsi' index='16' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x12' function='0x0'/> + </controller> + <controller type='scsi' index='17' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x13' function='0x0'/> + </controller> + <controller type='scsi' index='18' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x14' function='0x0'/> + </controller> + <controller type='scsi' index='19' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x15' function='0x0'/> + </controller> + <controller type='scsi' index='20' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x16' function='0x0'/> + </controller> + <controller type='scsi' index='21' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x17' function='0x0'/> + </controller> + <controller type='scsi' index='22' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x18' function='0x0'/> + </controller> + <controller type='scsi' index='23' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x19' function='0x0'/> + </controller> + <controller type='scsi' index='24' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1a' function='0x0'/> + </controller> + <controller type='scsi' index='25' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/> + </controller> + <controller type='scsi' index='26' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1c' function='0x0'/> + </controller> + <controller type='scsi' index='27' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0'/> + </controller> + <controller type='scsi' index='28' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/> + </controller> + <controller type='scsi' index='29' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x0'/> + </controller> + <controller type='scsi' index='30' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + </controller> + <controller type='scsi' index='31' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <controller type='pci' index='1' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index a0a846c..312e2b1 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -683,6 +683,42 @@ mymain(void) QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE);
+ DO_TEST("pseries-many-devices", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-many-buses-1", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-many-buses-2", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("pseries-hostdevs-1", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("pseries-hostdevs-2", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("pseries-hostdevs-3", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, + QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("balloon-device-auto", NONE); DO_TEST("balloon-device-period", NONE); DO_TEST("channel-virtio-auto", NONE);

PCI bus has to be numbered sequentially, and no index can be missing, so libvirt will fill in the blanks automatically for the user. Up until now, it has done so using either pci-bridge, for machine types based on legacy PCI, or pcie-root-port, for machine types based on PCI Express. Neither choice is good for pSeries guests, where PHBs (pci-root) should be used instead. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_domain_address.c | 16 +++++++++++++--- .../qemuxml2argv-pseries-many-buses-2.args | 2 +- tests/qemuxml2argvtest.c | 1 - .../qemuxml2xmlout-pseries-many-buses-2.xml | 7 +++---- tests/qemuxml2xmltest.c | 1 - 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 960ea04..082cb72 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1097,10 +1097,14 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def, * that don't yet have a corresponding controller in the domain * config. */ - if (hasPCIeRoot) + if (qemuDomainIsPSeries(def)) { + /* pSeries guests should use PHBs (pci-root controllers) */ + defaultModel = VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT; + } else if (hasPCIeRoot) { defaultModel = VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT; - else + } else { defaultModel = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE; + } for (i = 1; i < addrs->nbuses; i++) { @@ -2182,7 +2186,13 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, dev.data.controller = def->controllers[contIndex]; /* set connect flags so it will be properly addressed */ qemuDomainFillDevicePCIConnectFlags(def, &dev, qemuCaps, driver); - if (qemuDomainPCIAddressReserveNextAddr(addrs, + + /* Reserve an address for the controller. pci-root and pcie-root + * controllers don't plug into any other PCI controller, hence + * they should skip this step */ + if (bus->model != VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT && + bus->model != VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT && + qemuDomainPCIAddressReserveNextAddr(addrs, &dev.data.controller->info) < 0) { goto cleanup; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args index 1cb5831..13fed02 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args @@ -19,4 +19,4 @@ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ -device spapr-pci-host-bridge,index=1,id=pci.2 \ --device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 +-device spapr-pci-host-bridge,index=2,id=pci.1 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 137f59a..f1720cb 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1730,7 +1730,6 @@ mymain(void) DO_TEST("pseries-many-buses-2", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-hostdevs-1", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml index 75dfabf..14f3e36 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml @@ -23,10 +23,9 @@ <target index='1'/> </controller> <controller type='usb' index='0' model='none'/> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> </controller> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 312e2b1..378cd85 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -696,7 +696,6 @@ mymain(void) DO_TEST("pseries-many-buses-2", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-hostdevs-1", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
PCI bus has to be numbered sequentially, and no index can be missing,
I thought we had figured out later that this was a misunderstanding/misinterpretation/creation based on nothing, and that it really didn't matter. Keep in mind that the index of a PCI controller is used only for two things: 1) a device that is to be connected to PCI controller of index='x' should have "bus='x'" in its PCI address. 2) The value of index is used when creating the alias ("id" in qemu terms) of the controller, e.g. "pci.2". It is this string "pci.2" which is used on the qemu commandline to connect the controller and the devices plugged into that controller; as far as the guest firmware/OS are concerned, there are just a bunch of PCI controllers, and they are given bus numbers during probing according to the order they are encountered, *NOT* according to the id/alias of the controller. The result is that it's completely meaningless to create a bunch of empty PCI bridges/root-ports just so that you'll have controllers named "pcie.0, pci.1, pci.2, pci.3" instead of only "pcie.0, pci.3" (with a gap in the ordering).
so libvirt will fill in the blanks automatically for the user.
Hmm. I guess the *one* place that it matters is in our PCI address allocation functions, which assume that all the buses from 0 to the final bus can accept *something*.
Up until now, it has done so using either pci-bridge, for machine types based on legacy PCI, or pcie-root-port, for machine types based on PCI Express. Neither choice is good for pSeries guests, where PHBs (pci-root) should be used instead.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_domain_address.c | 16 +++++++++++++--- .../qemuxml2argv-pseries-many-buses-2.args | 2 +- tests/qemuxml2argvtest.c | 1 - .../qemuxml2xmlout-pseries-many-buses-2.xml | 7 +++---- tests/qemuxml2xmltest.c | 1 - 5 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 960ea04..082cb72 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1097,10 +1097,14 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def, * that don't yet have a corresponding controller in the domain * config. */ - if (hasPCIeRoot) + if (qemuDomainIsPSeries(def)) { + /* pSeries guests should use PHBs (pci-root controllers) */ + defaultModel = VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT; + } else if (hasPCIeRoot) { defaultModel = VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT; - else + } else { defaultModel = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE; + }
for (i = 1; i < addrs->nbuses; i++) {
@@ -2182,7 +2186,13 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, dev.data.controller = def->controllers[contIndex]; /* set connect flags so it will be properly addressed */ qemuDomainFillDevicePCIConnectFlags(def, &dev, qemuCaps, driver); - if (qemuDomainPCIAddressReserveNextAddr(addrs, + + /* Reserve an address for the controller. pci-root and pcie-root + * controllers don't plug into any other PCI controller, hence + * they should skip this step */ + if (bus->model != VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT && + bus->model != VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT && + qemuDomainPCIAddressReserveNextAddr(addrs, &dev.data.controller->info) < 0) { goto cleanup; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args index 1cb5831..13fed02 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-2.args @@ -19,4 +19,4 @@ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ -device spapr-pci-host-bridge,index=1,id=pci.2 \ --device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 +-device spapr-pci-host-bridge,index=2,id=pci.1 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 137f59a..f1720cb 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1730,7 +1730,6 @@ mymain(void) DO_TEST("pseries-many-buses-2", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-hostdevs-1", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml index 75dfabf..14f3e36 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-2.xml @@ -23,10 +23,9 @@ <target index='1'/> </controller> <controller type='usb' index='0' model='none'/> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/>
Interesting - since we initially had one with controller index=2 that was automatically given target index=1, now that this PHB controller is being automatically added at index=1, it uses the next free target index, which is '2'. I assume that works correctly? Reviewed-by: Laine Stump <laine@laine.org> Although I think (in a separate patch) someone should eliminate all this cruft about filling in empty places in the bus numbering with unused controllers - it's pointless, and in the case of pci-bridge at least, I think it creates controllers that are unusable (because they have no io space allocated).
</controller> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 312e2b1..378cd85 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -696,7 +696,6 @@ mymain(void) DO_TEST("pseries-many-buses-2", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-hostdevs-1", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG,

On Tue, 2017-06-27 at 11:59 -0400, Laine Stump wrote:
@@ -23,10 +23,9 @@ <target index='1'/> </controller> <controller type='usb' index='0' model='none'/> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> Interesting - since we initially had one with controller index=2 that was automatically given target index=1, now that this PHB controller is being automatically added at index=1, it uses the next free target index, which is '2'. I assume that works correctly?
Yes. The test case was crafted specifically to show that controller index and target index don't have to match.
Although I think (in a separate patch) someone should eliminate all this cruft about filling in empty places in the bus numbering with unused controllers - it's pointless, and in the case of pci-bridge at least, I think it creates controllers that are unusable (because they have no io space allocated).
The only drawback I can think of at the moment is that it might be confusing for the user to have controllers numbered eg. 0, 42 and 1337, even though of course the guest OS would not care at all. -- Andrea Bolognani / Red Hat / Virtualization

When looking for slots suitable for a PCI device, libvirt might need to add an extra PCI controller: for pSeries guests, we want that extra controller to be a PHB (pci-root) rather than a PCI bridge. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/domain_addr.c | 56 +++++++++-------- src/conf/domain_addr.h | 2 + src/qemu/qemu_domain_address.c | 4 ++ .../qemuxml2argv-pseries-hostdevs-2.args | 8 +-- .../qemuxml2argv-pseries-hostdevs-3.args | 8 +-- .../qemuxml2argv-pseries-many-buses-1.args | 4 +- .../qemuxml2argv-pseries-many-devices.args | 66 ++++++++++---------- tests/qemuxml2argvtest.c | 4 -- .../qemuxml2xmlout-pseries-hostdevs-2.xml | 9 ++- .../qemuxml2xmlout-pseries-hostdevs-3.xml | 16 +++-- .../qemuxml2xmlout-pseries-many-buses-1.xml | 7 +-- .../qemuxml2xmlout-pseries-many-devices.xml | 71 +++++++++++----------- tests/qemuxml2xmltest.c | 4 -- 13 files changed, 129 insertions(+), 130 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 86b1367..b9e9145 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -383,33 +383,39 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs, */ if (flags & VIR_PCI_CONNECT_TYPE_PCI_DEVICE) { - model = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE; + if (addrs->multipleRootsSupported) { + /* Use a pci-root controller to expand the guest's PCI + * topology if it supports having more than one */ + model = VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT; + } else { + model = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE; - /* if there aren't yet any buses that will accept a - * pci-bridge, and the caller is asking for one, we'll need to - * add a dmi-to-pci-bridge first. - */ - needDMIToPCIBridge = true; - for (i = 0; i < addrs->nbuses; i++) { - if (addrs->buses[i].flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE) { - needDMIToPCIBridge = false; - break; - } - } - if (needDMIToPCIBridge && add == 1) { - /* We need to add a single pci-bridge to provide the bus - * our legacy PCI device will be plugged into; however, we - * have also determined that there isn't yet any proper - * place to connect that pci-bridge we're about to add (on - * a system with pcie-root, that "proper place" would be a - * dmi-to-pci-bridge". So, to give the pci-bridge a place - * to connect, we increase the count of buses to add, - * while also incrementing the bus number in the address - * for the device (since the pci-bridge will now be at an - * index 1 higher than the caller had anticipated). + /* if there aren't yet any buses that will accept a + * pci-bridge, and the caller is asking for one, we'll need to + * add a dmi-to-pci-bridge first. */ - add++; - addr->bus++; + needDMIToPCIBridge = true; + for (i = 0; i < addrs->nbuses; i++) { + if (addrs->buses[i].flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE) { + needDMIToPCIBridge = false; + break; + } + } + if (needDMIToPCIBridge && add == 1) { + /* We need to add a single pci-bridge to provide the bus + * our legacy PCI device will be plugged into; however, we + * have also determined that there isn't yet any proper + * place to connect that pci-bridge we're about to add (on + * a system with pcie-root, that "proper place" would be a + * dmi-to-pci-bridge". So, to give the pci-bridge a place + * to connect, we increase the count of buses to add, + * while also incrementing the bus number in the address + * for the device (since the pci-bridge will now be at an + * index 1 higher than the caller had anticipated). + */ + add++; + addr->bus++; + } } } else if (flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE && addrs->buses[0].model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) { diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index c98a228..9cd1b29 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -108,6 +108,8 @@ struct _virDomainPCIAddressSet { size_t nbuses; bool dryRun; /* on a dry run, new buses are auto-added and addresses aren't saved in device infos */ + /* If true, the guest can have multiple pci-root controllers */ + bool multipleRootsSupported; }; typedef struct _virDomainPCIAddressSet virDomainPCIAddressSet; typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 082cb72..50e41a4 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1061,6 +1061,10 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def, addrs->dryRun = dryRun; + /* pSeries domains support multiple pci-root controllers */ + if (qemuDomainIsPSeries(def)) + addrs->multipleRootsSupported = true; + for (i = 0; i < def->ncontrollers; i++) { virDomainControllerDefPtr cont = def->controllers[i]; size_t idx = cont->idx; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args index c43e15d..83d4306 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args @@ -18,7 +18,7 @@ QEMU_AUDIO_DRV=none \ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ --device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ --device virtio-scsi-pci,id=scsi0,bus=pci.1,addr=0x1 \ --device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.1,addr=0x2 \ --device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x2 +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.1.0,addr=0x1 \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.1.0,addr=0x2 \ +-device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args index 99df2e7..eda6cc7 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args @@ -18,7 +18,7 @@ QEMU_AUDIO_DRV=none \ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ --device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.0,addr=0x2 \ --device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.2,addr=0x1 \ --device vfio-pci,host=0001:01:00.1,id=hostdev1,bus=pci.0,addr=0x3 +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device spapr-pci-host-bridge,index=2,id=pci.2 \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.2.0,addr=0x1 \ +-device vfio-pci,host=0001:01:00.1,id=hostdev1,bus=pci.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args index bf78fc1..eb5ccbd 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args @@ -18,5 +18,5 @@ QEMU_AUDIO_DRV=none \ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ --device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ --device virtio-scsi-pci,id=scsi0,bus=pci.1,addr=0x1 +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.1.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args index 1db4533..f20bc52 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args @@ -18,36 +18,36 @@ QEMU_AUDIO_DRV=none \ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ --device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ --device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x2 \ --device virtio-scsi-pci,id=scsi1,bus=pci.0,addr=0x3 \ --device virtio-scsi-pci,id=scsi2,bus=pci.0,addr=0x4 \ --device virtio-scsi-pci,id=scsi3,bus=pci.0,addr=0x5 \ --device virtio-scsi-pci,id=scsi4,bus=pci.0,addr=0x6 \ --device virtio-scsi-pci,id=scsi5,bus=pci.0,addr=0x7 \ --device virtio-scsi-pci,id=scsi6,bus=pci.0,addr=0x8 \ --device virtio-scsi-pci,id=scsi7,bus=pci.0,addr=0x9 \ --device virtio-scsi-pci,id=scsi8,bus=pci.0,addr=0xa \ --device virtio-scsi-pci,id=scsi9,bus=pci.0,addr=0xb \ --device virtio-scsi-pci,id=scsi10,bus=pci.0,addr=0xc \ --device virtio-scsi-pci,id=scsi11,bus=pci.0,addr=0xd \ --device virtio-scsi-pci,id=scsi12,bus=pci.0,addr=0xe \ --device virtio-scsi-pci,id=scsi13,bus=pci.0,addr=0xf \ --device virtio-scsi-pci,id=scsi14,bus=pci.0,addr=0x10 \ --device virtio-scsi-pci,id=scsi15,bus=pci.0,addr=0x11 \ --device virtio-scsi-pci,id=scsi16,bus=pci.0,addr=0x12 \ --device virtio-scsi-pci,id=scsi17,bus=pci.0,addr=0x13 \ --device virtio-scsi-pci,id=scsi18,bus=pci.0,addr=0x14 \ --device virtio-scsi-pci,id=scsi19,bus=pci.0,addr=0x15 \ --device virtio-scsi-pci,id=scsi20,bus=pci.0,addr=0x16 \ --device virtio-scsi-pci,id=scsi21,bus=pci.0,addr=0x17 \ --device virtio-scsi-pci,id=scsi22,bus=pci.0,addr=0x18 \ --device virtio-scsi-pci,id=scsi23,bus=pci.0,addr=0x19 \ --device virtio-scsi-pci,id=scsi24,bus=pci.0,addr=0x1a \ --device virtio-scsi-pci,id=scsi25,bus=pci.0,addr=0x1b \ --device virtio-scsi-pci,id=scsi26,bus=pci.0,addr=0x1c \ --device virtio-scsi-pci,id=scsi27,bus=pci.0,addr=0x1d \ --device virtio-scsi-pci,id=scsi28,bus=pci.0,addr=0x1e \ --device virtio-scsi-pci,id=scsi29,bus=pci.0,addr=0x1f \ --device virtio-scsi-pci,id=scsi30,bus=pci.1,addr=0x1 \ --device virtio-scsi-pci,id=scsi31,bus=pci.1,addr=0x2 +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x1 \ +-device virtio-scsi-pci,id=scsi1,bus=pci.0,addr=0x2 \ +-device virtio-scsi-pci,id=scsi2,bus=pci.0,addr=0x3 \ +-device virtio-scsi-pci,id=scsi3,bus=pci.0,addr=0x4 \ +-device virtio-scsi-pci,id=scsi4,bus=pci.0,addr=0x5 \ +-device virtio-scsi-pci,id=scsi5,bus=pci.0,addr=0x6 \ +-device virtio-scsi-pci,id=scsi6,bus=pci.0,addr=0x7 \ +-device virtio-scsi-pci,id=scsi7,bus=pci.0,addr=0x8 \ +-device virtio-scsi-pci,id=scsi8,bus=pci.0,addr=0x9 \ +-device virtio-scsi-pci,id=scsi9,bus=pci.0,addr=0xa \ +-device virtio-scsi-pci,id=scsi10,bus=pci.0,addr=0xb \ +-device virtio-scsi-pci,id=scsi11,bus=pci.0,addr=0xc \ +-device virtio-scsi-pci,id=scsi12,bus=pci.0,addr=0xd \ +-device virtio-scsi-pci,id=scsi13,bus=pci.0,addr=0xe \ +-device virtio-scsi-pci,id=scsi14,bus=pci.0,addr=0xf \ +-device virtio-scsi-pci,id=scsi15,bus=pci.0,addr=0x10 \ +-device virtio-scsi-pci,id=scsi16,bus=pci.0,addr=0x11 \ +-device virtio-scsi-pci,id=scsi17,bus=pci.0,addr=0x12 \ +-device virtio-scsi-pci,id=scsi18,bus=pci.0,addr=0x13 \ +-device virtio-scsi-pci,id=scsi19,bus=pci.0,addr=0x14 \ +-device virtio-scsi-pci,id=scsi20,bus=pci.0,addr=0x15 \ +-device virtio-scsi-pci,id=scsi21,bus=pci.0,addr=0x16 \ +-device virtio-scsi-pci,id=scsi22,bus=pci.0,addr=0x17 \ +-device virtio-scsi-pci,id=scsi23,bus=pci.0,addr=0x18 \ +-device virtio-scsi-pci,id=scsi24,bus=pci.0,addr=0x19 \ +-device virtio-scsi-pci,id=scsi25,bus=pci.0,addr=0x1a \ +-device virtio-scsi-pci,id=scsi26,bus=pci.0,addr=0x1b \ +-device virtio-scsi-pci,id=scsi27,bus=pci.0,addr=0x1c \ +-device virtio-scsi-pci,id=scsi28,bus=pci.0,addr=0x1d \ +-device virtio-scsi-pci,id=scsi29,bus=pci.0,addr=0x1e \ +-device virtio-scsi-pci,id=scsi30,bus=pci.0,addr=0x1f \ +-device virtio-scsi-pci,id=scsi31,bus=pci.1.0,addr=0x1 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index f1720cb..c0582c3 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1720,12 +1720,10 @@ mymain(void) DO_TEST("pseries-many-devices", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-many-buses-1", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-many-buses-2", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, @@ -1741,14 +1739,12 @@ mymain(void) QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VFIO_PCI); DO_TEST("pseries-hostdevs-3", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VFIO_PCI); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml index 62bead5..17ff4c8 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml @@ -22,10 +22,9 @@ <model name='spapr-pci-host-bridge'/> <target index='0'/> </controller> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> </controller> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> @@ -39,7 +38,7 @@ <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </hostdev> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml index 77c0909..58023ec 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml @@ -19,15 +19,13 @@ <model name='spapr-pci-host-bridge'/> <target index='0'/> </controller> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> </controller> - <controller type='pci' index='2' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='2'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> </controller> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> @@ -41,7 +39,7 @@ <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </hostdev> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml index 9044936..eb7bb80 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml @@ -22,10 +22,9 @@ <model name='spapr-pci-host-bridge'/> <target index='0'/> </controller> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> </controller> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml index b596fe6..ff7a08f 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml @@ -15,110 +15,109 @@ <devices> <emulator>/usr/bin/qemu-system-ppc64</emulator> <controller type='scsi' index='0' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> <controller type='scsi' index='1' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </controller> <controller type='scsi' index='2' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </controller> <controller type='scsi' index='3' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </controller> <controller type='scsi' index='4' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </controller> <controller type='scsi' index='5' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </controller> <controller type='scsi' index='6' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </controller> <controller type='scsi' index='7' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> </controller> <controller type='scsi' index='8' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> </controller> <controller type='scsi' index='9' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> </controller> <controller type='scsi' index='10' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> </controller> <controller type='scsi' index='11' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> </controller> <controller type='scsi' index='12' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/> </controller> <controller type='scsi' index='13' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/> </controller> <controller type='scsi' index='14' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x10' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/> </controller> <controller type='scsi' index='15' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x11' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x10' function='0x0'/> </controller> <controller type='scsi' index='16' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x12' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x11' function='0x0'/> </controller> <controller type='scsi' index='17' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x13' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x12' function='0x0'/> </controller> <controller type='scsi' index='18' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x14' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x13' function='0x0'/> </controller> <controller type='scsi' index='19' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x15' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x14' function='0x0'/> </controller> <controller type='scsi' index='20' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x16' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x15' function='0x0'/> </controller> <controller type='scsi' index='21' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x17' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x16' function='0x0'/> </controller> <controller type='scsi' index='22' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x18' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x17' function='0x0'/> </controller> <controller type='scsi' index='23' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x19' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x18' function='0x0'/> </controller> <controller type='scsi' index='24' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1a' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x19' function='0x0'/> </controller> <controller type='scsi' index='25' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1a' function='0x0'/> </controller> <controller type='scsi' index='26' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1c' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/> </controller> <controller type='scsi' index='27' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1c' function='0x0'/> </controller> <controller type='scsi' index='28' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0'/> </controller> <controller type='scsi' index='29' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/> </controller> <controller type='scsi' index='30' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x0'/> </controller> <controller type='scsi' index='31' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> </controller> <controller type='usb' index='0' model='none'/> <controller type='pci' index='0' model='pci-root'> <model name='spapr-pci-host-bridge'/> <target index='0'/> </controller> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> </controller> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 378cd85..8aac902 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -686,12 +686,10 @@ mymain(void) DO_TEST("pseries-many-devices", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-many-buses-1", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-many-buses-2", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, @@ -707,14 +705,12 @@ mymain(void) QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VFIO_PCI); DO_TEST("pseries-hostdevs-3", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VFIO_PCI); -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
When looking for slots suitable for a PCI device, libvirt might need to add an extra PCI controller: for pSeries guests, we want that extra controller to be a PHB (pci-root) rather than a PCI bridge.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Laine Stump <laine@laine.org> (pretty simple change once I saw that most of the diffs were just due to an indentation change)
--- src/conf/domain_addr.c | 56 +++++++++-------- src/conf/domain_addr.h | 2 + src/qemu/qemu_domain_address.c | 4 ++ .../qemuxml2argv-pseries-hostdevs-2.args | 8 +-- .../qemuxml2argv-pseries-hostdevs-3.args | 8 +-- .../qemuxml2argv-pseries-many-buses-1.args | 4 +- .../qemuxml2argv-pseries-many-devices.args | 66 ++++++++++---------- tests/qemuxml2argvtest.c | 4 -- .../qemuxml2xmlout-pseries-hostdevs-2.xml | 9 ++- .../qemuxml2xmlout-pseries-hostdevs-3.xml | 16 +++-- .../qemuxml2xmlout-pseries-many-buses-1.xml | 7 +-- .../qemuxml2xmlout-pseries-many-devices.xml | 71 +++++++++++----------- tests/qemuxml2xmltest.c | 4 -- 13 files changed, 129 insertions(+), 130 deletions(-)
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 86b1367..b9e9145 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -383,33 +383,39 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs, */
if (flags & VIR_PCI_CONNECT_TYPE_PCI_DEVICE) { - model = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE; + if (addrs->multipleRootsSupported) { + /* Use a pci-root controller to expand the guest's PCI + * topology if it supports having more than one */ + model = VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT; + } else { + model = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE;
- /* if there aren't yet any buses that will accept a - * pci-bridge, and the caller is asking for one, we'll need to - * add a dmi-to-pci-bridge first. - */ - needDMIToPCIBridge = true; - for (i = 0; i < addrs->nbuses; i++) { - if (addrs->buses[i].flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE) { - needDMIToPCIBridge = false; - break; - } - } - if (needDMIToPCIBridge && add == 1) { - /* We need to add a single pci-bridge to provide the bus - * our legacy PCI device will be plugged into; however, we - * have also determined that there isn't yet any proper - * place to connect that pci-bridge we're about to add (on - * a system with pcie-root, that "proper place" would be a - * dmi-to-pci-bridge". So, to give the pci-bridge a place - * to connect, we increase the count of buses to add, - * while also incrementing the bus number in the address - * for the device (since the pci-bridge will now be at an - * index 1 higher than the caller had anticipated). + /* if there aren't yet any buses that will accept a + * pci-bridge, and the caller is asking for one, we'll need to + * add a dmi-to-pci-bridge first. */ - add++; - addr->bus++; + needDMIToPCIBridge = true; + for (i = 0; i < addrs->nbuses; i++) { + if (addrs->buses[i].flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE) { + needDMIToPCIBridge = false; + break; + } + } + if (needDMIToPCIBridge && add == 1) { + /* We need to add a single pci-bridge to provide the bus + * our legacy PCI device will be plugged into; however, we + * have also determined that there isn't yet any proper + * place to connect that pci-bridge we're about to add (on + * a system with pcie-root, that "proper place" would be a + * dmi-to-pci-bridge". So, to give the pci-bridge a place + * to connect, we increase the count of buses to add, + * while also incrementing the bus number in the address + * for the device (since the pci-bridge will now be at an + * index 1 higher than the caller had anticipated). + */ + add++; + addr->bus++; + } } } else if (flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE && addrs->buses[0].model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) { diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index c98a228..9cd1b29 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -108,6 +108,8 @@ struct _virDomainPCIAddressSet { size_t nbuses; bool dryRun; /* on a dry run, new buses are auto-added and addresses aren't saved in device infos */ + /* If true, the guest can have multiple pci-root controllers */ + bool multipleRootsSupported; }; typedef struct _virDomainPCIAddressSet virDomainPCIAddressSet; typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 082cb72..50e41a4 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1061,6 +1061,10 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
addrs->dryRun = dryRun;
+ /* pSeries domains support multiple pci-root controllers */ + if (qemuDomainIsPSeries(def)) + addrs->multipleRootsSupported = true; + for (i = 0; i < def->ncontrollers; i++) { virDomainControllerDefPtr cont = def->controllers[i]; size_t idx = cont->idx; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args index c43e15d..83d4306 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args @@ -18,7 +18,7 @@ QEMU_AUDIO_DRV=none \ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ --device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ --device virtio-scsi-pci,id=scsi0,bus=pci.1,addr=0x1 \ --device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.1,addr=0x2 \ --device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x2 +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.1.0,addr=0x1 \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.1.0,addr=0x2 \ +-device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args index 99df2e7..eda6cc7 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args @@ -18,7 +18,7 @@ QEMU_AUDIO_DRV=none \ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ --device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.0,addr=0x2 \ --device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.2,addr=0x1 \ --device vfio-pci,host=0001:01:00.1,id=hostdev1,bus=pci.0,addr=0x3 +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device spapr-pci-host-bridge,index=2,id=pci.2 \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.2.0,addr=0x1 \ +-device vfio-pci,host=0001:01:00.1,id=hostdev1,bus=pci.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args index bf78fc1..eb5ccbd 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-buses-1.args @@ -18,5 +18,5 @@ QEMU_AUDIO_DRV=none \ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ --device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ --device virtio-scsi-pci,id=scsi0,bus=pci.1,addr=0x1 +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.1.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args index 1db4533..f20bc52 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-many-devices.args @@ -18,36 +18,36 @@ QEMU_AUDIO_DRV=none \ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ --device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \ --device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x2 \ --device virtio-scsi-pci,id=scsi1,bus=pci.0,addr=0x3 \ --device virtio-scsi-pci,id=scsi2,bus=pci.0,addr=0x4 \ --device virtio-scsi-pci,id=scsi3,bus=pci.0,addr=0x5 \ --device virtio-scsi-pci,id=scsi4,bus=pci.0,addr=0x6 \ --device virtio-scsi-pci,id=scsi5,bus=pci.0,addr=0x7 \ --device virtio-scsi-pci,id=scsi6,bus=pci.0,addr=0x8 \ --device virtio-scsi-pci,id=scsi7,bus=pci.0,addr=0x9 \ --device virtio-scsi-pci,id=scsi8,bus=pci.0,addr=0xa \ --device virtio-scsi-pci,id=scsi9,bus=pci.0,addr=0xb \ --device virtio-scsi-pci,id=scsi10,bus=pci.0,addr=0xc \ --device virtio-scsi-pci,id=scsi11,bus=pci.0,addr=0xd \ --device virtio-scsi-pci,id=scsi12,bus=pci.0,addr=0xe \ --device virtio-scsi-pci,id=scsi13,bus=pci.0,addr=0xf \ --device virtio-scsi-pci,id=scsi14,bus=pci.0,addr=0x10 \ --device virtio-scsi-pci,id=scsi15,bus=pci.0,addr=0x11 \ --device virtio-scsi-pci,id=scsi16,bus=pci.0,addr=0x12 \ --device virtio-scsi-pci,id=scsi17,bus=pci.0,addr=0x13 \ --device virtio-scsi-pci,id=scsi18,bus=pci.0,addr=0x14 \ --device virtio-scsi-pci,id=scsi19,bus=pci.0,addr=0x15 \ --device virtio-scsi-pci,id=scsi20,bus=pci.0,addr=0x16 \ --device virtio-scsi-pci,id=scsi21,bus=pci.0,addr=0x17 \ --device virtio-scsi-pci,id=scsi22,bus=pci.0,addr=0x18 \ --device virtio-scsi-pci,id=scsi23,bus=pci.0,addr=0x19 \ --device virtio-scsi-pci,id=scsi24,bus=pci.0,addr=0x1a \ --device virtio-scsi-pci,id=scsi25,bus=pci.0,addr=0x1b \ --device virtio-scsi-pci,id=scsi26,bus=pci.0,addr=0x1c \ --device virtio-scsi-pci,id=scsi27,bus=pci.0,addr=0x1d \ --device virtio-scsi-pci,id=scsi28,bus=pci.0,addr=0x1e \ --device virtio-scsi-pci,id=scsi29,bus=pci.0,addr=0x1f \ --device virtio-scsi-pci,id=scsi30,bus=pci.1,addr=0x1 \ --device virtio-scsi-pci,id=scsi31,bus=pci.1,addr=0x2 +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x1 \ +-device virtio-scsi-pci,id=scsi1,bus=pci.0,addr=0x2 \ +-device virtio-scsi-pci,id=scsi2,bus=pci.0,addr=0x3 \ +-device virtio-scsi-pci,id=scsi3,bus=pci.0,addr=0x4 \ +-device virtio-scsi-pci,id=scsi4,bus=pci.0,addr=0x5 \ +-device virtio-scsi-pci,id=scsi5,bus=pci.0,addr=0x6 \ +-device virtio-scsi-pci,id=scsi6,bus=pci.0,addr=0x7 \ +-device virtio-scsi-pci,id=scsi7,bus=pci.0,addr=0x8 \ +-device virtio-scsi-pci,id=scsi8,bus=pci.0,addr=0x9 \ +-device virtio-scsi-pci,id=scsi9,bus=pci.0,addr=0xa \ +-device virtio-scsi-pci,id=scsi10,bus=pci.0,addr=0xb \ +-device virtio-scsi-pci,id=scsi11,bus=pci.0,addr=0xc \ +-device virtio-scsi-pci,id=scsi12,bus=pci.0,addr=0xd \ +-device virtio-scsi-pci,id=scsi13,bus=pci.0,addr=0xe \ +-device virtio-scsi-pci,id=scsi14,bus=pci.0,addr=0xf \ +-device virtio-scsi-pci,id=scsi15,bus=pci.0,addr=0x10 \ +-device virtio-scsi-pci,id=scsi16,bus=pci.0,addr=0x11 \ +-device virtio-scsi-pci,id=scsi17,bus=pci.0,addr=0x12 \ +-device virtio-scsi-pci,id=scsi18,bus=pci.0,addr=0x13 \ +-device virtio-scsi-pci,id=scsi19,bus=pci.0,addr=0x14 \ +-device virtio-scsi-pci,id=scsi20,bus=pci.0,addr=0x15 \ +-device virtio-scsi-pci,id=scsi21,bus=pci.0,addr=0x16 \ +-device virtio-scsi-pci,id=scsi22,bus=pci.0,addr=0x17 \ +-device virtio-scsi-pci,id=scsi23,bus=pci.0,addr=0x18 \ +-device virtio-scsi-pci,id=scsi24,bus=pci.0,addr=0x19 \ +-device virtio-scsi-pci,id=scsi25,bus=pci.0,addr=0x1a \ +-device virtio-scsi-pci,id=scsi26,bus=pci.0,addr=0x1b \ +-device virtio-scsi-pci,id=scsi27,bus=pci.0,addr=0x1c \ +-device virtio-scsi-pci,id=scsi28,bus=pci.0,addr=0x1d \ +-device virtio-scsi-pci,id=scsi29,bus=pci.0,addr=0x1e \ +-device virtio-scsi-pci,id=scsi30,bus=pci.0,addr=0x1f \ +-device virtio-scsi-pci,id=scsi31,bus=pci.1.0,addr=0x1 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index f1720cb..c0582c3 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1720,12 +1720,10 @@ mymain(void) DO_TEST("pseries-many-devices", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-many-buses-1", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-many-buses-2", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, @@ -1741,14 +1739,12 @@ mymain(void) QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VFIO_PCI); DO_TEST("pseries-hostdevs-3", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VFIO_PCI);
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml index 62bead5..17ff4c8 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml @@ -22,10 +22,9 @@ <model name='spapr-pci-host-bridge'/> <target index='0'/> </controller> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> </controller> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> @@ -39,7 +38,7 @@ <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </hostdev> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml index 77c0909..58023ec 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml @@ -19,15 +19,13 @@ <model name='spapr-pci-host-bridge'/> <target index='0'/> </controller> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> </controller> - <controller type='pci' index='2' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='2'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> </controller> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> @@ -41,7 +39,7 @@ <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </hostdev> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml index 9044936..eb7bb80 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-buses-1.xml @@ -22,10 +22,9 @@ <model name='spapr-pci-host-bridge'/> <target index='0'/> </controller> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> </controller> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml index b596fe6..ff7a08f 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-many-devices.xml @@ -15,110 +15,109 @@ <devices> <emulator>/usr/bin/qemu-system-ppc64</emulator> <controller type='scsi' index='0' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </controller> <controller type='scsi' index='1' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </controller> <controller type='scsi' index='2' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </controller> <controller type='scsi' index='3' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </controller> <controller type='scsi' index='4' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </controller> <controller type='scsi' index='5' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </controller> <controller type='scsi' index='6' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </controller> <controller type='scsi' index='7' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> </controller> <controller type='scsi' index='8' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> </controller> <controller type='scsi' index='9' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> </controller> <controller type='scsi' index='10' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> </controller> <controller type='scsi' index='11' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> </controller> <controller type='scsi' index='12' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/> </controller> <controller type='scsi' index='13' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/> </controller> <controller type='scsi' index='14' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x10' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/> </controller> <controller type='scsi' index='15' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x11' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x10' function='0x0'/> </controller> <controller type='scsi' index='16' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x12' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x11' function='0x0'/> </controller> <controller type='scsi' index='17' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x13' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x12' function='0x0'/> </controller> <controller type='scsi' index='18' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x14' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x13' function='0x0'/> </controller> <controller type='scsi' index='19' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x15' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x14' function='0x0'/> </controller> <controller type='scsi' index='20' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x16' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x15' function='0x0'/> </controller> <controller type='scsi' index='21' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x17' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x16' function='0x0'/> </controller> <controller type='scsi' index='22' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x18' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x17' function='0x0'/> </controller> <controller type='scsi' index='23' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x19' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x18' function='0x0'/> </controller> <controller type='scsi' index='24' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1a' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x19' function='0x0'/> </controller> <controller type='scsi' index='25' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1a' function='0x0'/> </controller> <controller type='scsi' index='26' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1c' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/> </controller> <controller type='scsi' index='27' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1c' function='0x0'/> </controller> <controller type='scsi' index='28' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0'/> </controller> <controller type='scsi' index='29' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/> </controller> <controller type='scsi' index='30' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x0'/> </controller> <controller type='scsi' index='31' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> </controller> <controller type='usb' index='0' model='none'/> <controller type='pci' index='0' model='pci-root'> <model name='spapr-pci-host-bridge'/> <target index='0'/> </controller> - <controller type='pci' index='1' model='pci-bridge'> - <model name='pci-bridge'/> - <target chassisNr='1'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> </controller> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 378cd85..8aac902 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -686,12 +686,10 @@ mymain(void) DO_TEST("pseries-many-devices", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-many-buses-1", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("pseries-many-buses-2", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, @@ -707,14 +705,12 @@ mymain(void) QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VFIO_PCI); DO_TEST("pseries-hostdevs-3", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, - QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VFIO_PCI);

Isolation groups will eventually allow us to make sure certain devices, eg. PCI hostdevs, are assigned to guest PCI buses in a way that guarantees improved isolation, error detection and recovery for machine types and hypervisors that support it, eg. pSeries guest on QEMU. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/bhyve/bhyve_device.c | 4 ++-- src/conf/device_conf.h | 10 ++++++++++ src/conf/domain_addr.c | 17 ++++++++++++----- src/conf/domain_addr.h | 9 ++++++++- src/qemu/qemu_domain_address.c | 35 ++++++++++++++++++----------------- 5 files changed, 50 insertions(+), 25 deletions(-) diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c index fdfd512..03aa6c9 100644 --- a/src/bhyve/bhyve_device.c +++ b/src/bhyve/bhyve_device.c @@ -57,7 +57,7 @@ bhyveCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, } if (virDomainPCIAddressReserveAddr(addrs, addr, - VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) { + VIR_PCI_CONNECT_TYPE_PCI_DEVICE, 0) < 0) { goto cleanup; } @@ -100,7 +100,7 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def, lpc_addr.slot = 0x1; if (virDomainPCIAddressReserveAddr(addrs, &lpc_addr, - VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) { + VIR_PCI_CONNECT_TYPE_PCI_DEVICE, 0) < 0) { goto error; } diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index 14be2e3..b9beafd 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -164,6 +164,16 @@ struct _virDomainDeviceInfo { */ int pciConnectFlags; /* enum virDomainPCIConnectFlags */ char *loadparm; + + /* PCI devices will only be automatically placed on a PCI bus + * that shares the same isolation group */ + int isolationGroup; + + /* Usually, PCI buses will take on the same isolation group + * as the first device that is plugged into them, but in some + * cases we might want to prevent that from happening by + * locking the isolation group */ + bool isolationGroupLocked; }; diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index b9e9145..48af1f5 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -534,6 +534,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, virDomainPCIConnectFlags flags, + int isolationGroup ATTRIBUTE_UNUSED, bool fromConfig) { int ret = -1; @@ -586,9 +587,11 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, - virDomainPCIConnectFlags flags) + virDomainPCIConnectFlags flags, + int isolationGroup) { - return virDomainPCIAddressReserveAddrInternal(addrs, addr, flags, true); + return virDomainPCIAddressReserveAddrInternal(addrs, addr, flags, + isolationGroup, true); } int @@ -624,7 +627,8 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs, goto cleanup; ret = virDomainPCIAddressReserveAddrInternal(addrs, &dev->addr.pci, - flags, true); + flags, dev->isolationGroup, + true); } else { ret = virDomainPCIAddressReserveNextAddr(addrs, dev, flags, -1); } @@ -745,6 +749,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr next_addr, virDomainPCIConnectFlags flags, + int isolationGroup ATTRIBUTE_UNUSED, int function) { virPCIDeviceAddress a = { 0 }; @@ -825,10 +830,12 @@ virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, { virPCIDeviceAddress addr; - if (virDomainPCIAddressGetNextAddr(addrs, &addr, flags, function) < 0) + if (virDomainPCIAddressGetNextAddr(addrs, &addr, flags, + dev->isolationGroup, function) < 0) return -1; - if (virDomainPCIAddressReserveAddrInternal(addrs, &addr, flags, false) < 0) + if (virDomainPCIAddressReserveAddrInternal(addrs, &addr, flags, + dev->isolationGroup, false) < 0) return -1; if (!addrs->dryRun) { diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 9cd1b29..f8d63df 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -100,6 +100,12 @@ typedef struct { * bit is set, that function is in use by a device. */ virDomainPCIAddressSlot slot[VIR_PCI_ADDRESS_SLOT_LAST + 1]; + + /* See virDomainDeviceInfo::isolationGroup */ + int isolationGroup; + + /* See virDomainDeviceInfo::isolationGroupLocked */ + bool isolationGroupLocked; } virDomainPCIAddressBus; typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr; @@ -139,7 +145,8 @@ bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs, int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, - virDomainPCIConnectFlags flags) + virDomainPCIConnectFlags flags, + int isolationGroup) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); int virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 50e41a4..3d56900 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1037,7 +1037,8 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, } if (virDomainPCIAddressReserveAddr(addrs, addr, - info->pciConnectFlags) < 0) { + info->pciConnectFlags, + info->isolationGroup) < 0) { goto cleanup; } @@ -1082,6 +1083,10 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def, if (virDomainPCIAddressBusSetModel(&addrs->buses[idx], cont->model) < 0) goto error; + /* Forward the information about whether or not this bus should + * be allowed to change isolation groups */ + addrs->buses[idx].isolationGroupLocked = cont->info.isolationGroupLocked; + if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) hasPCIeRoot = true; } @@ -1198,7 +1203,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, if (addrs->nbuses) { memset(&tmp_addr, 0, sizeof(tmp_addr)); tmp_addr.slot = 1; - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; } @@ -1233,7 +1238,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, goto cleanup; } } else { - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; primaryVideo->info.addr.pci = tmp_addr; primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; @@ -1258,7 +1263,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, VIR_DEBUG("PCI address 0:0:2.0 in use, future addition of a video" " device will not be possible without manual" " intervention"); - } else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) { + } else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) { goto cleanup; } } @@ -1334,10 +1339,8 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, assign = true; } if (assign) { - if (virDomainPCIAddressReserveAddr(addrs, - &tmp_addr, flags) < 0) { + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; - } cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; cont->info.addr.pci.domain = 0; @@ -1359,10 +1362,8 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, memset(&tmp_addr, 0, sizeof(tmp_addr)); tmp_addr.slot = 0x1E; if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) { - if (virDomainPCIAddressReserveAddr(addrs, - &tmp_addr, flags) < 0) { + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; - } cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; cont->info.addr.pci.domain = 0; @@ -1385,12 +1386,12 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, tmp_addr.slot = 0x1F; tmp_addr.function = 0; tmp_addr.multi = VIR_TRISTATE_SWITCH_ON; - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; tmp_addr.function = 3; tmp_addr.multi = VIR_TRISTATE_SWITCH_ABSENT; - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; } @@ -1424,7 +1425,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, goto cleanup; } } else { - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; primaryVideo->info.addr.pci = tmp_addr; @@ -1450,8 +1451,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, " device will not be possible without manual" " intervention"); virResetLastError(); - } else if (virDomainPCIAddressReserveAddr(addrs, - &tmp_addr, flags) < 0) { + } else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) { goto cleanup; } } @@ -1472,7 +1472,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, !virDeviceInfoPCIAddressWanted(&sound->info)) { continue; } - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; sound->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; @@ -1689,7 +1689,8 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, if (foundAddr) { /* Reserve this function on the slot we found */ if (virDomainPCIAddressReserveAddr(addrs, &addr, - cont->info.pciConnectFlags) < 0) { + cont->info.pciConnectFlags, + cont->info.isolationGroup) < 0) { goto error; } -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
Isolation groups will eventually allow us to make sure certain devices, eg. PCI hostdevs, are assigned to guest PCI buses in a way that guarantees improved isolation, error detection and recovery for machine types and hypervisors that support it, eg. pSeries guest on QEMU.
This is a nice introduction of what isolation groups will do, but doesn't really explain what this patch does. As I understand it, it is just adding the isolation group to virDomainDeviceInfo (so that each device can have an isolation group associated with it) and to virDomainPCIAddressBus (so that each bus can have an isolation group), then adds an isolationGroup arg (so far unused) to all the PCI address allocation functions - presumably the next couple patches will fill in the hypervisor-specific logic to request a particular isolation group when desired, and the logic in the allocator to honor those requests. That all makes sense to me.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Laine Stump <laine@laine.org>
--- src/bhyve/bhyve_device.c | 4 ++-- src/conf/device_conf.h | 10 ++++++++++ src/conf/domain_addr.c | 17 ++++++++++++----- src/conf/domain_addr.h | 9 ++++++++- src/qemu/qemu_domain_address.c | 35 ++++++++++++++++++----------------- 5 files changed, 50 insertions(+), 25 deletions(-)
diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c index fdfd512..03aa6c9 100644 --- a/src/bhyve/bhyve_device.c +++ b/src/bhyve/bhyve_device.c @@ -57,7 +57,7 @@ bhyveCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, }
if (virDomainPCIAddressReserveAddr(addrs, addr, - VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) { + VIR_PCI_CONNECT_TYPE_PCI_DEVICE, 0) < 0) { goto cleanup; }
@@ -100,7 +100,7 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def, lpc_addr.slot = 0x1;
if (virDomainPCIAddressReserveAddr(addrs, &lpc_addr, - VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) { + VIR_PCI_CONNECT_TYPE_PCI_DEVICE, 0) < 0) { goto error; }
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index 14be2e3..b9beafd 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -164,6 +164,16 @@ struct _virDomainDeviceInfo { */ int pciConnectFlags; /* enum virDomainPCIConnectFlags */ char *loadparm; + + /* PCI devices will only be automatically placed on a PCI bus + * that shares the same isolation group */ + int isolationGroup; + + /* Usually, PCI buses will take on the same isolation group + * as the first device that is plugged into them, but in some + * cases we might want to prevent that from happening by + * locking the isolation group */ + bool isolationGroupLocked; };
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index b9e9145..48af1f5 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -534,6 +534,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, virDomainPCIConnectFlags flags, + int isolationGroup ATTRIBUTE_UNUSED, bool fromConfig) { int ret = -1; @@ -586,9 +587,11 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, - virDomainPCIConnectFlags flags) + virDomainPCIConnectFlags flags, + int isolationGroup) { - return virDomainPCIAddressReserveAddrInternal(addrs, addr, flags, true); + return virDomainPCIAddressReserveAddrInternal(addrs, addr, flags, + isolationGroup, true); }
int @@ -624,7 +627,8 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs, goto cleanup;
ret = virDomainPCIAddressReserveAddrInternal(addrs, &dev->addr.pci, - flags, true); + flags, dev->isolationGroup, + true); } else { ret = virDomainPCIAddressReserveNextAddr(addrs, dev, flags, -1); } @@ -745,6 +749,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr next_addr, virDomainPCIConnectFlags flags, + int isolationGroup ATTRIBUTE_UNUSED, int function) { virPCIDeviceAddress a = { 0 }; @@ -825,10 +830,12 @@ virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, { virPCIDeviceAddress addr;
- if (virDomainPCIAddressGetNextAddr(addrs, &addr, flags, function) < 0) + if (virDomainPCIAddressGetNextAddr(addrs, &addr, flags, + dev->isolationGroup, function) < 0) return -1;
- if (virDomainPCIAddressReserveAddrInternal(addrs, &addr, flags, false) < 0) + if (virDomainPCIAddressReserveAddrInternal(addrs, &addr, flags, + dev->isolationGroup, false) < 0) return -1;
if (!addrs->dryRun) { diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 9cd1b29..f8d63df 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -100,6 +100,12 @@ typedef struct { * bit is set, that function is in use by a device. */ virDomainPCIAddressSlot slot[VIR_PCI_ADDRESS_SLOT_LAST + 1]; + + /* See virDomainDeviceInfo::isolationGroup */ + int isolationGroup; + + /* See virDomainDeviceInfo::isolationGroupLocked */ + bool isolationGroupLocked; } virDomainPCIAddressBus; typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr;
@@ -139,7 +145,8 @@ bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, - virDomainPCIConnectFlags flags) + virDomainPCIConnectFlags flags, + int isolationGroup) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 50e41a4..3d56900 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1037,7 +1037,8 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, }
if (virDomainPCIAddressReserveAddr(addrs, addr, - info->pciConnectFlags) < 0) { + info->pciConnectFlags, + info->isolationGroup) < 0) { goto cleanup; }
@@ -1082,6 +1083,10 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def, if (virDomainPCIAddressBusSetModel(&addrs->buses[idx], cont->model) < 0) goto error;
+ /* Forward the information about whether or not this bus should + * be allowed to change isolation groups */ + addrs->buses[idx].isolationGroupLocked = cont->info.isolationGroupLocked; + if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) hasPCIeRoot = true; } @@ -1198,7 +1203,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, if (addrs->nbuses) { memset(&tmp_addr, 0, sizeof(tmp_addr)); tmp_addr.slot = 1; - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; }
@@ -1233,7 +1238,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, goto cleanup; } } else { - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; primaryVideo->info.addr.pci = tmp_addr; primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; @@ -1258,7 +1263,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, VIR_DEBUG("PCI address 0:0:2.0 in use, future addition of a video" " device will not be possible without manual" " intervention"); - } else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) { + } else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) { goto cleanup; } } @@ -1334,10 +1339,8 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, assign = true; } if (assign) { - if (virDomainPCIAddressReserveAddr(addrs, - &tmp_addr, flags) < 0) { + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; - }
cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; cont->info.addr.pci.domain = 0; @@ -1359,10 +1362,8 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, memset(&tmp_addr, 0, sizeof(tmp_addr)); tmp_addr.slot = 0x1E; if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) { - if (virDomainPCIAddressReserveAddr(addrs, - &tmp_addr, flags) < 0) { + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; - }
cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; cont->info.addr.pci.domain = 0; @@ -1385,12 +1386,12 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, tmp_addr.slot = 0x1F; tmp_addr.function = 0; tmp_addr.multi = VIR_TRISTATE_SWITCH_ON; - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup;
tmp_addr.function = 3; tmp_addr.multi = VIR_TRISTATE_SWITCH_ABSENT; - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; }
@@ -1424,7 +1425,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, goto cleanup; } } else { - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup; primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; primaryVideo->info.addr.pci = tmp_addr; @@ -1450,8 +1451,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, " device will not be possible without manual" " intervention"); virResetLastError(); - } else if (virDomainPCIAddressReserveAddr(addrs, - &tmp_addr, flags) < 0) { + } else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) { goto cleanup; } } @@ -1472,7 +1472,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, !virDeviceInfoPCIAddressWanted(&sound->info)) { continue; } - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) goto cleanup;
sound->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; @@ -1689,7 +1689,8 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, if (foundAddr) { /* Reserve this function on the slot we found */ if (virDomainPCIAddressReserveAddr(addrs, &addr, - cont->info.pciConnectFlags) < 0) { + cont->info.pciConnectFlags, + cont->info.isolationGroup) < 0) { goto error; }

On Wed, 2017-06-28 at 13:32 -0400, Laine Stump wrote:
Isolation groups will eventually allow us to make sure certain devices, eg. PCI hostdevs, are assigned to guest PCI buses in a way that guarantees improved isolation, error detection and recovery for machine types and hypervisors that support it, eg. pSeries guest on QEMU. This is a nice introduction of what isolation groups will do, but doesn't really explain what this patch does. As I understand it, it is just adding the isolation group to virDomainDeviceInfo (so that each device can have an isolation group associated with it) and to virDomainPCIAddressBus (so that each bus can have an isolation group), then adds an isolationGroup arg (so far unused) to all the PCI address allocation functions - presumably the next couple patches will fill in the hypervisor-specific logic to request a particular isolation group when desired, and the logic in the allocator to honor those requests. That all makes sense to me.
That's correct: this first patch merely defines storage for the new information we're going to need later on and makes sure it is passed between the QEMU (or bhyve) driver and PCI address allocation code. I'll add this information to the commit message. -- Andrea Bolognani / Red Hat / Virtualization

These rules will make it possible for libvirt to automatically assign PCI addresses in a way that respects any isolation constraints devices might have. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/domain_addr.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 5 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 48af1f5..22ff014 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -534,7 +534,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, virDomainPCIConnectFlags flags, - int isolationGroup ATTRIBUTE_UNUSED, + int isolationGroup, bool fromConfig) { int ret = -1; @@ -542,6 +542,8 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, virDomainPCIAddressBusPtr bus; virErrorNumber errType = (fromConfig ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR); + bool firstDevice; + size_t slot; if (!(addrStr = virDomainPCIAddressAsString(addr))) goto cleanup; @@ -572,6 +574,36 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, bus->slot[addr->slot].aggregate = true; } + /* Figure out whether this is the first device we're plugging + * into the bus by looking at all the slots */ + firstDevice = true; + for (slot = bus->minSlot; slot <= bus->maxSlot; slot++) { + if (bus->slot[slot].functions) { + firstDevice = false; + break; + } + } + + if (firstDevice && !bus->isolationGroupLocked) { + /* The first device decides the isolation group for the + * entire bus */ + bus->isolationGroup = isolationGroup; + VIR_DEBUG("PCI bus %.4x:%.2x assigned isolation group %d because of " + "first device %s", + addr->domain, addr->bus, isolationGroup, addrStr); + } else if (bus->isolationGroup != isolationGroup && fromConfig) { + /* If this is not the first function and its isolation group + * doesn't match the bus', then it should not be using this + * address. However, if the address comes from the user then + * we comply with the request and change the isolation group + * back to the default (because at that point isolation can't + * be guaranteed anymore) */ + bus->isolationGroup = 0; + VIR_DEBUG("PCI bus %.4x:%.2x assigned isolation group %d because of " + "user assigned address %s", + addr->domain, addr->bus, isolationGroup, addrStr); + } + /* mark the requested function as reserved */ bus->slot[addr->slot].functions |= (1 << addr->function); VIR_DEBUG("Reserving PCI address %s (aggregate='%s')", addrStr, @@ -643,7 +675,28 @@ int virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr) { - addrs->buses[addr->bus].slot[addr->slot].functions &= ~(1 << addr->function); + virDomainPCIAddressBusPtr bus = &addrs->buses[addr->bus]; + bool lastDevice; + size_t slot; + + bus->slot[addr->slot].functions &= ~(1 << addr->function); + + /* Figure out whether this is the first device we're plugging + * into the bus by looking at all the slots */ + lastDevice = true; + for (slot = bus->minSlot; slot <= bus->maxSlot; slot++) { + if (bus->slot[slot].functions) { + lastDevice = false; + break; + } + } + + /* If the one we just unplugged was the last device on the bus, + * we can reset the isolation group for the bus so that any + * device we'll try to plug in from now on will be accepted */ + if (lastDevice && !bus->isolationGroupLocked) + bus->isolationGroup = 0; + return 0; } @@ -749,7 +802,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr next_addr, virDomainPCIConnectFlags flags, - int isolationGroup ATTRIBUTE_UNUSED, + int isolationGroup, int function) { virPCIDeviceAddress a = { 0 }; @@ -765,11 +818,50 @@ virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, else a.function = function; - /* "Begin at the beginning," the King said, very gravely, "and go on - * till you come to the end: then stop." */ + /* When looking for a suitable bus for the device, start by being + * very strict and ignoring all those where the isolation groups + * don't match. This ensures all devices sharing the same isolation + * group will end up on the same group */ + for (a.bus = 0; a.bus < addrs->nbuses; a.bus++) { + virDomainPCIAddressBusPtr bus = &addrs->buses[a.bus]; + bool found = false; + + if (bus->isolationGroup != isolationGroup) + continue; + + a.slot = bus->minSlot; + + if (virDomainPCIAddressFindUnusedFunctionOnBus(bus, &a, function, + flags, &found) < 0) { + goto error; + } + + if (found) + goto success; + } + + /* We haven't been able to find a perfectly matching bus, but we + * might still be able to make this work by altering the isolation + * group for a bus that's currently empty. So let's try that */ for (a.bus = 0; a.bus < addrs->nbuses; a.bus++) { virDomainPCIAddressBusPtr bus = &addrs->buses[a.bus]; bool found = false; + bool firstDevice = true; + size_t slot; + + /* Go through all the slots and see whether they are empty */ + for (slot = bus->minSlot; slot <= bus->maxSlot; slot++) { + if (bus->slot[slot].functions) { + firstDevice = false; + break; + } + } + + /* We can only change the isolation group for a bus when + * plugging in the first device; moreover, some buses are + * prevented from ever changing it */ + if (!firstDevice || bus->isolationGroupLocked) + continue; a.slot = bus->minSlot; @@ -778,6 +870,8 @@ virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, goto error; } + /* The isolation group for the bus will actually be changed + * later, in virDomainPCIAddressReserveAddrInternal() */ if (found) goto success; } -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
These rules will make it possible for libvirt to automatically assign PCI addresses in a way that respects any isolation constraints devices might have.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/conf/domain_addr.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 5 deletions(-)
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 48af1f5..22ff014 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -534,7 +534,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, virDomainPCIConnectFlags flags, - int isolationGroup ATTRIBUTE_UNUSED, + int isolationGroup, bool fromConfig) { int ret = -1; @@ -542,6 +542,8 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, virDomainPCIAddressBusPtr bus; virErrorNumber errType = (fromConfig ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR); + bool firstDevice; + size_t slot;
if (!(addrStr = virDomainPCIAddressAsString(addr))) goto cleanup; @@ -572,6 +574,36 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, bus->slot[addr->slot].aggregate = true; }
+ /* Figure out whether this is the first device we're plugging + * into the bus by looking at all the slots */ + firstDevice = true; + for (slot = bus->minSlot; slot <= bus->maxSlot; slot++) { + if (bus->slot[slot].functions) { + firstDevice = false; + break; + } + }
You have the same loop 3 times in the code (although in one case the bool is called "lastDevice" instead of "firstDevice". How about a short utility function called virDomainPCIAddressBusIsEmpty() (or something like that)?
+ + if (firstDevice && !bus->isolationGroupLocked) { + /* The first device decides the isolation group for the + * entire bus */ + bus->isolationGroup = isolationGroup; + VIR_DEBUG("PCI bus %.4x:%.2x assigned isolation group %d because of " + "first device %s", + addr->domain, addr->bus, isolationGroup, addrStr);
I haven't tried out these patches, but it looks like all this stuff happens for everybody all the time, not just for pSeries, correct? I suppose it's an effective NOP if everything is group 0 though, right?
+ } else if (bus->isolationGroup != isolationGroup && fromConfig) { + /* If this is not the first function and its isolation group + * doesn't match the bus', then it should not be using this + * address. However, if the address comes from the user then + * we comply with the request and change the isolation group + * back to the default (because at that point isolation can't + * be guaranteed anymore) */ + bus->isolationGroup = 0; + VIR_DEBUG("PCI bus %.4x:%.2x assigned isolation group %d because of " + "user assigned address %s", + addr->domain, addr->bus, isolationGroup, addrStr);
Is this what we want to do? Or is it a bad enough situation that we want to log an error and fail? (I don't have any idea, that's why I'm asking :-)
+ } + /* mark the requested function as reserved */ bus->slot[addr->slot].functions |= (1 << addr->function); VIR_DEBUG("Reserving PCI address %s (aggregate='%s')", addrStr, @@ -643,7 +675,28 @@ int virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr) { - addrs->buses[addr->bus].slot[addr->slot].functions &= ~(1 << addr->function); + virDomainPCIAddressBusPtr bus = &addrs->buses[addr->bus]; + bool lastDevice; + size_t slot; + + bus->slot[addr->slot].functions &= ~(1 << addr->function); + + /* Figure out whether this is the first device we're plugging + * into the bus by looking at all the slots */ + lastDevice = true;
Here's instance 2 of the "check for an empty bus" loop.
+ for (slot = bus->minSlot; slot <= bus->maxSlot; slot++) { + if (bus->slot[slot].functions) { + lastDevice = false; + break; + } + } + + /* If the one we just unplugged was the last device on the bus, + * we can reset the isolation group for the bus so that any + * device we'll try to plug in from now on will be accepted */ + if (lastDevice && !bus->isolationGroupLocked) + bus->isolationGroup = 0;
Ah, for awhile I had been thinking that isolationGroupLocked would be set as soon as an isolationGroup was set for a bus. But I guess instead it's only set when specifically requested as the bus is added; otherwise an isolationGroup of 0 means "none selected". (Or is it that "BusIsEmpty == true && !isolationGroupLocked" means "none selected"?)
+ return 0; }
@@ -749,7 +802,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr next_addr, virDomainPCIConnectFlags flags, - int isolationGroup ATTRIBUTE_UNUSED, + int isolationGroup, int function) { virPCIDeviceAddress a = { 0 }; @@ -765,11 +818,50 @@ virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, else a.function = function;
- /* "Begin at the beginning," the King said, very gravely, "and go on - * till you come to the end: then stop." */ + /* When looking for a suitable bus for the device, start by being + * very strict and ignoring all those where the isolation groups + * don't match. This ensures all devices sharing the same isolation + * group will end up on the same group */
I think you wanted to say "on the same bus"
+ for (a.bus = 0; a.bus < addrs->nbuses; a.bus++) { + virDomainPCIAddressBusPtr bus = &addrs->buses[a.bus]; + bool found = false; + + if (bus->isolationGroup != isolationGroup) + continue; + + a.slot = bus->minSlot; + + if (virDomainPCIAddressFindUnusedFunctionOnBus(bus, &a, function, + flags, &found) < 0) { + goto error; + } + + if (found) + goto success; + } + + /* We haven't been able to find a perfectly matching bus, but we + * might still be able to make this work by altering the isolation + * group for a bus that's currently empty. So let's try that */ for (a.bus = 0; a.bus < addrs->nbuses; a.bus++) { virDomainPCIAddressBusPtr bus = &addrs->buses[a.bus]; bool found = false; + bool firstDevice = true; + size_t slot; + + /* Go through all the slots and see whether they are empty */ + for (slot = bus->minSlot; slot <= bus->maxSlot; slot++) { + if (bus->slot[slot].functions) { + firstDevice = false; + break; + } + }
...and here's the 3rd place you have the "check if the bus is empty" loop.
+ + /* We can only change the isolation group for a bus when + * plugging in the first device; moreover, some buses are + * prevented from ever changing it */ + if (!firstDevice || bus->isolationGroupLocked)
Yeah, how does that 2nd thing happen? (setting isolationGroupLocked on an empty bus) I see that happens in the next patch for the default (first) PHB, but will it ever happen otherwise?
+ continue;
a.slot = bus->minSlot;
@@ -778,6 +870,8 @@ virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, goto error; }
+ /* The isolation group for the bus will actually be changed + * later, in virDomainPCIAddressReserveAddrInternal() */ if (found) goto success; }
I think this just needs the one typo fixed and the utility "Is the bus empty" function. The rest is just me asking for out-of-band explanations of a couple things. I think I can trust your copy-paste sk1llz enough to give Reviewed-by: Laine Stump <laine@laine.org> assuming the function is added and typo fixed.

On Wed, 2017-06-28 at 14:12 -0400, Laine Stump wrote:
+ /* Figure out whether this is the first device we're plugging + * into the bus by looking at all the slots */ + firstDevice = true; + for (slot = bus->minSlot; slot <= bus->maxSlot; slot++) { + if (bus->slot[slot].functions) { + firstDevice = false; + break; + } + } You have the same loop 3 times in the code (although in one case the bool is called "lastDevice" instead of "firstDevice". How about a short utility function called virDomainPCIAddressBusIsEmpty() (or something like that)?
That makes perfect sense, and I'm not sure why I didn't think of it myself :/
+ if (firstDevice && !bus->isolationGroupLocked) { + /* The first device decides the isolation group for the + * entire bus */ + bus->isolationGroup = isolationGroup; + VIR_DEBUG("PCI bus %.4x:%.2x assigned isolation group %d because of " + "first device %s", + addr->domain, addr->bus, isolationGroup, addrStr); I haven't tried out these patches, but it looks like all this stuff happens for everybody all the time, not just for pSeries, correct? I suppose it's an effective NOP if everything is group 0 though, right?
That's the idea :) For all guests except pSeries, the isolation group for both devices and controllers will never change from the default, so it will not influence address allocation. If it did, either this patch or the next one would cause a massive test suite churn, which they don't ;)
+ } else if (bus->isolationGroup != isolationGroup && fromConfig) { + /* If this is not the first function and its isolation group + * doesn't match the bus', then it should not be using this + * address. However, if the address comes from the user then + * we comply with the request and change the isolation group + * back to the default (because at that point isolation can't + * be guaranteed anymore) */ + bus->isolationGroup = 0; + VIR_DEBUG("PCI bus %.4x:%.2x assigned isolation group %d because of " + "user assigned address %s", + addr->domain, addr->bus, isolationGroup, addrStr); Is this what we want to do? Or is it a bad enough situation that we want to log an error and fail? (I don't have any idea, that's why I'm asking :-)
If we did that, all existing pSeries guests using hostdevs would suddenly fail to start :( Degraded isolation (multiple indipendent hostdevs on the same PHB) is something we want to avoid but doesn't cause any harm in practice, you just don't get the advantages of isolation. It's worked fine until now. Splitting isolation groups (devices that are in the same host IOMMU group being assigned to separate PHBs), on the other hand, is problematic. Maybe I can add try to check for that situation and error out when it happens.
+ /* If the one we just unplugged was the last device on the bus, + * we can reset the isolation group for the bus so that any + * device we'll try to plug in from now on will be accepted */ + if (lastDevice && !bus->isolationGroupLocked) + bus->isolationGroup = 0; Ah, for awhile I had been thinking that isolationGroupLocked would be set as soon as an isolationGroup was set for a bus. But I guess instead it's only set when specifically requested as the bus is added; otherwise an isolationGroup of 0 means "none selected". (Or is it that "BusIsEmpty == true && !isolationGroupLocked" means "none selected"?)
Yes, isolationGroupLocked is set when the controller is created and never changed afterwards. There's not really a notion of "none selected" for isolation groups: 0 is not special in that regard, it just happens to be the default for both devices and controllers. ... Now what I look at that code again, I'm pretty sure resetting the isolation group for the bus when the last device is removed is not even needed: it will be changed back whenever another device is plugged in anyway. I'll try getting rid of that hunk and verify everything still works.
+ /* We can only change the isolation group for a bus when + * plugging in the first device; moreover, some buses are + * prevented from ever changing it */ + if (!firstDevice || bus->isolationGroupLocked) Yeah, how does that 2nd thing happen? (setting isolationGroupLocked on an empty bus) I see that happens in the next patch for the default (first) PHB, but will it ever happen otherwise?
That's the only use case at the moment. We want to assing all emulated devices to the default PHB, and locking its isolation group to the default one is a way to achieve that. -- Andrea Bolognani / Red Hat / Virtualization

On Thu, 2017-06-29 at 08:34 +0200, Andrea Bolognani wrote:
... Now what I look at that code again, I'm pretty sure resetting the isolation group for the bus when the last device is removed is not even needed: it will be changed back whenever another device is plugged in anyway. I'll try getting rid of that hunk and verify everything still works.
Yup yup yup. I was right. Consider that hunk gone. -- Andrea Bolognani / Red Hat / Virtualization

All the pieces are now in place, so we can finally start using isolation groups to achieve our initial goal, which is separating hostdevs from emulated PCI devices while keeping hostdevs that belong to the same host IOMMU group together. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1280542 Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_domain_address.c | 118 +++++++++++++++++++++ src/qemu/qemu_hotplug.c | 10 ++ .../qemuxml2argv-pseries-hostdevs-1.args | 8 +- .../qemuxml2argv-pseries-hostdevs-2.args | 3 +- .../qemuxml2argv-pseries-hostdevs-3.args | 2 +- .../qemuxml2xmlout-pseries-hostdevs-1.xml | 14 ++- .../qemuxml2xmlout-pseries-hostdevs-2.xml | 6 +- .../qemuxml2xmlout-pseries-hostdevs-3.xml | 2 +- 8 files changed, 153 insertions(+), 10 deletions(-) diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 3d56900..b884d06 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -906,6 +906,121 @@ qemuDomainFillAllPCIConnectFlags(virDomainDefPtr def, /** + * qemuDomainFillDeviceIsolationGroupIter: + * @def: domain definition + * @dev: device definition + * @info: device information + * @opaque: user data + * + * Fill isolation group information for a single device. + * + * Used by qemuDomainFillAllIsolationGroups(), don't call directly. + * + * Return: 0 on success, <0 on failure + * */ +static int +qemuDomainFillDeviceIsolationGroupIter(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev, + virDomainDeviceInfoPtr info, + void *opaque ATTRIBUTE_UNUSED) +{ + virDomainHostdevDefPtr hostdev; + virPCIDeviceAddressPtr hostAddr; + + /* Only hostdevs... */ + if (dev->type != VIR_DOMAIN_DEVICE_HOSTDEV) + return 0; + + hostdev = dev->data.hostdev; + + /* ... of the PCI kind need this extra information */ + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { + return 0; + } + + hostAddr = &hostdev->source.subsys.u.pci.addr; + + /* The isolation group is simply the IOMMU group assigned by the host */ + info->isolationGroup = virPCIDeviceAddressGetIOMMUGroupNum(hostAddr); + + if (info->isolationGroup < 0) { + VIR_WARN("Can't look up isolation group for device %04x:%02x:%02x.%x", + hostAddr->domain, hostAddr->bus, + hostAddr->slot, hostAddr->function); + } else { + VIR_DEBUG("Isolation group for device %04x:%02x:%02x.%x is %d", + hostAddr->domain, hostAddr->bus, + hostAddr->slot, hostAddr->function, + info->isolationGroup); + } + + return info->isolationGroup; +} + + +/** + * qemuDomainFillAllIsolationGroups: + * @def: domain definition + * + * Fill isolation group information for all devices in @def. + * + * Used by qemuDomainSetupIsolationGroups(), don't call directly. + * + * Return: 0 on success, <0 on failure + */ +static int +qemuDomainFillAllIsolationGroups(virDomainDefPtr def) +{ + return virDomainDeviceInfoIterate(def, + qemuDomainFillDeviceIsolationGroupIter, + NULL); +} + + +/** + * qemuDomainSetupIsolationGroups: + * @def: domain definition + * + * High-level function to set up isolation groups for all devices + * and controllers in @def. Isolation groups will only be set up if + * the guest architecture and machine type require it, so this + * function can and should be called unconditionally before attempting + * to assign any PCI address. + * + * Return: 0 on success, <0 on failure + */ +static int +qemuDomainSetupIsolationGroups(virDomainDefPtr def) +{ + virDomainControllerDefPtr defaultPHB; + int idx; + int ret = -1; + + /* Only pSeries guests care about isolation groups at the moment */ + if (!qemuDomainIsPSeries(def)) + return 0; + + if (qemuDomainFillAllIsolationGroups(def) < 0) + goto out; + + idx = virDomainControllerFind(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0); + if (idx < 0) + goto out; + + defaultPHB = def->controllers[idx]; + + /* We want to prevent hostdevs from being plugged into the default + * PHB, so we lock its isolation group */ + defaultPHB->info.isolationGroupLocked = true; + + ret = 0; + + out: + return ret; +} + +/** * qemuDomainFillDevicePCIConnectFlags: * * @def: the entire DomainDef @@ -2076,6 +2191,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, if (qemuDomainFillAllPCIConnectFlags(def, qemuCaps, driver) < 0) goto cleanup; + if (qemuDomainSetupIsolationGroups(def) < 0) + goto cleanup; + if (nbuses > 0) { /* 1st pass to figure out how many PCI bridges we need */ if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, true))) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 8ca5054..85db7af 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1468,6 +1468,16 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, if (qemuAssignDeviceHostdevAlias(vm->def, &info->alias, -1) < 0) goto error; + + /* When attaching a hostdev to a pSeries guest, we need to set up + * its isolation group if we want the assigned address to respect + * isolation constraints */ + if (qemuDomainIsPSeries(vm->def)) { + virPCIDeviceAddressPtr hostAddr = &hostdev->source.subsys.u.pci.addr; + + info->isolationGroup = virPCIDeviceAddressGetIOMMUGroupNum(hostAddr); + } + if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0) goto error; releaseaddr = true; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args index 88eb081..36f2def 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args @@ -18,6 +18,8 @@ QEMU_AUDIO_DRV=none \ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ --device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.0,addr=0x1 \ --device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x2 \ --device vfio-pci,host=0001:01:00.1,id=hostdev2,bus=pci.0,addr=0x3 +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device spapr-pci-host-bridge,index=2,id=pci.2 \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.1.0,addr=0x1 \ +-device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.2.0,addr=0x1 \ +-device vfio-pci,host=0001:01:00.1,id=hostdev2,bus=pci.1.0,addr=0x2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args index 83d4306..cd5b664 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args @@ -19,6 +19,7 @@ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ -device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device spapr-pci-host-bridge,index=2,id=pci.2 \ -device virtio-scsi-pci,id=scsi0,bus=pci.1.0,addr=0x1 \ -device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.1.0,addr=0x2 \ --device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x1 +-device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.2.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args index eda6cc7..66a31ba 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args @@ -21,4 +21,4 @@ server,nowait \ -device spapr-pci-host-bridge,index=1,id=pci.1 \ -device spapr-pci-host-bridge,index=2,id=pci.2 \ -device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.2.0,addr=0x1 \ --device vfio-pci,host=0001:01:00.1,id=hostdev1,bus=pci.0,addr=0x1 +-device vfio-pci,host=0001:01:00.1,id=hostdev1,bus=pci.2.0,addr=0x2 diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml index 34defea..494c414 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml @@ -19,26 +19,34 @@ <model name='spapr-pci-host-bridge'/> <target index='0'/> </controller> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> + </controller> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> + </controller> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> </hostdev> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml index 17ff4c8..cfa395b 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml @@ -26,6 +26,10 @@ <model name='spapr-pci-host-bridge'/> <target index='1'/> </controller> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> + </controller> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> @@ -38,7 +42,7 @@ <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> </hostdev> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml index 58023ec..f91959b 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml @@ -39,7 +39,7 @@ <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x02' function='0x0'/> </hostdev> <memballoon model='none'/> <panic model='pseries'/> -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
All the pieces are now in place, so we can finally start using isolation groups to achieve our initial goal, which is separating hostdevs from emulated PCI devices while keeping hostdevs that belong to the same host IOMMU group together. Set isolation groups for devices when allocating PCI addresses, so that hostdevs in different IOMMU groups will be placed on different PCI buses to maintain proper isolation.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1280542
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_domain_address.c | 118 +++++++++++++++++++++ src/qemu/qemu_hotplug.c | 10 ++ .../qemuxml2argv-pseries-hostdevs-1.args | 8 +- .../qemuxml2argv-pseries-hostdevs-2.args | 3 +- .../qemuxml2argv-pseries-hostdevs-3.args | 2 +- .../qemuxml2xmlout-pseries-hostdevs-1.xml | 14 ++- .../qemuxml2xmlout-pseries-hostdevs-2.xml | 6 +- .../qemuxml2xmlout-pseries-hostdevs-3.xml | 2 +- 8 files changed, 153 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 3d56900..b884d06 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -906,6 +906,121 @@ qemuDomainFillAllPCIConnectFlags(virDomainDefPtr def,
/** + * qemuDomainFillDeviceIsolationGroupIter: + * @def: domain definition + * @dev: device definition + * @info: device information + * @opaque: user data + * + * Fill isolation group information for a single device. + * + * Used by qemuDomainFillAllIsolationGroups(), don't call directly. + * + * Return: 0 on success, <0 on failure + * */ +static int +qemuDomainFillDeviceIsolationGroupIter(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev, + virDomainDeviceInfoPtr info, + void *opaque ATTRIBUTE_UNUSED) +{ + virDomainHostdevDefPtr hostdev; + virPCIDeviceAddressPtr hostAddr; + + /* Only hostdevs... */ + if (dev->type != VIR_DOMAIN_DEVICE_HOSTDEV) + return 0;
I can see one problem here - a device that is a hostdev network interface won't be properly recognized. We can solve the problem for plain <interface type='hostdev'> by just checking for that in addition to <hostdev> here. The one that we can't deal with is <interface type='network'> where the network is a pool of VFs. We had a similar problem when trying to decide whether a device needed to be placed on a PCI or PCIe bus, but were able to punt on that one because all SRIOV devices are PCIe. In this case it's a bit more problematic though. Maybe we can do this: if a device is <interface type='network'> then we look to the network to see if it's a "hostdev network". If so, we assign it "some isolation group that won't be otherwise used" (basically *anything* that assures the device is placed on a bus by itself). It's necessary to do this because we can't know until the domain is started exactly which SRIOV VF from the pool will be used, so we can't know the actual IOMMU group in advance. And it's reasonable because each SRIOV VF is by itself in its own IOMMU group, so we won't have the exact same number as the actual iommu group, but we'll be guaranteeing that it is different from any other device (which is really all that's important in this context).
+ + hostdev = dev->data.hostdev; + + /* ... of the PCI kind need this extra information */ + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { + return 0; + } + + hostAddr = &hostdev->source.subsys.u.pci.addr; + + /* The isolation group is simply the IOMMU group assigned by the host */ + info->isolationGroup = virPCIDeviceAddressGetIOMMUGroupNum(hostAddr); + + if (info->isolationGroup < 0) { + VIR_WARN("Can't look up isolation group for device %04x:%02x:%02x.%x", + hostAddr->domain, hostAddr->bus, + hostAddr->slot, hostAddr->function); + } else { + VIR_DEBUG("Isolation group for device %04x:%02x:%02x.%x is %d", + hostAddr->domain, hostAddr->bus, + hostAddr->slot, hostAddr->function, + info->isolationGroup); + } + + return info->isolationGroup; +} + + +/** + * qemuDomainFillAllIsolationGroups: + * @def: domain definition + * + * Fill isolation group information for all devices in @def. + * + * Used by qemuDomainSetupIsolationGroups(), don't call directly. + * + * Return: 0 on success, <0 on failure + */ +static int +qemuDomainFillAllIsolationGroups(virDomainDefPtr def) +{ + return virDomainDeviceInfoIterate(def, + qemuDomainFillDeviceIsolationGroupIter, + NULL); +} + + +/** + * qemuDomainSetupIsolationGroups: + * @def: domain definition + * + * High-level function to set up isolation groups for all devices + * and controllers in @def. Isolation groups will only be set up if + * the guest architecture and machine type require it, so this + * function can and should be called unconditionally before attempting + * to assign any PCI address. + * + * Return: 0 on success, <0 on failure + */ +static int +qemuDomainSetupIsolationGroups(virDomainDefPtr def) +{ + virDomainControllerDefPtr defaultPHB; + int idx; + int ret = -1; + + /* Only pSeries guests care about isolation groups at the moment */ + if (!qemuDomainIsPSeries(def)) + return 0;
I suppose this would be pointless on, e.g. Q35, since each device is on its own (isolated?) root-port anyway, right?
+ + if (qemuDomainFillAllIsolationGroups(def) < 0) + goto out; + + idx = virDomainControllerFind(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0); + if (idx < 0) + goto out; + + defaultPHB = def->controllers[idx]; + + /* We want to prevent hostdevs from being plugged into the default + * PHB, so we lock its isolation group */ + defaultPHB->info.isolationGroupLocked = true; + + ret = 0; + + out: + return ret; +} + +/** * qemuDomainFillDevicePCIConnectFlags: * * @def: the entire DomainDef @@ -2076,6 +2191,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, if (qemuDomainFillAllPCIConnectFlags(def, qemuCaps, driver) < 0) goto cleanup;
+ if (qemuDomainSetupIsolationGroups(def) < 0) + goto cleanup; + if (nbuses > 0) { /* 1st pass to figure out how many PCI bridges we need */ if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, true))) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 8ca5054..85db7af 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1468,6 +1468,16 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
if (qemuAssignDeviceHostdevAlias(vm->def, &info->alias, -1) < 0) goto error; + + /* When attaching a hostdev to a pSeries guest, we need to set up + * its isolation group if we want the assigned address to respect + * isolation constraints */ + if (qemuDomainIsPSeries(vm->def)) { + virPCIDeviceAddressPtr hostAddr = &hostdev->source.subsys.u.pci.addr; + + info->isolationGroup = virPCIDeviceAddressGetIOMMUGroupNum(hostAddr); + } + if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0) goto error; releaseaddr = true; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args index 88eb081..36f2def 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-1.args @@ -18,6 +18,8 @@ QEMU_AUDIO_DRV=none \ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ --device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.0,addr=0x1 \ --device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x2 \ --device vfio-pci,host=0001:01:00.1,id=hostdev2,bus=pci.0,addr=0x3 +-device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device spapr-pci-host-bridge,index=2,id=pci.2 \ +-device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.1.0,addr=0x1 \ +-device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.2.0,addr=0x1 \ +-device vfio-pci,host=0001:01:00.1,id=hostdev2,bus=pci.1.0,addr=0x2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args index 83d4306..cd5b664 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-2.args @@ -19,6 +19,7 @@ server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline \ -boot c \ -device spapr-pci-host-bridge,index=1,id=pci.1 \ +-device spapr-pci-host-bridge,index=2,id=pci.2 \ -device virtio-scsi-pci,id=scsi0,bus=pci.1.0,addr=0x1 \ -device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.1.0,addr=0x2 \ --device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.0,addr=0x1 +-device vfio-pci,host=0005:90:01.0,id=hostdev1,bus=pci.2.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args index eda6cc7..66a31ba 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-hostdevs-3.args @@ -21,4 +21,4 @@ server,nowait \ -device spapr-pci-host-bridge,index=1,id=pci.1 \ -device spapr-pci-host-bridge,index=2,id=pci.2 \ -device vfio-pci,host=0001:01:00.0,id=hostdev0,bus=pci.2.0,addr=0x1 \ --device vfio-pci,host=0001:01:00.1,id=hostdev1,bus=pci.0,addr=0x1 +-device vfio-pci,host=0001:01:00.1,id=hostdev1,bus=pci.2.0,addr=0x2 diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml index 34defea..494c414 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-1.xml @@ -19,26 +19,34 @@ <model name='spapr-pci-host-bridge'/> <target index='0'/> </controller> + <controller type='pci' index='1' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='1'/> + </controller> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> + </controller> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x0'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> </hostdev> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml index 17ff4c8..cfa395b 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-2.xml @@ -26,6 +26,10 @@ <model name='spapr-pci-host-bridge'/> <target index='1'/> </controller> + <controller type='pci' index='2' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='2'/> + </controller> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> @@ -38,7 +42,7 @@ <source> <address domain='0x0005' bus='0x90' slot='0x01' function='0x0'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> </hostdev> <memballoon model='none'/> <panic model='pseries'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml index 58023ec..f91959b 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-hostdevs-3.xml @@ -39,7 +39,7 @@ <source> <address domain='0x0001' bus='0x01' slot='0x00' function='0x1'/> </source> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x02' slot='0x02' function='0x0'/> </hostdev> <memballoon model='none'/> <panic model='pseries'/>

On Wed, 2017-06-28 at 18:22 -0400, Laine Stump wrote:
+static int +qemuDomainFillDeviceIsolationGroupIter(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev, + virDomainDeviceInfoPtr info, + void *opaque ATTRIBUTE_UNUSED) +{ + virDomainHostdevDefPtr hostdev; + virPCIDeviceAddressPtr hostAddr; + + /* Only hostdevs... */ + if (dev->type != VIR_DOMAIN_DEVICE_HOSTDEV) + return 0; I can see one problem here - a device that is a hostdev network interface won't be properly recognized. We can solve the problem for plain <interface type='hostdev'> by just checking for that in addition to <hostdev> here.
Right, I hadn't considered that case. I'll make sure it is handled correctly.
The one that we can't deal with is <interface type='network'> where the network is a pool of VFs. We had a similar problem when trying to decide whether a device needed to be placed on a PCI or PCIe bus, but were able to punt on that one because all SRIOV devices are PCIe. In this case it's a bit more problematic though. Maybe we can do this: if a device is <interface type='network'> then we look to the network to see if it's a "hostdev network". If so, we assign it "some isolation group that won't be otherwise used" (basically *anything* that assures the device is placed on a bus by itself). It's necessary to do this because we can't know until the domain is started exactly which SRIOV VF from the pool will be used, so we can't know the actual IOMMU group in advance. And it's reasonable because each SRIOV VF is by itself in its own IOMMU group, so we won't have the exact same number as the actual iommu group, but we'll be guaranteeing that it is different from any other device (which is really all that's important in this context).
Hm, that's quite a pickle. Choosing a synthetic isolation group that is guaranteed not to clash with any host device or other VFs sounds like it might require some annoying bookkeeping. I'm not sure isolating SR-IOV VFs is really needed, though, because by virtue of being subject to their own layer of virtualization / abstraction they might being unable to take advantage of EEH and similar isolation-dependent features. David, what's your take on this?
+static int +qemuDomainSetupIsolationGroups(virDomainDefPtr def) +{ + virDomainControllerDefPtr defaultPHB; + int idx; + int ret = -1; + + /* Only pSeries guests care about isolation groups at the moment */ + if (!qemuDomainIsPSeries(def)) + return 0; I suppose this would be pointless on, e.g. Q35, since each device is on its own (isolated?) root-port anyway, right?
I don't think PCIe Root Ports provide any isolation; not of the kind we're talking about here, at least. So the concepts implemented here don't apply AFAICT. -- Andrea Bolognani / Red Hat / Virtualization

On Thu, 2017-06-29 at 17:37 +0200, Andrea Bolognani wrote:
I can see one problem here - a device that is a hostdev network interface won't be properly recognized. We can solve the problem for plain <interface type='hostdev'> by just checking for that in addition to <hostdev> here. Right, I hadn't considered that case. I'll make sure it is handled correctly.
After implementing it, I realized this too applies to SR-IOV VFs. So depending on David's reply we might actually want to leave the code as it is. -- Andrea Bolognani / Red Hat / Virtualization

On Thu, 29 Jun 2017 17:37:30 +0200 Andrea Bolognani <abologna@redhat.com> wrote:
On Wed, 2017-06-28 at 18:22 -0400, Laine Stump wrote: [...] [...]
Right, I hadn't considered that case. I'll make sure it is handled correctly.
[...]
Hm, that's quite a pickle.
Choosing a synthetic isolation group that is guaranteed not to clash with any host device or other VFs sounds like it might require some annoying bookkeeping.
I'm not sure isolating SR-IOV VFs is really needed, though, because by virtue of being subject to their own layer of virtualization / abstraction they might being unable to take advantage of EEH and similar isolation-dependent features.
David, what's your take on this?
So, I still need to talk to the IBMers some more about this, but I'm pretty sure we want VF isolation. I believe EEH should work on VFs, but it will break if there is >1 VF on the vPHB (since every VF should be in its own IOMMU group). And, yes, things would be far nicer if EEH still worked with multiple (host) IOMMU groups on the vPHB, but doing so is a real PITA, and no-one is working on it.
[...] [...]
I don't think PCIe Root Ports provide any isolation; not of the kind we're talking about here, at least. So the concepts implemented here don't apply AFAICT.
-- Andrea Bolognani / Red Hat / Virtualization
-- David Gibson <dgibson@redhat.com> Principal Software Engineer, Virtualization, Red Hat

Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/news.xml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/news.xml b/docs/news.xml index 27562e1..d70ba08 100644 --- a/docs/news.xml +++ b/docs/news.xml @@ -46,6 +46,27 @@ select a boot entry. </description> </change> + <change> + <summary> + qemu: Support multiple PHBs for pSeries guests + </summary> + <description> + pSeries guests can now have multiple PHBs (PCI Host Bridges), which + show up as separate PCI domains in the guest. To create additional + PHBs, simply add PCI controllers with model <code>pci-root</code> + to the guest configuration. + </description> + </change> + <change> + <summary> + qemu: Isolate hostdevs on pSeries guests + </summary> + <description> + To enable better error reporting and recovery, unrelated hostdevs + will now be automatically isolated on pSeries guests by placing them + on separate PHBs (PCI Host Bridges). + </description> + </change> </section> <section title="Improvements"> </section> -- 2.7.5

On 06/23/2017 11:03 AM, Andrea Bolognani wrote:
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Laine Stump <laine@laine.org>
--- docs/news.xml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/docs/news.xml b/docs/news.xml index 27562e1..d70ba08 100644 --- a/docs/news.xml +++ b/docs/news.xml @@ -46,6 +46,27 @@ select a boot entry. </description> </change> + <change> + <summary> + qemu: Support multiple PHBs for pSeries guests + </summary> + <description> + pSeries guests can now have multiple PHBs (PCI Host Bridges), which + show up as separate PCI domains in the guest. To create additional + PHBs, simply add PCI controllers with model <code>pci-root</code> + to the guest configuration. + </description> + </change> + <change> + <summary> + qemu: Isolate hostdevs on pSeries guests + </summary> + <description> + To enable better error reporting and recovery, unrelated hostdevs + will now be automatically isolated on pSeries guests by placing them + on separate PHBs (PCI Host Bridges). + </description> + </change> </section> <section title="Improvements"> </section>
participants (4)
-
Andrea Bolognani
-
David Gibson
-
Laine Stump
-
Shivaprasad bhat