From 6e42d83f7ca2d2a481dde7d4cda85c5632759ee0 Mon Sep 17 00:00:00 2001 From: Andrea Bolognani Date: Tue, 28 Feb 2017 14:58:33 +0100 Subject: [PATCH] qemu: Automatically pick target index and model for pci-root controllers 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 Reviewed-by: Laine Stump --- src/conf/domain_conf.c | 31 ++++++++ src/conf/domain_conf.h | 6 +- src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 79 ++++++++++++++++++- .../qemuargv2xml-pseries-disk.xml | 5 +- .../qemuargv2xml-pseries-nvram.xml | 5 +- .../qemuxml2xmlout-panic-pseries.xml | 5 +- ...xml2xmlout-ppc64-usb-controller-legacy.xml | 5 +- .../qemuxml2xmlout-ppc64-usb-controller.xml | 5 +- .../qemuxml2xmlout-pseries-nvram.xml | 5 +- .../qemuxml2xmlout-pseries-panic-missing.xml | 5 +- ...emuxml2xmlout-pseries-panic-no-address.xml | 5 +- 12 files changed, 145 insertions(+), 12 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5dd1824701..3feeccb9f0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1899,6 +1899,37 @@ void virDomainControllerDefFree(virDomainControllerDefPtr def) VIR_FREE(def); } + +/** + * virDomainControllerIsPCIHostBridge: + * @cont: controller + * + * Checks whether @cont is a PCI Host Bridge (PHB), a specific type + * of PCI controller used by pSeries guests. + * + * Returns: true if @cont is a PHB, false otherwise. + */ +bool +virDomainControllerIsPCIHostBridge(const virDomainControllerDef *cont) +{ + virDomainControllerPCIModelName name; + + /* PHBs are pci-root controllers */ + if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI || + cont->model != VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) { + return false; + } + + name = cont->opts.pciopts.modelName; + + /* The actual device used for PHBs is spapr-pci-host-bridge */ + if (name != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) + return false; + + return true; +} + + virDomainFSDefPtr virDomainFSDefNew(void) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6e3608f24b..af15ee8b51 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2678,10 +2678,12 @@ int virDomainDeviceFindControllerModel(const virDomainDef *def, virDomainDiskDefPtr virDomainDiskFindByBusAndDst(virDomainDefPtr def, int bus, char *dst); + +virDomainControllerDefPtr virDomainControllerDefNew(virDomainControllerType type); void virDomainControllerDefFree(virDomainControllerDefPtr def); +bool virDomainControllerIsPCIHostBridge(const virDomainControllerDef *cont); + virDomainFSDefPtr virDomainFSDefNew(void); -virDomainControllerDefPtr -virDomainControllerDefNew(virDomainControllerType type); void virDomainFSDefFree(virDomainFSDefPtr def); void virDomainActualNetDefFree(virDomainActualNetDefPtr def); void virDomainNetDefClear(virDomainNetDefPtr def); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5d30090646..237162c095 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -226,6 +226,7 @@ virDomainControllerFindByType; virDomainControllerFindUnusedIndex; virDomainControllerInsert; virDomainControllerInsertPreAlloced; +virDomainControllerIsPCIHostBridge; virDomainControllerModelPCITypeToString; virDomainControllerModelSCSITypeFromString; virDomainControllerModelSCSITypeToString; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index efc698da13..bea95da444 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1848,6 +1848,7 @@ qemuDomainSupportsPCI(virDomainDefPtr def, static void qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont, + virDomainDefPtr def, virQEMUCapsPtr qemuCaps) { int *modelName = &cont->opts.pciopts.modelName; @@ -1884,6 +1885,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; @@ -1891,6 +1895,54 @@ 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 targetIndex; + 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 (targetIndex = 1; targetIndex <= 31; targetIndex++) { + bool found = false; + size_t i; + + for (i = 0; i < def->ncontrollers; i++) { + virDomainControllerDefPtr cont = def->controllers[i]; + + /* Skip everything but PHBs */ + if (!virDomainControllerIsPCIHostBridge(cont)) + continue; + + /* Stop looking as soon as we find a PHB that's + * already using this specific target index */ + if (cont->opts.pciopts.targetIndex == targetIndex) { + 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 = targetIndex; + break; + } + } + + return ret; +} + + static int qemuDomainAddressFindNewBusNr(virDomainDefPtr def) { @@ -2151,7 +2203,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 @@ -2188,9 +2240,32 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, goto cleanup; } break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + if (!qemuDomainIsPSeries(def)) + break; + if (options->targetIndex == -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->targetIndex = 0; + } else { + /* For all other PHBs the target index doesn't need + * to match the controller index or have any + * particular value, really */ + options->targetIndex = qemuDomainAddressFindNewTargetIndex(def); + } + } + if (options->targetIndex == -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 1bad8ee4c1..601d0f7f62 100644 --- a/tests/qemuargv2xmldata/qemuargv2xml-pseries-disk.xml +++ b/tests/qemuargv2xmldata/qemuargv2xml-pseries-disk.xml @@ -30,7 +30,10 @@
- + + + +
diff --git a/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml b/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml index 7e9f8644fb..7787847a90 100644 --- a/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml +++ b/tests/qemuargv2xmldata/qemuargv2xml-pseries-nvram.xml @@ -17,7 +17,10 @@
- + + + +
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml index 1ed11ce12d..7fb49feb0f 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-panic-pseries.xml @@ -17,7 +17,10 @@
- + + + +
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml index b7bde241dc..673b81dbc9 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller-legacy.xml @@ -22,7 +22,10 @@
- + + + +
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml index 82aaaca721..68995a9ce0 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-ppc64-usb-controller.xml @@ -22,7 +22,10 @@
- + + + +
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml index 713f31c0e9..f89b23b338 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-nvram.xml @@ -17,7 +17,10 @@
- + + + +
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml index 1ed11ce12d..7fb49feb0f 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-missing.xml @@ -17,7 +17,10 @@
- + + + +
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml index 1ed11ce12d..7fb49feb0f 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-panic-no-address.xml @@ -17,7 +17,10 @@
- + + + +