mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 16:54:20 +08:00
perf, x86: Add Nehelem PMU programming errata workaround
Implement the workaround for Intel Errata AAK100 and AAP53. Also, remove the Core-i7 name for Nehalem events since there are also Westmere based i7 chips. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephane Eranian <eranian@google.com> LKML-Reference: <1269608924.12097.147.camel@laptop> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
ea8e61b7bb
commit
11164cd4f6
@ -184,7 +184,7 @@ struct x86_pmu {
|
||||
int version;
|
||||
int (*handle_irq)(struct pt_regs *);
|
||||
void (*disable_all)(void);
|
||||
void (*enable_all)(void);
|
||||
void (*enable_all)(int added);
|
||||
void (*enable)(struct perf_event *);
|
||||
void (*disable)(struct perf_event *);
|
||||
int (*hw_config)(struct perf_event_attr *attr, struct hw_perf_event *hwc);
|
||||
@ -576,7 +576,7 @@ void hw_perf_disable(void)
|
||||
x86_pmu.disable_all();
|
||||
}
|
||||
|
||||
static void x86_pmu_enable_all(void)
|
||||
static void x86_pmu_enable_all(int added)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
||||
int idx;
|
||||
@ -784,7 +784,7 @@ void hw_perf_enable(void)
|
||||
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
||||
struct perf_event *event;
|
||||
struct hw_perf_event *hwc;
|
||||
int i;
|
||||
int i, added = cpuc->n_added;
|
||||
|
||||
if (!x86_pmu_initialized())
|
||||
return;
|
||||
@ -836,7 +836,7 @@ void hw_perf_enable(void)
|
||||
cpuc->enabled = 1;
|
||||
barrier();
|
||||
|
||||
x86_pmu.enable_all();
|
||||
x86_pmu.enable_all(added);
|
||||
}
|
||||
|
||||
static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc)
|
||||
|
@ -483,7 +483,7 @@ static void intel_pmu_disable_all(void)
|
||||
intel_pmu_lbr_disable_all();
|
||||
}
|
||||
|
||||
static void intel_pmu_enable_all(void)
|
||||
static void intel_pmu_enable_all(int added)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
||||
|
||||
@ -502,6 +502,40 @@ static void intel_pmu_enable_all(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Workaround for:
|
||||
* Intel Errata AAK100 (model 26)
|
||||
* Intel Errata AAP53 (model 30)
|
||||
*
|
||||
* These chips need to be 'reset' when adding counters by programming
|
||||
* the magic three (non counting) events 0x4300D2, 0x4300B1 and 0x4300B5
|
||||
* either in sequence on the same PMC or on different PMCs.
|
||||
*/
|
||||
static void intel_pmu_nhm_enable_all(int added)
|
||||
{
|
||||
if (added) {
|
||||
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
||||
int i;
|
||||
|
||||
wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 0, 0x4300D2);
|
||||
wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 1, 0x4300B1);
|
||||
wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 2, 0x4300B5);
|
||||
|
||||
wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x3);
|
||||
wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x0);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
struct perf_event *event = cpuc->events[i];
|
||||
|
||||
if (!event)
|
||||
continue;
|
||||
|
||||
__x86_pmu_enable_event(&event->hw);
|
||||
}
|
||||
}
|
||||
intel_pmu_enable_all(added);
|
||||
}
|
||||
|
||||
static inline u64 intel_pmu_get_status(void)
|
||||
{
|
||||
u64 status;
|
||||
@ -658,7 +692,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
|
||||
intel_pmu_drain_bts_buffer();
|
||||
status = intel_pmu_get_status();
|
||||
if (!status) {
|
||||
intel_pmu_enable_all();
|
||||
intel_pmu_enable_all(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -707,7 +741,7 @@ again:
|
||||
goto again;
|
||||
|
||||
done:
|
||||
intel_pmu_enable_all();
|
||||
intel_pmu_enable_all(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -920,7 +954,8 @@ static __init int intel_pmu_init(void)
|
||||
intel_pmu_lbr_init_nhm();
|
||||
|
||||
x86_pmu.event_constraints = intel_nehalem_event_constraints;
|
||||
pr_cont("Nehalem/Corei7 events, ");
|
||||
x86_pmu.enable_all = intel_pmu_nhm_enable_all;
|
||||
pr_cont("Nehalem events, ");
|
||||
break;
|
||||
|
||||
case 28: /* Atom */
|
||||
|
@ -535,7 +535,7 @@ static void p4_pmu_enable_event(struct perf_event *event)
|
||||
(cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
|
||||
}
|
||||
|
||||
static void p4_pmu_enable_all(void)
|
||||
static void p4_pmu_enable_all(int added)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
|
||||
int idx;
|
||||
|
@ -66,7 +66,7 @@ static void p6_pmu_disable_all(void)
|
||||
wrmsrl(MSR_P6_EVNTSEL0, val);
|
||||
}
|
||||
|
||||
static void p6_pmu_enable_all(void)
|
||||
static void p6_pmu_enable_all(int added)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user