blob: 1dcf67057f161162448c3d8b8f235cb6df58d4c5 [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
90#define CORE_EVNTSEL_COUNTER_MASK 0xFF000000ULL
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010091
92#define CORE_EVNTSEL_MASK \
93 (CORE_EVNTSEL_EVENT_MASK | \
94 CORE_EVNTSEL_UNIT_MASK | \
95 CORE_EVNTSEL_COUNTER_MASK)
96
97 return event & CORE_EVNTSEL_MASK;
98}
99
Ingo Molnar241771e2008-12-03 10:39:53 +0100100/*
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530101 * AMD Performance Monitor K7 and later.
102 */
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100103static const u64 amd_perfmon_event_map[] =
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530104{
105 [PERF_COUNT_CPU_CYCLES] = 0x0076,
106 [PERF_COUNT_INSTRUCTIONS] = 0x00c0,
107 [PERF_COUNT_CACHE_REFERENCES] = 0x0080,
108 [PERF_COUNT_CACHE_MISSES] = 0x0081,
109 [PERF_COUNT_BRANCH_INSTRUCTIONS] = 0x00c4,
110 [PERF_COUNT_BRANCH_MISSES] = 0x00c5,
111};
112
Robert Richter5f4ec282009-04-29 12:47:04 +0200113static u64 amd_pmu_event_map(int event)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530114{
115 return amd_perfmon_event_map[event];
116}
117
Robert Richter5f4ec282009-04-29 12:47:04 +0200118static u64 amd_pmu_raw_event(u64 event)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100119{
Peter Zijlstra82bae4f82009-03-13 12:21:31 +0100120#define K7_EVNTSEL_EVENT_MASK 0x7000000FFULL
121#define K7_EVNTSEL_UNIT_MASK 0x00000FF00ULL
122#define K7_EVNTSEL_COUNTER_MASK 0x0FF000000ULL
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100123
124#define K7_EVNTSEL_MASK \
125 (K7_EVNTSEL_EVENT_MASK | \
126 K7_EVNTSEL_UNIT_MASK | \
127 K7_EVNTSEL_COUNTER_MASK)
128
129 return event & K7_EVNTSEL_MASK;
130}
131
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530132/*
Ingo Molnaree060942008-12-13 09:00:03 +0100133 * Propagate counter elapsed time into the generic counter.
134 * Can only be executed on the CPU where the counter is active.
135 * Returns the delta events processed.
136 */
Robert Richter4b7bfd02009-04-29 12:47:22 +0200137static u64
Ingo Molnaree060942008-12-13 09:00:03 +0100138x86_perf_counter_update(struct perf_counter *counter,
139 struct hw_perf_counter *hwc, int idx)
140{
Peter Zijlstraec3232b2009-05-13 09:45:19 +0200141 int shift = 64 - x86_pmu.counter_bits;
142 u64 prev_raw_count, new_raw_count;
143 s64 delta;
Ingo Molnaree060942008-12-13 09:00:03 +0100144
Ingo Molnaree060942008-12-13 09:00:03 +0100145 /*
146 * Careful: an NMI might modify the previous counter value.
147 *
148 * Our tactic to handle this is to first atomically read and
149 * exchange a new raw count - then add that new-prev delta
150 * count to the generic counter atomically:
151 */
152again:
153 prev_raw_count = atomic64_read(&hwc->prev_count);
154 rdmsrl(hwc->counter_base + idx, new_raw_count);
155
156 if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
157 new_raw_count) != prev_raw_count)
158 goto again;
159
160 /*
161 * Now we have the new raw value and have updated the prev
162 * timestamp already. We can now calculate the elapsed delta
163 * (counter-)time and add that to the generic counter.
164 *
165 * Careful, not all hw sign-extends above the physical width
Peter Zijlstraec3232b2009-05-13 09:45:19 +0200166 * of the count.
Ingo Molnaree060942008-12-13 09:00:03 +0100167 */
Peter Zijlstraec3232b2009-05-13 09:45:19 +0200168 delta = (new_raw_count << shift) - (prev_raw_count << shift);
169 delta >>= shift;
Ingo Molnaree060942008-12-13 09:00:03 +0100170
171 atomic64_add(delta, &counter->count);
172 atomic64_sub(delta, &hwc->period_left);
Robert Richter4b7bfd02009-04-29 12:47:22 +0200173
174 return new_raw_count;
Ingo Molnaree060942008-12-13 09:00:03 +0100175}
176
Peter Zijlstraba778132009-05-04 18:47:44 +0200177static atomic_t active_counters;
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200178static DEFINE_MUTEX(pmc_reserve_mutex);
179
180static bool reserve_pmc_hardware(void)
181{
182 int i;
183
184 if (nmi_watchdog == NMI_LOCAL_APIC)
185 disable_lapic_nmi_watchdog();
186
Robert Richter0933e5c2009-04-29 12:47:12 +0200187 for (i = 0; i < x86_pmu.num_counters; i++) {
Robert Richter4a06bd82009-04-29 12:47:11 +0200188 if (!reserve_perfctr_nmi(x86_pmu.perfctr + i))
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200189 goto perfctr_fail;
190 }
191
Robert Richter0933e5c2009-04-29 12:47:12 +0200192 for (i = 0; i < x86_pmu.num_counters; i++) {
Robert Richter4a06bd82009-04-29 12:47:11 +0200193 if (!reserve_evntsel_nmi(x86_pmu.eventsel + i))
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200194 goto eventsel_fail;
195 }
196
197 return true;
198
199eventsel_fail:
200 for (i--; i >= 0; i--)
Robert Richter4a06bd82009-04-29 12:47:11 +0200201 release_evntsel_nmi(x86_pmu.eventsel + i);
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200202
Robert Richter0933e5c2009-04-29 12:47:12 +0200203 i = x86_pmu.num_counters;
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200204
205perfctr_fail:
206 for (i--; i >= 0; i--)
Robert Richter4a06bd82009-04-29 12:47:11 +0200207 release_perfctr_nmi(x86_pmu.perfctr + i);
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200208
209 if (nmi_watchdog == NMI_LOCAL_APIC)
210 enable_lapic_nmi_watchdog();
211
212 return false;
213}
214
215static void release_pmc_hardware(void)
216{
217 int i;
218
Robert Richter0933e5c2009-04-29 12:47:12 +0200219 for (i = 0; i < x86_pmu.num_counters; i++) {
Robert Richter4a06bd82009-04-29 12:47:11 +0200220 release_perfctr_nmi(x86_pmu.perfctr + i);
221 release_evntsel_nmi(x86_pmu.eventsel + i);
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200222 }
223
224 if (nmi_watchdog == NMI_LOCAL_APIC)
225 enable_lapic_nmi_watchdog();
226}
227
228static void hw_perf_counter_destroy(struct perf_counter *counter)
229{
Peter Zijlstraba778132009-05-04 18:47:44 +0200230 if (atomic_dec_and_mutex_lock(&active_counters, &pmc_reserve_mutex)) {
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200231 release_pmc_hardware();
232 mutex_unlock(&pmc_reserve_mutex);
233 }
234}
235
Robert Richter85cf9db2009-04-29 12:47:20 +0200236static inline int x86_pmu_initialized(void)
237{
238 return x86_pmu.handle_irq != NULL;
239}
240
Ingo Molnaree060942008-12-13 09:00:03 +0100241/*
Ingo Molnar241771e2008-12-03 10:39:53 +0100242 * Setup the hardware configuration for a given hw_event_type
243 */
Ingo Molnar621a01e2008-12-11 12:46:46 +0100244static int __hw_perf_counter_init(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100245{
Ingo Molnar9f66a382008-12-10 12:33:23 +0100246 struct perf_counter_hw_event *hw_event = &counter->hw_event;
Ingo Molnar241771e2008-12-03 10:39:53 +0100247 struct hw_perf_counter *hwc = &counter->hw;
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200248 int err;
Ingo Molnar241771e2008-12-03 10:39:53 +0100249
Robert Richter85cf9db2009-04-29 12:47:20 +0200250 if (!x86_pmu_initialized())
251 return -ENODEV;
Ingo Molnar241771e2008-12-03 10:39:53 +0100252
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200253 err = 0;
Peter Zijlstraba778132009-05-04 18:47:44 +0200254 if (!atomic_inc_not_zero(&active_counters)) {
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200255 mutex_lock(&pmc_reserve_mutex);
Peter Zijlstraba778132009-05-04 18:47:44 +0200256 if (atomic_read(&active_counters) == 0 && !reserve_pmc_hardware())
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200257 err = -EBUSY;
258 else
Peter Zijlstraba778132009-05-04 18:47:44 +0200259 atomic_inc(&active_counters);
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200260 mutex_unlock(&pmc_reserve_mutex);
261 }
262 if (err)
263 return err;
264
Ingo Molnar241771e2008-12-03 10:39:53 +0100265 /*
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100266 * Generate PMC IRQs:
Ingo Molnar241771e2008-12-03 10:39:53 +0100267 * (keep 'enabled' bit clear for now)
268 */
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100269 hwc->config = ARCH_PERFMON_EVENTSEL_INT;
Ingo Molnar241771e2008-12-03 10:39:53 +0100270
271 /*
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100272 * Count user and OS events unless requested not to.
273 */
274 if (!hw_event->exclude_user)
275 hwc->config |= ARCH_PERFMON_EVENTSEL_USR;
276 if (!hw_event->exclude_kernel)
277 hwc->config |= ARCH_PERFMON_EVENTSEL_OS;
278
279 /*
280 * If privileged enough, allow NMI events:
Ingo Molnar241771e2008-12-03 10:39:53 +0100281 */
282 hwc->nmi = 0;
Peter Zijlstraa026dfe2009-05-13 10:02:57 +0200283 if (hw_event->nmi) {
284 if (sysctl_perf_counter_priv && !capable(CAP_SYS_ADMIN))
285 return -EACCES;
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100286 hwc->nmi = 1;
Peter Zijlstraa026dfe2009-05-13 10:02:57 +0200287 }
Ingo Molnar241771e2008-12-03 10:39:53 +0100288
Peter Zijlstraba778132009-05-04 18:47:44 +0200289 hwc->irq_period = hw_event->irq_period;
Robert Richterc619b8f2009-04-29 12:47:23 +0200290 if ((s64)hwc->irq_period <= 0 || hwc->irq_period > x86_pmu.max_period)
291 hwc->irq_period = x86_pmu.max_period;
Ingo Molnar241771e2008-12-03 10:39:53 +0100292
Ingo Molnaree060942008-12-13 09:00:03 +0100293 atomic64_set(&hwc->period_left, hwc->irq_period);
Ingo Molnar241771e2008-12-03 10:39:53 +0100294
295 /*
Thomas Gleixnerdfa7c892008-12-08 19:35:37 +0100296 * Raw event type provide the config in the event structure
Ingo Molnar241771e2008-12-03 10:39:53 +0100297 */
Peter Zijlstraf4a2deb42009-03-23 18:22:06 +0100298 if (perf_event_raw(hw_event)) {
Robert Richter4a06bd82009-04-29 12:47:11 +0200299 hwc->config |= x86_pmu.raw_event(perf_event_config(hw_event));
Ingo Molnar241771e2008-12-03 10:39:53 +0100300 } else {
Robert Richter4a06bd82009-04-29 12:47:11 +0200301 if (perf_event_id(hw_event) >= x86_pmu.max_events)
Ingo Molnar241771e2008-12-03 10:39:53 +0100302 return -EINVAL;
303 /*
304 * The generic map:
305 */
Robert Richter4a06bd82009-04-29 12:47:11 +0200306 hwc->config |= x86_pmu.event_map(perf_event_id(hw_event));
Ingo Molnar241771e2008-12-03 10:39:53 +0100307 }
Ingo Molnar241771e2008-12-03 10:39:53 +0100308
Peter Zijlstra4e935e42009-03-30 19:07:16 +0200309 counter->destroy = hw_perf_counter_destroy;
310
Ingo Molnar241771e2008-12-03 10:39:53 +0100311 return 0;
312}
313
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200314static void intel_pmu_disable_all(void)
Thomas Gleixner4ac13292008-12-09 21:43:39 +0100315{
Ingo Molnar862a1a52008-12-17 13:09:20 +0100316 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
Thomas Gleixner4ac13292008-12-09 21:43:39 +0100317}
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530318
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200319static void amd_pmu_disable_all(void)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530320{
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100321 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200322 int idx;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100323
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200324 if (!cpuc->enabled)
325 return;
326
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100327 cpuc->enabled = 0;
Peter Zijlstra60b3df92009-03-13 12:21:30 +0100328 /*
329 * ensure we write the disable before we start disabling the
Robert Richter5f4ec282009-04-29 12:47:04 +0200330 * counters proper, so that amd_pmu_enable_counter() does the
331 * right thing.
Peter Zijlstra60b3df92009-03-13 12:21:30 +0100332 */
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100333 barrier();
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530334
Robert Richter0933e5c2009-04-29 12:47:12 +0200335 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100336 u64 val;
337
Robert Richter43f62012009-04-29 16:55:56 +0200338 if (!test_bit(idx, cpuc->active_mask))
Robert Richter4295ee62009-04-29 12:47:01 +0200339 continue;
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530340 rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
Robert Richter4295ee62009-04-29 12:47:01 +0200341 if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE))
342 continue;
343 val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
344 wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530345 }
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530346}
347
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200348void hw_perf_disable(void)
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530349{
Robert Richter85cf9db2009-04-29 12:47:20 +0200350 if (!x86_pmu_initialized())
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200351 return;
352 return x86_pmu.disable_all();
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530353}
Ingo Molnar241771e2008-12-03 10:39:53 +0100354
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200355static void intel_pmu_enable_all(void)
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530356{
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200357 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530358}
359
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200360static void amd_pmu_enable_all(void)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530361{
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100362 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530363 int idx;
364
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200365 if (cpuc->enabled)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100366 return;
367
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200368 cpuc->enabled = 1;
369 barrier();
370
Robert Richter0933e5c2009-04-29 12:47:12 +0200371 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
Robert Richter4295ee62009-04-29 12:47:01 +0200372 u64 val;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100373
Robert Richter43f62012009-04-29 16:55:56 +0200374 if (!test_bit(idx, cpuc->active_mask))
Robert Richter4295ee62009-04-29 12:47:01 +0200375 continue;
376 rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
377 if (val & ARCH_PERFMON_EVENTSEL0_ENABLE)
378 continue;
379 val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
380 wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530381 }
382}
383
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200384void hw_perf_enable(void)
Ingo Molnaree060942008-12-13 09:00:03 +0100385{
Robert Richter85cf9db2009-04-29 12:47:20 +0200386 if (!x86_pmu_initialized())
Ingo Molnar2b9ff0d2008-12-14 18:36:30 +0100387 return;
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200388 x86_pmu.enable_all();
Ingo Molnaree060942008-12-13 09:00:03 +0100389}
Ingo Molnaree060942008-12-13 09:00:03 +0100390
Robert Richter19d84da2009-04-29 12:47:25 +0200391static inline u64 intel_pmu_get_status(void)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100392{
393 u64 status;
394
395 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
396
397 return status;
398}
399
Robert Richterdee5d902009-04-29 12:47:07 +0200400static inline void intel_pmu_ack_status(u64 ack)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100401{
402 wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack);
403}
404
Robert Richter7c90cc42009-04-29 12:47:18 +0200405static inline void x86_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100406{
Robert Richter7c90cc42009-04-29 12:47:18 +0200407 int err;
Robert Richter7c90cc42009-04-29 12:47:18 +0200408 err = checking_wrmsrl(hwc->config_base + idx,
409 hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100410}
411
Robert Richterd4369892009-04-29 12:47:19 +0200412static inline void x86_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100413{
Robert Richterd4369892009-04-29 12:47:19 +0200414 int err;
Robert Richterd4369892009-04-29 12:47:19 +0200415 err = checking_wrmsrl(hwc->config_base + idx,
416 hwc->config);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100417}
418
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100419static inline void
Robert Richterd4369892009-04-29 12:47:19 +0200420intel_pmu_disable_fixed(struct hw_perf_counter *hwc, int __idx)
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100421{
422 int idx = __idx - X86_PMC_IDX_FIXED;
423 u64 ctrl_val, mask;
424 int err;
425
426 mask = 0xfULL << (idx * 4);
427
428 rdmsrl(hwc->config_base, ctrl_val);
429 ctrl_val &= ~mask;
430 err = checking_wrmsrl(hwc->config_base, ctrl_val);
431}
432
433static inline void
Robert Richterd4369892009-04-29 12:47:19 +0200434intel_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100435{
Robert Richterd4369892009-04-29 12:47:19 +0200436 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
437 intel_pmu_disable_fixed(hwc, idx);
438 return;
439 }
440
441 x86_pmu_disable_counter(hwc, idx);
442}
443
444static inline void
445amd_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
446{
447 x86_pmu_disable_counter(hwc, idx);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100448}
449
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100450static DEFINE_PER_CPU(u64, prev_left[X86_PMC_IDX_MAX]);
Ingo Molnar241771e2008-12-03 10:39:53 +0100451
Ingo Molnaree060942008-12-13 09:00:03 +0100452/*
453 * Set the next IRQ period, based on the hwc->period_left value.
454 * To be called with the counter disabled in hw:
455 */
456static void
Robert Richter26816c22009-04-29 12:47:08 +0200457x86_perf_counter_set_period(struct perf_counter *counter,
Ingo Molnaree060942008-12-13 09:00:03 +0100458 struct hw_perf_counter *hwc, int idx)
Ingo Molnar241771e2008-12-03 10:39:53 +0100459{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100460 s64 left = atomic64_read(&hwc->period_left);
Peter Zijlstra595258a2009-03-13 12:21:28 +0100461 s64 period = hwc->irq_period;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100462 int err;
Ingo Molnar241771e2008-12-03 10:39:53 +0100463
Ingo Molnaree060942008-12-13 09:00:03 +0100464 /*
465 * If we are way outside a reasoable range then just skip forward:
466 */
467 if (unlikely(left <= -period)) {
468 left = period;
469 atomic64_set(&hwc->period_left, left);
470 }
471
472 if (unlikely(left <= 0)) {
473 left += period;
474 atomic64_set(&hwc->period_left, left);
475 }
476
Ingo Molnaree060942008-12-13 09:00:03 +0100477 per_cpu(prev_left[idx], smp_processor_id()) = left;
478
479 /*
480 * The hw counter starts counting from this counter offset,
481 * mark it to be able to extra future deltas:
482 */
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100483 atomic64_set(&hwc->prev_count, (u64)-left);
Ingo Molnaree060942008-12-13 09:00:03 +0100484
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100485 err = checking_wrmsrl(hwc->counter_base + idx,
Robert Richter0933e5c2009-04-29 12:47:12 +0200486 (u64)(-left) & x86_pmu.counter_mask);
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100487}
488
489static inline void
Robert Richter7c90cc42009-04-29 12:47:18 +0200490intel_pmu_enable_fixed(struct hw_perf_counter *hwc, int __idx)
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100491{
492 int idx = __idx - X86_PMC_IDX_FIXED;
493 u64 ctrl_val, bits, mask;
494 int err;
495
496 /*
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100497 * Enable IRQ generation (0x8),
498 * and enable ring-3 counting (0x2) and ring-0 counting (0x1)
499 * if requested:
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100500 */
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100501 bits = 0x8ULL;
502 if (hwc->config & ARCH_PERFMON_EVENTSEL_USR)
503 bits |= 0x2;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100504 if (hwc->config & ARCH_PERFMON_EVENTSEL_OS)
505 bits |= 0x1;
506 bits <<= (idx * 4);
507 mask = 0xfULL << (idx * 4);
508
509 rdmsrl(hwc->config_base, ctrl_val);
510 ctrl_val &= ~mask;
511 ctrl_val |= bits;
512 err = checking_wrmsrl(hwc->config_base, ctrl_val);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100513}
514
Robert Richter7c90cc42009-04-29 12:47:18 +0200515static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100516{
Robert Richter7c90cc42009-04-29 12:47:18 +0200517 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
518 intel_pmu_enable_fixed(hwc, idx);
519 return;
520 }
521
522 x86_pmu_enable_counter(hwc, idx);
523}
524
525static void amd_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
526{
527 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
528
529 if (cpuc->enabled)
530 x86_pmu_enable_counter(hwc, idx);
Jaswinder Singh Rajput2b583d82008-12-27 19:15:43 +0530531 else
Robert Richterd4369892009-04-29 12:47:19 +0200532 x86_pmu_disable_counter(hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100533}
534
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100535static int
536fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc)
Ingo Molnar862a1a52008-12-17 13:09:20 +0100537{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100538 unsigned int event;
539
Robert Richteref7b3e02009-04-29 12:47:24 +0200540 if (!x86_pmu.num_counters_fixed)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530541 return -1;
542
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100543 if (unlikely(hwc->nmi))
544 return -1;
545
546 event = hwc->config & ARCH_PERFMON_EVENT_MASK;
547
Robert Richter4a06bd82009-04-29 12:47:11 +0200548 if (unlikely(event == x86_pmu.event_map(PERF_COUNT_INSTRUCTIONS)))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100549 return X86_PMC_IDX_FIXED_INSTRUCTIONS;
Robert Richter4a06bd82009-04-29 12:47:11 +0200550 if (unlikely(event == x86_pmu.event_map(PERF_COUNT_CPU_CYCLES)))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100551 return X86_PMC_IDX_FIXED_CPU_CYCLES;
Robert Richter4a06bd82009-04-29 12:47:11 +0200552 if (unlikely(event == x86_pmu.event_map(PERF_COUNT_BUS_CYCLES)))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100553 return X86_PMC_IDX_FIXED_BUS_CYCLES;
554
Ingo Molnar862a1a52008-12-17 13:09:20 +0100555 return -1;
556}
557
Ingo Molnaree060942008-12-13 09:00:03 +0100558/*
559 * Find a PMC slot for the freshly enabled / scheduled in counter:
560 */
Robert Richter4aeb0b42009-04-29 12:47:03 +0200561static int x86_pmu_enable(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100562{
563 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
564 struct hw_perf_counter *hwc = &counter->hw;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100565 int idx;
Ingo Molnar241771e2008-12-03 10:39:53 +0100566
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100567 idx = fixed_mode_idx(counter, hwc);
568 if (idx >= 0) {
569 /*
570 * Try to get the fixed counter, if that is already taken
571 * then try to get a generic counter:
572 */
Robert Richter43f62012009-04-29 16:55:56 +0200573 if (test_and_set_bit(idx, cpuc->used_mask))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100574 goto try_generic;
Ingo Molnar0dff86a2008-12-23 12:28:12 +0100575
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100576 hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
577 /*
578 * We set it so that counter_base + idx in wrmsr/rdmsr maps to
579 * MSR_ARCH_PERFMON_FIXED_CTR0 ... CTR2:
580 */
581 hwc->counter_base =
582 MSR_ARCH_PERFMON_FIXED_CTR0 - X86_PMC_IDX_FIXED;
Ingo Molnar241771e2008-12-03 10:39:53 +0100583 hwc->idx = idx;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100584 } else {
585 idx = hwc->idx;
586 /* Try to get the previous generic counter again */
Robert Richter43f62012009-04-29 16:55:56 +0200587 if (test_and_set_bit(idx, cpuc->used_mask)) {
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100588try_generic:
Robert Richter43f62012009-04-29 16:55:56 +0200589 idx = find_first_zero_bit(cpuc->used_mask,
Robert Richter0933e5c2009-04-29 12:47:12 +0200590 x86_pmu.num_counters);
591 if (idx == x86_pmu.num_counters)
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100592 return -EAGAIN;
593
Robert Richter43f62012009-04-29 16:55:56 +0200594 set_bit(idx, cpuc->used_mask);
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100595 hwc->idx = idx;
596 }
Robert Richter4a06bd82009-04-29 12:47:11 +0200597 hwc->config_base = x86_pmu.eventsel;
598 hwc->counter_base = x86_pmu.perfctr;
Ingo Molnar241771e2008-12-03 10:39:53 +0100599 }
600
601 perf_counters_lapic_init(hwc->nmi);
602
Robert Richterd4369892009-04-29 12:47:19 +0200603 x86_pmu.disable(hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100604
Ingo Molnar862a1a52008-12-17 13:09:20 +0100605 cpuc->counters[idx] = counter;
Robert Richter43f62012009-04-29 16:55:56 +0200606 set_bit(idx, cpuc->active_mask);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100607
Robert Richter26816c22009-04-29 12:47:08 +0200608 x86_perf_counter_set_period(counter, hwc, idx);
Robert Richter7c90cc42009-04-29 12:47:18 +0200609 x86_pmu.enable(hwc, idx);
Ingo Molnar95cdd2e2008-12-21 13:50:42 +0100610
611 return 0;
Ingo Molnar241771e2008-12-03 10:39:53 +0100612}
613
614void perf_counter_print_debug(void)
615{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100616 u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed;
Ingo Molnar0dff86a2008-12-23 12:28:12 +0100617 struct cpu_hw_counters *cpuc;
Peter Zijlstra5bb9efe2009-05-13 08:12:51 +0200618 unsigned long flags;
Ingo Molnar1e125672008-12-09 12:18:18 +0100619 int cpu, idx;
620
Robert Richter0933e5c2009-04-29 12:47:12 +0200621 if (!x86_pmu.num_counters)
Ingo Molnar1e125672008-12-09 12:18:18 +0100622 return;
Ingo Molnar241771e2008-12-03 10:39:53 +0100623
Peter Zijlstra5bb9efe2009-05-13 08:12:51 +0200624 local_irq_save(flags);
Ingo Molnar241771e2008-12-03 10:39:53 +0100625
626 cpu = smp_processor_id();
Ingo Molnar0dff86a2008-12-23 12:28:12 +0100627 cpuc = &per_cpu(cpu_hw_counters, cpu);
Ingo Molnar241771e2008-12-03 10:39:53 +0100628
Robert Richterfaa28ae2009-04-29 12:47:13 +0200629 if (x86_pmu.version >= 2) {
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530630 rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
631 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
632 rdmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
633 rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
Ingo Molnar241771e2008-12-03 10:39:53 +0100634
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530635 pr_info("\n");
636 pr_info("CPU#%d: ctrl: %016llx\n", cpu, ctrl);
637 pr_info("CPU#%d: status: %016llx\n", cpu, status);
638 pr_info("CPU#%d: overflow: %016llx\n", cpu, overflow);
639 pr_info("CPU#%d: fixed: %016llx\n", cpu, fixed);
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530640 }
Robert Richter43f62012009-04-29 16:55:56 +0200641 pr_info("CPU#%d: used: %016llx\n", cpu, *(u64 *)cpuc->used_mask);
Ingo Molnar241771e2008-12-03 10:39:53 +0100642
Robert Richter0933e5c2009-04-29 12:47:12 +0200643 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
Robert Richter4a06bd82009-04-29 12:47:11 +0200644 rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl);
645 rdmsrl(x86_pmu.perfctr + idx, pmc_count);
Ingo Molnar241771e2008-12-03 10:39:53 +0100646
Ingo Molnaree060942008-12-13 09:00:03 +0100647 prev_left = per_cpu(prev_left[idx], cpu);
Ingo Molnar241771e2008-12-03 10:39:53 +0100648
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530649 pr_info("CPU#%d: gen-PMC%d ctrl: %016llx\n",
Ingo Molnar241771e2008-12-03 10:39:53 +0100650 cpu, idx, pmc_ctrl);
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530651 pr_info("CPU#%d: gen-PMC%d count: %016llx\n",
Ingo Molnar241771e2008-12-03 10:39:53 +0100652 cpu, idx, pmc_count);
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530653 pr_info("CPU#%d: gen-PMC%d left: %016llx\n",
Ingo Molnaree060942008-12-13 09:00:03 +0100654 cpu, idx, prev_left);
Ingo Molnar241771e2008-12-03 10:39:53 +0100655 }
Robert Richter0933e5c2009-04-29 12:47:12 +0200656 for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) {
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100657 rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, pmc_count);
658
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530659 pr_info("CPU#%d: fixed-PMC%d count: %016llx\n",
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100660 cpu, idx, pmc_count);
661 }
Peter Zijlstra5bb9efe2009-05-13 08:12:51 +0200662 local_irq_restore(flags);
Ingo Molnar241771e2008-12-03 10:39:53 +0100663}
664
Robert Richter4aeb0b42009-04-29 12:47:03 +0200665static void x86_pmu_disable(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100666{
667 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
668 struct hw_perf_counter *hwc = &counter->hw;
Robert Richter6f00cad2009-04-29 12:47:17 +0200669 int idx = hwc->idx;
Ingo Molnar241771e2008-12-03 10:39:53 +0100670
Robert Richter09534232009-04-29 12:47:16 +0200671 /*
672 * Must be done before we disable, otherwise the nmi handler
673 * could reenable again:
674 */
Robert Richter43f62012009-04-29 16:55:56 +0200675 clear_bit(idx, cpuc->active_mask);
Robert Richterd4369892009-04-29 12:47:19 +0200676 x86_pmu.disable(hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100677
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100678 /*
679 * Make sure the cleared pointer becomes visible before we
680 * (potentially) free the counter:
681 */
Robert Richter527e26a2009-04-29 12:47:02 +0200682 barrier();
Ingo Molnar241771e2008-12-03 10:39:53 +0100683
Ingo Molnaree060942008-12-13 09:00:03 +0100684 /*
685 * Drain the remaining delta count out of a counter
686 * that we are disabling:
687 */
688 x86_perf_counter_update(counter, hwc, idx);
Robert Richter09534232009-04-29 12:47:16 +0200689 cpuc->counters[idx] = NULL;
Robert Richter43f62012009-04-29 16:55:56 +0200690 clear_bit(idx, cpuc->used_mask);
Ingo Molnar241771e2008-12-03 10:39:53 +0100691}
692
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100693/*
Ingo Molnaree060942008-12-13 09:00:03 +0100694 * Save and restart an expired counter. Called by NMI contexts,
695 * so it has to be careful about preempting normal counter ops:
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100696 */
Robert Richter55de0f22009-04-29 12:47:09 +0200697static void intel_pmu_save_and_restart(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100698{
699 struct hw_perf_counter *hwc = &counter->hw;
700 int idx = hwc->idx;
Ingo Molnar241771e2008-12-03 10:39:53 +0100701
Ingo Molnaree060942008-12-13 09:00:03 +0100702 x86_perf_counter_update(counter, hwc, idx);
Robert Richter26816c22009-04-29 12:47:08 +0200703 x86_perf_counter_set_period(counter, hwc, idx);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100704
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100705 if (counter->state == PERF_COUNTER_STATE_ACTIVE)
Robert Richter7c90cc42009-04-29 12:47:18 +0200706 intel_pmu_enable_counter(hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100707}
708
Ingo Molnar241771e2008-12-03 10:39:53 +0100709/*
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100710 * Maximum interrupt frequency of 100KHz per CPU
711 */
Jaswinder Singh Rajput169e41e2009-02-28 18:37:49 +0530712#define PERFMON_MAX_INTERRUPTS (100000/HZ)
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100713
714/*
Ingo Molnar241771e2008-12-03 10:39:53 +0100715 * This handler is triggered by the local APIC, so the APIC IRQ handling
716 * rules apply:
717 */
Robert Richter39d81ea2009-04-29 12:47:05 +0200718static int intel_pmu_handle_irq(struct pt_regs *regs, int nmi)
Ingo Molnar241771e2008-12-03 10:39:53 +0100719{
720 int bit, cpu = smp_processor_id();
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100721 u64 ack, status;
Mike Galbraith1b023a92009-01-23 10:13:01 +0100722 struct cpu_hw_counters *cpuc = &per_cpu(cpu_hw_counters, cpu);
Ingo Molnar43874d22008-12-09 12:23:59 +0100723
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200724 perf_disable();
Robert Richter19d84da2009-04-29 12:47:25 +0200725 status = intel_pmu_get_status();
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200726 if (!status) {
727 perf_enable();
728 return 0;
729 }
Ingo Molnar87b9cf42008-12-08 14:20:16 +0100730
Ingo Molnar241771e2008-12-03 10:39:53 +0100731again:
Mike Galbraithd278c482009-02-09 07:38:50 +0100732 inc_irq_stat(apic_perf_irqs);
Ingo Molnar241771e2008-12-03 10:39:53 +0100733 ack = status;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100734 for_each_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
Ingo Molnar862a1a52008-12-17 13:09:20 +0100735 struct perf_counter *counter = cpuc->counters[bit];
Ingo Molnar241771e2008-12-03 10:39:53 +0100736
737 clear_bit(bit, (unsigned long *) &status);
Robert Richter43f62012009-04-29 16:55:56 +0200738 if (!test_bit(bit, cpuc->active_mask))
Ingo Molnar241771e2008-12-03 10:39:53 +0100739 continue;
740
Robert Richter55de0f22009-04-29 12:47:09 +0200741 intel_pmu_save_and_restart(counter);
Peter Zijlstra78f13e92009-04-08 15:01:33 +0200742 if (perf_counter_overflow(counter, nmi, regs, 0))
Robert Richterd4369892009-04-29 12:47:19 +0200743 intel_pmu_disable_counter(&counter->hw, bit);
Ingo Molnar241771e2008-12-03 10:39:53 +0100744 }
745
Robert Richterdee5d902009-04-29 12:47:07 +0200746 intel_pmu_ack_status(ack);
Ingo Molnar241771e2008-12-03 10:39:53 +0100747
748 /*
749 * Repeat if there is more work to be done:
750 */
Robert Richter19d84da2009-04-29 12:47:25 +0200751 status = intel_pmu_get_status();
Ingo Molnar241771e2008-12-03 10:39:53 +0100752 if (status)
753 goto again;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100754
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200755 if (++cpuc->interrupts != PERFMON_MAX_INTERRUPTS)
756 perf_enable();
757
758 return 1;
Mike Galbraith1b023a92009-01-23 10:13:01 +0100759}
760
Robert Richtera29aa8a2009-04-29 12:47:21 +0200761static int amd_pmu_handle_irq(struct pt_regs *regs, int nmi)
762{
763 int cpu = smp_processor_id();
764 struct cpu_hw_counters *cpuc = &per_cpu(cpu_hw_counters, cpu);
765 u64 val;
766 int handled = 0;
767 struct perf_counter *counter;
768 struct hw_perf_counter *hwc;
Peter Zijlstra962bf7a2009-05-13 13:21:36 +0200769 int idx, throttle = 0;
Robert Richtera29aa8a2009-04-29 12:47:21 +0200770
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200771 if (++cpuc->interrupts == PERFMON_MAX_INTERRUPTS) {
772 throttle = 1;
773 __perf_disable();
774 cpuc->enabled = 0;
775 barrier();
Peter Zijlstra962bf7a2009-05-13 13:21:36 +0200776 }
777
Robert Richtera29aa8a2009-04-29 12:47:21 +0200778 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
Peter Zijlstra962bf7a2009-05-13 13:21:36 +0200779 int disable = 0;
780
Robert Richter43f62012009-04-29 16:55:56 +0200781 if (!test_bit(idx, cpuc->active_mask))
Robert Richtera29aa8a2009-04-29 12:47:21 +0200782 continue;
Peter Zijlstra962bf7a2009-05-13 13:21:36 +0200783
Robert Richtera29aa8a2009-04-29 12:47:21 +0200784 counter = cpuc->counters[idx];
785 hwc = &counter->hw;
Peter Zijlstraa4016a72009-05-14 14:52:17 +0200786
787 if (counter->hw_event.nmi != nmi)
788 goto next;
789
Robert Richter4b7bfd02009-04-29 12:47:22 +0200790 val = x86_perf_counter_update(counter, hwc, idx);
Robert Richtera29aa8a2009-04-29 12:47:21 +0200791 if (val & (1ULL << (x86_pmu.counter_bits - 1)))
Peter Zijlstra962bf7a2009-05-13 13:21:36 +0200792 goto next;
793
Robert Richtera29aa8a2009-04-29 12:47:21 +0200794 /* counter overflow */
795 x86_perf_counter_set_period(counter, hwc, idx);
796 handled = 1;
797 inc_irq_stat(apic_perf_irqs);
Peter Zijlstra962bf7a2009-05-13 13:21:36 +0200798 disable = perf_counter_overflow(counter, nmi, regs, 0);
799
800next:
801 if (disable || throttle)
Robert Richtera29aa8a2009-04-29 12:47:21 +0200802 amd_pmu_disable_counter(hwc, idx);
Robert Richtera29aa8a2009-04-29 12:47:21 +0200803 }
Peter Zijlstra962bf7a2009-05-13 13:21:36 +0200804
Robert Richtera29aa8a2009-04-29 12:47:21 +0200805 return handled;
806}
Robert Richter39d81ea2009-04-29 12:47:05 +0200807
Mike Galbraith1b023a92009-01-23 10:13:01 +0100808void perf_counter_unthrottle(void)
809{
810 struct cpu_hw_counters *cpuc;
811
Robert Richter85cf9db2009-04-29 12:47:20 +0200812 if (!x86_pmu_initialized())
Mike Galbraith1b023a92009-01-23 10:13:01 +0100813 return;
814
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100815 cpuc = &__get_cpu_var(cpu_hw_counters);
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100816 if (cpuc->interrupts >= PERFMON_MAX_INTERRUPTS) {
Ingo Molnarf5a5a2f2009-05-13 12:54:01 +0200817 /*
818 * Clear them before re-enabling irqs/NMIs again:
819 */
820 cpuc->interrupts = 0;
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200821 perf_enable();
Ingo Molnarf5a5a2f2009-05-13 12:54:01 +0200822 } else {
823 cpuc->interrupts = 0;
Mike Galbraith1b023a92009-01-23 10:13:01 +0100824 }
Ingo Molnar241771e2008-12-03 10:39:53 +0100825}
826
827void smp_perf_counter_interrupt(struct pt_regs *regs)
828{
829 irq_enter();
Ingo Molnar241771e2008-12-03 10:39:53 +0100830 apic_write(APIC_LVTPC, LOCAL_PERF_VECTOR);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100831 ack_APIC_irq();
Robert Richter4a06bd82009-04-29 12:47:11 +0200832 x86_pmu.handle_irq(regs, 0);
Ingo Molnar241771e2008-12-03 10:39:53 +0100833 irq_exit();
834}
835
Peter Zijlstrab6276f32009-04-06 11:45:03 +0200836void smp_perf_pending_interrupt(struct pt_regs *regs)
837{
838 irq_enter();
839 ack_APIC_irq();
840 inc_irq_stat(apic_pending_irqs);
841 perf_counter_do_pending();
842 irq_exit();
843}
844
845void set_perf_counter_pending(void)
846{
847 apic->send_IPI_self(LOCAL_PENDING_VECTOR);
848}
849
Mike Galbraith3415dd92009-01-23 14:16:53 +0100850void perf_counters_lapic_init(int nmi)
Ingo Molnar241771e2008-12-03 10:39:53 +0100851{
852 u32 apic_val;
853
Robert Richter85cf9db2009-04-29 12:47:20 +0200854 if (!x86_pmu_initialized())
Ingo Molnar241771e2008-12-03 10:39:53 +0100855 return;
Robert Richter85cf9db2009-04-29 12:47:20 +0200856
Ingo Molnar241771e2008-12-03 10:39:53 +0100857 /*
858 * Enable the performance counter vector in the APIC LVT:
859 */
860 apic_val = apic_read(APIC_LVTERR);
861
862 apic_write(APIC_LVTERR, apic_val | APIC_LVT_MASKED);
863 if (nmi)
864 apic_write(APIC_LVTPC, APIC_DM_NMI);
865 else
866 apic_write(APIC_LVTPC, LOCAL_PERF_VECTOR);
867 apic_write(APIC_LVTERR, apic_val);
868}
869
870static int __kprobes
871perf_counter_nmi_handler(struct notifier_block *self,
872 unsigned long cmd, void *__args)
873{
874 struct die_args *args = __args;
875 struct pt_regs *regs;
876
Peter Zijlstraba778132009-05-04 18:47:44 +0200877 if (!atomic_read(&active_counters))
Peter Zijlstra63a809a2009-05-01 12:23:17 +0200878 return NOTIFY_DONE;
879
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100880 switch (cmd) {
881 case DIE_NMI:
882 case DIE_NMI_IPI:
883 break;
884
885 default:
Ingo Molnar241771e2008-12-03 10:39:53 +0100886 return NOTIFY_DONE;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100887 }
Ingo Molnar241771e2008-12-03 10:39:53 +0100888
889 regs = args->regs;
890
891 apic_write(APIC_LVTPC, APIC_DM_NMI);
Peter Zijlstraa4016a72009-05-14 14:52:17 +0200892 /*
893 * Can't rely on the handled return value to say it was our NMI, two
894 * counters could trigger 'simultaneously' raising two back-to-back NMIs.
895 *
896 * If the first NMI handles both, the latter will be empty and daze
897 * the CPU.
898 */
899 x86_pmu.handle_irq(regs, 1);
Ingo Molnar241771e2008-12-03 10:39:53 +0100900
Peter Zijlstraa4016a72009-05-14 14:52:17 +0200901 return NOTIFY_STOP;
Ingo Molnar241771e2008-12-03 10:39:53 +0100902}
903
904static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
Mike Galbraith5b75af02009-02-04 17:11:34 +0100905 .notifier_call = perf_counter_nmi_handler,
906 .next = NULL,
907 .priority = 1
Ingo Molnar241771e2008-12-03 10:39:53 +0100908};
909
Robert Richter5f4ec282009-04-29 12:47:04 +0200910static struct x86_pmu intel_pmu = {
Robert Richterfaa28ae2009-04-29 12:47:13 +0200911 .name = "Intel",
Robert Richter39d81ea2009-04-29 12:47:05 +0200912 .handle_irq = intel_pmu_handle_irq,
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200913 .disable_all = intel_pmu_disable_all,
914 .enable_all = intel_pmu_enable_all,
Robert Richter5f4ec282009-04-29 12:47:04 +0200915 .enable = intel_pmu_enable_counter,
916 .disable = intel_pmu_disable_counter,
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530917 .eventsel = MSR_ARCH_PERFMON_EVENTSEL0,
918 .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
Robert Richter5f4ec282009-04-29 12:47:04 +0200919 .event_map = intel_pmu_event_map,
920 .raw_event = intel_pmu_raw_event,
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530921 .max_events = ARRAY_SIZE(intel_perfmon_event_map),
Robert Richterc619b8f2009-04-29 12:47:23 +0200922 /*
923 * Intel PMCs cannot be accessed sanely above 32 bit width,
924 * so we install an artificial 1<<31 period regardless of
925 * the generic counter period:
926 */
927 .max_period = (1ULL << 31) - 1,
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530928};
929
Robert Richter5f4ec282009-04-29 12:47:04 +0200930static struct x86_pmu amd_pmu = {
Robert Richterfaa28ae2009-04-29 12:47:13 +0200931 .name = "AMD",
Robert Richter39d81ea2009-04-29 12:47:05 +0200932 .handle_irq = amd_pmu_handle_irq,
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200933 .disable_all = amd_pmu_disable_all,
934 .enable_all = amd_pmu_enable_all,
Robert Richter5f4ec282009-04-29 12:47:04 +0200935 .enable = amd_pmu_enable_counter,
936 .disable = amd_pmu_disable_counter,
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530937 .eventsel = MSR_K7_EVNTSEL0,
938 .perfctr = MSR_K7_PERFCTR0,
Robert Richter5f4ec282009-04-29 12:47:04 +0200939 .event_map = amd_pmu_event_map,
940 .raw_event = amd_pmu_raw_event,
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530941 .max_events = ARRAY_SIZE(amd_perfmon_event_map),
Robert Richter0933e5c2009-04-29 12:47:12 +0200942 .num_counters = 4,
943 .counter_bits = 48,
944 .counter_mask = (1ULL << 48) - 1,
Robert Richterc619b8f2009-04-29 12:47:23 +0200945 /* use highest bit to detect overflow */
946 .max_period = (1ULL << 47) - 1,
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530947};
948
Robert Richter72eae042009-04-29 12:47:10 +0200949static int intel_pmu_init(void)
Ingo Molnar241771e2008-12-03 10:39:53 +0100950{
Ingo Molnar703e9372008-12-17 10:51:15 +0100951 union cpuid10_edx edx;
Ingo Molnar7bb497b2009-03-18 08:59:21 +0100952 union cpuid10_eax eax;
953 unsigned int unused;
954 unsigned int ebx;
Robert Richterfaa28ae2009-04-29 12:47:13 +0200955 int version;
Ingo Molnar241771e2008-12-03 10:39:53 +0100956
Robert Richterda1a7762009-04-29 12:46:58 +0200957 if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
Robert Richter72eae042009-04-29 12:47:10 +0200958 return -ENODEV;
Robert Richterda1a7762009-04-29 12:46:58 +0200959
Ingo Molnar241771e2008-12-03 10:39:53 +0100960 /*
961 * Check whether the Architectural PerfMon supports
962 * Branch Misses Retired Event or not.
963 */
Ingo Molnar703e9372008-12-17 10:51:15 +0100964 cpuid(10, &eax.full, &ebx, &unused, &edx.full);
Ingo Molnar241771e2008-12-03 10:39:53 +0100965 if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED)
Robert Richter72eae042009-04-29 12:47:10 +0200966 return -ENODEV;
Ingo Molnar241771e2008-12-03 10:39:53 +0100967
Robert Richterfaa28ae2009-04-29 12:47:13 +0200968 version = eax.split.version_id;
969 if (version < 2)
Robert Richter72eae042009-04-29 12:47:10 +0200970 return -ENODEV;
Ingo Molnar7bb497b2009-03-18 08:59:21 +0100971
Robert Richter4a06bd82009-04-29 12:47:11 +0200972 x86_pmu = intel_pmu;
Robert Richterfaa28ae2009-04-29 12:47:13 +0200973 x86_pmu.version = version;
Robert Richter0933e5c2009-04-29 12:47:12 +0200974 x86_pmu.num_counters = eax.split.num_counters;
Ingo Molnar066d7de2009-05-04 19:04:09 +0200975
976 /*
977 * Quirk: v2 perfmon does not report fixed-purpose counters, so
978 * assume at least 3 counters:
979 */
980 x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3);
981
Robert Richter0933e5c2009-04-29 12:47:12 +0200982 x86_pmu.counter_bits = eax.split.bit_width;
983 x86_pmu.counter_mask = (1ULL << eax.split.bit_width) - 1;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530984
Peter Zijlstra9e35ad32009-05-13 16:21:38 +0200985 rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
986
Robert Richter72eae042009-04-29 12:47:10 +0200987 return 0;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530988}
989
Robert Richter72eae042009-04-29 12:47:10 +0200990static int amd_pmu_init(void)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530991{
Robert Richter4a06bd82009-04-29 12:47:11 +0200992 x86_pmu = amd_pmu;
Robert Richter72eae042009-04-29 12:47:10 +0200993 return 0;
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530994}
995
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530996void __init init_hw_perf_counters(void)
997{
Robert Richter72eae042009-04-29 12:47:10 +0200998 int err;
999
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +05301000 switch (boot_cpu_data.x86_vendor) {
1001 case X86_VENDOR_INTEL:
Robert Richter72eae042009-04-29 12:47:10 +02001002 err = intel_pmu_init();
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +05301003 break;
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +05301004 case X86_VENDOR_AMD:
Robert Richter72eae042009-04-29 12:47:10 +02001005 err = amd_pmu_init();
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +05301006 break;
Robert Richter41389602009-04-29 12:47:00 +02001007 default:
1008 return;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +05301009 }
Robert Richter72eae042009-04-29 12:47:10 +02001010 if (err != 0)
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +05301011 return;
1012
Robert Richterfaa28ae2009-04-29 12:47:13 +02001013 pr_info("%s Performance Monitoring support detected.\n", x86_pmu.name);
1014 pr_info("... version: %d\n", x86_pmu.version);
1015 pr_info("... bit width: %d\n", x86_pmu.counter_bits);
1016
Robert Richter0933e5c2009-04-29 12:47:12 +02001017 pr_info("... num counters: %d\n", x86_pmu.num_counters);
1018 if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) {
1019 x86_pmu.num_counters = X86_PMC_MAX_GENERIC;
Ingo Molnar241771e2008-12-03 10:39:53 +01001020 WARN(1, KERN_ERR "hw perf counters %d > max(%d), clipping!",
Robert Richter0933e5c2009-04-29 12:47:12 +02001021 x86_pmu.num_counters, X86_PMC_MAX_GENERIC);
Ingo Molnar241771e2008-12-03 10:39:53 +01001022 }
Robert Richter0933e5c2009-04-29 12:47:12 +02001023 perf_counter_mask = (1 << x86_pmu.num_counters) - 1;
1024 perf_max_counters = x86_pmu.num_counters;
Ingo Molnar241771e2008-12-03 10:39:53 +01001025
Robert Richter0933e5c2009-04-29 12:47:12 +02001026 pr_info("... value mask: %016Lx\n", x86_pmu.counter_mask);
Robert Richterc619b8f2009-04-29 12:47:23 +02001027 pr_info("... max period: %016Lx\n", x86_pmu.max_period);
Ingo Molnar2f18d1e2008-12-22 11:10:42 +01001028
Robert Richter0933e5c2009-04-29 12:47:12 +02001029 if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) {
1030 x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED;
Ingo Molnar703e9372008-12-17 10:51:15 +01001031 WARN(1, KERN_ERR "hw perf counters fixed %d > max(%d), clipping!",
Robert Richter0933e5c2009-04-29 12:47:12 +02001032 x86_pmu.num_counters_fixed, X86_PMC_MAX_FIXED);
Ingo Molnar703e9372008-12-17 10:51:15 +01001033 }
Robert Richter0933e5c2009-04-29 12:47:12 +02001034 pr_info("... fixed counters: %d\n", x86_pmu.num_counters_fixed);
Ingo Molnar241771e2008-12-03 10:39:53 +01001035
Robert Richter0933e5c2009-04-29 12:47:12 +02001036 perf_counter_mask |=
1037 ((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED;
Ingo Molnar862a1a52008-12-17 13:09:20 +01001038
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +05301039 pr_info("... counter mask: %016Lx\n", perf_counter_mask);
Ingo Molnar75f224cf2008-12-14 21:58:46 +01001040
Ingo Molnar241771e2008-12-03 10:39:53 +01001041 perf_counters_lapic_init(0);
1042 register_die_notifier(&perf_counter_nmi_notifier);
Ingo Molnar241771e2008-12-03 10:39:53 +01001043}
Ingo Molnar621a01e2008-12-11 12:46:46 +01001044
Robert Richterbb775fc2009-04-29 12:47:14 +02001045static inline void x86_pmu_read(struct perf_counter *counter)
Ingo Molnaree060942008-12-13 09:00:03 +01001046{
1047 x86_perf_counter_update(counter, &counter->hw, counter->hw.idx);
1048}
1049
Robert Richter4aeb0b42009-04-29 12:47:03 +02001050static const struct pmu pmu = {
1051 .enable = x86_pmu_enable,
1052 .disable = x86_pmu_disable,
1053 .read = x86_pmu_read,
Ingo Molnar621a01e2008-12-11 12:46:46 +01001054};
1055
Robert Richter4aeb0b42009-04-29 12:47:03 +02001056const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
Ingo Molnar621a01e2008-12-11 12:46:46 +01001057{
1058 int err;
1059
1060 err = __hw_perf_counter_init(counter);
1061 if (err)
Peter Zijlstra9ea98e12009-03-30 19:07:09 +02001062 return ERR_PTR(err);
Ingo Molnar621a01e2008-12-11 12:46:46 +01001063
Robert Richter4aeb0b42009-04-29 12:47:03 +02001064 return &pmu;
Ingo Molnar621a01e2008-12-11 12:46:46 +01001065}
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001066
1067/*
1068 * callchain support
1069 */
1070
1071static inline
1072void callchain_store(struct perf_callchain_entry *entry, unsigned long ip)
1073{
1074 if (entry->nr < MAX_STACK_DEPTH)
1075 entry->ip[entry->nr++] = ip;
1076}
1077
1078static DEFINE_PER_CPU(struct perf_callchain_entry, irq_entry);
1079static DEFINE_PER_CPU(struct perf_callchain_entry, nmi_entry);
1080
1081
1082static void
1083backtrace_warning_symbol(void *data, char *msg, unsigned long symbol)
1084{
1085 /* Ignore warnings */
1086}
1087
1088static void backtrace_warning(void *data, char *msg)
1089{
1090 /* Ignore warnings */
1091}
1092
1093static int backtrace_stack(void *data, char *name)
1094{
1095 /* Don't bother with IRQ stacks for now */
1096 return -1;
1097}
1098
1099static void backtrace_address(void *data, unsigned long addr, int reliable)
1100{
1101 struct perf_callchain_entry *entry = data;
1102
1103 if (reliable)
1104 callchain_store(entry, addr);
1105}
1106
1107static const struct stacktrace_ops backtrace_ops = {
1108 .warning = backtrace_warning,
1109 .warning_symbol = backtrace_warning_symbol,
1110 .stack = backtrace_stack,
1111 .address = backtrace_address,
1112};
1113
1114static void
1115perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)
1116{
1117 unsigned long bp;
1118 char *stack;
Peter Zijlstra5872bdb82009-04-02 11:12:03 +02001119 int nr = entry->nr;
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001120
1121 callchain_store(entry, instruction_pointer(regs));
1122
1123 stack = ((char *)regs + sizeof(struct pt_regs));
1124#ifdef CONFIG_FRAME_POINTER
1125 bp = frame_pointer(regs);
1126#else
1127 bp = 0;
1128#endif
1129
1130 dump_trace(NULL, regs, (void *)stack, bp, &backtrace_ops, entry);
Peter Zijlstra5872bdb82009-04-02 11:12:03 +02001131
1132 entry->kernel = entry->nr - nr;
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001133}
1134
1135
1136struct stack_frame {
1137 const void __user *next_fp;
1138 unsigned long return_address;
1139};
1140
1141static int copy_stack_frame(const void __user *fp, struct stack_frame *frame)
1142{
1143 int ret;
1144
1145 if (!access_ok(VERIFY_READ, fp, sizeof(*frame)))
1146 return 0;
1147
1148 ret = 1;
1149 pagefault_disable();
1150 if (__copy_from_user_inatomic(frame, fp, sizeof(*frame)))
1151 ret = 0;
1152 pagefault_enable();
1153
1154 return ret;
1155}
1156
1157static void
1158perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry)
1159{
1160 struct stack_frame frame;
1161 const void __user *fp;
Peter Zijlstra5872bdb82009-04-02 11:12:03 +02001162 int nr = entry->nr;
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001163
1164 regs = (struct pt_regs *)current->thread.sp0 - 1;
1165 fp = (void __user *)regs->bp;
1166
1167 callchain_store(entry, regs->ip);
1168
1169 while (entry->nr < MAX_STACK_DEPTH) {
1170 frame.next_fp = NULL;
1171 frame.return_address = 0;
1172
1173 if (!copy_stack_frame(fp, &frame))
1174 break;
1175
1176 if ((unsigned long)fp < user_stack_pointer(regs))
1177 break;
1178
1179 callchain_store(entry, frame.return_address);
1180 fp = frame.next_fp;
1181 }
Peter Zijlstra5872bdb82009-04-02 11:12:03 +02001182
1183 entry->user = entry->nr - nr;
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001184}
1185
1186static void
1187perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
1188{
1189 int is_user;
1190
1191 if (!regs)
1192 return;
1193
1194 is_user = user_mode(regs);
1195
1196 if (!current || current->pid == 0)
1197 return;
1198
1199 if (is_user && current->state != TASK_RUNNING)
1200 return;
1201
1202 if (!is_user)
1203 perf_callchain_kernel(regs, entry);
1204
1205 if (current->mm)
1206 perf_callchain_user(regs, entry);
1207}
1208
1209struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
1210{
1211 struct perf_callchain_entry *entry;
1212
1213 if (in_nmi())
1214 entry = &__get_cpu_var(nmi_entry);
1215 else
1216 entry = &__get_cpu_var(irq_entry);
1217
1218 entry->nr = 0;
Peter Zijlstra5872bdb82009-04-02 11:12:03 +02001219 entry->hv = 0;
1220 entry->kernel = 0;
1221 entry->user = 0;
Peter Zijlstrad7d59fb2009-03-30 19:07:15 +02001222
1223 perf_do_callchain(regs, entry);
1224
1225 return entry;
1226}