1 #ifndef _X86_PMU_H_ 2 #define _X86_PMU_H_ 3 4 #include "processor.h" 5 #include "libcflat.h" 6 7 #define FIXED_CNT_INDEX 32 8 #define MAX_NUM_LBR_ENTRY 32 9 10 /* Performance Counter Vector for the LVT PC Register */ 11 #define PMI_VECTOR 32 12 13 #define DEBUGCTLMSR_LBR (1UL << 0) 14 15 #define PMU_CAP_LBR_FMT 0x3f 16 #define PMU_CAP_FW_WRITES (1ULL << 13) 17 18 #define EVNSEL_EVENT_SHIFT 0 19 #define EVNTSEL_UMASK_SHIFT 8 20 #define EVNTSEL_USR_SHIFT 16 21 #define EVNTSEL_OS_SHIFT 17 22 #define EVNTSEL_EDGE_SHIFT 18 23 #define EVNTSEL_PC_SHIFT 19 24 #define EVNTSEL_INT_SHIFT 20 25 #define EVNTSEL_EN_SHIF 22 26 #define EVNTSEL_INV_SHIF 23 27 #define EVNTSEL_CMASK_SHIFT 24 28 29 #define EVNTSEL_EN (1 << EVNTSEL_EN_SHIF) 30 #define EVNTSEL_USR (1 << EVNTSEL_USR_SHIFT) 31 #define EVNTSEL_OS (1 << EVNTSEL_OS_SHIFT) 32 #define EVNTSEL_PC (1 << EVNTSEL_PC_SHIFT) 33 #define EVNTSEL_INT (1 << EVNTSEL_INT_SHIFT) 34 #define EVNTSEL_INV (1 << EVNTSEL_INV_SHIF) 35 36 struct pmu_caps { 37 u64 perf_cap; 38 }; 39 40 extern struct pmu_caps pmu; 41 42 void pmu_init(void); 43 44 static inline u8 pmu_version(void) 45 { 46 return cpuid(10).a & 0xff; 47 } 48 49 static inline bool this_cpu_has_pmu(void) 50 { 51 return !!pmu_version(); 52 } 53 54 static inline bool this_cpu_has_perf_global_ctrl(void) 55 { 56 return pmu_version() > 1; 57 } 58 59 static inline u8 pmu_nr_gp_counters(void) 60 { 61 return (cpuid(10).a >> 8) & 0xff; 62 } 63 64 static inline u8 pmu_gp_counter_width(void) 65 { 66 return (cpuid(10).a >> 16) & 0xff; 67 } 68 69 static inline u8 pmu_gp_counter_mask_length(void) 70 { 71 return (cpuid(10).a >> 24) & 0xff; 72 } 73 74 static inline u8 pmu_nr_fixed_counters(void) 75 { 76 struct cpuid id = cpuid(10); 77 78 if ((id.a & 0xff) > 1) 79 return id.d & 0x1f; 80 else 81 return 0; 82 } 83 84 static inline u8 pmu_fixed_counter_width(void) 85 { 86 struct cpuid id = cpuid(10); 87 88 if ((id.a & 0xff) > 1) 89 return (id.d >> 5) & 0xff; 90 else 91 return 0; 92 } 93 94 static inline bool pmu_gp_counter_is_available(int i) 95 { 96 /* CPUID.0xA.EBX bit is '1 if they counter is NOT available. */ 97 return !(cpuid(10).b & BIT(i)); 98 } 99 100 static inline u64 this_cpu_perf_capabilities(void) 101 { 102 return pmu.perf_cap; 103 } 104 105 static inline u64 pmu_lbr_version(void) 106 { 107 return this_cpu_perf_capabilities() & PMU_CAP_LBR_FMT; 108 } 109 110 static inline bool pmu_has_full_writes(void) 111 { 112 return this_cpu_perf_capabilities() & PMU_CAP_FW_WRITES; 113 } 114 115 #endif /* _X86_PMU_H_ */ 116