Path: blob/master/arch/x86/kernel/cpu/perf_event_p6.c
10699 views
#ifdef CONFIG_CPU_SUP_INTEL12/*3* Not sure about some of these4*/5static const u64 p6_perfmon_event_map[] =6{7[PERF_COUNT_HW_CPU_CYCLES] = 0x0079,8[PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,9[PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e,10[PERF_COUNT_HW_CACHE_MISSES] = 0x012e,11[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4,12[PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5,13[PERF_COUNT_HW_BUS_CYCLES] = 0x0062,14};1516static u64 p6_pmu_event_map(int hw_event)17{18return p6_perfmon_event_map[hw_event];19}2021/*22* Event setting that is specified not to count anything.23* We use this to effectively disable a counter.24*25* L2_RQSTS with 0 MESI unit mask.26*/27#define P6_NOP_EVENT 0x0000002EULL2829static struct event_constraint p6_event_constraints[] =30{31INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */32INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */33INTEL_EVENT_CONSTRAINT(0x11, 0x1), /* FP_ASSIST */34INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */35INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */36INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */37EVENT_CONSTRAINT_END38};3940static void p6_pmu_disable_all(void)41{42u64 val;4344/* p6 only has one enable register */45rdmsrl(MSR_P6_EVNTSEL0, val);46val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;47wrmsrl(MSR_P6_EVNTSEL0, val);48}4950static void p6_pmu_enable_all(int added)51{52unsigned long val;5354/* p6 only has one enable register */55rdmsrl(MSR_P6_EVNTSEL0, val);56val |= ARCH_PERFMON_EVENTSEL_ENABLE;57wrmsrl(MSR_P6_EVNTSEL0, val);58}5960static inline void61p6_pmu_disable_event(struct perf_event *event)62{63struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);64struct hw_perf_event *hwc = &event->hw;65u64 val = P6_NOP_EVENT;6667if (cpuc->enabled)68val |= ARCH_PERFMON_EVENTSEL_ENABLE;6970(void)checking_wrmsrl(hwc->config_base, val);71}7273static void p6_pmu_enable_event(struct perf_event *event)74{75struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);76struct hw_perf_event *hwc = &event->hw;77u64 val;7879val = hwc->config;80if (cpuc->enabled)81val |= ARCH_PERFMON_EVENTSEL_ENABLE;8283(void)checking_wrmsrl(hwc->config_base, val);84}8586static __initconst const struct x86_pmu p6_pmu = {87.name = "p6",88.handle_irq = x86_pmu_handle_irq,89.disable_all = p6_pmu_disable_all,90.enable_all = p6_pmu_enable_all,91.enable = p6_pmu_enable_event,92.disable = p6_pmu_disable_event,93.hw_config = x86_pmu_hw_config,94.schedule_events = x86_schedule_events,95.eventsel = MSR_P6_EVNTSEL0,96.perfctr = MSR_P6_PERFCTR0,97.event_map = p6_pmu_event_map,98.max_events = ARRAY_SIZE(p6_perfmon_event_map),99.apic = 1,100.max_period = (1ULL << 31) - 1,101.version = 0,102.num_counters = 2,103/*104* Events have 40 bits implemented. However they are designed such105* that bits [32-39] are sign extensions of bit 31. As such the106* effective width of a event for P6-like PMU is 32 bits only.107*108* See IA-32 Intel Architecture Software developer manual Vol 3B109*/110.cntval_bits = 32,111.cntval_mask = (1ULL << 32) - 1,112.get_event_constraints = x86_get_event_constraints,113.event_constraints = p6_event_constraints,114};115116static __init int p6_pmu_init(void)117{118switch (boot_cpu_data.x86_model) {119case 1:120case 3: /* Pentium Pro */121case 5:122case 6: /* Pentium II */123case 7:124case 8:125case 11: /* Pentium III */126case 9:127case 13:128/* Pentium M */129break;130default:131pr_cont("unsupported p6 CPU model %d ",132boot_cpu_data.x86_model);133return -ENODEV;134}135136x86_pmu = p6_pmu;137138return 0;139}140141#endif /* CONFIG_CPU_SUP_INTEL */142143144