xref: /kvm-unit-tests/lib/x86/pmu.h (revision 879e7f07f0a718619058af8b26aa636f12f345f0)
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 
36*879e7f07SLike Xu struct pmu_caps {
37*879e7f07SLike Xu 	u64 perf_cap;
38*879e7f07SLike Xu };
39*879e7f07SLike Xu 
40*879e7f07SLike Xu extern struct pmu_caps pmu;
41*879e7f07SLike Xu 
42*879e7f07SLike Xu void pmu_init(void);
43*879e7f07SLike Xu 
449f17508dSLike Xu static inline u8 pmu_version(void)
459f17508dSLike Xu {
469f17508dSLike Xu 	return cpuid(10).a & 0xff;
479f17508dSLike Xu }
489f17508dSLike Xu 
499f17508dSLike Xu static inline bool this_cpu_has_pmu(void)
509f17508dSLike Xu {
519f17508dSLike Xu 	return !!pmu_version();
529f17508dSLike Xu }
539f17508dSLike Xu 
549f17508dSLike Xu static inline bool this_cpu_has_perf_global_ctrl(void)
559f17508dSLike Xu {
569f17508dSLike Xu 	return pmu_version() > 1;
579f17508dSLike Xu }
589f17508dSLike Xu 
599f17508dSLike Xu static inline u8 pmu_nr_gp_counters(void)
609f17508dSLike Xu {
619f17508dSLike Xu 	return (cpuid(10).a >> 8) & 0xff;
629f17508dSLike Xu }
639f17508dSLike Xu 
649f17508dSLike Xu static inline u8 pmu_gp_counter_width(void)
659f17508dSLike Xu {
669f17508dSLike Xu 	return (cpuid(10).a >> 16) & 0xff;
679f17508dSLike Xu }
689f17508dSLike Xu 
699f17508dSLike Xu static inline u8 pmu_gp_counter_mask_length(void)
709f17508dSLike Xu {
719f17508dSLike Xu 	return (cpuid(10).a >> 24) & 0xff;
729f17508dSLike Xu }
739f17508dSLike Xu 
749f17508dSLike Xu static inline u8 pmu_nr_fixed_counters(void)
759f17508dSLike Xu {
769f17508dSLike Xu 	struct cpuid id = cpuid(10);
779f17508dSLike Xu 
789f17508dSLike Xu 	if ((id.a & 0xff) > 1)
799f17508dSLike Xu 		return id.d & 0x1f;
809f17508dSLike Xu 	else
819f17508dSLike Xu 		return 0;
829f17508dSLike Xu }
839f17508dSLike Xu 
849f17508dSLike Xu static inline u8 pmu_fixed_counter_width(void)
859f17508dSLike Xu {
869f17508dSLike Xu 	struct cpuid id = cpuid(10);
879f17508dSLike Xu 
889f17508dSLike Xu 	if ((id.a & 0xff) > 1)
899f17508dSLike Xu 		return (id.d >> 5) & 0xff;
909f17508dSLike Xu 	else
919f17508dSLike Xu 		return 0;
929f17508dSLike Xu }
939f17508dSLike Xu 
949f17508dSLike Xu static inline bool pmu_gp_counter_is_available(int i)
959f17508dSLike Xu {
969f17508dSLike Xu 	/* CPUID.0xA.EBX bit is '1 if they counter is NOT available. */
979f17508dSLike Xu 	return !(cpuid(10).b & BIT(i));
989f17508dSLike Xu }
999f17508dSLike Xu 
1009f17508dSLike Xu static inline u64 this_cpu_perf_capabilities(void)
1019f17508dSLike Xu {
102*879e7f07SLike Xu 	return pmu.perf_cap;
103*879e7f07SLike Xu }
1049f17508dSLike Xu 
105*879e7f07SLike Xu static inline u64 pmu_lbr_version(void)
106*879e7f07SLike Xu {
107*879e7f07SLike Xu 	return this_cpu_perf_capabilities() & PMU_CAP_LBR_FMT;
108*879e7f07SLike Xu }
109*879e7f07SLike Xu 
110*879e7f07SLike Xu static inline bool pmu_has_full_writes(void)
111*879e7f07SLike Xu {
112*879e7f07SLike Xu 	return this_cpu_perf_capabilities() & PMU_CAP_FW_WRITES;
1139f17508dSLike Xu }
1149f17508dSLike Xu 
1159f17508dSLike Xu #endif /* _X86_PMU_H_ */
116