qemu: move qemuDomainDeviceDefValidateController() to qemu_validate.c

Move the function and all its static helper functions.

Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Daniel Henrique Barboza 2020-03-26 18:31:20 -03:00 committed by Ján Tomko
parent b8f1f037ed
commit 4d3d025ecb
3 changed files with 808 additions and 803 deletions

View File

@ -5430,808 +5430,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,
@ -6896,7 +6094,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;

View File

@ -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"
@ -1915,3 +1916,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;
}

View File

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