[libvirt] [PATCH v6 00/11] qemu: Validate PCI controller options

Applies cleanly on top of 11819aee65b8ea71860526f529d86ab646b9cd1f. Patches 2/11 and 4/11 are the only ones missing R-bs, everything else hasn't been significantly altered since the previous respin. Changes from [v5]: * patch 1 has been pushed; * add virReportController*() functions to cut down on redundant error reporting, as suggested by laine; * report index and modelName along with model in error messages. Changes from [v4]: * patch 1/12 is new; * use virReportEnumRangeError(), as suggested by laine. Changes from [v3]: * don't introduce new test cases that won't be able to provide full test coverage anyway, as suggested by laine. Changes from [v2]: * replace the old implementation bit by bit using a clever trick suggested by pkrempa; * don't move QEMU capability validation; * add a default: label to all switch statements as recommended by danpb. Changes from [v1]: * error out instead of silently accept invalid options; * shave quite a lot of yaks. [v5] https://www.redhat.com/archives/libvir-list/2018-March/msg00096.html [v4] https://www.redhat.com/archives/libvir-list/2018-February/msg01232.html [v3] https://www.redhat.com/archives/libvir-list/2018-February/msg00996.html [v2] https://www.redhat.com/archives/libvir-list/2018-February/msg00813.html [v1] https://www.redhat.com/archives/libvir-list/2018-February/msg00244.html Andrea Bolognani (11): qemu: Create new qemuDomainDeviceDefValidateControllerPCI() qemu: Validate PCI controller options (modelName) qemu: Validate PCI controller options (index) qemu: Validate PCI controller options (targetIndex) qemu: Validate PCI controller options (pcihole64) qemu: Validate PCI controller options (busNr) qemu: Validate PCI controller options (numaNode) qemu: Validate PCI controller options (chassisNr) qemu: Validate PCI controller options (chassis and port) qemu: Validate PCI controllers (QEMU capabilities) qemu: Remove old qemuDomainDeviceDefValidateControllerPCI() src/qemu/qemu_domain.c | 540 +++++++++++++++++-------- tests/qemuxml2argvdata/pcie-expander-bus.xml | 3 - tests/qemuxml2xmloutdata/pcie-expander-bus.xml | 4 +- 3 files changed, 382 insertions(+), 165 deletions(-) -- 2.14.3

The existing function is renamed and called from the new one, so that even while we're in the process of implementing new checks all the existing ones will be performed. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_domain.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 8b4efc82de..a45a676520 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4268,9 +4268,9 @@ qemuDomainDeviceDefValidateControllerSCSI(const virDomainControllerDef *controll static int -qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *controller, - const virDomainDef *def, - virQEMUCapsPtr qemuCaps) +qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *controller, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps) { virDomainControllerModelPCI model = controller->model; const virDomainPCIControllerOpts *pciopts; @@ -4547,6 +4547,29 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *controlle } +static int +qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps) + +{ + const virDomainPCIControllerOpts *pciopts = &cont->opts.pciopts; + const char *model = virDomainControllerModelPCITypeToString(cont->model); + const char *modelName = virDomainControllerPCIModelNameTypeToString(pciopts->modelName); + + if (!model) { + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + return -1; + } + if (!modelName) { + virReportEnumRangeError(virDomainControllerPCIModelName, pciopts->modelName); + return -1; + } + + return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); +} + + static int qemuDomainDeviceDefValidateControllerSATA(const virDomainControllerDef *controller, const virDomainDef *def, -- 2.14.3

