diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 87d76827e8..34d57606f0 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6243,13 +6243,6 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, if (def->os.arch == VIR_ARCH_ARMV7L && driver->hostarch == VIR_ARCH_AARCH64) { - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_AARCH64_OFF)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("QEMU binary does not support CPU " - "host-passthrough for armv7l on " - "aarch64 host")); - return -1; - } virBufferAddLit(buf, ",aarch64=off"); } @@ -6257,19 +6250,16 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_MIGRATABLE)) { virBufferAsprintf(buf, ",migratable=%s", virTristateSwitchTypeToString(cpu->migratable)); - } else if (ARCH_IS_X86(def->os.arch) && - cpu->migratable == VIR_TRISTATE_SWITCH_OFF) { - /* This is the default on x86 */ - } else { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Migratable attribute for host-passthrough " - "CPU is not supported by QEMU binary")); - return -1; } } break; case VIR_CPU_MODE_HOST_MODEL: + /* HOST_MODEL is a valid CPU mode for domain XMLs of all archs, meaning + * that we can't move this validation to parse time. By the time we reach + * this point, all non-PPC64 archs must have translated the CPU model to + * something else and set the CPU mode to MODE_CUSTOM. + */ if (ARCH_IS_PPC64(def->os.arch)) { virBufferAddLit(buf, "host"); if (cpu->model && diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 4a7a25ae8e..dafef84bd7 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -352,6 +352,59 @@ qemuValidateDomainDefFeatures(const virDomainDef *def, } +static int +qemuValidateDomainDefCpu(virQEMUDriverPtr driver, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps) +{ + virCPUDefPtr cpu = def->cpu; + + if (!cpu) + return 0; + + if (!cpu->model && cpu->mode == VIR_CPU_MODE_CUSTOM) + return 0; + + switch ((virCPUMode) cpu->mode) { + case VIR_CPU_MODE_HOST_PASSTHROUGH: + if (def->os.arch == VIR_ARCH_ARMV7L && + driver->hostarch == VIR_ARCH_AARCH64) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_AARCH64_OFF)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("QEMU binary does not support CPU " + "host-passthrough for armv7l on " + "aarch64 host")); + return -1; + } + } + + if (cpu->migratable && + cpu->migratable != VIR_TRISTATE_SWITCH_OFF && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_MIGRATABLE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Migratable attribute for host-passthrough " + "CPU is not supported by QEMU binary")); + return -1; + } + break; + + case VIR_CPU_MODE_HOST_MODEL: + /* qemu_command.c will error out if cpu->mode is HOST_MODEL for + * every arch but PPC64. However, we can't move this validation + * here because non-PPC64 archs will translate HOST_MODEL to + * something else during domain start, changing cpu->mode to + * CUSTOM. + */ + break; + case VIR_CPU_MODE_CUSTOM: + case VIR_CPU_MODE_LAST: + break; + } + + return 0; +} + + static int qemuValidateDomainDefClockTimers(const virDomainDef *def, virQEMUCapsPtr qemuCaps) @@ -935,6 +988,9 @@ qemuValidateDomainDef(const virDomainDef *def, } } + if (qemuValidateDomainDefCpu(driver, def, qemuCaps) < 0) + return -1; + if (qemuDomainDefValidateMemoryHotplug(def, qemuCaps, NULL) < 0) return -1; diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 40ce346a73..67e29ba085 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2892,9 +2892,9 @@ mymain(void) QEMU_CAPS_DEVICE_VIRTIO_MMIO, QEMU_CAPS_DEVICE_PL011, QEMU_CAPS_KVM, QEMU_CAPS_CPU_AARCH64_OFF); - DO_TEST_FAILURE("aarch64-kvm-32-on-64", - QEMU_CAPS_DEVICE_VIRTIO_MMIO, - QEMU_CAPS_KVM); + DO_TEST_PARSE_ERROR("aarch64-kvm-32-on-64", + QEMU_CAPS_DEVICE_VIRTIO_MMIO, + QEMU_CAPS_KVM); DO_TEST("aarch64-pci-serial", QEMU_CAPS_DEVICE_PCI_SERIAL, QEMU_CAPS_CHARDEV_LOGFILE,