blob: 0f2afd650bc913b84579134d8ef4d9a6fe45563c [file] [log] [blame]
#include "pmu.h"
struct pmu_caps pmu;
void pmu_init(void)
{
pmu.is_intel = is_intel();
if (pmu.is_intel) {
struct cpuid cpuid_10 = cpuid(10);
pmu.version = cpuid_10.a & 0xff;
if (pmu.version > 1) {
pmu.nr_fixed_counters = cpuid_10.d & 0x1f;
pmu.fixed_counter_width = (cpuid_10.d >> 5) & 0xff;
}
if (pmu.version > 1) {
pmu.nr_fixed_counters = cpuid_10.d & 0x1f;
pmu.fixed_counter_width = (cpuid_10.d >> 5) & 0xff;
}
pmu.nr_gp_counters = (cpuid_10.a >> 8) & 0xff;
pmu.gp_counter_width = (cpuid_10.a >> 16) & 0xff;
pmu.gp_counter_mask_length = (cpuid_10.a >> 24) & 0xff;
/* CPUID.0xA.EBX bit is '1' if a counter is NOT available. */
pmu.gp_counter_available = ~cpuid_10.b;
if (this_cpu_has(X86_FEATURE_PDCM))
pmu.perf_cap = rdmsr(MSR_IA32_PERF_CAPABILITIES);
pmu.msr_gp_counter_base = MSR_IA32_PERFCTR0;
pmu.msr_gp_event_select_base = MSR_P6_EVNTSEL0;
if (this_cpu_has_perf_global_status()) {
pmu.msr_global_status = MSR_CORE_PERF_GLOBAL_STATUS;
pmu.msr_global_ctl = MSR_CORE_PERF_GLOBAL_CTRL;
pmu.msr_global_status_clr = MSR_CORE_PERF_GLOBAL_OVF_CTRL;
}
} else {
if (this_cpu_has(X86_FEATURE_PERFCTR_CORE)) {
/* Performance Monitoring Version 2 Supported */
if (this_cpu_has(X86_FEATURE_AMD_PMU_V2)) {
pmu.version = 2;
pmu.nr_gp_counters = cpuid(0x80000022).b & 0xf;
} else {
pmu.nr_gp_counters = AMD64_NUM_COUNTERS_CORE;
}
pmu.msr_gp_counter_base = MSR_F15H_PERF_CTR0;
pmu.msr_gp_event_select_base = MSR_F15H_PERF_CTL0;
} else {
pmu.nr_gp_counters = AMD64_NUM_COUNTERS;
pmu.msr_gp_counter_base = MSR_K7_PERFCTR0;
pmu.msr_gp_event_select_base = MSR_K7_EVNTSEL0;
}
pmu.gp_counter_width = PMC_DEFAULT_WIDTH;
pmu.gp_counter_mask_length = pmu.nr_gp_counters;
pmu.gp_counter_available = (1u << pmu.nr_gp_counters) - 1;
if (this_cpu_has_perf_global_status()) {
pmu.msr_global_status = MSR_AMD64_PERF_CNTR_GLOBAL_STATUS;
pmu.msr_global_ctl = MSR_AMD64_PERF_CNTR_GLOBAL_CTL;
pmu.msr_global_status_clr = MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR;
}
}
pmu_reset_all_counters();
}