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);