blob: 8c8177f859fe145488f8633025bc31dbf2b2cef2 [file] [log] [blame]
Ingo Molnar241771e2008-12-03 10:39:53 +01001/*
2 * Performance counter x86 architecture code
3 *
Ingo Molnar98144512009-04-29 14:52:50 +02004 * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
5 * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
6 * Copyright (C) 2009 Jaswinder Singh Rajput
7 * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
8 * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
Ingo Molnar241771e2008-12-03 10:39:53 +01009 *
10 * For licencing details see kernel-base/COPYING
11 */
12
13#include <linux/perf_counter.h>
14#include <linux/capability.h>
15#include <linux/notifier.h>
16#include <linux/hardirq.h>
17#include <linux/kprobes.h>
Thomas Gleixner4ac13292008-12-09 21:43:39 +010018#include <linux/module.h>
Ingo Molnar241771e2008-12-03 10:39:53 +010019#include <linux/kdebug.h>
20#include <linux/sched.h>
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +020021#include <linux/uaccess.h>
Ingo Molnar241771e2008-12-03 10:39:53 +010022
Ingo Molnar241771e2008-12-03 10:39:53 +010023#include <asm/apic.h>
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +020024#include <asm/stacktrace.h>
Peter Zijlstra4e935e42009-03-30 19:07:16 +020025#include <asm/nmi.h>
Ingo Molnar241771e2008-12-03 10:39:53 +010026
Ingo Molnar862a1a52008-12-17 13:09:20 +010027static u64 perf_counter_mask __read_mostly;
Ingo Molnar703e9372008-12-17 10:51:15 +010028
Ingo Molnar241771e2008-12-03 10:39:53 +010029struct cpu_hw_counters {
Ingo Molnar862a1a52008-12-17 13:09:20 +010030 struct perf_counter *counters[X86_PMC_IDX_MAX];
Robert Richter43f62012009-04-29 16:55:56 +020031 unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
32 unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
Mike Galbraith4b39fd92009-01-23 14:36:16 +010033 unsigned long interrupts;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010034 int enabled;
Ingo Molnar241771e2008-12-03 10:39:53 +010035};
36
37/*
Robert Richter5f4ec282009-04-29 12:47:04 +020038 * struct x86_pmu - generic x86 pmu
Ingo Molnar241771e2008-12-03 10:39:53 +010039 */
Robert Richter5f4ec282009-04-29 12:47:04 +020040struct x86_pmu {
Robert Richterfaa28ae2009-04-29 12:47:13 +020041 const char *name;
42 int version;
Robert Richter39d81ea2009-04-29 12:47:05 +020043 int (*handle_irq)(struct pt_regs *, int);
Peter Zijlstra9e35ad32009-05-13 16:21:38 +020044 void (*disable_all)(void);
45 void (*enable_all)(void);
Robert Richter7c90cc42009-04-29 12:47:18 +020046 void (*enable)(struct hw_perf_counter *, int);
Robert Richterd4369892009-04-29 12:47:19 +020047 void (*disable)(struct hw_perf_counter *, int);
Jaswinder Singh Rajput169e41e2009-02-28 18:37:49 +053048 unsigned eventsel;
49 unsigned perfctr;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010050 u64 (*event_map)(int);
51 u64 (*raw_event)(u64);
Jaswinder Singh Rajput169e41e2009-02-28 18:37:49 +053052 int max_events;
Robert Richter0933e5c2009-04-29 12:47:12 +020053 int num_counters;
54 int num_counters_fixed;
55 int counter_bits;
56 u64 counter_mask;
Robert Richterc619b8f2009-04-29 12:47:23 +020057 u64 max_period;
Peter Zijlstra9e35ad32009-05-13 16:21:38 +020058 u64 intel_ctrl;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +053059};
60
Robert Richter4a06bd82009-04-29 12:47:11 +020061static struct x86_pmu x86_pmu __read_mostly;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +053062
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010063static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters) = {
64 .enabled = 1,
65};
Ingo Molnar241771e2008-12-03 10:39:53 +010066
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +053067/*
68 * Intel PerfMon v3. Used on Core2 and later.
69 */
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010070static const u64 intel_perfmon_event_map[] =
Ingo Molnar241771e2008-12-03 10:39:53 +010071{
Ingo Molnarf650a672008-12-23 12:17:29 +010072 [PERF_COUNT_CPU_CYCLES] = 0x003c,
Ingo Molnar241771e2008-12-03 10:39:53 +010073 [PERF_COUNT_INSTRUCTIONS] = 0x00c0,
74 [PERF_COUNT_CACHE_REFERENCES] = 0x4f2e,
75 [PERF_COUNT_CACHE_MISSES] = 0x412e,
76 [PERF_COUNT_BRANCH_INSTRUCTIONS] = 0x00c4,
77 [PERF_COUNT_BRANCH_MISSES] = 0x00c5,
Ingo Molnarf650a672008-12-23 12:17:29 +010078 [PERF_COUNT_BUS_CYCLES] = 0x013c,
Ingo Molnar241771e2008-12-03 10:39:53 +010079};
80
Robert Richter5f4ec282009-04-29 12:47:04 +020081static u64 intel_pmu_event_map(int event)
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +053082{
83 return intel_perfmon_event_map[event];
84}
Ingo Molnar241771e2008-12-03 10:39:53 +010085
Robert Richter5f4ec282009-04-29 12:47:04 +020086static u64 intel_pmu_raw_event(u64 event)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010087{
Peter Zijlstra82bae4f82009-03-13 12:21:31 +010088#define CORE_EVNTSEL_EVENT_MASK 0x000000FFULL
89#define CORE_EVNTSEL_UNIT_MASK 0x0000FF00ULL
Peter Zijlstraff99be52009-05-25 17:39:03 +020090#define CORE_EVNTSEL_EDGE_MASK 0x00040000ULL
91#define CORE_EVNTSEL_INV_MASK 0x00800000ULL
Peter Zijlstra82bae4f82009-03-13 12:21:31 +010092#define CORE_EVNTSEL_COUNTER_MASK 0xFF000000ULL
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010093
94#define CORE_EVNTSEL_MASK \
95 (CORE_EVNTSEL_EVENT_MASK | \
96 CORE_EVNTSEL_UNIT_MASK | \
Peter Zijlstraff99be52009-05-25 17:39:03 +020097 CORE_EVNTSEL_EDGE_MASK | \
98 CORE_EVNTSEL_INV_MASK | \
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010099 CORE_EVNTSEL_COUNTER_MASK)
100
101 return event & CORE_EVNTSEL_MASK;
102}
103
Ingo Molnar241771e2008-12-03 10:39:53 +0100104/*
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530105 * AMD Performance Monitor K7 and later.
106 */
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100107static const u64 amd_perfmon_event_map[] =
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530108{
109 [PERF_COUNT_CPU_CYCLES] = 0x0076,
110 [PERF_COUNT_INSTRUCTIONS] = 0x00c0,
111 [PERF_COUNT_CACHE_REFERENCES] = 0x0080,
112 [PERF_COUNT_CACHE_MISSES] = 0x0081,
113 [PERF_COUNT_BRANCH_INSTRUCTIONS] = 0x00c4,
114 [PERF_COUNT_BRANCH_MISSES] = 0x00c5,
115};
116
Robert Richter5f4ec282009-04-29 12:47:04 +0200117static u64 amd_pmu_event_map(int event)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530118{
119 return amd_perfmon_event_map[event];
120}
121
Robert Richter5f4ec282009-04-29 12:47:04 +0200122static u64 amd_pmu_raw_event(u64 event)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100123{
Peter Zijlstra82bae4f82009-03-13 12:21:31 +0100124#define K7_EVNTSEL_EVENT_MASK 0x7000000FFULL
125#define K7_EVNTSEL_UNIT_MASK 0x00000FF00ULL
Peter Zijlstraff99be52009-05-25 17:39:03 +0200126#define K7_EVNTSEL_EDGE_MASK 0x000040000ULL
127#define K7_EVNTSEL_INV_MASK 0x000800000ULL
Peter Zijlstra82bae4f82009-03-13 12:21:31 +0100128#define K7_EVNTSEL_COUNTER_MASK 0x0FF000000ULL
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100129
130#define K7_EVNTSEL_MASK \
131 (K7_EVNTSEL_EVENT_MASK | \
132 K7_EVNTSEL_UNIT_MASK | \
Peter Zijlstraff99be52009-05-25 17:39:03 +0200133 K7_EVNTSEL_EDGE_MASK | \
134 K7_EVNTSEL_INV_MASK | \
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100135 K7_EVNTSEL_COUNTER_MASK)
136
137 return event & K7_EVNTSEL_MASK;
138}
139
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530140/*
Ingo Molnaree060942008-12-13 09:00:03 +0100141 * Propagate counter elapsed time into the generic counter.
142 * Can only be executed on the CPU where the counter is active.
143 * Returns the delta events processed.
144 */
Robert Richter4b7bfd02009-04-29 12:47:22 +0200145static u64
Ingo Molnaree060942008-12-13 09:00:03 +0100146x86_perf_counter_update(struct perf_counter *counter,
147 struct hw_perf_counter *hwc, int idx)
148{
Peter Zijlstraec3232b2009-05-13 09:45:19 +0200149 int shift = 64 - x86_pmu.counter_bits;
150 u64 prev_raw_count, new_raw_count;
151 s64 delta;
Ingo Molnaree060942008-12-13 09:00:03 +0100152
Ingo Molnaree060942008-12-13 09:00:03 +0100153 /*
154 * Careful: an NMI might modify the previous counter value.
155 *
156 * Our tactic to handle this is to first atomically read and
157 * exchange a new raw count - then add that new-prev delta
158 * count to the generic counter atomically:
159 */
160again:
161 prev_raw_count = atomic64_read(&hwc->prev_count);
162 rdmsrl(hwc->counter_base + idx, new_raw_count);
163
164 if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
165 new_raw_count) != prev_raw_count)
166 goto again;
167
168 /*
169 * Now we have the new raw value and have updated the prev
170 * timestamp already. We can now calculate the elapsed delta
171 * (counter-)time and add that to the generic counter.
172 *
173 * Careful, not all hw sign-extends above the physical width
Peter Zijlstraec3232b2009-05-13 09:45:19 +0200174 * of the count.
Ingo Molnaree060942008-12-13 09:00:03 +0100175 */
Peter Zijlstraec3232b2009-05-13 09:45:19 +0200176 delta = (new_raw_count << shift) - (prev_raw_count << shift);
177 delta >>= shift;
Ingo Molnaree060942008-12-13 09:00:03 +0100178
179 atomic64_add(delta, &counter->count);
180 atomic64_sub(delta, &hwc->period_left);
Robert Richter4b7bfd02009-04-29 12:47:22 +0200181
182 return new_raw_count;
Ingo Molnaree060942008-12-13 09:00:03 +0100183}
184
Peter Zijlstraba778132009-05-04 18:47:44 +0200185static atomic_t active_counters;
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200186static DEFINE_MUTEX(pmc_reserve_mutex);
187
188static bool reserve_pmc_hardware(void)
189{
190 int i;
191
192 if (nmi_watchdog == NMI_LOCAL_APIC)
193 disable_lapic_nmi_watchdog();
194
Robert Richter0933e5c2009-04-29 12:47:12 +0200195 for (i = 0; i < x86_pmu.num_counters; i++) {
Robert Richter4a06bd82009-04-29 12:47:11 +0200196 if (!reserve_perfctr_nmi(x86_pmu.perfctr + i))
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200197 goto perfctr_fail;
198 }
199
Robert Richter0933e5c2009-04-29 12:47:12 +0200200 for (i = 0; i < x86_pmu.num_counters; i++) {
Robert Richter4a06bd82009-04-29 12:47:11 +0200201 if (!reserve_evntsel_nmi(x86_pmu.eventsel + i))
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200202 goto eventsel_fail;
203 }
204
205 return true;
206
207eventsel_fail:
208 for (i--; i >= 0; i--)
Robert Richter4a06bd82009-04-29 12:47:11 +0200209 release_evntsel_nmi(x86_pmu.eventsel + i);
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200210
Robert Richter0933e5c2009-04-29 12:47:12 +0200211 i = x86_pmu.num_counters;
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200212
213perfctr_fail:
214 for (i--; i >= 0; i--)
Robert Richter4a06bd82009-04-29 12:47:11 +0200215 release_perfctr_nmi(x86_pmu.perfctr + i);
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200216
217 if (nmi_watchdog == NMI_LOCAL_APIC)
218 enable_lapic_nmi_watchdog();
219
220 return false;
221}
222
223static void release_pmc_hardware(void)
224{
225 int i;
226
Robert Richter0933e5c2009-04-29 12:47:12 +0200227 for (i = 0; i < x86_pmu.num_counters; i++) {
Robert Richter4a06bd82009-04-29 12:47:11 +0200228 release_perfctr_nmi(x86_pmu.perfctr + i);
229 release_evntsel_nmi(x86_pmu.eventsel + i);
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200230 }
231
232 if (nmi_watchdog == NMI_LOCAL_APIC)
233 enable_lapic_nmi_watchdog();
234}
235
236static void hw_perf_counter_destroy(struct perf_counter *counter)
237{
Peter Zijlstraba778132009-05-04 18:47:44 +0200238 if (atomic_dec_and_mutex_lock(&active_counters, &pmc_reserve_mutex)) {
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200239 release_pmc_hardware();
240 mutex_unlock(&pmc_reserve_mutex);
241 }
242}
243
Robert Richter85cf9db2009-04-29 12:47:20 +0200244static inline int x86_pmu_initialized(void)
245{
246 return x86_pmu.handle_irq != NULL;
247}
248
Ingo Molnaree060942008-12-13 09:00:03 +0100249/*
Ingo Molnar241771e2008-12-03 10:39:53 +0100250 * Setup the hardware configuration for a given hw_event_type
251 */
Ingo Molnar621a01e2008-12-11 12:46:46 +0100252static int __hw_perf_counter_init(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100253{
Ingo Molnar9f66a382008-12-10 12:33:23 +0100254 struct perf_counter_hw_event *hw_event = &counter->hw_event;
Ingo Molnar241771e2008-12-03 10:39:53 +0100255 struct hw_perf_counter *hwc = &counter->hw;
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200256 int err;
Ingo Molnar241771e2008-12-03 10:39:53 +0100257
Robert Richter85cf9db2009-04-29 12:47:20 +0200258 if (!x86_pmu_initialized())
259 return -ENODEV;
Ingo Molnar241771e2008-12-03 10:39:53 +0100260
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200261 err = 0;
Peter Zijlstraba778132009-05-04 18:47:44 +0200262 if (!atomic_inc_not_zero(&active_counters)) {
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200263 mutex_lock(&pmc_reserve_mutex);
Peter Zijlstraba778132009-05-04 18:47:44 +0200264 if (atomic_read(&active_counters) == 0 && !reserve_pmc_hardware())
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200265 err = -EBUSY;
266 else
Peter Zijlstraba778132009-05-04 18:47:44 +0200267 atomic_inc(&active_counters);
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200268 mutex_unlock(&pmc_reserve_mutex);
269 }
270 if (err)
271 return err;
272
Ingo Molnar241771e2008-12-03 10:39:53 +0100273 /*
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100274 * Generate PMC IRQs:
Ingo Molnar241771e2008-12-03 10:39:53 +0100275 * (keep 'enabled' bit clear for now)
276 */
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100277 hwc->config = ARCH_PERFMON_EVENTSEL_INT;
Ingo Molnar241771e2008-12-03 10:39:53 +0100278
279 /*
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100280 * Count user and OS events unless requested not to.
281 */
282 if (!hw_event->exclude_user)
283 hwc->config |= ARCH_PERFMON_EVENTSEL_USR;
284 if (!hw_event->exclude_kernel)
285 hwc->config |= ARCH_PERFMON_EVENTSEL_OS;
286
287 /*
288 * If privileged enough, allow NMI events:
Ingo Molnar241771e2008-12-03 10:39:53 +0100289 */
290 hwc->nmi = 0;
Peter Zijlstraa026dfe2009-05-13 10:02:57 +0200291 if (hw_event->nmi) {
292 if (sysctl_perf_counter_priv && !capable(CAP_SYS_ADMIN))
293 return -EACCES;
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100294 hwc->nmi = 1;
Peter Zijlstraa026dfe2009-05-13 10:02:57 +0200295 }
Ingo Molnarb68f1d22009-05-17 19:37:25 +0200296 perf_counters_lapic_init(hwc->nmi);
Ingo Molnar241771e2008-12-03 10:39:53 +0100297
Ingo Molnard2517a42009-05-17 10:04:45 +0200298 if (!hwc->irq_period)
299 hwc->irq_period = x86_pmu.max_period;
300
Peter Zijlstra60db5e02009-05-15 15:19:28 +0200301 atomic64_set(&hwc->period_left,
302 min(x86_pmu.max_period, hwc->irq_period));
Ingo Molnar241771e2008-12-03 10:39:53 +0100303
304 /*
Thomas Gleixnerdfa7c892008-12-08 19:35:37 +0100305 * Raw event type provide the config in the event structure
Ingo Molnar241771e2008-12-03 10:39:53 +0100306 */
Peter Zijlstraf4a2deb42009-03-23 18:22:06 +0100307 if (perf_event_raw(hw_event)) {
Robert Richter4a06bd82009-04-29 12:47:11 +0200308 hwc->config |= x86_pmu.raw_event(perf_event_config(hw_event));
Ingo Molnar241771e2008-12-03 10:39:53 +0100309 } else {
Robert Richter4a06bd82009-04-29 12:47:11 +0200310 if (perf_event_id(hw_event) >= x86_pmu.max_events)
Ingo Molnar241771e2008-12-03 10:39:53 +0100311 return -EINVAL;
312 /*
313 * The generic map:
314 */
Robert Richter4a06bd82009-04-29 12:47:11 +0200315 hwc->config |= x86_pmu.event_map(perf_event_id(hw_event));
Ingo Molnar241771e2008-12-03 10:39:53 +0100316 }
Ingo Molnar241771e2008-12-03 10:39:53 +0100317
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200318 counter->destroy = hw_perf_counter_destroy;
319
Ingo Molnar241771e2008-12-03 10:39:53 +0100320 return 0;
321}
322
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200323static void intel_pmu_disable_all(void)
Thomas Gleixner4ac13292008-12-09 21:43:39 +0100324{
Ingo Molnar862a1a52008-12-17 13:09:20 +0100325 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
Thomas Gleixner4ac13292008-12-09 21:43:39 +0100326}
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530327
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200328static void amd_pmu_disable_all(void)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530329{
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100330 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200331 int idx;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100332
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200333 if (!cpuc->enabled)
334 return;
335
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100336 cpuc->enabled = 0;
Peter Zijlstra60b3df92009-03-13 12:21:30 +0100337 /*
338 * ensure we write the disable before we start disabling the
Robert Richter5f4ec282009-04-29 12:47:04 +0200339 * counters proper, so that amd_pmu_enable_counter() does the
340 * right thing.
Peter Zijlstra60b3df92009-03-13 12:21:30 +0100341 */
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100342 barrier();
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530343
Robert Richter0933e5c2009-04-29 12:47:12 +0200344 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100345 u64 val;
346
Robert Richter43f62012009-04-29 16:55:56 +0200347 if (!test_bit(idx, cpuc->active_mask))
Robert Richter4295ee62009-04-29 12:47:01 +0200348 continue;
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530349 rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
Robert Richter4295ee62009-04-29 12:47:01 +0200350 if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE))
351 continue;
352 val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
353 wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530354 }
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530355}
356
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200357void hw_perf_disable(void)
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530358{
Robert Richter85cf9db2009-04-29 12:47:20 +0200359 if (!x86_pmu_initialized())
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200360 return;
361 return x86_pmu.disable_all();
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530362}
Ingo Molnar241771e2008-12-03 10:39:53 +0100363
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200364static void intel_pmu_enable_all(void)
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530365{
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200366 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530367}
368
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200369static void amd_pmu_enable_all(void)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530370{
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100371 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530372 int idx;
373
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200374 if (cpuc->enabled)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100375 return;
376
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200377 cpuc->enabled = 1;
378 barrier();
379
Robert Richter0933e5c2009-04-29 12:47:12 +0200380 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
Robert Richter4295ee62009-04-29 12:47:01 +0200381 u64 val;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100382
Robert Richter43f62012009-04-29 16:55:56 +0200383 if (!test_bit(idx, cpuc->active_mask))
Robert Richter4295ee62009-04-29 12:47:01 +0200384 continue;
385 rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
386 if (val & ARCH_PERFMON_EVENTSEL0_ENABLE)
387 continue;
388 val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
389 wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530390 }
391}
392
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200393void hw_perf_enable(void)
Ingo Molnaree060942008-12-13 09:00:03 +0100394{
Robert Richter85cf9db2009-04-29 12:47:20 +0200395 if (!x86_pmu_initialized())
Ingo Molnar2b9ff0d2008-12-14 18:36:30 +0100396 return;
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200397 x86_pmu.enable_all();
Ingo Molnaree060942008-12-13 09:00:03 +0100398}
Ingo Molnaree060942008-12-13 09:00:03 +0100399
Robert Richter19d84da2009-04-29 12:47:25 +0200400static inline u64 intel_pmu_get_status(void)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100401{
402 u64 status;
403
404 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
405
406 return status;
407}
408
Robert Richterdee5d902009-04-29 12:47:07 +0200409static inline void intel_pmu_ack_status(u64 ack)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100410{
411 wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack);
412}
413
Robert Richter7c90cc42009-04-29 12:47:18 +0200414static inline void x86_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100415{
Robert Richter7c90cc42009-04-29 12:47:18 +0200416 int err;
Robert Richter7c90cc42009-04-29 12:47:18 +0200417 err = checking_wrmsrl(hwc->config_base + idx,
418 hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100419}
420
Robert Richterd4369892009-04-29 12:47:19 +0200421static inline void x86_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100422{
Robert Richterd4369892009-04-29 12:47:19 +0200423 int err;
Robert Richterd4369892009-04-29 12:47:19 +0200424 err = checking_wrmsrl(hwc->config_base + idx,
425 hwc->config);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100426}
427
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100428static inline void
Robert Richterd4369892009-04-29 12:47:19 +0200429intel_pmu_disable_fixed(struct hw_perf_counter *hwc, int __idx)
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100430{
431 int idx = __idx - X86_PMC_IDX_FIXED;
432 u64 ctrl_val, mask;
433 int err;
434
435 mask = 0xfULL << (idx * 4);
436
437 rdmsrl(hwc->config_base, ctrl_val);
438 ctrl_val &= ~mask;
439 err = checking_wrmsrl(hwc->config_base, ctrl_val);
440}
441
442static inline void
Robert Richterd4369892009-04-29 12:47:19 +0200443intel_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100444{
Robert Richterd4369892009-04-29 12:47:19 +0200445 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
446 intel_pmu_disable_fixed(hwc, idx);
447 return;
448 }
449
450 x86_pmu_disable_counter(hwc, idx);
451}
452
453static inline void
454amd_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
455{
456 x86_pmu_disable_counter(hwc, idx);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100457}
458
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100459static DEFINE_PER_CPU(u64, prev_left[X86_PMC_IDX_MAX]);
Ingo Molnar241771e2008-12-03 10:39:53 +0100460
Ingo Molnaree060942008-12-13 09:00:03 +0100461/*
462 * Set the next IRQ period, based on the hwc->period_left value.
463 * To be called with the counter disabled in hw:
464 */
465static void
Robert Richter26816c22009-04-29 12:47:08 +0200466x86_perf_counter_set_period(struct perf_counter *counter,
Ingo Molnaree060942008-12-13 09:00:03 +0100467 struct hw_perf_counter *hwc, int idx)
Ingo Molnar241771e2008-12-03 10:39:53 +0100468{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100469 s64 left = atomic64_read(&hwc->period_left);
Peter Zijlstra60db5e02009-05-15 15:19:28 +0200470 s64 period = min(x86_pmu.max_period, hwc->irq_period);
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100471 int err;
Ingo Molnar241771e2008-12-03 10:39:53 +0100472
Ingo Molnaree060942008-12-13 09:00:03 +0100473 /*
474 * If we are way outside a reasoable range then just skip forward:
475 */
476 if (unlikely(left <= -period)) {
477 left = period;
478 atomic64_set(&hwc->period_left, left);
479 }
480
481 if (unlikely(left <= 0)) {
482 left += period;
483 atomic64_set(&hwc->period_left, left);
484 }
Ingo Molnar1c80f4b2009-05-15 08:25:22 +0200485 /*
486 * Quirk: certain CPUs dont like it if just 1 event is left:
487 */
488 if (unlikely(left < 2))
489 left = 2;
Ingo Molnaree060942008-12-13 09:00:03 +0100490
Ingo Molnaree060942008-12-13 09:00:03 +0100491 per_cpu(prev_left[idx], smp_processor_id()) = left;
492
493 /*
494 * The hw counter starts counting from this counter offset,
495 * mark it to be able to extra future deltas:
496 */
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100497 atomic64_set(&hwc->prev_count, (u64)-left);
Ingo Molnaree060942008-12-13 09:00:03 +0100498
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100499 err = checking_wrmsrl(hwc->counter_base + idx,
Robert Richter0933e5c2009-04-29 12:47:12 +0200500 (u64)(-left) & x86_pmu.counter_mask);
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100501}
502
503static inline void
Robert Richter7c90cc42009-04-29 12:47:18 +0200504intel_pmu_enable_fixed(struct hw_perf_counter *hwc, int __idx)
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100505{
506 int idx = __idx - X86_PMC_IDX_FIXED;
507 u64 ctrl_val, bits, mask;
508 int err;
509
510 /*
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100511 * Enable IRQ generation (0x8),
512 * and enable ring-3 counting (0x2) and ring-0 counting (0x1)
513 * if requested:
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100514 */
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100515 bits = 0x8ULL;
516 if (hwc->config & ARCH_PERFMON_EVENTSEL_USR)
517 bits |= 0x2;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100518 if (hwc->config & ARCH_PERFMON_EVENTSEL_OS)
519 bits |= 0x1;
520 bits <<= (idx * 4);
521 mask = 0xfULL << (idx * 4);
522
523 rdmsrl(hwc->config_base, ctrl_val);
524 ctrl_val &= ~mask;
525 ctrl_val |= bits;
526 err = checking_wrmsrl(hwc->config_base, ctrl_val);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100527}
528
Robert Richter7c90cc42009-04-29 12:47:18 +0200529static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100530{
Robert Richter7c90cc42009-04-29 12:47:18 +0200531 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
532 intel_pmu_enable_fixed(hwc, idx);
533 return;
534 }
535
536 x86_pmu_enable_counter(hwc, idx);
537}
538
539static void amd_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
540{
541 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
542
543 if (cpuc->enabled)
544 x86_pmu_enable_counter(hwc, idx);
Jaswinder Singh Rajput2b583d82008-12-27 19:15:43 +0530545 else
Robert Richterd4369892009-04-29 12:47:19 +0200546 x86_pmu_disable_counter(hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100547}
548
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100549static int
550fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc)
Ingo Molnar862a1a52008-12-17 13:09:20 +0100551{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100552 unsigned int event;
553
Robert Richteref7b3e02009-04-29 12:47:24 +0200554 if (!x86_pmu.num_counters_fixed)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530555 return -1;
556
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100557 if (unlikely(hwc->nmi))
558 return -1;
559
560 event = hwc->config & ARCH_PERFMON_EVENT_MASK;
561
Robert Richter4a06bd82009-04-29 12:47:11 +0200562 if (unlikely(event == x86_pmu.event_map(PERF_COUNT_INSTRUCTIONS)))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100563 return X86_PMC_IDX_FIXED_INSTRUCTIONS;
Robert Richter4a06bd82009-04-29 12:47:11 +0200564 if (unlikely(event == x86_pmu.event_map(PERF_COUNT_CPU_CYCLES)))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100565 return X86_PMC_IDX_FIXED_CPU_CYCLES;
Robert Richter4a06bd82009-04-29 12:47:11 +0200566 if (unlikely(event == x86_pmu.event_map(PERF_COUNT_BUS_CYCLES)))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100567 return X86_PMC_IDX_FIXED_BUS_CYCLES;
568
Ingo Molnar862a1a52008-12-17 13:09:20 +0100569 return -1;
570}
571
Ingo Molnaree060942008-12-13 09:00:03 +0100572/*
573 * Find a PMC slot for the freshly enabled / scheduled in counter:
574 */
Robert Richter4aeb0b42009-04-29 12:47:03 +0200575static int x86_pmu_enable(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100576{
577 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
578 struct hw_perf_counter *hwc = &counter->hw;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100579 int idx;
Ingo Molnar241771e2008-12-03 10:39:53 +0100580
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100581 idx = fixed_mode_idx(counter, hwc);
582 if (idx >= 0) {
583 /*
584 * Try to get the fixed counter, if that is already taken
585 * then try to get a generic counter:
586 */
Robert Richter43f62012009-04-29 16:55:56 +0200587 if (test_and_set_bit(idx, cpuc->used_mask))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100588 goto try_generic;
Ingo Molnar0dff86a2008-12-23 12:28:12 +0100589
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100590 hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
591 /*
592 * We set it so that counter_base + idx in wrmsr/rdmsr maps to
593 * MSR_ARCH_PERFMON_FIXED_CTR0 ... CTR2:
594 */
595 hwc->counter_base =
596 MSR_ARCH_PERFMON_FIXED_CTR0 - X86_PMC_IDX_FIXED;
Ingo Molnar241771e2008-12-03 10:39:53 +0100597 hwc->idx = idx;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100598 } else {
599 idx = hwc->idx;
600 /* Try to get the previous generic counter again */
Robert Richter43f62012009-04-29 16:55:56 +0200601 if (test_and_set_bit(idx, cpuc->used_mask)) {
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100602try_generic:
Robert Richter43f62012009-04-29 16:55:56 +0200603 idx = find_first_zero_bit(cpuc->used_mask,
Robert Richter0933e5c2009-04-29 12:47:12 +0200604 x86_pmu.num_counters);
605 if (idx == x86_pmu.num_counters)
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100606 return -EAGAIN;
607
Robert Richter43f62012009-04-29 16:55:56 +0200608 set_bit(idx, cpuc->used_mask);
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100609 hwc->idx = idx;
610 }
Robert Richter4a06bd82009-04-29 12:47:11 +0200611 hwc->config_base = x86_pmu.eventsel;
612 hwc->counter_base = x86_pmu.perfctr;
Ingo Molnar241771e2008-12-03 10:39:53 +0100613 }
614
Robert Richterd4369892009-04-29 12:47:19 +0200615 x86_pmu.disable(hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100616
Ingo Molnar862a1a52008-12-17 13:09:20 +0100617 cpuc->counters[idx] = counter;
Robert Richter43f62012009-04-29 16:55:56 +0200618 set_bit(idx, cpuc->active_mask);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100619
Robert Richter26816c22009-04-29 12:47:08 +0200620 x86_perf_counter_set_period(counter, hwc, idx);
Robert Richter7c90cc42009-04-29 12:47:18 +0200621 x86_pmu.enable(hwc, idx);
Ingo Molnar95cdd2e2008-12-21 13:50:42 +0100622
623 return 0;
Ingo Molnar241771e2008-12-03 10:39:53 +0100624}
625
626void perf_counter_print_debug(void)
627{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100628 u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed;
Ingo Molnar0dff86a2008-12-23 12:28:12 +0100629 struct cpu_hw_counters *cpuc;
Peter Zijlstra5bb9efe2009-05-13 08:12:51 +0200630 unsigned long flags;
Ingo Molnar1e125672008-12-09 12:18:18 +0100631 int cpu, idx;
632
Robert Richter0933e5c2009-04-29 12:47:12 +0200633 if (!x86_pmu.num_counters)
Ingo Molnar1e125672008-12-09 12:18:18 +0100634 return;
Ingo Molnar241771e2008-12-03 10:39:53 +0100635
Peter Zijlstra5bb9efe2009-05-13 08:12:51 +0200636 local_irq_save(flags);
Ingo Molnar241771e2008-12-03 10:39:53 +0100637
638 cpu = smp_processor_id();
Ingo Molnar0dff86a2008-12-23 12:28:12 +0100639 cpuc = &per_cpu(cpu_hw_counters, cpu);
Ingo Molnar241771e2008-12-03 10:39:53 +0100640
Robert Richterfaa28ae2009-04-29 12:47:13 +0200641 if (x86_pmu.version >= 2) {
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530642 rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
643 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
644 rdmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
645 rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
Ingo Molnar241771e2008-12-03 10:39:53 +0100646
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530647 pr_info("\n");
648 pr_info("CPU#%d: ctrl: %016llx\n", cpu, ctrl);
649 pr_info("CPU#%d: status: %016llx\n", cpu, status);
650 pr_info("CPU#%d: overflow: %016llx\n", cpu, overflow);
651 pr_info("CPU#%d: fixed: %016llx\n", cpu, fixed);
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530652 }
Robert Richter43f62012009-04-29 16:55:56 +0200653 pr_info("CPU#%d: used: %016llx\n", cpu, *(u64 *)cpuc->used_mask);
Ingo Molnar241771e2008-12-03 10:39:53 +0100654
Robert Richter0933e5c2009-04-29 12:47:12 +0200655 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
Robert Richter4a06bd82009-04-29 12:47:11 +0200656 rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl);
657 rdmsrl(x86_pmu.perfctr + idx, pmc_count);
Ingo Molnar241771e2008-12-03 10:39:53 +0100658
Ingo Molnaree060942008-12-13 09:00:03 +0100659 prev_left = per_cpu(prev_left[idx], cpu);
Ingo Molnar241771e2008-12-03 10:39:53 +0100660
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530661 pr_info("CPU#%d: gen-PMC%d ctrl: %016llx\n",
Ingo Molnar241771e2008-12-03 10:39:53 +0100662 cpu, idx, pmc_ctrl);
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530663 pr_info("CPU#%d: gen-PMC%d count: %016llx\n",
Ingo Molnar241771e2008-12-03 10:39:53 +0100664 cpu, idx, pmc_count);
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530665 pr_info("CPU#%d: gen-PMC%d left: %016llx\n",
Ingo Molnaree060942008-12-13 09:00:03 +0100666 cpu, idx, prev_left);
Ingo Molnar241771e2008-12-03 10:39:53 +0100667 }
Robert Richter0933e5c2009-04-29 12:47:12 +0200668 for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) {
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100669 rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, pmc_count);
670
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530671 pr_info("CPU#%d: fixed-PMC%d count: %016llx\n",
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100672 cpu, idx, pmc_count);
673 }
Peter Zijlstra5bb9efe2009-05-13 08:12:51 +0200674 local_irq_restore(flags);
Ingo Molnar241771e2008-12-03 10:39:53 +0100675}
676
Robert Richter4aeb0b42009-04-29 12:47:03 +0200677static void x86_pmu_disable(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100678{
679 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
680 struct hw_perf_counter *hwc = &counter->hw;
Robert Richter6f00cad2009-04-29 12:47:17 +0200681 int idx = hwc->idx;
Ingo Molnar241771e2008-12-03 10:39:53 +0100682
Robert Richter09534232009-04-29 12:47:16 +0200683 /*
684 * Must be done before we disable, otherwise the nmi handler
685 * could reenable again:
686 */
Robert Richter43f62012009-04-29 16:55:56 +0200687 clear_bit(idx, cpuc->active_mask);
Robert Richterd4369892009-04-29 12:47:19 +0200688 x86_pmu.disable(hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100689
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100690 /*
691 * Make sure the cleared pointer becomes visible before we
692 * (potentially) free the counter:
693 */
Robert Richter527e26a2009-04-29 12:47:02 +0200694 barrier();
Ingo Molnar241771e2008-12-03 10:39:53 +0100695
Ingo Molnaree060942008-12-13 09:00:03 +0100696 /*
697 * Drain the remaining delta count out of a counter
698 * that we are disabling:
699 */
700 x86_perf_counter_update(counter, hwc, idx);
Robert Richter09534232009-04-29 12:47:16 +0200701 cpuc->counters[idx] = NULL;
Robert Richter43f62012009-04-29 16:55:56 +0200702 clear_bit(idx, cpuc->used_mask);
Ingo Molnar241771e2008-12-03 10:39:53 +0100703}
704
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100705/*
Ingo Molnaree060942008-12-13 09:00:03 +0100706 * Save and restart an expired counter. Called by NMI contexts,
707 * so it has to be careful about preempting normal counter ops:
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100708 */
Robert Richter55de0f22009-04-29 12:47:09 +0200709static void intel_pmu_save_and_restart(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100710{
711 struct hw_perf_counter *hwc = &counter->hw;
712 int idx = hwc->idx;
Ingo Molnar241771e2008-12-03 10:39:53 +0100713
Ingo Molnaree060942008-12-13 09:00:03 +0100714 x86_perf_counter_update(counter, hwc, idx);
Robert Richter26816c22009-04-29 12:47:08 +0200715 x86_perf_counter_set_period(counter, hwc, idx);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100716
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100717 if (counter->state == PERF_COUNTER_STATE_ACTIVE)
Robert Richter7c90cc42009-04-29 12:47:18 +0200718 intel_pmu_enable_counter(hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100719}
720
Ingo Molnar241771e2008-12-03 10:39:53 +0100721/*
722 * This handler is triggered by the local APIC, so the APIC IRQ handling
723 * rules apply:
724 */
Robert Richter39d81ea2009-04-29 12:47:05 +0200725static int intel_pmu_handle_irq(struct pt_regs *regs, int nmi)
Ingo Molnar241771e2008-12-03 10:39:53 +0100726{
Ingo Molnar9029a5e2009-05-15 08:26:20 +0200727 struct cpu_hw_counters *cpuc;
728 struct cpu_hw_counters;
729 int bit, cpu, loops;
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100730 u64 ack, status;
Ingo Molnar9029a5e2009-05-15 08:26:20 +0200731
732 cpu = smp_processor_id();
733 cpuc = &per_cpu(cpu_hw_counters, cpu);
Ingo Molnar43874d22008-12-09 12:23:59 +0100734
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200735 perf_disable();
Robert Richter19d84da2009-04-29 12:47:25 +0200736 status = intel_pmu_get_status();
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200737 if (!status) {
738 perf_enable();
739 return 0;
740 }
Ingo Molnar87b9cf42008-12-08 14:20:16 +0100741
Ingo Molnar9029a5e2009-05-15 08:26:20 +0200742 loops = 0;
Ingo Molnar241771e2008-12-03 10:39:53 +0100743again:
Ingo Molnar9029a5e2009-05-15 08:26:20 +0200744 if (++loops > 100) {
745 WARN_ONCE(1, "perfcounters: irq loop stuck!\n");
Ingo Molnar34adc802009-05-20 20:13:28 +0200746 perf_counter_print_debug();
Ingo Molnar9029a5e2009-05-15 08:26:20 +0200747 return 1;
748 }
749
Mike Galbraithd278c482009-02-09 07:38:50 +0100750 inc_irq_stat(apic_perf_irqs);
Ingo Molnar241771e2008-12-03 10:39:53 +0100751 ack = status;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100752 for_each_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
Ingo Molnar862a1a52008-12-17 13:09:20 +0100753 struct perf_counter *counter = cpuc->counters[bit];
Ingo Molnar241771e2008-12-03 10:39:53 +0100754
755 clear_bit(bit, (unsigned long *) &status);
Robert Richter43f62012009-04-29 16:55:56 +0200756 if (!test_bit(bit, cpuc->active_mask))
Ingo Molnar241771e2008-12-03 10:39:53 +0100757 continue;
758
Robert Richter55de0f22009-04-29 12:47:09 +0200759 intel_pmu_save_and_restart(counter);
Peter Zijlstra78f13e92009-04-08 15:01:33 +0200760 if (perf_counter_overflow(counter, nmi, regs, 0))
Robert Richterd4369892009-04-29 12:47:19 +0200761 intel_pmu_disable_counter(&counter->hw, bit);
Ingo Molnar241771e2008-12-03 10:39:53 +0100762 }
763
Robert Richterdee5d902009-04-29 12:47:07 +0200764 intel_pmu_ack_status(ack);
Ingo Molnar241771e2008-12-03 10:39:53 +0100765
766 /*
767 * Repeat if there is more work to be done:
768 */
Robert Richter19d84da2009-04-29 12:47:25 +0200769 status = intel_pmu_get_status();
Ingo Molnar241771e2008-12-03 10:39:53 +0100770 if (status)
771 goto again;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100772
Peter Zijlstra48e22d52009-05-25 17:39:04 +0200773 perf_enable();
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200774
775 return 1;
Mike Galbraith1b023a92009-01-23 10:13:01 +0100776}
777
Robert Richtera29aa8a2009-04-29 12:47:21 +0200778static int amd_pmu_handle_irq(struct pt_regs *regs, int nmi)
779{
Peter Zijlstra48e22d52009-05-25 17:39:04 +0200780 int cpu, idx, handled = 0;
Ingo Molnar9029a5e2009-05-15 08:26:20 +0200781 struct cpu_hw_counters *cpuc;
Robert Richtera29aa8a2009-04-29 12:47:21 +0200782 struct perf_counter *counter;
783 struct hw_perf_counter *hwc;
Ingo Molnar9029a5e2009-05-15 08:26:20 +0200784 u64 val;
785
786 cpu = smp_processor_id();
787 cpuc = &per_cpu(cpu_hw_counters, cpu);
Robert Richtera29aa8a2009-04-29 12:47:21 +0200788
Robert Richtera29aa8a2009-04-29 12:47:21 +0200789 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
Robert Richter43f62012009-04-29 16:55:56 +0200790 if (!test_bit(idx, cpuc->active_mask))
Robert Richtera29aa8a2009-04-29 12:47:21 +0200791 continue;
Peter Zijlstra962bf7a2009-05-13 13:21:36 +0200792
Robert Richtera29aa8a2009-04-29 12:47:21 +0200793 counter = cpuc->counters[idx];
794 hwc = &counter->hw;
Peter Zijlstraa4016a72009-05-14 14:52:17 +0200795
796 if (counter->hw_event.nmi != nmi)
Peter Zijlstra48e22d52009-05-25 17:39:04 +0200797 continue;
Peter Zijlstraa4016a72009-05-14 14:52:17 +0200798
Robert Richter4b7bfd02009-04-29 12:47:22 +0200799 val = x86_perf_counter_update(counter, hwc, idx);
Robert Richtera29aa8a2009-04-29 12:47:21 +0200800 if (val & (1ULL << (x86_pmu.counter_bits - 1)))
Peter Zijlstra48e22d52009-05-25 17:39:04 +0200801 continue;
Peter Zijlstra962bf7a2009-05-13 13:21:36 +0200802
Robert Richtera29aa8a2009-04-29 12:47:21 +0200803 /* counter overflow */
804 x86_perf_counter_set_period(counter, hwc, idx);
805 handled = 1;
806 inc_irq_stat(apic_perf_irqs);
Peter Zijlstra48e22d52009-05-25 17:39:04 +0200807 if (perf_counter_overflow(counter, nmi, regs, 0))
Robert Richtera29aa8a2009-04-29 12:47:21 +0200808 amd_pmu_disable_counter(hwc, idx);
Robert Richtera29aa8a2009-04-29 12:47:21 +0200809 }
Peter Zijlstra962bf7a2009-05-13 13:21:36 +0200810
Robert Richtera29aa8a2009-04-29 12:47:21 +0200811 return handled;
812}
Robert Richter39d81ea2009-04-29 12:47:05 +0200813
Ingo Molnar241771e2008-12-03 10:39:53 +0100814void smp_perf_counter_interrupt(struct pt_regs *regs)
815{
816 irq_enter();
Ingo Molnar241771e2008-12-03 10:39:53 +0100817 apic_write(APIC_LVTPC, LOCAL_PERF_VECTOR);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100818 ack_APIC_irq();
Robert Richter4a06bd82009-04-29 12:47:11 +0200819 x86_pmu.handle_irq(regs, 0);
Ingo Molnar241771e2008-12-03 10:39:53 +0100820 irq_exit();
821}
822
Peter Zijlstrab6276f32009-04-06 11:45:03 +0200823void smp_perf_pending_interrupt(struct pt_regs *regs)
824{
825 irq_enter();
826 ack_APIC_irq();
827 inc_irq_stat(apic_pending_irqs);
828 perf_counter_do_pending();
829 irq_exit();
830}
831
832void set_perf_counter_pending(void)
833{
834 apic->send_IPI_self(LOCAL_PENDING_VECTOR);
835}
836
Mike Galbraith3415dd92009-01-23 14:16:53 +0100837void perf_counters_lapic_init(int nmi)
Ingo Molnar241771e2008-12-03 10:39:53 +0100838{
839 u32 apic_val;
840
Robert Richter85cf9db2009-04-29 12:47:20 +0200841 if (!x86_pmu_initialized())
Ingo Molnar241771e2008-12-03 10:39:53 +0100842 return;
Robert Richter85cf9db2009-04-29 12:47:20 +0200843
Ingo Molnar241771e2008-12-03 10:39:53 +0100844 /*
845 * Enable the performance counter vector in the APIC LVT:
846 */
847 apic_val = apic_read(APIC_LVTERR);
848
849 apic_write(APIC_LVTERR, apic_val | APIC_LVT_MASKED);
850 if (nmi)
851 apic_write(APIC_LVTPC, APIC_DM_NMI);
852 else
853 apic_write(APIC_LVTPC, LOCAL_PERF_VECTOR);
854 apic_write(APIC_LVTERR, apic_val);
855}
856
857static int __kprobes
858perf_counter_nmi_handler(struct notifier_block *self,
859 unsigned long cmd, void *__args)
860{
861 struct die_args *args = __args;
862 struct pt_regs *regs;
863
Peter Zijlstraba778132009-05-04 18:47:44 +0200864 if (!atomic_read(&active_counters))
Peter Zijlstra63a809a2009-05-01 12:23:17 +0200865 return NOTIFY_DONE;
866
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100867 switch (cmd) {
868 case DIE_NMI:
869 case DIE_NMI_IPI:
870 break;
871
872 default:
Ingo Molnar241771e2008-12-03 10:39:53 +0100873 return NOTIFY_DONE;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100874 }
Ingo Molnar241771e2008-12-03 10:39:53 +0100875
876 regs = args->regs;
877
878 apic_write(APIC_LVTPC, APIC_DM_NMI);
Peter Zijlstraa4016a72009-05-14 14:52:17 +0200879 /*
880 * Can't rely on the handled return value to say it was our NMI, two
881 * counters could trigger 'simultaneously' raising two back-to-back NMIs.
882 *
883 * If the first NMI handles both, the latter will be empty and daze
884 * the CPU.
885 */
886 x86_pmu.handle_irq(regs, 1);
Ingo Molnar241771e2008-12-03 10:39:53 +0100887
Peter Zijlstraa4016a72009-05-14 14:52:17 +0200888 return NOTIFY_STOP;
Ingo Molnar241771e2008-12-03 10:39:53 +0100889}
890
891static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
Mike Galbraith5b75af02009-02-04 17:11:34 +0100892 .notifier_call = perf_counter_nmi_handler,
893 .next = NULL,
894 .priority = 1
Ingo Molnar241771e2008-12-03 10:39:53 +0100895};
896
Robert Richter5f4ec282009-04-29 12:47:04 +0200897static struct x86_pmu intel_pmu = {
Robert Richterfaa28ae2009-04-29 12:47:13 +0200898 .name = "Intel",
Robert Richter39d81ea2009-04-29 12:47:05 +0200899 .handle_irq = intel_pmu_handle_irq,
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200900 .disable_all = intel_pmu_disable_all,
901 .enable_all = intel_pmu_enable_all,
Robert Richter5f4ec282009-04-29 12:47:04 +0200902 .enable = intel_pmu_enable_counter,
903 .disable = intel_pmu_disable_counter,
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530904 .eventsel = MSR_ARCH_PERFMON_EVENTSEL0,
905 .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
Robert Richter5f4ec282009-04-29 12:47:04 +0200906 .event_map = intel_pmu_event_map,
907 .raw_event = intel_pmu_raw_event,
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530908 .max_events = ARRAY_SIZE(intel_perfmon_event_map),
Robert Richterc619b8f2009-04-29 12:47:23 +0200909 /*
910 * Intel PMCs cannot be accessed sanely above 32 bit width,
911 * so we install an artificial 1<<31 period regardless of
912 * the generic counter period:
913 */
914 .max_period = (1ULL << 31) - 1,
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530915};
916
Robert Richter5f4ec282009-04-29 12:47:04 +0200917static struct x86_pmu amd_pmu = {
Robert Richterfaa28ae2009-04-29 12:47:13 +0200918 .name = "AMD",
Robert Richter39d81ea2009-04-29 12:47:05 +0200919 .handle_irq = amd_pmu_handle_irq,
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200920 .disable_all = amd_pmu_disable_all,
921 .enable_all = amd_pmu_enable_all,
Robert Richter5f4ec282009-04-29 12:47:04 +0200922 .enable = amd_pmu_enable_counter,
923 .disable = amd_pmu_disable_counter,
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530924 .eventsel = MSR_K7_EVNTSEL0,
925 .perfctr = MSR_K7_PERFCTR0,
Robert Richter5f4ec282009-04-29 12:47:04 +0200926 .event_map = amd_pmu_event_map,
927 .raw_event = amd_pmu_raw_event,
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530928 .max_events = ARRAY_SIZE(amd_perfmon_event_map),
Robert Richter0933e5c2009-04-29 12:47:12 +0200929 .num_counters = 4,
930 .counter_bits = 48,
931 .counter_mask = (1ULL << 48) - 1,
Robert Richterc619b8f2009-04-29 12:47:23 +0200932 /* use highest bit to detect overflow */
933 .max_period = (1ULL << 47) - 1,
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530934};
935
Robert Richter72eae042009-04-29 12:47:10 +0200936static int intel_pmu_init(void)
Ingo Molnar241771e2008-12-03 10:39:53 +0100937{
Ingo Molnar703e9372008-12-17 10:51:15 +0100938 union cpuid10_edx edx;
Ingo Molnar7bb497b2009-03-18 08:59:21 +0100939 union cpuid10_eax eax;
940 unsigned int unused;
941 unsigned int ebx;
Robert Richterfaa28ae2009-04-29 12:47:13 +0200942 int version;
Ingo Molnar241771e2008-12-03 10:39:53 +0100943
Robert Richterda1a7762009-04-29 12:46:58 +0200944 if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
Robert Richter72eae042009-04-29 12:47:10 +0200945 return -ENODEV;
Robert Richterda1a7762009-04-29 12:46:58 +0200946
Ingo Molnar241771e2008-12-03 10:39:53 +0100947 /*
948 * Check whether the Architectural PerfMon supports
949 * Branch Misses Retired Event or not.
950 */
Ingo Molnar703e9372008-12-17 10:51:15 +0100951 cpuid(10, &eax.full, &ebx, &unused, &edx.full);
Ingo Molnar241771e2008-12-03 10:39:53 +0100952 if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED)
Robert Richter72eae042009-04-29 12:47:10 +0200953 return -ENODEV;
Ingo Molnar241771e2008-12-03 10:39:53 +0100954
Robert Richterfaa28ae2009-04-29 12:47:13 +0200955 version = eax.split.version_id;
956 if (version < 2)
Robert Richter72eae042009-04-29 12:47:10 +0200957 return -ENODEV;
Ingo Molnar7bb497b2009-03-18 08:59:21 +0100958
Robert Richter4a06bd82009-04-29 12:47:11 +0200959 x86_pmu = intel_pmu;
Robert Richterfaa28ae2009-04-29 12:47:13 +0200960 x86_pmu.version = version;
Robert Richter0933e5c2009-04-29 12:47:12 +0200961 x86_pmu.num_counters = eax.split.num_counters;
Ingo Molnar066d7de2009-05-04 19:04:09 +0200962
963 /*
964 * Quirk: v2 perfmon does not report fixed-purpose counters, so
965 * assume at least 3 counters:
966 */
967 x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3);
968
Robert Richter0933e5c2009-04-29 12:47:12 +0200969 x86_pmu.counter_bits = eax.split.bit_width;
970 x86_pmu.counter_mask = (1ULL << eax.split.bit_width) - 1;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530971
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200972 rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
973
Robert Richter72eae042009-04-29 12:47:10 +0200974 return 0;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530975}
976
Robert Richter72eae042009-04-29 12:47:10 +0200977static int amd_pmu_init(void)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530978{
Robert Richter4a06bd82009-04-29 12:47:11 +0200979 x86_pmu = amd_pmu;
Robert Richter72eae042009-04-29 12:47:10 +0200980 return 0;
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530981}
982
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530983void __init init_hw_perf_counters(void)
984{
Robert Richter72eae042009-04-29 12:47:10 +0200985 int err;
986
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530987 switch (boot_cpu_data.x86_vendor) {
988 case X86_VENDOR_INTEL:
Robert Richter72eae042009-04-29 12:47:10 +0200989 err = intel_pmu_init();
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530990 break;
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530991 case X86_VENDOR_AMD:
Robert Richter72eae042009-04-29 12:47:10 +0200992 err = amd_pmu_init();
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530993 break;
Robert Richter41389602009-04-29 12:47:00 +0200994 default:
995 return;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530996 }
Robert Richter72eae042009-04-29 12:47:10 +0200997 if (err != 0)
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530998 return;
999
Robert Richterfaa28ae2009-04-29 12:47:13 +02001000 pr_info("%s Performance Monitoring support detected.\n", x86_pmu.name);
1001 pr_info("... version: %d\n", x86_pmu.version);
1002 pr_info("... bit width: %d\n", x86_pmu.counter_bits);
1003
Robert Richter0933e5c2009-04-29 12:47:12 +02001004 pr_info("... num counters: %d\n", x86_pmu.num_counters);
1005 if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) {
1006 x86_pmu.num_counters = X86_PMC_MAX_GENERIC;
Ingo Molnar241771e2008-12-03 10:39:53 +01001007 WARN(1, KERN_ERR "hw perf counters %d > max(%d), clipping!",
Robert Richter0933e5c2009-04-29 12:47:12 +02001008 x86_pmu.num_counters, X86_PMC_MAX_GENERIC);
Ingo Molnar241771e2008-12-03 10:39:53 +01001009 }
Robert Richter0933e5c2009-04-29 12:47:12 +02001010 perf_counter_mask = (1 << x86_pmu.num_counters) - 1;
1011 perf_max_counters = x86_pmu.num_counters;
Ingo Molnar241771e2008-12-03 10:39:53 +01001012
Robert Richter0933e5c2009-04-29 12:47:12 +02001013 pr_info("... value mask: %016Lx\n", x86_pmu.counter_mask);
Robert Richterc619b8f2009-04-29 12:47:23 +02001014 pr_info("... max period: %016Lx\n", x86_pmu.max_period);
Ingo Molnar2f18d1e2008-12-22 11:10:42 +01001015
Robert Richter0933e5c2009-04-29 12:47:12 +02001016 if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) {
1017 x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED;
Ingo Molnar703e9372008-12-17 10:51:15 +01001018 WARN(1, KERN_ERR "hw perf counters fixed %d > max(%d), clipping!",
Robert Richter0933e5c2009-04-29 12:47:12 +02001019 x86_pmu.num_counters_fixed, X86_PMC_MAX_FIXED);
Ingo Molnar703e9372008-12-17 10:51:15 +01001020 }
Robert Richter0933e5c2009-04-29 12:47:12 +02001021 pr_info("... fixed counters: %d\n", x86_pmu.num_counters_fixed);
Ingo Molnar241771e2008-12-03 10:39:53 +01001022
Robert Richter0933e5c2009-04-29 12:47:12 +02001023 perf_counter_mask |=
1024 ((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED;
Ingo Molnar862a1a52008-12-17 13:09:20 +01001025
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +05301026 pr_info("... counter mask: %016Lx\n", perf_counter_mask);
Ingo Molnar75f224c2008-12-14 21:58:46 +01001027
Ingo Molnarb68f1d22009-05-17 19:37:25 +02001028 perf_counters_lapic_init(1);
Ingo Molnar241771e2008-12-03 10:39:53 +01001029 register_die_notifier(&perf_counter_nmi_notifier);
Ingo Molnar241771e2008-12-03 10:39:53 +01001030}
Ingo Molnar621a01e2008-12-11 12:46:46 +01001031
Robert Richterbb775fc2009-04-29 12:47:14 +02001032static inline void x86_pmu_read(struct perf_counter *counter)
Ingo Molnaree060942008-12-13 09:00:03 +01001033{
1034 x86_perf_counter_update(counter, &counter->hw, counter->hw.idx);
1035}
1036
Robert Richter4aeb0b42009-04-29 12:47:03 +02001037static const struct pmu pmu = {
1038 .enable = x86_pmu_enable,
1039 .disable = x86_pmu_disable,
1040 .read = x86_pmu_read,
Ingo Molnar621a01e2008-12-11 12:46:46 +01001041};
1042
Robert Richter4aeb0b42009-04-29 12:47:03 +02001043const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
Ingo Molnar621a01e2008-12-11 12:46:46 +01001044{
1045 int err;
1046
1047 err = __hw_perf_counter_init(counter);
1048 if (err)
Peter Zijlstra9ea98e12009-03-30 19:07:09 +02001049 return ERR_PTR(err);
Ingo Molnar621a01e2008-12-11 12:46:46 +01001050
Robert Richter4aeb0b42009-04-29 12:47:03 +02001051 return &pmu;
Ingo Molnar621a01e2008-12-11 12:46:46 +01001052}
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001053
1054/*
1055 * callchain support
1056 */
1057
1058static inline
1059void callchain_store(struct perf_callchain_entry *entry, unsigned long ip)
1060{
1061 if (entry->nr < MAX_STACK_DEPTH)
1062 entry->ip[entry->nr++] = ip;
1063}
1064
1065static DEFINE_PER_CPU(struct perf_callchain_entry, irq_entry);
1066static DEFINE_PER_CPU(struct perf_callchain_entry, nmi_entry);
1067
1068
1069static void
1070backtrace_warning_symbol(void *data, char *msg, unsigned long symbol)
1071{
1072 /* Ignore warnings */
1073}
1074
1075static void backtrace_warning(void *data, char *msg)
1076{
1077 /* Ignore warnings */
1078}
1079
1080static int backtrace_stack(void *data, char *name)
1081{
1082 /* Don't bother with IRQ stacks for now */
1083 return -1;
1084}
1085
1086static void backtrace_address(void *data, unsigned long addr, int reliable)
1087{
1088 struct perf_callchain_entry *entry = data;
1089
1090 if (reliable)
1091 callchain_store(entry, addr);
1092}
1093
1094static const struct stacktrace_ops backtrace_ops = {
1095 .warning = backtrace_warning,
1096 .warning_symbol = backtrace_warning_symbol,
1097 .stack = backtrace_stack,
1098 .address = backtrace_address,
1099};
1100
1101static void
1102perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)
1103{
1104 unsigned long bp;
1105 char *stack;
Peter Zijlstra5872bdb82009-04-02 11:12:03 +02001106 int nr = entry->nr;
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001107
1108 callchain_store(entry, instruction_pointer(regs));
1109
1110 stack = ((char *)regs + sizeof(struct pt_regs));
1111#ifdef CONFIG_FRAME_POINTER
1112 bp = frame_pointer(regs);
1113#else
1114 bp = 0;
1115#endif
1116
1117 dump_trace(NULL, regs, (void *)stack, bp, &backtrace_ops, entry);
Peter Zijlstra5872bdb82009-04-02 11:12:03 +02001118
1119 entry->kernel = entry->nr - nr;
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001120}
1121
1122
1123struct stack_frame {
1124 const void __user *next_fp;
1125 unsigned long return_address;
1126};
1127
1128static int copy_stack_frame(const void __user *fp, struct stack_frame *frame)
1129{
1130 int ret;
1131
1132 if (!access_ok(VERIFY_READ, fp, sizeof(*frame)))
1133 return 0;
1134
1135 ret = 1;
1136 pagefault_disable();
1137 if (__copy_from_user_inatomic(frame, fp, sizeof(*frame)))
1138 ret = 0;
1139 pagefault_enable();
1140
1141 return ret;
1142}
1143
1144static void
1145perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry)
1146{
1147 struct stack_frame frame;
1148 const void __user *fp;
Peter Zijlstra5872bdb82009-04-02 11:12:03 +02001149 int nr = entry->nr;
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001150
1151 regs = (struct pt_regs *)current->thread.sp0 - 1;
1152 fp = (void __user *)regs->bp;
1153
1154 callchain_store(entry, regs->ip);
1155
1156 while (entry->nr < MAX_STACK_DEPTH) {
1157 frame.next_fp = NULL;
1158 frame.return_address = 0;
1159
1160 if (!copy_stack_frame(fp, &frame))
1161 break;
1162
1163 if ((unsigned long)fp < user_stack_pointer(regs))
1164 break;
1165
1166 callchain_store(entry, frame.return_address);
1167 fp = frame.next_fp;
1168 }
Peter Zijlstra5872bdb82009-04-02 11:12:03 +02001169
1170 entry->user = entry->nr - nr;
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001171}
1172
1173static void
1174perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
1175{
1176 int is_user;
1177
1178 if (!regs)
1179 return;
1180
1181 is_user = user_mode(regs);
1182
1183 if (!current || current->pid == 0)
1184 return;
1185
1186 if (is_user && current->state != TASK_RUNNING)
1187 return;
1188
1189 if (!is_user)
1190 perf_callchain_kernel(regs, entry);
1191
1192 if (current->mm)
1193 perf_callchain_user(regs, entry);
1194}
1195
1196struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
1197{
1198 struct perf_callchain_entry *entry;
1199
1200 if (in_nmi())
1201 entry = &__get_cpu_var(nmi_entry);
1202 else
1203 entry = &__get_cpu_var(irq_entry);
1204
1205 entry->nr = 0;
Peter Zijlstra5872bdb82009-04-02 11:12:03 +02001206 entry->hv = 0;
1207 entry->kernel = 0;
1208 entry->user = 0;
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001209
1210 perf_do_callchain(regs, entry);
1211
1212 return entry;
1213}