diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9528b4a49f..ec5e3d453e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3585,6 +3585,46 @@ qemuCheckDiskConfig(virDomainDiskDefPtr disk) } +/* Check whether the device address is using either 'ccw' or default s390 + * address format and whether that's "legal" for the current qemu and/or + * guest os.machine type. This is the corollary to the code which doesn't + * find the address type set using an emulator that supports either 'ccw' + * or s390 and sets the address type based on the capabilities. + * + * If the address is using 'ccw' or s390 and it's not supported, generate + * an error and return false; otherwise, return true. + */ +bool +qemuCheckCCWS390AddressSupport(virDomainDefPtr def, + virDomainDeviceInfo info, + virQEMUCapsPtr qemuCaps, + const char *devicename) +{ + if (info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + if (!qemuDomainMachineIsS390CCW(def)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("cannot use CCW address type for device " + "'%s' using machine type '%s'"), + devicename, def->os.machine); + return false; + } else if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_CCW)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("CCW address type is not supported by " + "this QEMU")); + return false; + } + } else if (info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_S390)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtio S390 address type is not supported by " + "this QEMU")); + return false; + } + } + return true; +} + + /* Qemu 1.2 and later have a binary flag -enable-fips that must be * used for VNC auth to obey FIPS settings; but the flag only * exists on Linux, and with no way to probe for it via QMP. Our @@ -4138,6 +4178,9 @@ qemuBuildDriveDevStr(virDomainDefPtr def, } } + if (!qemuCheckCCWS390AddressSupport(def, disk->info, qemuCaps, disk->dst)) + goto error; + if (disk->iothread && !qemuCheckIOThreads(def, qemuCaps, disk)) goto error; @@ -4592,6 +4635,10 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, int model = def->model; const char *modelName = NULL; + if (!qemuCheckCCWS390AddressSupport(domainDef, def->info, qemuCaps, + "controller")) + return NULL; + if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { if ((qemuSetSCSIControllerModel(domainDef, qemuCaps, &model)) < 0) return NULL; @@ -6884,6 +6931,10 @@ qemuBuildRNGDevStr(virDomainDefPtr def, goto error; } + if (!qemuCheckCCWS390AddressSupport(def, dev->info, qemuCaps, + dev->source.file)) + goto error; + if (dev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) virBufferAsprintf(&buf, "virtio-rng-ccw,rng=obj%s,id=%s", dev->info.alias, dev->info.alias); diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index e356f5bb33..767d31f0c5 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -318,4 +318,9 @@ int qemuCheckDiskConfig(virDomainDiskDefPtr disk); bool qemuCheckFips(void); + +bool qemuCheckCCWS390AddressSupport(virDomainDefPtr def, + virDomainDeviceInfo info, + virQEMUCapsPtr qemuCaps, + const char *devicename); #endif /* __QEMU_COMMAND_H__*/ diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index f46ec5e703..63fafa6bde 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -331,6 +331,10 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW; else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_S390)) disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390; + } else { + if (!qemuCheckCCWS390AddressSupport(vm->def, disk->info, priv->qemuCaps, + disk->dst)) + goto cleanup; } for (i = 0; i < vm->def->ndisks; i++) { @@ -448,6 +452,10 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, controller->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW; else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_S390)) controller->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390; + } else { + if (!qemuCheckCCWS390AddressSupport(vm->def, controller->info, + priv->qemuCaps, "controller")) + goto cleanup; } if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || @@ -1663,6 +1671,10 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver, } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_S390)) { rng->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390; } + } else { + if (!qemuCheckCCWS390AddressSupport(vm->def, rng->info, priv->qemuCaps, + rng->source.file)) + return -1; } if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||