https://bugzilla.redhat.com/show_bug.cgi?id=1483816 Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_domain.c | 226 +++++++++++++++++++++++++++++++------------------ 1 file changed, 142 insertions(+), 84 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index a45a676520..ab6bb4fda0 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4274,7 +4274,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro { virDomainControllerModelPCI model = controller->model; const virDomainPCIControllerOpts *pciopts; - const char *modelName = NULL; /* skip pcie-root */ if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) @@ -4312,24 +4311,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro } pciopts = &controller->opts.pciopts; - if (controller->model != VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT && - controller->model != VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST) { - if (pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("autogenerated %s options not set"), - virDomainControllerModelPCITypeToString(controller->model)); - return -1; - } - - modelName = virDomainControllerPCIModelNameTypeToString(pciopts->modelName); - if (!modelName) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown %s modelName value %d"), - virDomainControllerModelPCITypeToString(controller->model), - pciopts->modelName); - return -1; - } - } /* Second pass - now the model specific checks */ switch (model) { @@ -4340,14 +4321,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro return -1; } - if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("PCI controller model name '%s' is not valid " - "for a pci-bridge"), - modelName); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PCI_BRIDGE)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the pci-bridge controller is not supported " @@ -4364,14 +4337,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro return -1; } - if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("PCI controller model name '%s' is not valid " - "for a pci-expander-bus"), - modelName); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PXB)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the pxb controller is not supported in this " @@ -4382,14 +4347,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: - if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("PCI controller model name '%s' is not valid " - "for a dmi-to-pci-bridge"), - modelName); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the dmi-to-pci-bridge (i82801b11-bridge) " @@ -4406,15 +4363,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro return -1; } - if ((pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420) && - (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCIE_ROOT_PORT)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("PCI controller model name '%s' is not valid " - "for a pcie-root-port"), - modelName); - return -1; - } - if ((pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420) && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IOH3420)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -4434,14 +4382,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("PCI controller model name '%s' is not valid " - "for a pcie-switch-upstream-port"), - modelName); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_X3130_UPSTREAM)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the pcie-switch-upstream-port (x3130-upstream) " @@ -4459,14 +4399,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro return -1; } - if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("PCI controller model name '%s' is not valid " - "for a pcie-switch-downstream-port"), - modelName); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_XIO3130_DOWNSTREAM)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("The pcie-switch-downstream-port " @@ -4484,14 +4416,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro return -1; } - if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("PCI controller model name '%s' is not valid " - "for a pcie-expander-bus"), - modelName); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PXB_PCIE)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the pxb-pcie controller is not supported " @@ -4512,14 +4436,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro if (pciopts->targetIndex == 0) return 0; - if (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); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the spapr-pci-host-bridge controller is not " @@ -4547,6 +4463,23 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro } +#define virReportControllerMissingOption(cont, model, modelName, option) \ + virReportError(VIR_ERR_INTERNAL_ERROR, \ + _("Required option '%s' is not set for PCI controller " \ + "with index '%d', model '%s' and modelName '%s'"), \ + (option), (cont->idx), (model), (modelName)); +#define virReportControllerInvalidOption(cont, model, modelName, option) \ + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \ + _("Option '%s' is not valid for PCI controller " \ + "with index '%d', model '%s' and modelName '%s'"), \ + (option), (cont->idx), (model), (modelName)); +#define virReportControllerInvalidValue(cont, model, modelName, option) \ + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \ + _("Option '%s' has invalid value for PCI controller " \ + "with index '%d', model '%s' and modelName '%s'"), \ + (option), (cont->idx), (model), (modelName)); + + static int qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, const virDomainDef *def, @@ -4566,10 +4499,135 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, return -1; } + /* modelName */ + switch ((virDomainControllerModelPCI) cont->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: + /* modelName should have been set automatically */ + if (pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) { + virReportControllerMissingOption(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + /* modelName must be set for pSeries guests, but it's an error + * for it to be set for any other guest */ + if (qemuDomainIsPSeries(def)) { + if (pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) { + virReportControllerMissingOption(cont, model, modelName, "modelName"); + return -1; + } + } else { + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) { + virReportControllerInvalidOption(cont, model, modelName, "modelName"); + return -1; + } + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) { + virReportControllerInvalidOption(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + default: + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + return -1; + } + + /* modelName (cont'd) */ + switch ((virDomainControllerModelPCI) cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE && + pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) { + virReportControllerInvalidValue(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE) { + virReportControllerInvalidValue(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE) { + virReportControllerInvalidValue(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420 && + pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCIE_ROOT_PORT) { + virReportControllerInvalidValue(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM) { + virReportControllerInvalidValue(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM) { + virReportControllerInvalidValue(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB) { + virReportControllerInvalidValue(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE) { + virReportControllerInvalidValue(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) { + virReportControllerInvalidValue(cont, model, modelName, "modelName"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + default: + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + return -1; + } + return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); } +#undef virReportControllerInvalidValue +#undef virReportControllerInvalidOption +#undef virReportControllerMissingOption + + static int qemuDomainDeviceDefValidateControllerSATA(const virDomainControllerDef *controller, const virDomainDef *def, -- 2.14.3

