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 #define PMU_CAP_PEBS_BASELINE (1ULL << 14) 18 #define PERF_CAP_PEBS_FORMAT 0xf00 19 20 #define EVNSEL_EVENT_SHIFT 0 21 #define EVNTSEL_UMASK_SHIFT 8 22 #define EVNTSEL_USR_SHIFT 16 23 #define EVNTSEL_OS_SHIFT 17 24 #define EVNTSEL_EDGE_SHIFT 18 25 #define EVNTSEL_PC_SHIFT 19 26 #define EVNTSEL_INT_SHIFT 20 27 #define EVNTSEL_EN_SHIF 22 28 #define EVNTSEL_INV_SHIF 23 29 #define EVNTSEL_CMASK_SHIFT 24 30 31 #define EVNTSEL_EN (1 << EVNTSEL_EN_SHIF) 32 #define EVNTSEL_USR (1 << EVNTSEL_USR_SHIFT) 33 #define EVNTSEL_OS (1 << EVNTSEL_OS_SHIFT) 34 #define EVNTSEL_PC (1 << EVNTSEL_PC_SHIFT) 35 #define EVNTSEL_INT (1 << EVNTSEL_INT_SHIFT) 36 #define EVNTSEL_INV (1 << EVNTSEL_INV_SHIF) 37 38 #define GLOBAL_STATUS_BUFFER_OVF_BIT 62 39 #define GLOBAL_STATUS_BUFFER_OVF BIT_ULL(GLOBAL_STATUS_BUFFER_OVF_BIT) 40 41 #define PEBS_DATACFG_MEMINFO BIT_ULL(0) 42 #define PEBS_DATACFG_GP BIT_ULL(1) 43 #define PEBS_DATACFG_XMMS BIT_ULL(2) 44 #define PEBS_DATACFG_LBRS BIT_ULL(3) 45 46 #define ICL_EVENTSEL_ADAPTIVE (1ULL << 34) 47 #define PEBS_DATACFG_LBR_SHIFT 24 48 #define MAX_NUM_LBR_ENTRY 32 49 50 struct pmu_caps { 51 bool is_intel; 52 u8 version; 53 u8 nr_fixed_counters; 54 u8 fixed_counter_width; 55 u8 nr_gp_counters; 56 u8 gp_counter_width; 57 u8 gp_counter_mask_length; 58 u32 gp_counter_available; 59 u32 msr_gp_counter_base; 60 u32 msr_gp_event_select_base; 61 62 u32 msr_global_status; 63 u32 msr_global_ctl; 64 u32 msr_global_status_clr; 65 66 u64 perf_cap; 67 }; 68 69 extern struct pmu_caps pmu; 70 71 void pmu_init(void); 72 73 static inline u32 MSR_GP_COUNTERx(unsigned int i) 74 { 75 return pmu.msr_gp_counter_base + i; 76 } 77 78 static inline u32 MSR_GP_EVENT_SELECTx(unsigned int i) 79 { 80 return pmu.msr_gp_event_select_base + i; 81 } 82 83 static inline bool this_cpu_has_pmu(void) 84 { 85 return !!pmu.version; 86 } 87 88 static inline bool this_cpu_has_perf_global_ctrl(void) 89 { 90 return pmu.version > 1; 91 } 92 93 static inline bool this_cpu_has_perf_global_status(void) 94 { 95 return pmu.version > 1; 96 } 97 98 static inline bool pmu_gp_counter_is_available(int i) 99 { 100 return pmu.gp_counter_available & BIT(i); 101 } 102 103 static inline u64 pmu_lbr_version(void) 104 { 105 return pmu.perf_cap & PMU_CAP_LBR_FMT; 106 } 107 108 static inline bool pmu_has_full_writes(void) 109 { 110 return pmu.perf_cap & PMU_CAP_FW_WRITES; 111 } 112 113 static inline void pmu_activate_full_writes(void) 114 { 115 pmu.msr_gp_counter_base = MSR_IA32_PMC0; 116 } 117 118 static inline bool pmu_use_full_writes(void) 119 { 120 return pmu.msr_gp_counter_base == MSR_IA32_PMC0; 121 } 122 123 static inline u32 MSR_PERF_FIXED_CTRx(unsigned int i) 124 { 125 return MSR_CORE_PERF_FIXED_CTR0 + i; 126 } 127 128 static inline void pmu_reset_all_gp_counters(void) 129 { 130 unsigned int idx; 131 132 for (idx = 0; idx < pmu.nr_gp_counters; idx++) { 133 wrmsr(MSR_GP_EVENT_SELECTx(idx), 0); 134 wrmsr(MSR_GP_COUNTERx(idx), 0); 135 } 136 } 137 138 static inline void pmu_reset_all_fixed_counters(void) 139 { 140 unsigned int idx; 141 142 if (!pmu.nr_fixed_counters) 143 return; 144 145 wrmsr(MSR_CORE_PERF_FIXED_CTR_CTRL, 0); 146 for (idx = 0; idx < pmu.nr_fixed_counters; idx++) 147 wrmsr(MSR_PERF_FIXED_CTRx(idx), 0); 148 } 149 150 static inline void pmu_reset_all_counters(void) 151 { 152 pmu_reset_all_gp_counters(); 153 pmu_reset_all_fixed_counters(); 154 } 155 156 static inline void pmu_clear_global_status(void) 157 { 158 wrmsr(pmu.msr_global_status_clr, rdmsr(pmu.msr_global_status)); 159 } 160 161 static inline bool pmu_has_pebs(void) 162 { 163 return pmu.version > 1; 164 } 165 166 static inline u8 pmu_pebs_format(void) 167 { 168 return (pmu.perf_cap & PERF_CAP_PEBS_FORMAT ) >> 8; 169 } 170 171 static inline bool pmu_has_pebs_baseline(void) 172 { 173 return pmu.perf_cap & PMU_CAP_PEBS_BASELINE; 174 } 175 176 #endif /* _X86_PMU_H_ */ 177