xref: /kvm-unit-tests/lib/x86/pmu.h (revision cda64e80ee72f3dfa8a9107e21ebe91a05c18c68)
19f17508dSLike Xu #ifndef _X86_PMU_H_
29f17508dSLike Xu #define _X86_PMU_H_
39f17508dSLike Xu 
49f17508dSLike Xu #include "processor.h"
59f17508dSLike Xu #include "libcflat.h"
69f17508dSLike Xu 
79f17508dSLike Xu #define FIXED_CNT_INDEX 32
89f17508dSLike Xu #define MAX_NUM_LBR_ENTRY	  32
99f17508dSLike Xu 
109f17508dSLike Xu /* Performance Counter Vector for the LVT PC Register */
119f17508dSLike Xu #define PMI_VECTOR	32
129f17508dSLike Xu 
139f17508dSLike Xu #define DEBUGCTLMSR_LBR	  (1UL <<  0)
149f17508dSLike Xu 
159f17508dSLike Xu #define PMU_CAP_LBR_FMT	  0x3f
169f17508dSLike Xu #define PMU_CAP_FW_WRITES	(1ULL << 13)
179f17508dSLike Xu 
189f17508dSLike Xu #define EVNSEL_EVENT_SHIFT	0
199f17508dSLike Xu #define EVNTSEL_UMASK_SHIFT	8
209f17508dSLike Xu #define EVNTSEL_USR_SHIFT	16
219f17508dSLike Xu #define EVNTSEL_OS_SHIFT	17
229f17508dSLike Xu #define EVNTSEL_EDGE_SHIFT	18
239f17508dSLike Xu #define EVNTSEL_PC_SHIFT	19
249f17508dSLike Xu #define EVNTSEL_INT_SHIFT	20
259f17508dSLike Xu #define EVNTSEL_EN_SHIF		22
269f17508dSLike Xu #define EVNTSEL_INV_SHIF	23
279f17508dSLike Xu #define EVNTSEL_CMASK_SHIFT	24
289f17508dSLike Xu 
299f17508dSLike Xu #define EVNTSEL_EN	(1 << EVNTSEL_EN_SHIF)
309f17508dSLike Xu #define EVNTSEL_USR	(1 << EVNTSEL_USR_SHIFT)
319f17508dSLike Xu #define EVNTSEL_OS	(1 << EVNTSEL_OS_SHIFT)
329f17508dSLike Xu #define EVNTSEL_PC	(1 << EVNTSEL_PC_SHIFT)
339f17508dSLike Xu #define EVNTSEL_INT	(1 << EVNTSEL_INT_SHIFT)
349f17508dSLike Xu #define EVNTSEL_INV	(1 << EVNTSEL_INV_SHIF)
359f17508dSLike Xu 
36879e7f07SLike Xu struct pmu_caps {
37f85e94a2SSean Christopherson 	u8 version;
38f85e94a2SSean Christopherson 	u8 nr_fixed_counters;
39f85e94a2SSean Christopherson 	u8 fixed_counter_width;
40f85e94a2SSean Christopherson 	u8 nr_gp_counters;
41f85e94a2SSean Christopherson 	u8 gp_counter_width;
42f85e94a2SSean Christopherson 	u8 gp_counter_mask_length;
43f85e94a2SSean Christopherson 	u32 gp_counter_available;
44*cda64e80SLike Xu 	u32 msr_gp_counter_base;
45*cda64e80SLike Xu 	u32 msr_gp_event_select_base;
46*cda64e80SLike Xu 
47879e7f07SLike Xu 	u64 perf_cap;
48879e7f07SLike Xu };
49879e7f07SLike Xu 
50879e7f07SLike Xu extern struct pmu_caps pmu;
51879e7f07SLike Xu 
52879e7f07SLike Xu void pmu_init(void);
53879e7f07SLike Xu 
54*cda64e80SLike Xu static inline u32 MSR_GP_COUNTERx(unsigned int i)
55*cda64e80SLike Xu {
56*cda64e80SLike Xu 	return pmu.msr_gp_counter_base + i;
57*cda64e80SLike Xu }
58*cda64e80SLike Xu 
59*cda64e80SLike Xu static inline u32 MSR_GP_EVENT_SELECTx(unsigned int i)
60*cda64e80SLike Xu {
61*cda64e80SLike Xu 	return pmu.msr_gp_event_select_base + i;
62*cda64e80SLike Xu }
63*cda64e80SLike Xu 
649f17508dSLike Xu static inline bool this_cpu_has_pmu(void)
659f17508dSLike Xu {
66414ee7d1SSean Christopherson 	return !!pmu.version;
679f17508dSLike Xu }
689f17508dSLike Xu 
699f17508dSLike Xu static inline bool this_cpu_has_perf_global_ctrl(void)
709f17508dSLike Xu {
71414ee7d1SSean Christopherson 	return pmu.version > 1;
729f17508dSLike Xu }
739f17508dSLike Xu 
749f17508dSLike Xu static inline bool pmu_gp_counter_is_available(int i)
759f17508dSLike Xu {
76f85e94a2SSean Christopherson 	return pmu.gp_counter_available & BIT(i);
779f17508dSLike Xu }
789f17508dSLike Xu 
79879e7f07SLike Xu static inline u64 pmu_lbr_version(void)
80879e7f07SLike Xu {
81414ee7d1SSean Christopherson 	return pmu.perf_cap & PMU_CAP_LBR_FMT;
82879e7f07SLike Xu }
83879e7f07SLike Xu 
84879e7f07SLike Xu static inline bool pmu_has_full_writes(void)
85879e7f07SLike Xu {
86414ee7d1SSean Christopherson 	return pmu.perf_cap & PMU_CAP_FW_WRITES;
879f17508dSLike Xu }
889f17508dSLike Xu 
89*cda64e80SLike Xu static inline bool pmu_use_full_writes(void)
90*cda64e80SLike Xu {
91*cda64e80SLike Xu 	return pmu.msr_gp_counter_base == MSR_IA32_PMC0;
92*cda64e80SLike Xu }
93*cda64e80SLike Xu 
949f17508dSLike Xu #endif /* _X86_PMU_H_ */
95