qemu_command.c should deal with translating our domain definition into a
QEMU command line and nothing else.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
Notes:
Version 2:
- no change
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 c657354..d6462d3 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6572,9 +6572,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 ||
@@ -6586,15 +6583,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;
@@ -6603,53 +6591,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
@@ -6674,7 +6618,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 "
@@ -6693,7 +6637,6 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
} else {
featCpu = cpu;
}
-
} else {
if (VIR_ALLOC(guest) < 0)
goto cleanup;
@@ -6709,6 +6652,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;
@@ -6738,9 +6685,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 cecd321..b2d1127 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4437,6 +4437,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
@@ -4506,6 +4608,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 1b1918a..8190556 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1416,13 +1416,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);
@@ -1974,14 +1974,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.10.0