https://bugzilla.redhat.com/show_bug.cgi?id=1483816 Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_domain.c | 68 +++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index ab6bb4fda0..38c7fb8fe7 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4285,31 +4285,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) return 0; - /* First pass - just check the controller index for the model's - * that we care to check... */ - switch (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 (controller->idx == 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("index for pci controllers of model '%s' must be > 0"), - virDomainControllerModelPCITypeToString(model)); - return -1; - } - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: - break; - } - pciopts = &controller->opts.pciopts; /* Second pass - now the model specific checks */ @@ -4619,6 +4594,49 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, return -1; } + /* index */ + switch ((virDomainControllerModelPCI) cont->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 (cont->idx == 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Index for '%s' controllers must be > 0"), + model); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + /* pSeries guests can have multiple PHBs, so it's expected that + * the index will not be zero for some of them */ + if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT && + pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) { + break; + } + + /* For all other pci-root and pcie-root controllers, though, + * the index must be zero*/ + if (cont->idx != 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Index for '%s' controllers must be 0"), + model); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + default: + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + return -1; + } + return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); } -- 2.14.3

https://bugzilla.redhat.com/show_bug.cgi?id=1483816 Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- src/qemu/qemu_domain.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 38c7fb8fe7..d05ae77cd1 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4401,12 +4401,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: - if (pciopts->targetIndex == -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("autogenerated pci-root options not set")); - return -1; - } - /* Skip the implicit one */ if (pciopts->targetIndex == 0) return 0; @@ -4637,6 +4631,46 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, return -1; } + /* targetIndex */ + switch ((virDomainControllerModelPCI) cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + /* PHBs for pSeries guests must have been assigned a targetIndex */ + if (pciopts->targetIndex == -1 && + pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) { + virReportControllerMissingOption(cont, model, modelName, "targetIndex"); + return -1; + } + + /* targetIndex only applies to PHBs, so for any other pci-root + * controller it being present is an error */ + if (pciopts->targetIndex != -1 && + pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) { + virReportControllerInvalidOption(cont, model, modelName, "targetIndex"); + return -1; + } + break; + + 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: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + if (pciopts->targetIndex != -1) { + virReportControllerInvalidOption(cont, model, modelName, "targetIndex"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + default: + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + return -1; + } + return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); } -- 2.14.3

https://bugzilla.redhat.com/show_bug.cgi?id=1483816 Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_domain.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index d05ae77cd1..3fe1167155 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4671,6 +4671,40 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, return -1; } + /* pcihole64 */ + switch ((virDomainControllerModelPCI) cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + /* The pcihole64 option only applies to x86 guests */ + if ((pciopts->pcihole64 || + pciopts->pcihole64size != 0) && + !ARCH_IS_X86(def->os.arch)) { + virReportControllerInvalidOption(cont, model, modelName, "pcihole64"); + return -1; + } + break; + + 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 (pciopts->pcihole64 || + pciopts->pcihole64size != 0) { + virReportControllerInvalidOption(cont, model, modelName, "pcihole64"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + default: + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + return -1; + } + return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); } -- 2.14.3

