提交 e9634933 编写于 作者: J Jiri Denemark

qemu: Separate guest CPU validation from command line creation

qemu_command.c should deal with translating our domain definition into a
QEMU command line and nothing else.
Signed-off-by: NJiri Denemark <jdenemar@redhat.com>
上级 bfc5a5e6
......@@ -6552,9 +6552,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 ||
......@@ -6566,15 +6563,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;
......@@ -6583,53 +6571,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
......@@ -6654,7 +6598,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 "
......@@ -6673,7 +6617,6 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
} else {
featCpu = cpu;
}
} else {
if (VIR_ALLOC(guest) < 0)
goto cleanup;
......@@ -6689,6 +6632,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;
......@@ -6718,9 +6665,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
ret = 0;
cleanup:
virObjectUnref(caps);
VIR_FREE(compare_msg);
cpuDataFree(data);
cpuDataFree(hostData);
virCPUDefFree(guest);
virCPUDefFree(cpu);
virStringFreeListCount(cpus, ncpus);
......
......@@ -4437,6 +4437,9 @@ qemuProcessStartValidateGraphics(virDomainObjPtr vm)
}
}
if (qemuProcessStartValidateGuestCPU(vm, qemuCaps, caps, flags) < 0)
return -1;
return 0;
}
......@@ -4469,6 +4472,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
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册