mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
KVM: x86: Virtualize AMD CPUID faulting
On AMD CPUs, CPUID faulting support is advertised via CPUID.80000021H:EAX.CpuidUserDis[bit 17] and enabled by setting HWCR.CpuidUserDis[bit 35]. Advertise the feature to userspace regardless of host CPU support. Allow writes to HWCR to set bit 35 when the guest CPUID advertises CpuidUserDis. Update cpuid_fault_enabled() to check HWCR.CpuidUserDis as well as MSR_FEATURE_ENABLES.CPUID_GP_ON_CPL_GT_0. Unlike VMX, SVM prioritizes the CPUID intercept over the #GP induced by CPUID faulting.[1] This behavior has been confirmed on a Turin CPU (F/M/S 1AH/2/1). Link: https://lore.kernel.org/r/DS7PR12MB82011943131DF5415365E19E940B2@DS7PR12MB8201.namprd12.prod.outlook.com [1] Signed-off-by: Jim Mattson <jmattson@google.com> Link: https://patch.msgid.link/20260527174347.2356165-5-jmattson@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
d1bc99885a
commit
e93a93f114
|
|
@ -898,6 +898,7 @@
|
||||||
#define MSR_K7_HWCR_IRPERF_EN_BIT 30
|
#define MSR_K7_HWCR_IRPERF_EN_BIT 30
|
||||||
#define MSR_K7_HWCR_IRPERF_EN BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT)
|
#define MSR_K7_HWCR_IRPERF_EN BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT)
|
||||||
#define MSR_K7_HWCR_CPUID_USER_DIS_BIT 35
|
#define MSR_K7_HWCR_CPUID_USER_DIS_BIT 35
|
||||||
|
#define MSR_K7_HWCR_CPUID_USER_DIS BIT_ULL(MSR_K7_HWCR_CPUID_USER_DIS_BIT)
|
||||||
#define MSR_K7_FID_VID_CTL 0xc0010041
|
#define MSR_K7_FID_VID_CTL 0xc0010041
|
||||||
#define MSR_K7_FID_VID_STATUS 0xc0010042
|
#define MSR_K7_FID_VID_STATUS 0xc0010042
|
||||||
#define MSR_K7_HWCR_CPB_DIS_BIT 25
|
#define MSR_K7_HWCR_CPB_DIS_BIT 25
|
||||||
|
|
|
||||||
|
|
@ -1248,7 +1248,7 @@ void kvm_initialize_cpu_caps(void)
|
||||||
F(AUTOIBRS),
|
F(AUTOIBRS),
|
||||||
EMULATED_F(NO_SMM_CTL_MSR),
|
EMULATED_F(NO_SMM_CTL_MSR),
|
||||||
/* PrefetchCtlMsr */
|
/* PrefetchCtlMsr */
|
||||||
/* GpOnUserCpuid */
|
EMULATED_F(GP_ON_USER_CPUID),
|
||||||
/* EPSF */
|
/* EPSF */
|
||||||
F(PREFETCHI),
|
F(PREFETCHI),
|
||||||
F(AVX512_BMM),
|
F(AVX512_BMM),
|
||||||
|
|
|
||||||
|
|
@ -185,8 +185,9 @@ static inline int guest_cpuid_stepping(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
|
static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
return vcpu->arch.msr_misc_features_enables &
|
return (vcpu->arch.msr_misc_features_enables &
|
||||||
MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;
|
MSR_MISC_FEATURES_ENABLES_CPUID_FAULT) ||
|
||||||
|
(vcpu->arch.msr_hwcr & MSR_K7_HWCR_CPUID_USER_DIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool kvm_is_cpuid_allowed(struct kvm_vcpu *vcpu)
|
static inline bool kvm_is_cpuid_allowed(struct kvm_vcpu *vcpu)
|
||||||
|
|
|
||||||
|
|
@ -4002,22 +4002,28 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||||
break;
|
break;
|
||||||
case MSR_EFER:
|
case MSR_EFER:
|
||||||
return set_efer(vcpu, msr_info);
|
return set_efer(vcpu, msr_info);
|
||||||
case MSR_K7_HWCR:
|
case MSR_K7_HWCR: {
|
||||||
data &= ~(u64)0x40; /* ignore flush filter disable */
|
|
||||||
data &= ~(u64)0x100; /* ignore ignne emulation enable */
|
|
||||||
data &= ~(u64)0x8; /* ignore TLB cache disable */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allow McStatusWrEn and TscFreqSel. (Linux guests from v3.2
|
* Allow McStatusWrEn and TscFreqSel. (Linux guests from v3.2
|
||||||
* through at least v6.6 whine if TscFreqSel is clear,
|
* through at least v6.6 whine if TscFreqSel is clear,
|
||||||
* depending on F/M/S.
|
* depending on F/M/S.
|
||||||
*/
|
*/
|
||||||
if (data & ~(BIT_ULL(18) | BIT_ULL(24))) {
|
u64 valid = BIT_ULL(18) | BIT_ULL(24);
|
||||||
|
|
||||||
|
data &= ~(u64)0x40; /* ignore flush filter disable */
|
||||||
|
data &= ~(u64)0x100; /* ignore ignne emulation enable */
|
||||||
|
data &= ~(u64)0x8; /* ignore TLB cache disable */
|
||||||
|
|
||||||
|
if (guest_cpu_cap_has(vcpu, X86_FEATURE_GP_ON_USER_CPUID))
|
||||||
|
valid |= MSR_K7_HWCR_CPUID_USER_DIS;
|
||||||
|
|
||||||
|
if (data & ~valid) {
|
||||||
kvm_pr_unimpl_wrmsr(vcpu, msr, data);
|
kvm_pr_unimpl_wrmsr(vcpu, msr, data);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
vcpu->arch.msr_hwcr = data;
|
vcpu->arch.msr_hwcr = data;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case MSR_FAM10H_MMIO_CONF_BASE:
|
case MSR_FAM10H_MMIO_CONF_BASE:
|
||||||
if (data != 0) {
|
if (data != 0) {
|
||||||
kvm_pr_unimpl_wrmsr(vcpu, msr, data);
|
kvm_pr_unimpl_wrmsr(vcpu, msr, data);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user