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