19f17508dSLike Xu #include "pmu.h" 2879e7f07SLike Xu 3879e7f07SLike Xu struct pmu_caps pmu; 4879e7f07SLike Xu 5879e7f07SLike Xu void pmu_init(void) 6879e7f07SLike Xu { 7f85e94a2SSean Christopherson struct cpuid cpuid_10 = cpuid(10); 8f85e94a2SSean Christopherson 9*dd602b6fSSean Christopherson pmu.is_intel = is_intel(); 10*dd602b6fSSean Christopherson 11*dd602b6fSSean Christopherson if (!pmu.is_intel) 12*dd602b6fSSean Christopherson return; 13*dd602b6fSSean Christopherson 14f85e94a2SSean Christopherson pmu.version = cpuid_10.a & 0xff; 15f85e94a2SSean Christopherson 16f85e94a2SSean Christopherson if (pmu.version > 1) { 17f85e94a2SSean Christopherson pmu.nr_fixed_counters = cpuid_10.d & 0x1f; 18f85e94a2SSean Christopherson pmu.fixed_counter_width = (cpuid_10.d >> 5) & 0xff; 19f85e94a2SSean Christopherson } 20f85e94a2SSean Christopherson 21f85e94a2SSean Christopherson pmu.nr_gp_counters = (cpuid_10.a >> 8) & 0xff; 22f85e94a2SSean Christopherson pmu.gp_counter_width = (cpuid_10.a >> 16) & 0xff; 23f85e94a2SSean Christopherson pmu.gp_counter_mask_length = (cpuid_10.a >> 24) & 0xff; 24f85e94a2SSean Christopherson 25f85e94a2SSean Christopherson /* CPUID.0xA.EBX bit is '1' if a counter is NOT available. */ 26f85e94a2SSean Christopherson pmu.gp_counter_available = ~cpuid_10.b; 27f85e94a2SSean Christopherson 28879e7f07SLike Xu if (this_cpu_has(X86_FEATURE_PDCM)) 29879e7f07SLike Xu pmu.perf_cap = rdmsr(MSR_IA32_PERF_CAPABILITIES); 30cda64e80SLike Xu pmu.msr_gp_counter_base = MSR_IA32_PERFCTR0; 31cda64e80SLike Xu pmu.msr_gp_event_select_base = MSR_P6_EVNTSEL0; 3262ba5036SLike Xu 3362ba5036SLike Xu if (this_cpu_has_perf_global_status()) { 348a2866d1SLike Xu pmu.msr_global_status = MSR_CORE_PERF_GLOBAL_STATUS; 358a2866d1SLike Xu pmu.msr_global_ctl = MSR_CORE_PERF_GLOBAL_CTRL; 368a2866d1SLike Xu pmu.msr_global_status_clr = MSR_CORE_PERF_GLOBAL_OVF_CTRL; 3762ba5036SLike Xu } 38f33d3946SSean Christopherson 39f33d3946SSean Christopherson pmu_reset_all_counters(); 40879e7f07SLike Xu } 41