@@ -677,6 +677,20 @@ static bool kvm_pmc_counts_at_el2(struct kvm_pmc *pmc)
677
677
return kvm_pmc_read_evtreg (pmc ) & ARMV8_PMU_INCLUDE_EL2 ;
678
678
}
679
679
680
+ static int kvm_map_pmu_event (struct kvm * kvm , unsigned int eventsel )
681
+ {
682
+ struct arm_pmu * pmu = kvm -> arch .arm_pmu ;
683
+
684
+ /*
685
+ * The CPU PMU likely isn't PMUv3; let the driver provide a mapping
686
+ * for the guest's PMUv3 event ID.
687
+ */
688
+ if (unlikely (pmu -> map_pmuv3_event ))
689
+ return pmu -> map_pmuv3_event (eventsel );
690
+
691
+ return eventsel ;
692
+ }
693
+
680
694
/**
681
695
* kvm_pmu_create_perf_event - create a perf event for a counter
682
696
* @pmc: Counter context
@@ -687,7 +701,8 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
687
701
struct arm_pmu * arm_pmu = vcpu -> kvm -> arch .arm_pmu ;
688
702
struct perf_event * event ;
689
703
struct perf_event_attr attr ;
690
- u64 eventsel , evtreg ;
704
+ int eventsel ;
705
+ u64 evtreg ;
691
706
692
707
evtreg = kvm_pmc_read_evtreg (pmc );
693
708
@@ -713,6 +728,14 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
713
728
!test_bit (eventsel , vcpu -> kvm -> arch .pmu_filter ))
714
729
return ;
715
730
731
+ /*
732
+ * Don't create an event if we're running on hardware that requires
733
+ * PMUv3 event translation and we couldn't find a valid mapping.
734
+ */
735
+ eventsel = kvm_map_pmu_event (vcpu -> kvm , eventsel );
736
+ if (eventsel < 0 )
737
+ return ;
738
+
716
739
memset (& attr , 0 , sizeof (struct perf_event_attr ));
717
740
attr .type = arm_pmu -> pmu .type ;
718
741
attr .size = sizeof (attr );
0 commit comments