Backport of AMD's TSA mitigation to 6.1.y did not set CPUID bits that are passed to a guest correctly (commit c334ae4a545a "KVM: SVM: Advertise TSA CPUID bits to guests")
Boris Ostrovsky (1): KVM: SVM: Return TSA_SQ_NO and TSA_L1_NO bits in __do_cpuid_func()
Borislav Petkov (AMD) (1): KVM: SVM: Set synthesized TSA CPUID flags
Kim Phillips (1): KVM: x86: Move open-coded CPUID leaf 0x80000021 EAX bit propagation code
arch/x86/kvm/cpuid.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-)
From: Kim Phillips kim.phillips@amd.com
Commit c35ac8c4bf600ee23bacb20f863aa7830efb23fb upstream
Move code from __do_cpuid_func() to kvm_set_cpu_caps() in preparation for adding the features in their native leaf.
Also drop the bit description comments as it will be more self-describing once the individual features are added.
Whilst there, switch to using the more efficient cpu_feature_enabled() instead of static_cpu_has().
Note, LFENCE_RDTSC and "NULL selector clears base" are currently synthetic, Linux-defined feature flags as Linux tracking of the features predates AMD's definition. Keep the manual propagation of the flags from their synthetic counterparts until the kernel fully converts to AMD's definition, otherwise KVM would stop synthesizing the flags as intended.
Signed-off-by: Kim Phillips kim.phillips@amd.com Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Acked-by: Sean Christopherson seanjc@google.com Link: https://lore.kernel.org/r/20230124163319.2277355-3-kim.phillips@amd.com
Move setting of VERW_CLEAR bit to the new kvm_cpu_cap_mask(CPUID_8000_0021_EAX, ...) site.
Cc: stable@vger.kernel.org # 6.1.y Signed-off-by: Boris Ostrovsky boris.ostrovsky@oracle.com --- arch/x86/kvm/cpuid.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 1bb5e8f6c63e..4f60341b1e94 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -749,6 +749,18 @@ void kvm_set_cpu_caps(void) 0 /* SME */ | F(SEV) | 0 /* VM_PAGE_FLUSH */ | F(SEV_ES) | F(SME_COHERENT));
+ kvm_cpu_cap_mask(CPUID_8000_0021_EAX, + BIT(0) /* NO_NESTED_DATA_BP */ | + BIT(2) /* LFENCE Always serializing */ | 0 /* SmmPgCfgLock */ | + BIT(5) /* The memory form of VERW mitigates TSA */ | + BIT(6) /* NULL_SEL_CLR_BASE */ | 0 /* PrefetchCtlMsr */ + ); + if (cpu_feature_enabled(X86_FEATURE_LFENCE_RDTSC)) + kvm_cpu_caps[CPUID_8000_0021_EAX] |= BIT(2) /* LFENCE Always serializing */; + if (!static_cpu_has_bug(X86_BUG_NULL_SEG)) + kvm_cpu_caps[CPUID_8000_0021_EAX] |= BIT(6) /* NULL_SEL_CLR_BASE */; + kvm_cpu_caps[CPUID_8000_0021_EAX] |= BIT(9) /* NO_SMM_CTL_MSR */; + kvm_cpu_cap_mask(CPUID_C000_0001_EDX, F(XSTORE) | F(XSTORE_EN) | F(XCRYPT) | F(XCRYPT_EN) | F(ACE2) | F(ACE2_EN) | F(PHE) | F(PHE_EN) | @@ -758,8 +770,6 @@ void kvm_set_cpu_caps(void) if (cpu_feature_enabled(X86_FEATURE_SRSO_NO)) kvm_cpu_cap_set(X86_FEATURE_SRSO_NO);
- kvm_cpu_cap_mask(CPUID_8000_0021_EAX, F(VERW_CLEAR)); - kvm_cpu_cap_init_kvm_defined(CPUID_8000_0021_ECX, F(TSA_SQ_NO) | F(TSA_L1_NO) ); @@ -1249,23 +1259,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) entry->eax = entry->ebx = entry->ecx = entry->edx = 0; break; case 0x80000021: - entry->ebx = entry->edx = 0; - /* - * Pass down these bits: - * EAX 0 NNDBP, Processor ignores nested data breakpoints - * EAX 2 LAS, LFENCE always serializing - * EAX 6 NSCB, Null selector clear base - * - * Other defined bits are for MSRs that KVM does not expose: - * EAX 3 SPCL, SMM page configuration lock - * EAX 13 PCMSR, Prefetch control MSR - */ - entry->eax &= BIT(0) | BIT(2) | BIT(6); - if (static_cpu_has(X86_FEATURE_LFENCE_RDTSC)) - entry->eax |= BIT(2); - if (!static_cpu_has_bug(X86_BUG_NULL_SEG)) - entry->eax |= BIT(6); - cpuid_entry_override(entry, CPUID_8000_0021_ECX); + entry->ebx = entry->ecx = entry->edx = 0; + cpuid_entry_override(entry, CPUID_8000_0021_EAX); break; /*Add support for Centaur's CPUID instruction*/ case 0xC0000000:
Commit c334ae4a545a ("KVM: SVM: Advertise TSA CPUID bits to guests") set VERW_CLEAR, TSA_SQ_NO and TSA_L1_NO kvm_caps bits that are supposed to be provided to guest when it requests CPUID 0x80000021. However, the latter two (in the %ecx register) are instead returned as zeroes in __do_cpuid_func().
Return values of TSA_SQ_NO and TSA_L1_NO as set in the kvm_cpu_caps.
This fix is stable-only.
Cc: stable@vger.kernel.org # 6.1.y Fixes: c334ae4a545a ("KVM: SVM: Advertise TSA CPUID bits to guests") Signed-off-by: Boris Ostrovsky boris.ostrovsky@oracle.com --- arch/x86/kvm/cpuid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 4f60341b1e94..e53ccf8a090d 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1259,8 +1259,9 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) entry->eax = entry->ebx = entry->ecx = entry->edx = 0; break; case 0x80000021: - entry->ebx = entry->ecx = entry->edx = 0; + entry->ebx = entry->edx = 0; cpuid_entry_override(entry, CPUID_8000_0021_EAX); + cpuid_entry_override(entry, CPUID_8000_0021_ECX); break; /*Add support for Centaur's CPUID instruction*/ case 0xC0000000:
From: "Borislav Petkov (AMD)" bp@alien8.de
Commit f3f9deccfc68a6b7c8c1cc51e902edba23d309d4 LTS
VERW_CLEAR is supposed to be set only by the hypervisor to denote TSA mitigation support to a guest. SQ_NO and L1_NO are both synthesizable, and are going to be set by hw CPUID on future machines.
So keep the kvm_cpu_cap_init_kvm_defined() invocation *and* set them when synthesized.
This fix is stable-only.
Co-developed-by: Jinpu Wang jinpu.wang@ionos.com Signed-off-by: Jinpu Wang jinpu.wang@ionos.com Signed-off-by: Borislav Petkov (AMD) bp@alien8.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: stable@vger.kernel.org # 6.1.y Signed-off-by: Boris Ostrovsky boris.ostrovsky@oracle.com --- arch/x86/kvm/cpuid.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index e53ccf8a090d..db508118891d 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -770,10 +770,15 @@ void kvm_set_cpu_caps(void) if (cpu_feature_enabled(X86_FEATURE_SRSO_NO)) kvm_cpu_cap_set(X86_FEATURE_SRSO_NO);
+ kvm_cpu_cap_check_and_set(X86_FEATURE_VERW_CLEAR); + kvm_cpu_cap_init_kvm_defined(CPUID_8000_0021_ECX, F(TSA_SQ_NO) | F(TSA_L1_NO) );
+ kvm_cpu_cap_check_and_set(X86_FEATURE_TSA_SQ_NO); + kvm_cpu_cap_check_and_set(X86_FEATURE_TSA_L1_NO); + /* * Hide RDTSCP and RDPID if either feature is reported as supported but * probing MSR_TSC_AUX failed. This is purely a sanity check and
linux-stable-mirror@lists.linaro.org