On 07-08-2025 01:26, Sean Christopherson wrote: > Take a snapshot of the unadulterated PMU capabilities provided by perf so > that KVM can compare guest vPMU capabilities against hardware capabilities > when determining whether or not to intercept PMU MSRs (and RDPMC). > > Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> > --- > arch/x86/kvm/pmu.c | 15 ++++++++++----- > 1 file changed, 10 insertions(+), 5 deletions(-) > > diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c > index 3206412a35a1..0f3e011824ed 100644 > --- a/arch/x86/kvm/pmu.c > +++ b/arch/x86/kvm/pmu.c > @@ -26,6 +26,10 @@ > /* This is enough to filter the vast majority of currently defined events. */ > #define KVM_PMU_EVENT_FILTER_MAX_EVENTS 300 > > +/* Unadultered PMU capabilities of the host, i.e. of hardware. */ > +static struct x86_pmu_capability __read_mostly kvm_host_pmu; > + > +/* KVM's PMU capabilities, i.e. the intersection of KVM and hardware support. */ > struct x86_pmu_capability __read_mostly kvm_pmu_cap; > EXPORT_SYMBOL_GPL(kvm_pmu_cap); > > @@ -104,6 +108,8 @@ void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops) > bool is_intel = boot_cpu_data.x86_vendor == X86_VENDOR_INTEL; > int min_nr_gp_ctrs = pmu_ops->MIN_NR_GP_COUNTERS; > > + perf_get_x86_pmu_capability(&kvm_host_pmu); > + > /* > * Hybrid PMUs don't play nice with virtualization without careful > * configuration by userspace, and KVM's APIs for reporting supported > @@ -114,18 +120,16 @@ void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops) > enable_pmu = false; > > if (enable_pmu) { > - perf_get_x86_pmu_capability(&kvm_pmu_cap); > - > /* > * WARN if perf did NOT disable hardware PMU if the number of > * architecturally required GP counters aren't present, i.e. if > * there are a non-zero number of counters, but fewer than what > * is architecturally required. > */ > - if (!kvm_pmu_cap.num_counters_gp || > - WARN_ON_ONCE(kvm_pmu_cap.num_counters_gp < min_nr_gp_ctrs)) > + if (!kvm_host_pmu.num_counters_gp || > + WARN_ON_ONCE(kvm_host_pmu.num_counters_gp < min_nr_gp_ctrs)) > enable_pmu = false; > - else if (is_intel && !kvm_pmu_cap.version) > + else if (is_intel && !kvm_host_pmu.version) > enable_pmu = false; > } > > @@ -134,6 +138,7 @@ void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops) > return; > } > > + memcpy(&kvm_pmu_cap, &kvm_host_pmu, sizeof(kvm_host_pmu)); > kvm_pmu_cap.version = min(kvm_pmu_cap.version, 2); > kvm_pmu_cap.num_counters_gp = min(kvm_pmu_cap.num_counters_gp, > pmu_ops->MAX_NR_GP_COUNTERS); Reviewed-by: Sandipan Das <sandipan.das@xxxxxxx>