KVM emulates the ARCH_CAPABILITIES on x86 for both Intel and AMD cpus, although the IA32_ARCH_CAPABILITIES MSR is an Intel-specific MSR and it makes no sense to emulate it on AMD.
As a consequence, VMs created on AMD with qemu -cpu host and using KVM will advertise the ARCH_CAPABILITIES feature and provide the IA32_ARCH_CAPABILITIES MSR. This can cause issues (like Windows BSOD) as the guest OS might not expect this MSR to exist on such cpus (the AMD documentation specifies that ARCH_CAPABILITIES feature and MSR are not defined on the AMD architecture). A fix was proposed in KVM code, however KVM maintainers don't want to change this behavior that exists for 6+ years and suggest changes to be done in qemu instead. So this commit changes the behavior in qemu so that ARCH_CAPABILITIES is not available anymore for AMD cpus on i440fx and q35 machines. The capability remains available (and enabled by default) on older versions of i440fx/q35 machines. Suggested-by: Zhao Liu <zhao1....@intel.com> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3001 Signed-off-by: Alexandre Chartre <alexandre.char...@oracle.com> --- hw/i386/pc.c | 4 +++- target/i386/cpu.c | 18 ++++++++++++++++++ target/i386/cpu.h | 7 +++++++ target/i386/kvm/kvm.c | 5 +++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index b211633575..c175e7d9e7 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -81,7 +81,9 @@ { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, }, -GlobalProperty pc_compat_10_0[] = {}; +GlobalProperty pc_compat_10_0[] = { + { TYPE_X86_CPU, "x-amd-disable-arch-capabs", "false" }, +}; const size_t pc_compat_10_0_len = G_N_ELEMENTS(pc_compat_10_0); GlobalProperty pc_compat_9_2[] = {}; diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 0d35e95430..6247e347ea 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -8324,6 +8324,22 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp) } } + /* + * For years, KVM has inadvertently emulated the ARCH_CAPABILITIES + * MSR on AMD although this is an Intel-specific MSR; and KVM will + * continue doing so to not change its ABI for existing setups. + * + * So ensure that the ARCH_CAPABILITIES MSR is disabled on AMD cpus + * to prevent providing a cpu with an MSR which is not supposed to + * be there. + */ + if (cpu->amd_disable_arch_capabs && IS_AMD_CPU(env)) { + mark_unavailable_features(cpu, FEAT_7_0_EDX, + env->user_features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_CAPABILITIES, + "This feature is not available for AMD Guest"); + env->features[FEAT_7_0_EDX] &= ~CPUID_7_0_EDX_ARCH_CAPABILITIES; + } + if (x86_threads_per_pkg(&env->topo_info) > 1) { env->features[FEAT_1_EDX] |= CPUID_HT; @@ -9393,6 +9409,8 @@ static const Property x86_cpu_properties[] = { DEFINE_PROP_BOOL("x-intel-pt-auto-level", X86CPU, intel_pt_auto_level, true), DEFINE_PROP_BOOL("x-l1-cache-per-thread", X86CPU, l1_cache_per_core, true), + DEFINE_PROP_BOOL("x-amd-disable-arch-capabs", X86CPU, amd_disable_arch_capabs, + true), }; #ifndef CONFIG_USER_ONLY diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 51e10139df..a3fc80de3a 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2306,6 +2306,13 @@ struct ArchCPU { */ uint32_t guest_phys_bits; + /* + * Compatibility bits for old machine types. + * If true disable CPUID_7_0_EDX_ARCH_CAPABILITIES and + * MSR_IA32_ARCH_CAPABILITIES for AMD Guest. + */ + bool amd_disable_arch_capabs; + /* in order to simplify APIC support, we leave this pointer to the user */ struct DeviceState *apic_state; diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 234878c613..40a50ae193 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -2368,6 +2368,11 @@ int kvm_arch_init_vcpu(CPUState *cs) cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE); + if (cpu->amd_disable_arch_capabs && + !(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_CAPABILITIES)) { + has_msr_arch_capabs = false; + } + if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_RDTSCP)) { has_msr_tsc_aux = false; } -- 2.43.5