Skip to content

Commit fd706c9

Browse files
sean-jcbonzini
authored andcommitted
KVM: x86: Snapshot if a vCPU's vendor model is AMD vs. Intel compatible
Add kvm_vcpu_arch.is_amd_compatible to cache if a vCPU's vendor model is compatible with AMD, i.e. if the vCPU vendor is AMD or Hygon, along with helpers to check if a vCPU is compatible AMD vs. Intel. To handle Intel vs. AMD behavior related to masking the LVTPC entry, KVM will need to check for vendor compatibility on every PMI injection, i.e. querying for AMD will soon be a moderately hot path. Note! This subtly (or maybe not-so-subtly) makes "Intel compatible" KVM's default behavior, both if userspace omits (or never sets) CPUID 0x0 and if userspace sets a completely unknown vendor. One could argue that KVM should treat such vCPUs as not being compatible with Intel *or* AMD, but that would add useless complexity to KVM. KVM needs to do *something* in the face of vendor specific behavior, and so unless KVM conjured up a magic third option, choosing to treat unknown vendors as neither Intel nor AMD means that checks on AMD compatibility would yield Intel behavior, and checks for Intel compatibility would yield AMD behavior. And that's far worse as it would effectively yield random behavior depending on whether KVM checked for AMD vs. Intel vs. !AMD vs. !Intel. And practically speaking, all x86 CPUs follow either Intel or AMD architecture, i.e. "supporting" an unknown third architecture adds no value. Deliberately don't convert any of the existing guest_cpuid_is_intel() checks, as the Intel side of things is messier due to some flows explicitly checking for exactly vendor==Intel, versus some flows assuming anything that isn't "AMD compatible" gets Intel behavior. The Intel code will be cleaned up in the future. Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson <seanjc@google.com> Message-ID: <20240405235603.1173076-2-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent fec50db commit fd706c9

File tree

5 files changed

+14
-2
lines changed

5 files changed

+14
-2
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,7 @@ struct kvm_vcpu_arch {
855855
int cpuid_nent;
856856
struct kvm_cpuid_entry2 *cpuid_entries;
857857
struct kvm_hypervisor_cpuid kvm_cpuid;
858+
bool is_amd_compatible;
858859

859860
/*
860861
* FIXME: Drop this macro and use KVM_NR_GOVERNED_FEATURES directly

arch/x86/kvm/cpuid.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
376376

377377
kvm_update_pv_runtime(vcpu);
378378

379+
vcpu->arch.is_amd_compatible = guest_cpuid_is_amd_or_hygon(vcpu);
379380
vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
380381
vcpu->arch.reserved_gpa_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu);
381382

arch/x86/kvm/cpuid.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,16 @@ static inline bool guest_cpuid_is_intel(struct kvm_vcpu *vcpu)
120120
return best && is_guest_vendor_intel(best->ebx, best->ecx, best->edx);
121121
}
122122

123+
static inline bool guest_cpuid_is_amd_compatible(struct kvm_vcpu *vcpu)
124+
{
125+
return vcpu->arch.is_amd_compatible;
126+
}
127+
128+
static inline bool guest_cpuid_is_intel_compatible(struct kvm_vcpu *vcpu)
129+
{
130+
return !guest_cpuid_is_amd_compatible(vcpu);
131+
}
132+
123133
static inline int guest_cpuid_family(struct kvm_vcpu *vcpu)
124134
{
125135
struct kvm_cpuid_entry2 *best;

arch/x86/kvm/mmu/mmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4935,7 +4935,7 @@ static void reset_guest_rsvds_bits_mask(struct kvm_vcpu *vcpu,
49354935
context->cpu_role.base.level, is_efer_nx(context),
49364936
guest_can_use(vcpu, X86_FEATURE_GBPAGES),
49374937
is_cr4_pse(context),
4938-
guest_cpuid_is_amd_or_hygon(vcpu));
4938+
guest_cpuid_is_amd_compatible(vcpu));
49394939
}
49404940

49414941
static void __reset_rsvds_bits_mask_ept(struct rsvd_bits_validate *rsvd_check,

arch/x86/kvm/x86.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3470,7 +3470,7 @@ static bool is_mci_status_msr(u32 msr)
34703470
static bool can_set_mci_status(struct kvm_vcpu *vcpu)
34713471
{
34723472
/* McStatusWrEn enabled? */
3473-
if (guest_cpuid_is_amd_or_hygon(vcpu))
3473+
if (guest_cpuid_is_amd_compatible(vcpu))
34743474
return !!(vcpu->arch.msr_hwcr & BIT_ULL(18));
34753475

34763476
return false;

0 commit comments

Comments
 (0)