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.liu@intel.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3001
Signed-off-by: Alexandre Chartre <alexandre.chartre@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