This change catches an invalid use of the option in our test suite. https://bugzilla.redhat.com/show_bug.cgi?id=1483816 Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_domain.c | 42 ++++++++++++++++++-------- tests/qemuxml2argvdata/pcie-expander-bus.xml | 2 +- tests/qemuxml2xmloutdata/pcie-expander-bus.xml | 2 +- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 3fe1167155..6470c7ca03 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4306,12 +4306,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: - if (pciopts->busNr == -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("autogenerated pci-expander-bus options not set")); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PXB)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the pxb controller is not supported in this " @@ -4385,12 +4379,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: - if (pciopts->busNr == -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("autogenerated pcie-expander-bus options not set")); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PXB_PCIE)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the pxb-pcie controller is not supported " @@ -4705,6 +4693,36 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, return -1; } + /* busNr */ + switch ((virDomainControllerModelPCI) cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + if (pciopts->busNr == -1) { + virReportControllerMissingOption(cont, model, modelName, "busNr"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + 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_PCIE_ROOT: + if (pciopts->busNr != -1) { + virReportControllerInvalidOption(cont, model, modelName, "busNr"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + default: + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + return -1; + } + return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); } diff --git a/tests/qemuxml2argvdata/pcie-expander-bus.xml b/tests/qemuxml2argvdata/pcie-expander-bus.xml index ac01c26ccf..237430a1e5 100644 --- a/tests/qemuxml2argvdata/pcie-expander-bus.xml +++ b/tests/qemuxml2argvdata/pcie-expander-bus.xml @@ -35,7 +35,7 @@ <address type='pci' bus='0x00' slot='4'/> </controller> <controller type='pci' index='2' model='pcie-root-port'> - <target busNr='220'> + <target> <node>1</node> </target> <address type='pci' bus='0x01'/> diff --git a/tests/qemuxml2xmloutdata/pcie-expander-bus.xml b/tests/qemuxml2xmloutdata/pcie-expander-bus.xml index aaac423cac..d5e741b80d 100644 --- a/tests/qemuxml2xmloutdata/pcie-expander-bus.xml +++ b/tests/qemuxml2xmloutdata/pcie-expander-bus.xml @@ -36,7 +36,7 @@ </controller> <controller type='pci' index='2' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='2' port='0x0' busNr='220'> + <target chassis='2' port='0x0'> <node>1</node> </target> <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> -- 2.14.3

This change catches an invalid use of the option in our test suite. https://bugzilla.redhat.com/show_bug.cgi?id=1483816 Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_domain.c | 44 ++++++++++++++++++++++++++ tests/qemuxml2argvdata/pcie-expander-bus.xml | 3 -- tests/qemuxml2xmloutdata/pcie-expander-bus.xml | 4 +-- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 6470c7ca03..4278b52144 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4723,6 +4723,50 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, return -1; } + /* numaNode */ + switch ((virDomainControllerModelPCI) cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + /* numaNode can be used for these controllers, but it's not set + * automatically so it can be missing */ + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + /* Only PHBs support numaNode */ + if (pciopts->numaNode != -1 && + pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE) { + virReportControllerInvalidOption(cont, model, modelName, "numaNode"); + return -1; + } + + /* However, the default PHB doesn't support numaNode */ + if (pciopts->numaNode != -1 && + pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE && + pciopts->targetIndex == 0) { + virReportControllerInvalidOption(cont, model, modelName, "numaNode"); + return -1; + } + break; + + 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_PCIE_ROOT: + if (pciopts->numaNode != -1) { + virReportControllerInvalidOption(cont, model, modelName, "numaNode"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + default: + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + return -1; + } + return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); } diff --git a/tests/qemuxml2argvdata/pcie-expander-bus.xml b/tests/qemuxml2argvdata/pcie-expander-bus.xml index 237430a1e5..5c5d34d1e0 100644 --- a/tests/qemuxml2argvdata/pcie-expander-bus.xml +++ b/tests/qemuxml2argvdata/pcie-expander-bus.xml @@ -35,9 +35,6 @@ <address type='pci' bus='0x00' slot='4'/> </controller> <controller type='pci' index='2' model='pcie-root-port'> - <target> - <node>1</node> - </target> <address type='pci' bus='0x01'/> </controller> <controller type='pci' index='3' model='pcie-switch-upstream-port'> diff --git a/tests/qemuxml2xmloutdata/pcie-expander-bus.xml b/tests/qemuxml2xmloutdata/pcie-expander-bus.xml index d5e741b80d..b6498fd2eb 100644 --- a/tests/qemuxml2xmloutdata/pcie-expander-bus.xml +++ b/tests/qemuxml2xmloutdata/pcie-expander-bus.xml @@ -36,9 +36,7 @@ </controller> <controller type='pci' index='2' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='2' port='0x0'> - <node>1</node> - </target> + <target chassis='2' port='0x0'/> <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='pci' index='3' model='pcie-switch-upstream-port'> -- 2.14.3

