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 13b883751aSLike Xu #define AMD64_NUM_COUNTERS 4 14b883751aSLike Xu #define AMD64_NUM_COUNTERS_CORE 6 15b883751aSLike Xu 16b883751aSLike Xu #define PMC_DEFAULT_WIDTH 48 17b883751aSLike 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) 47*fc17d527SSean Christopherson #define PEBS_DATACFG_GPRS BIT_ULL(1) 482ae41f5dSLike Xu #define PEBS_DATACFG_XMMS BIT_ULL(2) 492ae41f5dSLike Xu #define PEBS_DATACFG_LBRS BIT_ULL(3) 50*fc17d527SSean Christopherson #define PEBS_DATACFG_MASK (PEBS_DATACFG_MEMINFO | \ 51*fc17d527SSean Christopherson PEBS_DATACFG_GPRS | \ 52*fc17d527SSean Christopherson PEBS_DATACFG_XMMS | \ 53*fc17d527SSean Christopherson PEBS_DATACFG_LBRS) 542ae41f5dSLike Xu 552ae41f5dSLike Xu #define ICL_EVENTSEL_ADAPTIVE (1ULL << 34) 562ae41f5dSLike Xu #define PEBS_DATACFG_LBR_SHIFT 24 572ae41f5dSLike Xu #define MAX_NUM_LBR_ENTRY 32 582ae41f5dSLike Xu 59879e7f07SLike Xu struct pmu_caps { 60dd602b6fSSean Christopherson bool is_intel; 61f85e94a2SSean Christopherson u8 version; 62f85e94a2SSean Christopherson u8 nr_fixed_counters; 63f85e94a2SSean Christopherson u8 fixed_counter_width; 64f85e94a2SSean Christopherson u8 nr_gp_counters; 65f85e94a2SSean Christopherson u8 gp_counter_width; 66f85e94a2SSean Christopherson u8 gp_counter_mask_length; 67f85e94a2SSean Christopherson u32 gp_counter_available; 68cda64e80SLike Xu u32 msr_gp_counter_base; 69cda64e80SLike Xu u32 msr_gp_event_select_base; 70cda64e80SLike Xu 718a2866d1SLike Xu u32 msr_global_status; 728a2866d1SLike Xu u32 msr_global_ctl; 738a2866d1SLike Xu u32 msr_global_status_clr; 748a2866d1SLike Xu 75879e7f07SLike Xu u64 perf_cap; 76879e7f07SLike Xu }; 77879e7f07SLike Xu 78879e7f07SLike Xu extern struct pmu_caps pmu; 79879e7f07SLike Xu 80879e7f07SLike Xu void pmu_init(void); 81879e7f07SLike Xu MSR_GP_COUNTERx(unsigned int i)82cda64e80SLike Xustatic inline u32 MSR_GP_COUNTERx(unsigned int i) 83cda64e80SLike Xu { 84b883751aSLike Xu if (pmu.msr_gp_counter_base == MSR_F15H_PERF_CTR0) 85b883751aSLike Xu return pmu.msr_gp_counter_base + 2 * i; 86b883751aSLike Xu 87cda64e80SLike Xu return pmu.msr_gp_counter_base + i; 88cda64e80SLike Xu } 89cda64e80SLike Xu MSR_GP_EVENT_SELECTx(unsigned int i)90cda64e80SLike Xustatic inline u32 MSR_GP_EVENT_SELECTx(unsigned int i) 91cda64e80SLike Xu { 92b883751aSLike Xu if (pmu.msr_gp_event_select_base == MSR_F15H_PERF_CTL0) 93b883751aSLike Xu return pmu.msr_gp_event_select_base + 2 * i; 94b883751aSLike Xu 95cda64e80SLike Xu return pmu.msr_gp_event_select_base + i; 96cda64e80SLike Xu } 97cda64e80SLike Xu this_cpu_has_pmu(void)989f17508dSLike Xustatic inline bool this_cpu_has_pmu(void) 999f17508dSLike Xu { 100b883751aSLike Xu return !pmu.is_intel || !!pmu.version; 1019f17508dSLike Xu } 1029f17508dSLike Xu this_cpu_has_perf_global_ctrl(void)1039f17508dSLike Xustatic inline bool this_cpu_has_perf_global_ctrl(void) 1049f17508dSLike Xu { 105414ee7d1SSean Christopherson return pmu.version > 1; 1069f17508dSLike Xu } 1079f17508dSLike Xu this_cpu_has_perf_global_status(void)10862ba5036SLike Xustatic inline bool this_cpu_has_perf_global_status(void) 10962ba5036SLike Xu { 11062ba5036SLike Xu return pmu.version > 1; 11162ba5036SLike Xu } 11262ba5036SLike Xu pmu_gp_counter_is_available(int i)1139f17508dSLike Xustatic inline bool pmu_gp_counter_is_available(int i) 1149f17508dSLike Xu { 115f85e94a2SSean Christopherson return pmu.gp_counter_available & BIT(i); 1169f17508dSLike Xu } 1179f17508dSLike Xu pmu_lbr_version(void)118879e7f07SLike Xustatic inline u64 pmu_lbr_version(void) 119879e7f07SLike Xu { 120414ee7d1SSean Christopherson return pmu.perf_cap & PMU_CAP_LBR_FMT; 121879e7f07SLike Xu } 122879e7f07SLike Xu pmu_has_full_writes(void)123879e7f07SLike Xustatic inline bool pmu_has_full_writes(void) 124879e7f07SLike Xu { 125414ee7d1SSean Christopherson return pmu.perf_cap & PMU_CAP_FW_WRITES; 1269f17508dSLike Xu } 1279f17508dSLike Xu pmu_activate_full_writes(void)1282ae41f5dSLike Xustatic inline void pmu_activate_full_writes(void) 1292ae41f5dSLike Xu { 1302ae41f5dSLike Xu pmu.msr_gp_counter_base = MSR_IA32_PMC0; 1312ae41f5dSLike Xu } 1322ae41f5dSLike Xu pmu_use_full_writes(void)133cda64e80SLike Xustatic inline bool pmu_use_full_writes(void) 134cda64e80SLike Xu { 135cda64e80SLike Xu return pmu.msr_gp_counter_base == MSR_IA32_PMC0; 136cda64e80SLike Xu } 137cda64e80SLike Xu MSR_PERF_FIXED_CTRx(unsigned int i)1383f914933SLike Xustatic inline u32 MSR_PERF_FIXED_CTRx(unsigned int i) 1393f914933SLike Xu { 1403f914933SLike Xu return MSR_CORE_PERF_FIXED_CTR0 + i; 1413f914933SLike Xu } 1423f914933SLike Xu pmu_reset_all_gp_counters(void)143f33d3946SSean Christophersonstatic inline void pmu_reset_all_gp_counters(void) 144f33d3946SSean Christopherson { 145f33d3946SSean Christopherson unsigned int idx; 146f33d3946SSean Christopherson 147f33d3946SSean Christopherson for (idx = 0; idx < pmu.nr_gp_counters; idx++) { 148f33d3946SSean Christopherson wrmsr(MSR_GP_EVENT_SELECTx(idx), 0); 149f33d3946SSean Christopherson wrmsr(MSR_GP_COUNTERx(idx), 0); 150f33d3946SSean Christopherson } 151f33d3946SSean Christopherson } 152f33d3946SSean Christopherson pmu_reset_all_fixed_counters(void)153f33d3946SSean Christophersonstatic inline void pmu_reset_all_fixed_counters(void) 154f33d3946SSean Christopherson { 155f33d3946SSean Christopherson unsigned int idx; 156f33d3946SSean Christopherson 157f33d3946SSean Christopherson if (!pmu.nr_fixed_counters) 158f33d3946SSean Christopherson return; 159f33d3946SSean Christopherson 160f33d3946SSean Christopherson wrmsr(MSR_CORE_PERF_FIXED_CTR_CTRL, 0); 161f33d3946SSean Christopherson for (idx = 0; idx < pmu.nr_fixed_counters; idx++) 162f33d3946SSean Christopherson wrmsr(MSR_PERF_FIXED_CTRx(idx), 0); 163f33d3946SSean Christopherson } 164f33d3946SSean Christopherson pmu_reset_all_counters(void)165f33d3946SSean Christophersonstatic inline void pmu_reset_all_counters(void) 166f33d3946SSean Christopherson { 167f33d3946SSean Christopherson pmu_reset_all_gp_counters(); 168f33d3946SSean Christopherson pmu_reset_all_fixed_counters(); 169f33d3946SSean Christopherson } 170f33d3946SSean Christopherson pmu_clear_global_status(void)1718a2866d1SLike Xustatic inline void pmu_clear_global_status(void) 1728a2866d1SLike Xu { 1738a2866d1SLike Xu wrmsr(pmu.msr_global_status_clr, rdmsr(pmu.msr_global_status)); 1748a2866d1SLike Xu } 1758a2866d1SLike Xu pmu_has_pebs(void)1762ae41f5dSLike Xustatic inline bool pmu_has_pebs(void) 1772ae41f5dSLike Xu { 1782ae41f5dSLike Xu return pmu.version > 1; 1792ae41f5dSLike Xu } 1802ae41f5dSLike Xu pmu_pebs_format(void)1812ae41f5dSLike Xustatic inline u8 pmu_pebs_format(void) 1822ae41f5dSLike Xu { 1832ae41f5dSLike Xu return (pmu.perf_cap & PERF_CAP_PEBS_FORMAT ) >> 8; 1842ae41f5dSLike Xu } 1852ae41f5dSLike Xu pmu_has_pebs_baseline(void)1862ae41f5dSLike Xustatic inline bool pmu_has_pebs_baseline(void) 1872ae41f5dSLike Xu { 1882ae41f5dSLike Xu return pmu.perf_cap & PMU_CAP_PEBS_BASELINE; 1892ae41f5dSLike Xu } 1902ae41f5dSLike Xu 1919f17508dSLike Xu #endif /* _X86_PMU_H_ */ 192