Now that LBRv2 is fully virtualized, advertise it and report the LBR stack depth in CPUID. Gate the advertisement on LBR virtualization, the mediated PMU, PerfMonV2 and a 16-entry host stack, so KVM never exposes a configuration it cannot faithfully virtualize. Co-developed-by: Sandipan Das Signed-off-by: Sandipan Das Signed-off-by: Shivansh Dhiman --- Changes in v2: * Clear AMD_LBR_V2 in svm_set_cpu_caps() if the host LBR stack does not have 16 entries. * Removed the per-vCPU clear of AMD_LBR_V2 in svm_vcpu_after_set_cpuid(). * Report the host LBR stack depth in CPUID 0x80000022.EBX directly. * Added a comment. --- arch/x86/kvm/cpuid.c | 3 +++ arch/x86/kvm/svm/svm.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index adafd6fa2c54..bb24d8362132 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1258,6 +1258,7 @@ void kvm_initialize_cpu_caps(void) kvm_cpu_cap_init(CPUID_8000_0022_EAX, F(PERFMON_V2), + SCATTERED_F(AMD_LBR_V2), ); if (!static_cpu_has_bug(X86_BUG_NULL_SEG)) @@ -1904,6 +1905,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) cpuid_entry_override(entry, CPUID_8000_0022_EAX); ebx.split.num_core_pmc = kvm_pmu_cap.num_counters_gp; + ebx.split.lbr_v2_stack_sz = kvm_pmu_cap.num_branches_lbr; + entry->ebx = ebx.full; break; } diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 69f9ea746bb6..ea7535ccc3fe 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -5843,6 +5843,18 @@ static __init void svm_set_cpu_caps(void) if (kvm_pmu_cap.version != 2 || !kvm_cpu_cap_has(X86_FEATURE_PERFCTR_CORE)) kvm_cpu_cap_clear(X86_FEATURE_PERFMON_V2); + + /* + * LBRv2 requires LBR virtualization and the mediated PMU to + * let the guest own the LBR stack, and is enumerated through + * PerfMonV2's CPUID leaf. KVM also can't faithfully virtualize + * a stack depth other than the architectural 16 entries, as the + * VMCB save area provides exactly that many entries. + */ + if (!lbrv || !enable_mediated_pmu || + !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2) || + kvm_pmu_cap.num_branches_lbr != SVM_LBR_V2_STACK_SIZE) + kvm_cpu_cap_clear(X86_FEATURE_AMD_LBR_V2); } /* CPUID 0x8000001F (SME/SEV features) */ -- 2.43.0