Prior to v10.1, if requested by user, arch-capabilities is always on despite the fact that CPUID advertises it to be off/unvailable. this causes a migration issue for VMs that are run on a machine without arch-capabilities and expect this feature to be present on the destination host with QEMU 10.1.
This commit add a compatibility property to restore the legacy behavior for all machines with version prior to 10.1 Signed-off-by: Hector Cao <hector....@canonical.com> --- hw/core/machine.c | 1 + migration/migration.h | 12 ++++++++++++ migration/options.c | 3 +++ target/i386/kvm/kvm.c | 5 ++++- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 38c949c4f2..8ad5d79cb3 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -45,6 +45,7 @@ GlobalProperty hw_compat_10_0[] = { { "vfio-pci", "x-migration-load-config-after-iter", "off" }, { "ramfb", "use-legacy-x86-rom", "true"}, { "vfio-pci-nohotplug", "use-legacy-x86-rom", "true" }, + { "migration", "arch-cap-always-on", "true" }, }; const size_t hw_compat_10_0_len = G_N_ELEMENTS(hw_compat_10_0); diff --git a/migration/migration.h b/migration/migration.h index 01329bf824..5124ff3636 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -510,6 +510,18 @@ struct MigrationState { bool rdma_migration; GSource *hup_source; + + /* + * This variable allows to keep the backward compatibility with QEMU (<10.1) + * on the arch-capabilities detection. + * With the commit d3a2413 (since 10.1), the arch-capabilities feature is gated + * with the CPUID bit (CPUID_7_0_EDX_ARCH_CAPABILITIES) instead of being always + * enabled when user requests for it. this new behavior breaks migration of VMs + * created and run with older QEMU on machines without IA32_ARCH_CAPABILITIES MSR, + * those VMs might have arch-capabilities enabled and break when migrating + * to a host with QEMU 10.1 with error : missing feature arch-capabilities + */ + bool arch_cap_always_on; }; void migrate_set_state(MigrationStatus *state, MigrationStatus old_state, diff --git a/migration/options.c b/migration/options.c index 4e923a2e07..3a80dba9c5 100644 --- a/migration/options.c +++ b/migration/options.c @@ -203,6 +203,9 @@ const Property migration_properties[] = { MIGRATION_CAPABILITY_SWITCHOVER_ACK), DEFINE_PROP_MIG_CAP("x-dirty-limit", MIGRATION_CAPABILITY_DIRTY_LIMIT), DEFINE_PROP_MIG_CAP("mapped-ram", MIGRATION_CAPABILITY_MAPPED_RAM), + + DEFINE_PROP_BOOL("arch-cap-always-on", MigrationState, + arch_cap_always_on, false), }; const size_t migration_properties_count = ARRAY_SIZE(migration_properties); diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 306430a052..e2ec4e6de5 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -42,6 +42,7 @@ #include "xen-emu.h" #include "hyperv.h" #include "hyperv-proto.h" +#include "migration/migration.h" #include "gdbstub/enums.h" #include "qemu/host-utils.h" @@ -438,6 +439,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, uint32_t ret = 0; uint32_t cpuid_1_edx, unused; uint64_t bitmask; + MigrationState *ms = migrate_get_current(); cpuid = get_supported_cpuid(s); @@ -508,7 +510,8 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, * mcahines at all, do not show the fake ARCH_CAPABILITIES MSR that * KVM sets up. */ - if (!has_msr_arch_capabs || !(edx & CPUID_7_0_EDX_ARCH_CAPABILITIES)) { + if (!has_msr_arch_capabs + || (!(edx & CPUID_7_0_EDX_ARCH_CAPABILITIES) && (!ms->arch_cap_always_on))) { ret &= ~CPUID_7_0_EDX_ARCH_CAPABILITIES; } } else if (function == 7 && index == 1 && reg == R_EAX) { -- 2.45.2