Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf, x86: Make a second write to performance counter if needed

On Netburst PMU we need a second write to a performance counter
due to cpu erratum.

A simple flag test instead of alternative instructions was choosen
because wrmsrl is already a macro and if virtualization is turned
on will need an additional wrapper call which is more expencise.

nb: we should propably switch to jump-labels as only this facility
reach the mainline.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Robert Richter <robert.richter@amd.com>
Cc: Lin Ming <ming.m.lin@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20100602212304.GC5264@lenovo>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Cyrill Gorcunov and committed by
Ingo Molnar
68aa00ac 8d2cacbb

+20 -1
+11 -1
arch/x86/kernel/cpu/perf_event.c
··· 220 220 struct perf_event *event); 221 221 struct event_constraint *event_constraints; 222 222 void (*quirks)(void); 223 + int perfctr_second_write; 223 224 224 225 int (*cpu_prepare)(int cpu); 225 226 void (*cpu_starting)(int cpu); ··· 926 925 */ 927 926 atomic64_set(&hwc->prev_count, (u64)-left); 928 927 929 - wrmsrl(hwc->event_base + idx, 928 + wrmsrl(hwc->event_base + idx, (u64)(-left) & x86_pmu.cntval_mask); 929 + 930 + /* 931 + * Due to erratum on certan cpu we need 932 + * a second write to be sure the register 933 + * is updated properly 934 + */ 935 + if (x86_pmu.perfctr_second_write) { 936 + wrmsrl(hwc->event_base + idx, 930 937 (u64)(-left) & x86_pmu.cntval_mask); 938 + } 931 939 932 940 perf_event_update_userpage(event); 933 941
+9
arch/x86/kernel/cpu/perf_event_p4.c
··· 829 829 .max_period = (1ULL << 39) - 1, 830 830 .hw_config = p4_hw_config, 831 831 .schedule_events = p4_pmu_schedule_events, 832 + /* 833 + * This handles erratum N15 in intel doc 249199-029, 834 + * the counter may not be updated correctly on write 835 + * so we need a second write operation to do the trick 836 + * (the official workaround didn't work) 837 + * 838 + * the former idea is taken from OProfile code 839 + */ 840 + .perfctr_second_write = 1, 832 841 }; 833 842 834 843 static __init int p4_pmu_init(void)