https://bugzilla.redhat.com/show_bug.cgi?id=1483816 Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_domain.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 4278b52144..393d533935 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4290,12 +4290,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro /* Second pass - now the model specific checks */ switch (model) { case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: - if (pciopts->chassisNr == -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("autogenerated pci-bridge options not set")); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PCI_BRIDGE)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the pci-bridge controller is not supported " @@ -4767,6 +4761,36 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, return -1; } + /* chassisNr */ + switch ((virDomainControllerModelPCI) cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: + if (pciopts->chassisNr == -1) { + virReportControllerMissingOption(cont, model, modelName, "chassisNr"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + 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: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + if (pciopts->chassisNr != -1) { + virReportControllerInvalidOption(cont, model, modelName, "chassisNr"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + default: + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + return -1; + } + return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); } -- 2.14.3

https://bugzilla.redhat.com/show_bug.cgi?id=1483816 Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_domain.c | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 393d533935..f0eb30d248 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4320,12 +4320,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: - if (pciopts->chassis == -1 || pciopts->port == -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("autogenerated pcie-root-port options not set")); - return -1; - } - if ((pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420) && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IOH3420)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -4355,13 +4349,6 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: - if (pciopts->chassis == -1 || pciopts->port == -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("autogenerated pcie-switch-downstream-port " - "options not set")); - return -1; - } - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_XIO3130_DOWNSTREAM)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("The pcie-switch-downstream-port " @@ -4791,6 +4778,43 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, return -1; } + /* chassis and port */ + switch ((virDomainControllerModelPCI) cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: + if (pciopts->chassis == -1) { + virReportControllerMissingOption(cont, model, modelName, "chassis"); + return -1; + } + if (pciopts->port == -1) { + virReportControllerMissingOption(cont, model, modelName, "port"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: + case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + if (pciopts->chassis != -1) { + virReportControllerInvalidOption(cont, model, modelName, "chassis"); + return -1; + } + if (pciopts->port != -1) { + virReportControllerInvalidOption(cont, model, modelName, "port"); + return -1; + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + default: + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + } + return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); } -- 2.14.3

Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_domain.c | 190 ++++++++++++++++++++----------------------------- 1 file changed, 77 insertions(+), 113 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index f0eb30d248..bb0ae72db7 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4270,11 +4270,8 @@ qemuDomainDeviceDefValidateControllerSCSI(const virDomainControllerDef *controll static int qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *controller, const virDomainDef *def, - virQEMUCapsPtr qemuCaps) + virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED) { - virDomainControllerModelPCI model = controller->model; - const virDomainPCIControllerOpts *pciopts; - /* skip pcie-root */ if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) return 0; @@ -4285,119 +4282,50 @@ qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *contro controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) return 0; - pciopts = &controller->opts.pciopts; - - /* Second pass - now the model specific checks */ - switch (model) { - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PCI_BRIDGE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("the pci-bridge controller is not supported " - "in this QEMU binary")); - return -1; - } - - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PXB)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("the pxb controller is not supported in this " - "QEMU binary")); - return -1; - } - - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("the dmi-to-pci-bridge (i82801b11-bridge) " - "controller is not supported in this QEMU binary")); - return -1; - } - - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: - if ((pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420) && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IOH3420)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("the pcie-root-port (ioh3420) controller " - "is not supported in this QEMU binary")); - return -1; - } - - if ((pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCIE_ROOT_PORT) && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PCIE_ROOT_PORT)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("the pcie-root-port (pcie-root-port) controller " - "is not supported in this QEMU binary")); - return -1; - } - - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_X3130_UPSTREAM)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("the pcie-switch-upstream-port (x3130-upstream) " - "controller is not supported in this QEMU binary")); - return -1; - } - - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_XIO3130_DOWNSTREAM)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("The pcie-switch-downstream-port " - "(xio3130-downstream) controller is not " - "supported in this QEMU binary")); - return -1; - } - - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PXB_PCIE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("the pxb-pcie controller is not supported " - "in this QEMU binary")); - return -1; - } - - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: - /* Skip the implicit one */ - if (pciopts->targetIndex == 0) - return 0; - - 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")); - return -1; - } - - if (pciopts->numaNode != -1 && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("the spapr-pci-host-bridge controller doesn't " - "support numa_node in this QEMU binary")); - return -1; - } + return 0; +} - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT: - break; +/** + * virDomainControllerPCIModelNameToQEMUCaps: + * @modelName: model name + * + * Maps model names for PCI controllers (virDomainControllerPCIModelName) + * to the QEMU capabilities required to use them (virQEMUCapsFlags). + * + * Returns: the QEMU capability itself (>0) on success; 0 if no QEMU + * capability is needed; <0 on error. + */ +static int +virDomainControllerPCIModelNameToQEMUCaps(int modelName) +{ + switch ((virDomainControllerPCIModelName) modelName) { + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE: + return QEMU_CAPS_DEVICE_PCI_BRIDGE; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE: + return QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420: + return QEMU_CAPS_DEVICE_IOH3420; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM: + return QEMU_CAPS_DEVICE_X3130_UPSTREAM; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM: + return QEMU_CAPS_DEVICE_XIO3130_DOWNSTREAM; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB: + return QEMU_CAPS_DEVICE_PXB; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE: + return QEMU_CAPS_DEVICE_PXB_PCIE; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCIE_ROOT_PORT: + return QEMU_CAPS_DEVICE_PCIE_ROOT_PORT; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE: + return QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE: + return 0; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST: + default: + return -1; } - return 0; + return -1; } @@ -4427,6 +4355,7 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, const virDomainPCIControllerOpts *pciopts = &cont->opts.pciopts; const char *model = virDomainControllerModelPCITypeToString(cont->model); const char *modelName = virDomainControllerPCIModelNameTypeToString(pciopts->modelName); + int cap = virDomainControllerPCIModelNameToQEMUCaps(pciopts->modelName); if (!model) { virReportEnumRangeError(virDomainControllerModelPCI, cont->model); @@ -4815,6 +4744,41 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, virReportEnumRangeError(virDomainControllerModelPCI, cont->model); } + /* The default PHB for pSeries guests doesn't need any QEMU capability + * to be used, so we should skip the capabilities check altogether */ + if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT && + pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE && + pciopts->targetIndex == 0) { + goto done; + } + + /* QEMU device availability */ + if (cap < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown QEMU device for '%s' controller"), + modelName); + return -1; + } + if (cap > 0 && !virQEMUCapsGet(qemuCaps, cap)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("The '%s' device is not supported by this QEMU binary"), + modelName); + return -1; + } + + /* PHBs didn't support numaNode from the very beginning, so an extra + * capability check is required */ + if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT && + pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE && + pciopts->numaNode != -1 && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Option '%s' is not supported by '%s' device with this QEMU binary"), + "numaNode", modelName); + return -1; + } + + done: return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); } -- 2.14.3

We've implemented all existing checks, and more, in the new function, so we can finally drop the old one. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Laine Stump <laine@laine.org> --- src/qemu/qemu_domain.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index bb0ae72db7..f6db6e2865 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4267,25 +4267,6 @@ qemuDomainDeviceDefValidateControllerSCSI(const virDomainControllerDef *controll } -static int -qemuDomainDeviceDefValidateControllerPCIOld(const virDomainControllerDef *controller, - const virDomainDef *def, - virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED) -{ - /* skip pcie-root */ - if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) - return 0; - - /* Skip pci-root, except for pSeries guests (which actually - * support more than one PCI Host Bridge per guest) */ - if (!qemuDomainIsPSeries(def) && - controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) - return 0; - - return 0; -} - - /** * virDomainControllerPCIModelNameToQEMUCaps: * @modelName: model name @@ -4779,7 +4760,7 @@ qemuDomainDeviceDefValidateControllerPCI(const virDomainControllerDef *cont, } done: - return qemuDomainDeviceDefValidateControllerPCIOld(cont, def, qemuCaps); + return 0; } -- 2.14.3
participants (1)
-
Andrea Bolognani