Move the function and all its static helper functions. Signed-off-by: Daniel Henrique Barboza <danielhb413@xxxxxxxxx> --- src/qemu/qemu_domain.c | 804 +-------------------------------------- src/qemu/qemu_validate.c | 804 +++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_validate.h | 3 + 3 files changed, 808 insertions(+), 803 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 2b3dea9d3f..522edb8274 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5421,808 +5421,6 @@ qemuDomainValidateStorageSource(virStorageSourcePtr src, } -static int -qemuDomainDeviceDefValidateControllerAttributes(const virDomainControllerDef *controller) -{ - if (!(controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI && - (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI || - controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL || - controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL))) { - if (controller->queues) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("'queues' is only supported by virtio-scsi controller")); - return -1; - } - if (controller->cmd_per_lun) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("'cmd_per_lun' is only supported by virtio-scsi controller")); - return -1; - } - if (controller->max_sectors) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("'max_sectors' is only supported by virtio-scsi controller")); - return -1; - } - if (controller->ioeventfd) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("'ioeventfd' is only supported by virtio-scsi controller")); - return -1; - } - if (controller->iothread) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("'iothread' is only supported for virtio-scsi controller")); - return -1; - } - } - - return 0; -} - - -/** - * @qemuCaps: QEMU capabilities - * @model: SCSI model to check - * - * Using the @qemuCaps, let's ensure the provided @model can be supported - * - * Returns true if acceptable, false otherwise with error message set. - */ -static bool -qemuDomainCheckSCSIControllerModel(virQEMUCapsPtr qemuCaps, - int model) -{ - switch ((virDomainControllerModelSCSI) model) { - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_LSI)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("This QEMU doesn't support " - "the LSI 53C895A SCSI controller")); - return false; - } - break; - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_SCSI)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("This QEMU doesn't support " - "virtio scsi controller")); - return false; - } - break; - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI: - /*TODO: need checking work here if necessary */ - break; - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_MPTSAS1068)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("This QEMU doesn't support " - "the LSI SAS1068 (MPT Fusion) controller")); - return false; - } - break; - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_MEGASAS)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("This QEMU doesn't support " - "the LSI SAS1078 (MegaRAID) controller")); - return false; - } - break; - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI: - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unsupported controller model: %s"), - virDomainControllerModelSCSITypeToString(model)); - return false; - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST: - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unexpected SCSI controller model %d"), - model); - return false; - } - - return true; -} - - -static int -qemuDomainDeviceDefValidateControllerIDE(const virDomainControllerDef *controller, - const virDomainDef *def) -{ - /* first IDE controller is implicit on various machines */ - if (controller->idx == 0 && qemuDomainHasBuiltinIDE(def)) - return 0; - - /* Since we currently only support the integrated IDE - * controller on various boards, if we ever get to here, it's - * because some other machinetype had an IDE controller - * specified, or one with a single IDE controller had multiple - * IDE controllers specified. - */ - if (qemuDomainHasBuiltinIDE(def)) - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Only a single IDE controller is supported " - "for this machine type")); - else - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("IDE controllers are unsupported for " - "this QEMU binary or machine type")); - return -1; -} - - -/* qemuDomainCheckSCSIControllerIOThreads: - * @controller: Pointer to controller def - * @def: Pointer to domain def - * - * If this controller definition has iothreads set, let's make sure the - * configuration is right before adding to the command line - * - * Returns true if either supported or there are no iothreads for controller; - * otherwise, returns false if configuration is not quite right. - */ -static bool -qemuDomainCheckSCSIControllerIOThreads(const virDomainControllerDef *controller, - const virDomainDef *def) -{ - if (!controller->iothread) - return true; - - if (controller->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && - controller->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI && - controller->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("virtio-scsi IOThreads only available for virtio " - "pci and virtio ccw controllers")); - return false; - } - - /* Can we find the controller iothread in the iothreadid list? */ - if (!virDomainIOThreadIDFind(def, controller->iothread)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("controller iothread '%u' not defined in iothreadid"), - controller->iothread); - return false; - } - - return true; -} - - -static int -qemuDomainDeviceDefValidateControllerSCSI(const virDomainControllerDef *controller, - const virDomainDef *def) -{ - switch ((virDomainControllerModelSCSI) controller->model) { - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL: - if (!qemuDomainCheckSCSIControllerIOThreads(controller, def)) - return -1; - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT: - case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST: - break; - } - - return 0; -} - - -/** - * 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_PCIE_PCI_BRIDGE: - return QEMU_CAPS_DEVICE_PCIE_PCI_BRIDGE; - case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE: - return 0; - case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST: - default: - return -1; - } - - return -1; -} - - -#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, - virQEMUCapsPtr qemuCaps) - -{ - 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); - return -1; - } - if (!modelName) { - virReportEnumRangeError(virDomainControllerPCIModelName, pciopts->modelName); - 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: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: - /* 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_PCIE_TO_PCI_BRIDGE: - if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCIE_PCI_BRIDGE) { - 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; - } - - /* 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: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: - 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; - } - - /* 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: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: - 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; - } - - /* pcihole64 */ - switch ((virDomainControllerModelPCI) cont->model) { - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: - if (pciopts->pcihole64 || pciopts->pcihole64size != 0) { - if (!qemuDomainIsI440FX(def)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Setting the 64-bit PCI hole size is not " - "supported for machine '%s'"), def->os.machine); - return -1; - } - - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_I440FX_PCI_HOLE64_SIZE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("64-bit PCI hole size setting is not supported " - "with this QEMU binary")); - return -1; - } - } - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: - if (pciopts->pcihole64 || pciopts->pcihole64size != 0) { - if (!qemuDomainIsQ35(def)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Setting the 64-bit PCI hole size is not " - "supported for machine '%s'"), def->os.machine); - return -1; - } - - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_Q35_PCI_HOLE64_SIZE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("64-bit PCI hole size setting is not supported " - "with this QEMU binary")); - 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_TO_PCI_BRIDGE: - 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; - } - - /* 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: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: - 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; - } - - /* 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: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: - 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; - } - - /* 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: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: - 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; - } - - /* 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: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: - 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); - } - - /* 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; - } - - return 0; -} - - -#undef virReportControllerInvalidValue -#undef virReportControllerInvalidOption -#undef virReportControllerMissingOption - - -static int -qemuDomainDeviceDefValidateControllerSATA(const virDomainControllerDef *controller, - const virDomainDef *def, - virQEMUCapsPtr qemuCaps) -{ - /* first SATA controller on Q35 machines is implicit */ - if (controller->idx == 0 && qemuDomainIsQ35(def)) - return 0; - - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_AHCI)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("SATA is not supported with this QEMU binary")); - return -1; - } - return 0; -} - - -static int -qemuDomainDeviceDefValidateController(const virDomainControllerDef *controller, - const virDomainDef *def, - virQEMUCapsPtr qemuCaps) -{ - int ret = 0; - - if (!qemuDomainCheckCCWS390AddressSupport(def, &controller->info, qemuCaps, - "controller")) - return -1; - - if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI && - !qemuDomainCheckSCSIControllerModel(qemuCaps, controller->model)) - return -1; - - if (qemuDomainDeviceDefValidateControllerAttributes(controller) < 0) - return -1; - - switch ((virDomainControllerType)controller->type) { - case VIR_DOMAIN_CONTROLLER_TYPE_IDE: - ret = qemuDomainDeviceDefValidateControllerIDE(controller, def); - break; - - case VIR_DOMAIN_CONTROLLER_TYPE_SCSI: - ret = qemuDomainDeviceDefValidateControllerSCSI(controller, def); - break; - - case VIR_DOMAIN_CONTROLLER_TYPE_PCI: - ret = qemuDomainDeviceDefValidateControllerPCI(controller, def, - qemuCaps); - break; - - case VIR_DOMAIN_CONTROLLER_TYPE_SATA: - ret = qemuDomainDeviceDefValidateControllerSATA(controller, def, - qemuCaps); - break; - - case VIR_DOMAIN_CONTROLLER_TYPE_FDC: - case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: - case VIR_DOMAIN_CONTROLLER_TYPE_CCID: - case VIR_DOMAIN_CONTROLLER_TYPE_USB: - case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS: - case VIR_DOMAIN_CONTROLLER_TYPE_LAST: - break; - } - - return ret; -} - - static int qemuDomainDeviceDefValidateVsock(const virDomainVsockDef *vsock, const virDomainDef *def, @@ -6887,7 +6085,7 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev, break; case VIR_DOMAIN_DEVICE_CONTROLLER: - ret = qemuDomainDeviceDefValidateController(dev->data.controller, def, + ret = qemuValidateDomainDeviceDefController(dev->data.controller, def, qemuCaps); break; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 0f267b4abe..f8228f3491 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -23,6 +23,7 @@ #include "qemu_validate.h" #include "qemu_block.h" #include "qemu_domain.h" +#include "domain_conf.h" #include "virlog.h" #include "virutil.h" @@ -1914,3 +1915,806 @@ qemuValidateDomainDeviceDefDisk(const virDomainDiskDef *disk, return 0; } + + +/** + * @qemuCaps: QEMU capabilities + * @model: SCSI model to check + * + * Using the @qemuCaps, let's ensure the provided @model can be supported + * + * Returns true if acceptable, false otherwise with error message set. + */ +static bool +qemuValidateCheckSCSIControllerModel(virQEMUCapsPtr qemuCaps, + int model) +{ + switch ((virDomainControllerModelSCSI) model) { + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_LSI)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support " + "the LSI 53C895A SCSI controller")); + return false; + } + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_SCSI)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support " + "virtio scsi controller")); + return false; + } + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI: + /*TODO: need checking work here if necessary */ + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_MPTSAS1068)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support " + "the LSI SAS1068 (MPT Fusion) controller")); + return false; + } + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_MEGASAS)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support " + "the LSI SAS1078 (MegaRAID) controller")); + return false; + } + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unsupported controller model: %s"), + virDomainControllerModelSCSITypeToString(model)); + return false; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected SCSI controller model %d"), + model); + return false; + } + + return true; +} + + + +static int +qemuValidateDomainDeviceDefControllerSATA(const virDomainControllerDef *controller, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps) +{ + /* first SATA controller on Q35 machines is implicit */ + if (controller->idx == 0 && qemuDomainIsQ35(def)) + return 0; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_AHCI)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("SATA is not supported with this QEMU binary")); + return -1; + } + return 0; +} + + +static int +qemuValidateDomainDeviceDefControllerIDE(const virDomainControllerDef *controller, + const virDomainDef *def) +{ + /* first IDE controller is implicit on various machines */ + if (controller->idx == 0 && qemuDomainHasBuiltinIDE(def)) + return 0; + + /* Since we currently only support the integrated IDE + * controller on various boards, if we ever get to here, it's + * because some other machinetype had an IDE controller + * specified, or one with a single IDE controller had multiple + * IDE controllers specified. + */ + if (qemuDomainHasBuiltinIDE(def)) + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only a single IDE controller is supported " + "for this machine type")); + else + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("IDE controllers are unsupported for " + "this QEMU binary or machine type")); + return -1; +} + + +/* qemuValidateCheckSCSIControllerIOThreads: + * @controller: Pointer to controller def + * @def: Pointer to domain def + * + * If this controller definition has iothreads set, let's make sure the + * configuration is right before adding to the command line + * + * Returns true if either supported or there are no iothreads for controller; + * otherwise, returns false if configuration is not quite right. + */ +static bool +qemuValidateCheckSCSIControllerIOThreads(const virDomainControllerDef *controller, + const virDomainDef *def) +{ + if (!controller->iothread) + return true; + + if (controller->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && + controller->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI && + controller->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtio-scsi IOThreads only available for virtio " + "pci and virtio ccw controllers")); + return false; + } + + /* Can we find the controller iothread in the iothreadid list? */ + if (!virDomainIOThreadIDFind(def, controller->iothread)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("controller iothread '%u' not defined in iothreadid"), + controller->iothread); + return false; + } + + return true; +} + + +static int +qemuValidateDomainDeviceDefControllerSCSI(const virDomainControllerDef *controller, + const virDomainDef *def) +{ + switch ((virDomainControllerModelSCSI) controller->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL: + if (!qemuValidateCheckSCSIControllerIOThreads(controller, def)) + return -1; + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST: + break; + } + + return 0; +} + + +/** + * virValidateControllerPCIModelNameToQEMUCaps: + * @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 +virValidateControllerPCIModelNameToQEMUCaps(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_PCIE_PCI_BRIDGE: + return QEMU_CAPS_DEVICE_PCIE_PCI_BRIDGE; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE: + return 0; + case VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST: + default: + return -1; + } + + return -1; +} + + +static int +qemuValidateDomainDeviceDefControllerAttributes(const virDomainControllerDef *controller) +{ + if (!(controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI && + (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI || + controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL || + controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL))) { + if (controller->queues) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("'queues' is only supported by virtio-scsi controller")); + return -1; + } + if (controller->cmd_per_lun) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("'cmd_per_lun' is only supported by virtio-scsi controller")); + return -1; + } + if (controller->max_sectors) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("'max_sectors' is only supported by virtio-scsi controller")); + return -1; + } + if (controller->ioeventfd) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("'ioeventfd' is only supported by virtio-scsi controller")); + return -1; + } + if (controller->iothread) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("'iothread' is only supported for virtio-scsi controller")); + return -1; + } + } + + return 0; +} + + +#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 +qemuValidateDomainDeviceDefControllerPCI(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); + int cap = virValidateControllerPCIModelNameToQEMUCaps(pciopts->modelName); + + if (!model) { + virReportEnumRangeError(virDomainControllerModelPCI, cont->model); + return -1; + } + if (!modelName) { + virReportEnumRangeError(virDomainControllerPCIModelName, pciopts->modelName); + 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: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: + /* 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_PCIE_TO_PCI_BRIDGE: + if (pciopts->modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCIE_PCI_BRIDGE) { + 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; + } + + /* 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: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: + 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; + } + + /* 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: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: + 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; + } + + /* pcihole64 */ + switch ((virDomainControllerModelPCI) cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + if (pciopts->pcihole64 || pciopts->pcihole64size != 0) { + if (!qemuDomainIsI440FX(def)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Setting the 64-bit PCI hole size is not " + "supported for machine '%s'"), def->os.machine); + return -1; + } + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_I440FX_PCI_HOLE64_SIZE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("64-bit PCI hole size setting is not supported " + "with this QEMU binary")); + return -1; + } + } + break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + if (pciopts->pcihole64 || pciopts->pcihole64size != 0) { + if (!qemuDomainIsQ35(def)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Setting the 64-bit PCI hole size is not " + "supported for machine '%s'"), def->os.machine); + return -1; + } + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_Q35_PCI_HOLE64_SIZE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("64-bit PCI hole size setting is not supported " + "with this QEMU binary")); + 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_TO_PCI_BRIDGE: + 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; + } + + /* 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: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: + 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; + } + + /* 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: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: + 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; + } + + /* 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: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: + 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; + } + + /* 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: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE: + 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); + } + + /* 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; + } + + return 0; +} + + +#undef virReportControllerInvalidValue +#undef virReportControllerInvalidOption +#undef virReportControllerMissingOption + + +int +qemuValidateDomainDeviceDefController(const virDomainControllerDef *controller, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps) +{ + int ret = 0; + + if (!qemuDomainCheckCCWS390AddressSupport(def, &controller->info, qemuCaps, + "controller")) + return -1; + + if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI && + !qemuValidateCheckSCSIControllerModel(qemuCaps, controller->model)) + return -1; + + if (qemuValidateDomainDeviceDefControllerAttributes(controller) < 0) + return -1; + + switch ((virDomainControllerType)controller->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_IDE: + ret = qemuValidateDomainDeviceDefControllerIDE(controller, def); + break; + + case VIR_DOMAIN_CONTROLLER_TYPE_SCSI: + ret = qemuValidateDomainDeviceDefControllerSCSI(controller, def); + break; + + case VIR_DOMAIN_CONTROLLER_TYPE_PCI: + ret = qemuValidateDomainDeviceDefControllerPCI(controller, def, + qemuCaps); + break; + + case VIR_DOMAIN_CONTROLLER_TYPE_SATA: + ret = qemuValidateDomainDeviceDefControllerSATA(controller, def, + qemuCaps); + break; + + case VIR_DOMAIN_CONTROLLER_TYPE_FDC: + case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: + case VIR_DOMAIN_CONTROLLER_TYPE_CCID: + case VIR_DOMAIN_CONTROLLER_TYPE_USB: + case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS: + case VIR_DOMAIN_CONTROLLER_TYPE_LAST: + break; + } + + return ret; +} diff --git a/src/qemu/qemu_validate.h b/src/qemu/qemu_validate.h index ba732d05d8..85efa9354f 100644 --- a/src/qemu/qemu_validate.h +++ b/src/qemu/qemu_validate.h @@ -48,3 +48,6 @@ int qemuValidateDomainDeviceDefHostdev(const virDomainHostdevDef *hostdev, virQEMUCapsPtr qemuCaps); int qemuValidateDomainDeviceDefVideo(const virDomainVideoDef *video, virQEMUCapsPtr qemuCaps); +int qemuValidateDomainDeviceDefController(const virDomainControllerDef *controller, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps); -- 2.25.1