qemu_command.c should deal with translating our domain definition into a QEMU command line and nothing else. Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx> --- src/qemu/qemu_command.c | 71 ++++---------------------------- src/qemu/qemu_process.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++ tests/qemuxml2argvtest.c | 8 ++-- 3 files changed, 117 insertions(+), 67 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3f542bc..823b58d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6445,9 +6445,6 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, size_t ncpus = 0; char **cpus = NULL; virCPUDataPtr data = NULL; - virCPUDataPtr hostData = NULL; - char *compare_msg = NULL; - virCPUCompareResult cmp; const char *preferred; virCapsPtr caps = NULL; bool compareAgainstHost = ((def->virtType == VIR_DOMAIN_VIRT_KVM || @@ -6459,15 +6456,6 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, host = caps->host.cpu; - if (virQEMUCapsGetCPUDefinitions(qemuCaps, &cpus, &ncpus) < 0) - goto cleanup; - - if (!host || !host->model || ncpus == 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("CPU specification not supported by hypervisor")); - goto cleanup; - } - if (!(cpu = virCPUDefCopy(def->cpu))) goto cleanup; @@ -6476,53 +6464,9 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, cpuUpdate(cpu, host) < 0) goto cleanup; - /* For non-KVM, CPU features are emulated, so host compat doesn't matter */ - if (compareAgainstHost) { - bool noTSX = false; - - cmp = cpuGuestData(host, cpu, &data, &compare_msg); - switch (cmp) { - case VIR_CPU_COMPARE_INCOMPATIBLE: - if (cpuEncode(host->arch, host, NULL, &hostData, - NULL, NULL, NULL, NULL) == 0 && - (!cpuHasFeature(hostData, "hle") || - !cpuHasFeature(hostData, "rtm")) && - (STREQ_NULLABLE(cpu->model, "Haswell") || - STREQ_NULLABLE(cpu->model, "Broadwell"))) - noTSX = true; - - if (compare_msg) { - if (noTSX) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("guest and host CPU are not compatible: " - "%s; try using '%s-noTSX' CPU model"), - compare_msg, cpu->model); - } else { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("guest and host CPU are not compatible: " - "%s"), - compare_msg); - } - } else { - if (noTSX) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("guest CPU is not compatible with host " - "CPU; try using '%s-noTSX' CPU model"), - cpu->model); - } else { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("guest CPU is not compatible with host " - "CPU")); - } - } - /* fall through */ - case VIR_CPU_COMPARE_ERROR: - goto cleanup; - - default: - break; - } - } + if (compareAgainstHost && + cpuGuestData(host, cpu, &data, NULL) == VIR_CPU_COMPARE_ERROR) + goto cleanup; /* Only 'svm' requires --enable-nesting. The nested * 'vmx' patches now simply hook off the CPU features @@ -6547,7 +6491,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, virBufferAddLit(buf, "host"); if (def->os.arch == VIR_ARCH_ARMV7L && - host->arch == VIR_ARCH_AARCH64) { + caps->host.arch == VIR_ARCH_AARCH64) { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_AARCH64_OFF)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("QEMU binary does not support CPU " @@ -6566,7 +6510,6 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, } else { featCpu = cpu; } - } else { if (VIR_ALLOC(guest) < 0) goto cleanup; @@ -6582,6 +6525,10 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, guest->type = VIR_CPU_TYPE_GUEST; guest->fallback = cpu->fallback; + + if (virQEMUCapsGetCPUDefinitions(qemuCaps, &cpus, &ncpus) < 0) + goto cleanup; + if (cpuDecode(guest, data, (const char **)cpus, ncpus, preferred) < 0) goto cleanup; @@ -6611,9 +6558,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, ret = 0; cleanup: virObjectUnref(caps); - VIR_FREE(compare_msg); cpuDataFree(data); - cpuDataFree(hostData); virCPUDefFree(guest); virCPUDefFree(cpu); virStringFreeListCount(cpus, ncpus); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 7481626..4d709fc 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4390,6 +4390,108 @@ qemuProcessStartValidateXML(virQEMUDriverPtr driver, return 0; } + +static int +qemuProcessStartValidateGuestCPU(virDomainObjPtr vm, + virQEMUCapsPtr qemuCaps, + virCapsPtr caps, + unsigned int flags) +{ + int ret = -1; + virCPUDefPtr host = NULL; + virCPUDefPtr cpu = NULL; + size_t ncpus = 0; + char **cpus = NULL; + bool noTSX = false; + virCPUCompareResult cmp; + virCPUDataPtr data = NULL; + virCPUDataPtr hostData = NULL; + char *compare_msg = NULL; + + if (!vm->def->cpu || + (vm->def->cpu->mode == VIR_CPU_MODE_CUSTOM && + !vm->def->cpu->model)) + return 0; + + if ((vm->def->virtType != VIR_DOMAIN_VIRT_KVM && + vm->def->cpu->mode == VIR_CPU_MODE_CUSTOM) || + vm->def->cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) + return 0; + + host = caps->host.cpu; + + if (virQEMUCapsGetCPUDefinitions(qemuCaps, &cpus, &ncpus) < 0) + goto cleanup; + + if (!host || !host->model || ncpus == 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("CPU specification not supported by hypervisor")); + goto cleanup; + } + + if (!(cpu = virCPUDefCopy(vm->def->cpu))) + goto cleanup; + + if (cpu->mode == VIR_CPU_MODE_HOST_MODEL && + flags & VIR_QEMU_PROCESS_START_NEW && + cpuUpdate(cpu, host) < 0) + goto cleanup; + + cmp = cpuGuestData(host, cpu, &data, &compare_msg); + switch (cmp) { + case VIR_CPU_COMPARE_INCOMPATIBLE: + if (cpuEncode(host->arch, host, NULL, &hostData, + NULL, NULL, NULL, NULL) == 0 && + (!cpuHasFeature(hostData, "hle") || + !cpuHasFeature(hostData, "rtm")) && + (STREQ_NULLABLE(cpu->model, "Haswell") || + STREQ_NULLABLE(cpu->model, "Broadwell"))) + noTSX = true; + + if (compare_msg) { + if (noTSX) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("guest and host CPU are not compatible: " + "%s; try using '%s-noTSX' CPU model"), + compare_msg, cpu->model); + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("guest and host CPU are not compatible: " + "%s"), + compare_msg); + } + } else { + if (noTSX) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("guest CPU is not compatible with host " + "CPU; try using '%s-noTSX' CPU model"), + cpu->model); + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("guest CPU is not compatible with host " + "CPU")); + } + } + /* fall through */ + case VIR_CPU_COMPARE_ERROR: + goto cleanup; + + default: + break; + } + + ret = 0; + + cleanup: + VIR_FREE(compare_msg); + cpuDataFree(data); + cpuDataFree(hostData); + virCPUDefFree(cpu); + virStringFreeListCount(cpus, ncpus); + return ret; +} + + /** * qemuProcessStartValidate: * @vm: domain object @@ -4459,6 +4561,9 @@ qemuProcessStartValidate(virQEMUDriverPtr driver, } } + if (qemuProcessStartValidateGuestCPU(vm, qemuCaps, caps, flags) < 0) + return -1; + return 0; } diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index f9ed6f5..2b94ff0 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1394,13 +1394,13 @@ mymain(void) DO_TEST_FAILURE("cpu-host-passthrough", NONE); DO_TEST_FAILURE("cpu-qemu-host-passthrough", QEMU_CAPS_KVM); - driver.caps->host.cpu = cpuHaswell; + qemuTestSetHostCPU(driver.caps, cpuHaswell); DO_TEST("cpu-Haswell", QEMU_CAPS_KVM); DO_TEST("cpu-Haswell2", QEMU_CAPS_KVM); DO_TEST("cpu-Haswell3", QEMU_CAPS_KVM); DO_TEST("cpu-Haswell-noTSX", QEMU_CAPS_KVM); DO_TEST("cpu-host-model-cmt", NONE); - driver.caps->host.cpu = cpuDefault; + qemuTestSetHostCPU(driver.caps, NULL); DO_TEST("encrypted-disk", NONE); DO_TEST("encrypted-disk-usage", NONE); @@ -1947,14 +1947,14 @@ mymain(void) QEMU_CAPS_KVM, QEMU_CAPS_MACHINE_OPT, QEMU_CAPS_MACH_VIRT_GIC_VERSION); - driver.caps->host.cpu->arch = VIR_ARCH_AARCH64; + qemuTestSetHostArch(driver.caps, VIR_ARCH_AARCH64); DO_TEST("aarch64-kvm-32-on-64", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_VIRTIO_MMIO, QEMU_CAPS_KVM, QEMU_CAPS_CPU_AARCH64_OFF); DO_TEST_FAILURE("aarch64-kvm-32-on-64", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_VIRTIO_MMIO, QEMU_CAPS_KVM); - driver.caps->host.cpu->arch = cpuDefault->arch; + qemuTestSetHostArch(driver.caps, VIR_ARCH_NONE); DO_TEST("kvm-pit-device", QEMU_CAPS_KVM_PIT_TICK_POLICY); DO_TEST("kvm-pit-delay", QEMU_CAPS_NO_KVM_PIT); -- 2.9.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list