mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
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: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
parent
bfc5a5e6ff
commit
e9634933ea
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user