xref: /kvm-unit-tests/lib/x86/pmu.h (revision b883751a540486067c9d511c0d0afdc69f22792a)
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 
13*b883751aSLike Xu #define AMD64_NUM_COUNTERS	4
14*b883751aSLike Xu #define AMD64_NUM_COUNTERS_CORE	6
15*b883751aSLike Xu 
16*b883751aSLike Xu #define PMC_DEFAULT_WIDTH	48
17*b883751aSLike Xu 
189f17508dSLike Xu #define DEBUGCTLMSR_LBR	  (1UL <<  0)
199f17508dSLike Xu 
209f17508dSLike Xu #define PMU_CAP_LBR_FMT	  0x3f
219f17508dSLike Xu #define PMU_CAP_FW_WRITES	(1ULL << 13)
222ae41f5dSLike Xu #define PMU_CAP_PEBS_BASELINE	(1ULL << 14)
232ae41f5dSLike Xu #define PERF_CAP_PEBS_FORMAT           0xf00
249f17508dSLike Xu 
259f17508dSLike Xu #define EVNSEL_EVENT_SHIFT	0
269f17508dSLike Xu #define EVNTSEL_UMASK_SHIFT	8
279f17508dSLike Xu #define EVNTSEL_USR_SHIFT	16
289f17508dSLike Xu #define EVNTSEL_OS_SHIFT	17
299f17508dSLike Xu #define EVNTSEL_EDGE_SHIFT	18
309f17508dSLike Xu #define EVNTSEL_PC_SHIFT	19
319f17508dSLike Xu #define EVNTSEL_INT_SHIFT	20
329f17508dSLike Xu #define EVNTSEL_EN_SHIF		22
339f17508dSLike Xu #define EVNTSEL_INV_SHIF	23
349f17508dSLike Xu #define EVNTSEL_CMASK_SHIFT	24
359f17508dSLike Xu 
369f17508dSLike Xu #define EVNTSEL_EN	(1 << EVNTSEL_EN_SHIF)
379f17508dSLike Xu #define EVNTSEL_USR	(1 << EVNTSEL_USR_SHIFT)
389f17508dSLike Xu #define EVNTSEL_OS	(1 << EVNTSEL_OS_SHIFT)
399f17508dSLike Xu #define EVNTSEL_PC	(1 << EVNTSEL_PC_SHIFT)
409f17508dSLike Xu #define EVNTSEL_INT	(1 << EVNTSEL_INT_SHIFT)
419f17508dSLike Xu #define EVNTSEL_INV	(1 << EVNTSEL_INV_SHIF)
429f17508dSLike Xu 
432ae41f5dSLike Xu #define GLOBAL_STATUS_BUFFER_OVF_BIT		62
442ae41f5dSLike Xu #define GLOBAL_STATUS_BUFFER_OVF	BIT_ULL(GLOBAL_STATUS_BUFFER_OVF_BIT)
452ae41f5dSLike Xu 
462ae41f5dSLike Xu #define PEBS_DATACFG_MEMINFO	BIT_ULL(0)
472ae41f5dSLike Xu #define PEBS_DATACFG_GP	BIT_ULL(1)
482ae41f5dSLike Xu #define PEBS_DATACFG_XMMS	BIT_ULL(2)
492ae41f5dSLike Xu #define PEBS_DATACFG_LBRS	BIT_ULL(3)
502ae41f5dSLike Xu 
512ae41f5dSLike Xu #define ICL_EVENTSEL_ADAPTIVE				(1ULL << 34)
522ae41f5dSLike Xu #define PEBS_DATACFG_LBR_SHIFT	24
532ae41f5dSLike Xu #define MAX_NUM_LBR_ENTRY	32
542ae41f5dSLike Xu 
55879e7f07SLike Xu struct pmu_caps {
56dd602b6fSSean Christopherson 	bool is_intel;
57f85e94a2SSean Christopherson 	u8 version;
58f85e94a2SSean Christopherson 	u8 nr_fixed_counters;
59f85e94a2SSean Christopherson 	u8 fixed_counter_width;
60f85e94a2SSean Christopherson 	u8 nr_gp_counters;
61f85e94a2SSean Christopherson 	u8 gp_counter_width;
62f85e94a2SSean Christopherson 	u8 gp_counter_mask_length;
63f85e94a2SSean Christopherson 	u32 gp_counter_available;
64cda64e80SLike Xu 	u32 msr_gp_counter_base;
65cda64e80SLike Xu 	u32 msr_gp_event_select_base;
66cda64e80SLike Xu 
678a2866d1SLike Xu 	u32 msr_global_status;
688a2866d1SLike Xu 	u32 msr_global_ctl;
698a2866d1SLike Xu 	u32 msr_global_status_clr;
708a2866d1SLike Xu 
71879e7f07SLike Xu 	u64 perf_cap;
72879e7f07SLike Xu };
73879e7f07SLike Xu 
74879e7f07SLike Xu extern struct pmu_caps pmu;
75879e7f07SLike Xu 
76879e7f07SLike Xu void pmu_init(void);
77879e7f07SLike Xu 
78cda64e80SLike Xu static inline u32 MSR_GP_COUNTERx(unsigned int i)
79cda64e80SLike Xu {
80*b883751aSLike Xu 	if (pmu.msr_gp_counter_base == MSR_F15H_PERF_CTR0)
81*b883751aSLike Xu 		return pmu.msr_gp_counter_base + 2 * i;
82*b883751aSLike Xu 
83cda64e80SLike Xu 	return pmu.msr_gp_counter_base + i;
84cda64e80SLike Xu }
85cda64e80SLike Xu 
86cda64e80SLike Xu static inline u32 MSR_GP_EVENT_SELECTx(unsigned int i)
87cda64e80SLike Xu {
88*b883751aSLike Xu 	if (pmu.msr_gp_event_select_base == MSR_F15H_PERF_CTL0)
89*b883751aSLike Xu 		return pmu.msr_gp_event_select_base + 2 * i;
90*b883751aSLike Xu 
91cda64e80SLike Xu 	return pmu.msr_gp_event_select_base + i;
92cda64e80SLike Xu }
93cda64e80SLike Xu 
949f17508dSLike Xu static inline bool this_cpu_has_pmu(void)
959f17508dSLike Xu {
96*b883751aSLike Xu 	return !pmu.is_intel || !!pmu.version;
979f17508dSLike Xu }
989f17508dSLike Xu 
999f17508dSLike Xu static inline bool this_cpu_has_perf_global_ctrl(void)
1009f17508dSLike Xu {
101414ee7d1SSean Christopherson 	return pmu.version > 1;
1029f17508dSLike Xu }
1039f17508dSLike Xu 
10462ba5036SLike Xu static inline bool this_cpu_has_perf_global_status(void)
10562ba5036SLike Xu {
10662ba5036SLike Xu 	return pmu.version > 1;
10762ba5036SLike Xu }
10862ba5036SLike Xu 
1099f17508dSLike Xu static inline bool pmu_gp_counter_is_available(int i)
1109f17508dSLike Xu {
111f85e94a2SSean Christopherson 	return pmu.gp_counter_available & BIT(i);
1129f17508dSLike Xu }
1139f17508dSLike Xu 
114879e7f07SLike Xu static inline u64 pmu_lbr_version(void)
115879e7f07SLike Xu {
116414ee7d1SSean Christopherson 	return pmu.perf_cap & PMU_CAP_LBR_FMT;
117879e7f07SLike Xu }
118879e7f07SLike Xu 
119879e7f07SLike Xu static inline bool pmu_has_full_writes(void)
120879e7f07SLike Xu {
121414ee7d1SSean Christopherson 	return pmu.perf_cap & PMU_CAP_FW_WRITES;
1229f17508dSLike Xu }
1239f17508dSLike Xu 
1242ae41f5dSLike Xu static inline void pmu_activate_full_writes(void)
1252ae41f5dSLike Xu {
1262ae41f5dSLike Xu 	pmu.msr_gp_counter_base = MSR_IA32_PMC0;
1272ae41f5dSLike Xu }
1282ae41f5dSLike Xu 
129cda64e80SLike Xu static inline bool pmu_use_full_writes(void)
130cda64e80SLike Xu {
131cda64e80SLike Xu 	return pmu.msr_gp_counter_base == MSR_IA32_PMC0;
132cda64e80SLike Xu }
133cda64e80SLike Xu 
1343f914933SLike Xu static inline u32 MSR_PERF_FIXED_CTRx(unsigned int i)
1353f914933SLike Xu {
1363f914933SLike Xu 	return MSR_CORE_PERF_FIXED_CTR0 + i;
1373f914933SLike Xu }
1383f914933SLike Xu 
139f33d3946SSean Christopherson static inline void pmu_reset_all_gp_counters(void)
140f33d3946SSean Christopherson {
141f33d3946SSean Christopherson 	unsigned int idx;
142f33d3946SSean Christopherson 
143f33d3946SSean Christopherson 	for (idx = 0; idx < pmu.nr_gp_counters; idx++) {
144f33d3946SSean Christopherson 		wrmsr(MSR_GP_EVENT_SELECTx(idx), 0);
145f33d3946SSean Christopherson 		wrmsr(MSR_GP_COUNTERx(idx), 0);
146f33d3946SSean Christopherson 	}
147f33d3946SSean Christopherson }
148f33d3946SSean Christopherson 
149f33d3946SSean Christopherson static inline void pmu_reset_all_fixed_counters(void)
150f33d3946SSean Christopherson {
151f33d3946SSean Christopherson 	unsigned int idx;
152f33d3946SSean Christopherson 
153f33d3946SSean Christopherson 	if (!pmu.nr_fixed_counters)
154f33d3946SSean Christopherson 		return;
155f33d3946SSean Christopherson 
156f33d3946SSean Christopherson 	wrmsr(MSR_CORE_PERF_FIXED_CTR_CTRL, 0);
157f33d3946SSean Christopherson 	for (idx = 0; idx < pmu.nr_fixed_counters; idx++)
158f33d3946SSean Christopherson 		wrmsr(MSR_PERF_FIXED_CTRx(idx), 0);
159f33d3946SSean Christopherson }
160f33d3946SSean Christopherson 
161f33d3946SSean Christopherson static inline void pmu_reset_all_counters(void)
162f33d3946SSean Christopherson {
163f33d3946SSean Christopherson 	pmu_reset_all_gp_counters();
164f33d3946SSean Christopherson 	pmu_reset_all_fixed_counters();
165f33d3946SSean Christopherson }
166f33d3946SSean Christopherson 
1678a2866d1SLike Xu static inline void pmu_clear_global_status(void)
1688a2866d1SLike Xu {
1698a2866d1SLike Xu 	wrmsr(pmu.msr_global_status_clr, rdmsr(pmu.msr_global_status));
1708a2866d1SLike Xu }
1718a2866d1SLike Xu 
1722ae41f5dSLike Xu static inline bool pmu_has_pebs(void)
1732ae41f5dSLike Xu {
1742ae41f5dSLike Xu 	return pmu.version > 1;
1752ae41f5dSLike Xu }
1762ae41f5dSLike Xu 
1772ae41f5dSLike Xu static inline u8 pmu_pebs_format(void)
1782ae41f5dSLike Xu {
1792ae41f5dSLike Xu 	return (pmu.perf_cap & PERF_CAP_PEBS_FORMAT ) >> 8;
1802ae41f5dSLike Xu }
1812ae41f5dSLike Xu 
1822ae41f5dSLike Xu static inline bool pmu_has_pebs_baseline(void)
1832ae41f5dSLike Xu {
1842ae41f5dSLike Xu 	return pmu.perf_cap & PMU_CAP_PEBS_BASELINE;
1852ae41f5dSLike Xu }
1862ae41f5dSLike Xu 
1879f17508dSLike Xu #endif /* _X86_PMU_H_ */
188