[PATCH v2] qemu: stop silently narrowing the guest CPU during live migration
qemuDomainMakeCPUMigratable() strips the features that a CPU model marks as added (in src/cpu_map/x86_*.xml) from the migratable definition unless the user requested them explicitly. This keeps a custom CPU migratable to an older destination libvirt whose copy of the model does not know those features yet. A host-model CPU gains nothing from this and is actively harmed by it. By the time it reaches this function host-model has already been expanded into an explicit custom model that is exactly what we ask QEMU for on the source, and host-model is not guaranteed to migrate to an older libvirt in the first place. Stripping the added features only narrows the guest CPU silently on the destination. Every Intel model from Westmere through Sapphire Rapids marks vmx-exit-load-perf-global-ctrl and vmx-entry-load-perf-global-ctrl as added. These control the LOAD_IA32_PERF_GLOBAL_CTRL allowed-1 bits of the MSR_IA32_VMX_{EXIT,ENTRY}_CTLS MSRs, which modern QEMU only advertises when the features are present on the -cpu command line. After a host-model live migration the destination QEMU is started without them, so a nested guest observes different VMX capability MSRs than it did before the migration. A guest that snapshots those MSRs at kvm_intel module load and validates every newly onlined CPU against the snapshot -- Linux does exactly that -- then refuses to bring up a vCPU hot-plugged after the migration: kvm_intel: Inconsistent VMCS config on CPU N kvm: enabling virtualization on CPUN failed smpboot: CPU N is now offline and the guest agent's online attempt returns -EIO. Treat a host-model CPU's features as explicitly requested by building the keep list from the already expanded definition rather than from origCPU. Custom CPUs are unaffected, so their migration compatibility with older destinations is preserved. Signed-off-by: Denis V. Lunev <den@openvz.org> --- v1 -> v2: instead of dropping the added-feature stripping altogether (v1), keep it and only stop applying it to a host-model CPU. Custom CPUs still rely on the stripping to stay migratable to an older destination libvirt, which v1 regressed. src/qemu/qemu_domain.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index a43a5c0e4f..e1b805d906 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5373,12 +5373,18 @@ qemuDomainMakeCPUMigratable(virArch arch, if (virCPUx86GetAddedFeatures(cpu->model, &data.added) < 0) return -1; - /* Drop features marked as added in a cpu model, but only - * when they are not mentioned in origCPU, i.e., when they were not - * explicitly mentioned by the user. - */ + /* Drop features marked as added in a CPU model unless they were + * explicitly requested, so the migratable definition stays + * compatible with destinations that do not know them. For host-model + * the expanded definition is itself the requested CPU, so keep all of + * its features; for a custom CPU keep only those listed in origCPU. */ if (data.added) { - g_auto(GStrv) keep = virCPUDefListExplicitFeatures(origCPU); + g_auto(GStrv) keep = NULL; + + if (origCPU->mode == VIR_CPU_MODE_HOST_MODEL) + keep = virCPUDefListExplicitFeatures(cpu); + else + keep = virCPUDefListExplicitFeatures(origCPU); data.keep = keep; virCPUDefFilterFeatures(cpu, qemuDomainDropAddedCPUFeatures, &data); -- 2.53.0
participants (1)
-
Denis V. Lunev