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