mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
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:
parent
b8f1f037ed
commit
4d3d025ecb
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user