blob: f5853718d4d374c18d5cf34fb599e4eb76e36e92 [file] [log] [blame]
Ingo Molnar241771e2008-12-03 10:39:53 +01001/*
2 * Performance counter x86 architecture code
3 *
4 * Copyright(C) 2008 Thomas Gleixner <tglx@linutronix.de>
5 * Copyright(C) 2008 Red Hat, Inc., Ingo Molnar
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +05306 * Copyright(C) 2009 Jaswinder Singh Rajput
Ingo Molnar241771e2008-12-03 10:39:53 +01007 *
8 * For licencing details see kernel-base/COPYING
9 */
10
11#include <linux/perf_counter.h>
12#include <linux/capability.h>
13#include <linux/notifier.h>
14#include <linux/hardirq.h>
15#include <linux/kprobes.h>
Thomas Gleixner4ac13292008-12-09 21:43:39 +010016#include <linux/module.h>
Ingo Molnar241771e2008-12-03 10:39:53 +010017#include <linux/kdebug.h>
18#include <linux/sched.h>
19
Ingo Molnar5c167b82008-12-17 09:02:19 +010020#include <asm/perf_counter.h>
Ingo Molnar241771e2008-12-03 10:39:53 +010021#include <asm/apic.h>
22
23static bool perf_counters_initialized __read_mostly;
24
25/*
26 * Number of (generic) HW counters:
27 */
Ingo Molnar862a1a52008-12-17 13:09:20 +010028static int nr_counters_generic __read_mostly;
29static u64 perf_counter_mask __read_mostly;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +010030static u64 counter_value_mask __read_mostly;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010031static int counter_value_bits __read_mostly;
Ingo Molnar241771e2008-12-03 10:39:53 +010032
Ingo Molnar862a1a52008-12-17 13:09:20 +010033static int nr_counters_fixed __read_mostly;
Ingo Molnar703e9372008-12-17 10:51:15 +010034
Ingo Molnar241771e2008-12-03 10:39:53 +010035struct cpu_hw_counters {
Ingo Molnar862a1a52008-12-17 13:09:20 +010036 struct perf_counter *counters[X86_PMC_IDX_MAX];
37 unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
Mike Galbraith4b39fd92009-01-23 14:36:16 +010038 unsigned long interrupts;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010039 u64 throttle_ctrl;
40 u64 active_mask;
41 int enabled;
Ingo Molnar241771e2008-12-03 10:39:53 +010042};
43
44/*
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +053045 * struct pmc_x86_ops - performance counter x86 ops
Ingo Molnar241771e2008-12-03 10:39:53 +010046 */
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +053047struct pmc_x86_ops {
Jaswinder Singh Rajput169e41e2009-02-28 18:37:49 +053048 u64 (*save_disable_all)(void);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010049 void (*restore_all)(u64);
50 u64 (*get_status)(u64);
51 void (*ack_status)(u64);
52 void (*enable)(int, u64);
53 void (*disable)(int, u64);
Jaswinder Singh Rajput169e41e2009-02-28 18:37:49 +053054 unsigned eventsel;
55 unsigned perfctr;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010056 u64 (*event_map)(int);
57 u64 (*raw_event)(u64);
Jaswinder Singh Rajput169e41e2009-02-28 18:37:49 +053058 int max_events;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +053059};
60
61static struct pmc_x86_ops *pmc_ops;
62
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
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010081static u64 pmc_intel_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
Peter Zijlstrab0f3f282009-03-05 18:08:27 +010086static u64 pmc_intel_raw_event(u64 event)
87{
88#define CORE_EVNTSEL_EVENT_MASK 0x000000FF
89#define CORE_EVNTSEL_UNIT_MASK 0x0000FF00
90#define CORE_EVNTSEL_COUNTER_MASK 0xFF000000
91
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
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100113static u64 pmc_amd_event_map(int event)
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530114{
115 return amd_perfmon_event_map[event];
116}
117
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100118static u64 pmc_amd_raw_event(u64 event)
119{
120#define K7_EVNTSEL_EVENT_MASK 0x7000000FF
121#define K7_EVNTSEL_UNIT_MASK 0x00000FF00
122#define K7_EVNTSEL_COUNTER_MASK 0x0FF000000
123
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 */
137static void
138x86_perf_counter_update(struct perf_counter *counter,
139 struct hw_perf_counter *hwc, int idx)
140{
141 u64 prev_raw_count, new_raw_count, delta;
142
Ingo Molnaree060942008-12-13 09:00:03 +0100143 /*
144 * Careful: an NMI might modify the previous counter value.
145 *
146 * Our tactic to handle this is to first atomically read and
147 * exchange a new raw count - then add that new-prev delta
148 * count to the generic counter atomically:
149 */
150again:
151 prev_raw_count = atomic64_read(&hwc->prev_count);
152 rdmsrl(hwc->counter_base + idx, new_raw_count);
153
154 if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
155 new_raw_count) != prev_raw_count)
156 goto again;
157
158 /*
159 * Now we have the new raw value and have updated the prev
160 * timestamp already. We can now calculate the elapsed delta
161 * (counter-)time and add that to the generic counter.
162 *
163 * Careful, not all hw sign-extends above the physical width
164 * of the count, so we do that by clipping the delta to 32 bits:
165 */
166 delta = (u64)(u32)((s32)new_raw_count - (s32)prev_raw_count);
Ingo Molnaree060942008-12-13 09:00:03 +0100167
168 atomic64_add(delta, &counter->count);
169 atomic64_sub(delta, &hwc->period_left);
170}
171
172/*
Ingo Molnar241771e2008-12-03 10:39:53 +0100173 * Setup the hardware configuration for a given hw_event_type
174 */
Ingo Molnar621a01e2008-12-11 12:46:46 +0100175static int __hw_perf_counter_init(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100176{
Ingo Molnar9f66a382008-12-10 12:33:23 +0100177 struct perf_counter_hw_event *hw_event = &counter->hw_event;
Ingo Molnar241771e2008-12-03 10:39:53 +0100178 struct hw_perf_counter *hwc = &counter->hw;
179
180 if (unlikely(!perf_counters_initialized))
181 return -EINVAL;
182
183 /*
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100184 * Generate PMC IRQs:
Ingo Molnar241771e2008-12-03 10:39:53 +0100185 * (keep 'enabled' bit clear for now)
186 */
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100187 hwc->config = ARCH_PERFMON_EVENTSEL_INT;
Ingo Molnar241771e2008-12-03 10:39:53 +0100188
189 /*
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100190 * Count user and OS events unless requested not to.
191 */
192 if (!hw_event->exclude_user)
193 hwc->config |= ARCH_PERFMON_EVENTSEL_USR;
194 if (!hw_event->exclude_kernel)
195 hwc->config |= ARCH_PERFMON_EVENTSEL_OS;
196
197 /*
198 * If privileged enough, allow NMI events:
Ingo Molnar241771e2008-12-03 10:39:53 +0100199 */
200 hwc->nmi = 0;
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100201 if (capable(CAP_SYS_ADMIN) && hw_event->nmi)
202 hwc->nmi = 1;
Ingo Molnar241771e2008-12-03 10:39:53 +0100203
Ingo Molnar9f66a382008-12-10 12:33:23 +0100204 hwc->irq_period = hw_event->irq_period;
Ingo Molnar241771e2008-12-03 10:39:53 +0100205 /*
206 * Intel PMCs cannot be accessed sanely above 32 bit width,
207 * so we install an artificial 1<<31 period regardless of
208 * the generic counter period:
209 */
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530210 if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
211 if ((s64)hwc->irq_period <= 0 || hwc->irq_period > 0x7FFFFFFF)
212 hwc->irq_period = 0x7FFFFFFF;
Ingo Molnar241771e2008-12-03 10:39:53 +0100213
Ingo Molnaree060942008-12-13 09:00:03 +0100214 atomic64_set(&hwc->period_left, hwc->irq_period);
Ingo Molnar241771e2008-12-03 10:39:53 +0100215
216 /*
Thomas Gleixnerdfa7c892008-12-08 19:35:37 +0100217 * Raw event type provide the config in the event structure
Ingo Molnar241771e2008-12-03 10:39:53 +0100218 */
Ingo Molnar9f66a382008-12-10 12:33:23 +0100219 if (hw_event->raw) {
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100220 hwc->config |= pmc_ops->raw_event(hw_event->type);
Ingo Molnar241771e2008-12-03 10:39:53 +0100221 } else {
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530222 if (hw_event->type >= pmc_ops->max_events)
Ingo Molnar241771e2008-12-03 10:39:53 +0100223 return -EINVAL;
224 /*
225 * The generic map:
226 */
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530227 hwc->config |= pmc_ops->event_map(hw_event->type);
Ingo Molnar241771e2008-12-03 10:39:53 +0100228 }
Ingo Molnar241771e2008-12-03 10:39:53 +0100229 counter->wakeup_pending = 0;
230
231 return 0;
232}
233
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530234static u64 pmc_intel_save_disable_all(void)
Thomas Gleixner4ac13292008-12-09 21:43:39 +0100235{
236 u64 ctrl;
237
238 rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
Ingo Molnar862a1a52008-12-17 13:09:20 +0100239 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
Ingo Molnar2b9ff0d2008-12-14 18:36:30 +0100240
Thomas Gleixner4ac13292008-12-09 21:43:39 +0100241 return ctrl;
242}
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530243
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530244static u64 pmc_amd_save_disable_all(void)
245{
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100246 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
247 int enabled, idx;
248
249 enabled = cpuc->enabled;
250 cpuc->enabled = 0;
251 barrier();
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530252
253 for (idx = 0; idx < nr_counters_generic; idx++) {
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100254 u64 val;
255
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530256 rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100257 if (val & ARCH_PERFMON_EVENTSEL0_ENABLE) {
258 val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
259 wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
260 }
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530261 }
262
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100263 return enabled;
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530264}
265
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530266u64 hw_perf_save_disable(void)
267{
268 if (unlikely(!perf_counters_initialized))
269 return 0;
270
271 return pmc_ops->save_disable_all();
272}
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100273/*
274 * Exported because of ACPI idle
275 */
Ingo Molnar01b28382008-12-11 13:45:51 +0100276EXPORT_SYMBOL_GPL(hw_perf_save_disable);
Ingo Molnar241771e2008-12-03 10:39:53 +0100277
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530278static void pmc_intel_restore_all(u64 ctrl)
279{
280 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
281}
282
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530283static void pmc_amd_restore_all(u64 ctrl)
284{
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100285 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530286 int idx;
287
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100288 cpuc->enabled = ctrl;
289 barrier();
290 if (!ctrl)
291 return;
292
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530293 for (idx = 0; idx < nr_counters_generic; idx++) {
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100294 if (test_bit(idx, (unsigned long *)&cpuc->active_mask)) {
295 u64 val;
296
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530297 rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
298 val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
299 wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
300 }
301 }
302}
303
Ingo Molnaree060942008-12-13 09:00:03 +0100304void hw_perf_restore(u64 ctrl)
305{
Ingo Molnar2b9ff0d2008-12-14 18:36:30 +0100306 if (unlikely(!perf_counters_initialized))
307 return;
308
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530309 pmc_ops->restore_all(ctrl);
Ingo Molnaree060942008-12-13 09:00:03 +0100310}
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100311/*
312 * Exported because of ACPI idle
313 */
Ingo Molnaree060942008-12-13 09:00:03 +0100314EXPORT_SYMBOL_GPL(hw_perf_restore);
315
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100316static u64 pmc_intel_get_status(u64 mask)
317{
318 u64 status;
319
320 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
321
322 return status;
323}
324
325static u64 pmc_amd_get_status(u64 mask)
326{
327 u64 status = 0;
328 int idx;
329
330 for (idx = 0; idx < nr_counters_generic; idx++) {
331 s64 val;
332
333 if (!(mask & (1 << idx)))
334 continue;
335
336 rdmsrl(MSR_K7_PERFCTR0 + idx, val);
337 val <<= (64 - counter_value_bits);
338 if (val >= 0)
339 status |= (1 << idx);
340 }
341
342 return status;
343}
344
345static u64 hw_perf_get_status(u64 mask)
346{
347 if (unlikely(!perf_counters_initialized))
348 return 0;
349
350 return pmc_ops->get_status(mask);
351}
352
353static void pmc_intel_ack_status(u64 ack)
354{
355 wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack);
356}
357
358static void pmc_amd_ack_status(u64 ack)
359{
360}
361
362static void hw_perf_ack_status(u64 ack)
363{
364 if (unlikely(!perf_counters_initialized))
365 return;
366
367 pmc_ops->ack_status(ack);
368}
369
370static void pmc_intel_enable(int idx, u64 config)
371{
372 wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + idx,
373 config | ARCH_PERFMON_EVENTSEL0_ENABLE);
374}
375
376static void pmc_amd_enable(int idx, u64 config)
377{
378 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
379
380 set_bit(idx, (unsigned long *)&cpuc->active_mask);
381 if (cpuc->enabled)
382 config |= ARCH_PERFMON_EVENTSEL0_ENABLE;
383
384 wrmsrl(MSR_K7_EVNTSEL0 + idx, config);
385}
386
387static void hw_perf_enable(int idx, u64 config)
388{
389 if (unlikely(!perf_counters_initialized))
390 return;
391
392 pmc_ops->enable(idx, config);
393}
394
395static void pmc_intel_disable(int idx, u64 config)
396{
397 wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + idx, config);
398}
399
400static void pmc_amd_disable(int idx, u64 config)
401{
402 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
403
404 clear_bit(idx, (unsigned long *)&cpuc->active_mask);
405 wrmsrl(MSR_K7_EVNTSEL0 + idx, config);
406
407}
408
409static void hw_perf_disable(int idx, u64 config)
410{
411 if (unlikely(!perf_counters_initialized))
412 return;
413
414 pmc_ops->disable(idx, config);
415}
416
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100417static inline void
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100418__pmc_fixed_disable(struct perf_counter *counter,
419 struct hw_perf_counter *hwc, unsigned int __idx)
420{
421 int idx = __idx - X86_PMC_IDX_FIXED;
422 u64 ctrl_val, mask;
423 int err;
424
425 mask = 0xfULL << (idx * 4);
426
427 rdmsrl(hwc->config_base, ctrl_val);
428 ctrl_val &= ~mask;
429 err = checking_wrmsrl(hwc->config_base, ctrl_val);
430}
431
432static inline void
Ingo Molnareb2b8612008-12-17 09:09:13 +0100433__pmc_generic_disable(struct perf_counter *counter,
Ingo Molnaree060942008-12-13 09:00:03 +0100434 struct hw_perf_counter *hwc, unsigned int idx)
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100435{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100436 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL))
Jaswinder Singh Rajput2b583d82008-12-27 19:15:43 +0530437 __pmc_fixed_disable(counter, hwc, idx);
438 else
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100439 hw_perf_disable(idx, hwc->config);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100440}
441
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100442static DEFINE_PER_CPU(u64, prev_left[X86_PMC_IDX_MAX]);
Ingo Molnar241771e2008-12-03 10:39:53 +0100443
Ingo Molnaree060942008-12-13 09:00:03 +0100444/*
445 * Set the next IRQ period, based on the hwc->period_left value.
446 * To be called with the counter disabled in hw:
447 */
448static void
449__hw_perf_counter_set_period(struct perf_counter *counter,
450 struct hw_perf_counter *hwc, int idx)
Ingo Molnar241771e2008-12-03 10:39:53 +0100451{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100452 s64 left = atomic64_read(&hwc->period_left);
Ingo Molnaree060942008-12-13 09:00:03 +0100453 s32 period = hwc->irq_period;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100454 int err;
Ingo Molnar241771e2008-12-03 10:39:53 +0100455
Ingo Molnaree060942008-12-13 09:00:03 +0100456 /*
457 * If we are way outside a reasoable range then just skip forward:
458 */
459 if (unlikely(left <= -period)) {
460 left = period;
461 atomic64_set(&hwc->period_left, left);
462 }
463
464 if (unlikely(left <= 0)) {
465 left += period;
466 atomic64_set(&hwc->period_left, left);
467 }
468
Ingo Molnaree060942008-12-13 09:00:03 +0100469 per_cpu(prev_left[idx], smp_processor_id()) = left;
470
471 /*
472 * The hw counter starts counting from this counter offset,
473 * mark it to be able to extra future deltas:
474 */
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100475 atomic64_set(&hwc->prev_count, (u64)-left);
Ingo Molnaree060942008-12-13 09:00:03 +0100476
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100477 err = checking_wrmsrl(hwc->counter_base + idx,
478 (u64)(-left) & counter_value_mask);
479}
480
481static inline void
482__pmc_fixed_enable(struct perf_counter *counter,
483 struct hw_perf_counter *hwc, unsigned int __idx)
484{
485 int idx = __idx - X86_PMC_IDX_FIXED;
486 u64 ctrl_val, bits, mask;
487 int err;
488
489 /*
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100490 * Enable IRQ generation (0x8),
491 * and enable ring-3 counting (0x2) and ring-0 counting (0x1)
492 * if requested:
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100493 */
Paul Mackerras0475f9e2009-02-11 14:35:35 +1100494 bits = 0x8ULL;
495 if (hwc->config & ARCH_PERFMON_EVENTSEL_USR)
496 bits |= 0x2;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100497 if (hwc->config & ARCH_PERFMON_EVENTSEL_OS)
498 bits |= 0x1;
499 bits <<= (idx * 4);
500 mask = 0xfULL << (idx * 4);
501
502 rdmsrl(hwc->config_base, ctrl_val);
503 ctrl_val &= ~mask;
504 ctrl_val |= bits;
505 err = checking_wrmsrl(hwc->config_base, ctrl_val);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100506}
507
Ingo Molnaree060942008-12-13 09:00:03 +0100508static void
Ingo Molnareb2b8612008-12-17 09:09:13 +0100509__pmc_generic_enable(struct perf_counter *counter,
Ingo Molnaree060942008-12-13 09:00:03 +0100510 struct hw_perf_counter *hwc, int idx)
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100511{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100512 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL))
Jaswinder Singh Rajput2b583d82008-12-27 19:15:43 +0530513 __pmc_fixed_enable(counter, hwc, idx);
514 else
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100515 hw_perf_enable(idx, hwc->config);
Ingo Molnar241771e2008-12-03 10:39:53 +0100516}
517
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100518static int
519fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc)
Ingo Molnar862a1a52008-12-17 13:09:20 +0100520{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100521 unsigned int event;
522
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530523 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
524 return -1;
525
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100526 if (unlikely(hwc->nmi))
527 return -1;
528
529 event = hwc->config & ARCH_PERFMON_EVENT_MASK;
530
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530531 if (unlikely(event == pmc_ops->event_map(PERF_COUNT_INSTRUCTIONS)))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100532 return X86_PMC_IDX_FIXED_INSTRUCTIONS;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530533 if (unlikely(event == pmc_ops->event_map(PERF_COUNT_CPU_CYCLES)))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100534 return X86_PMC_IDX_FIXED_CPU_CYCLES;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530535 if (unlikely(event == pmc_ops->event_map(PERF_COUNT_BUS_CYCLES)))
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100536 return X86_PMC_IDX_FIXED_BUS_CYCLES;
537
Ingo Molnar862a1a52008-12-17 13:09:20 +0100538 return -1;
539}
540
Ingo Molnaree060942008-12-13 09:00:03 +0100541/*
542 * Find a PMC slot for the freshly enabled / scheduled in counter:
543 */
Ingo Molnar95cdd2e2008-12-21 13:50:42 +0100544static int pmc_generic_enable(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100545{
546 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
547 struct hw_perf_counter *hwc = &counter->hw;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100548 int idx;
Ingo Molnar241771e2008-12-03 10:39:53 +0100549
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100550 idx = fixed_mode_idx(counter, hwc);
551 if (idx >= 0) {
552 /*
553 * Try to get the fixed counter, if that is already taken
554 * then try to get a generic counter:
555 */
556 if (test_and_set_bit(idx, cpuc->used))
557 goto try_generic;
Ingo Molnar0dff86a2008-12-23 12:28:12 +0100558
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100559 hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
560 /*
561 * We set it so that counter_base + idx in wrmsr/rdmsr maps to
562 * MSR_ARCH_PERFMON_FIXED_CTR0 ... CTR2:
563 */
564 hwc->counter_base =
565 MSR_ARCH_PERFMON_FIXED_CTR0 - X86_PMC_IDX_FIXED;
Ingo Molnar241771e2008-12-03 10:39:53 +0100566 hwc->idx = idx;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100567 } else {
568 idx = hwc->idx;
569 /* Try to get the previous generic counter again */
570 if (test_and_set_bit(idx, cpuc->used)) {
571try_generic:
572 idx = find_first_zero_bit(cpuc->used, nr_counters_generic);
573 if (idx == nr_counters_generic)
574 return -EAGAIN;
575
576 set_bit(idx, cpuc->used);
577 hwc->idx = idx;
578 }
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530579 hwc->config_base = pmc_ops->eventsel;
580 hwc->counter_base = pmc_ops->perfctr;
Ingo Molnar241771e2008-12-03 10:39:53 +0100581 }
582
583 perf_counters_lapic_init(hwc->nmi);
584
Ingo Molnareb2b8612008-12-17 09:09:13 +0100585 __pmc_generic_disable(counter, hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100586
Ingo Molnar862a1a52008-12-17 13:09:20 +0100587 cpuc->counters[idx] = counter;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100588 /*
589 * Make it visible before enabling the hw:
590 */
591 smp_wmb();
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100592
Ingo Molnaree060942008-12-13 09:00:03 +0100593 __hw_perf_counter_set_period(counter, hwc, idx);
Ingo Molnareb2b8612008-12-17 09:09:13 +0100594 __pmc_generic_enable(counter, hwc, idx);
Ingo Molnar95cdd2e2008-12-21 13:50:42 +0100595
596 return 0;
Ingo Molnar241771e2008-12-03 10:39:53 +0100597}
598
599void perf_counter_print_debug(void)
600{
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100601 u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed;
Ingo Molnar0dff86a2008-12-23 12:28:12 +0100602 struct cpu_hw_counters *cpuc;
Ingo Molnar1e125672008-12-09 12:18:18 +0100603 int cpu, idx;
604
Ingo Molnar862a1a52008-12-17 13:09:20 +0100605 if (!nr_counters_generic)
Ingo Molnar1e125672008-12-09 12:18:18 +0100606 return;
Ingo Molnar241771e2008-12-03 10:39:53 +0100607
608 local_irq_disable();
609
610 cpu = smp_processor_id();
Ingo Molnar0dff86a2008-12-23 12:28:12 +0100611 cpuc = &per_cpu(cpu_hw_counters, cpu);
Ingo Molnar241771e2008-12-03 10:39:53 +0100612
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530613 if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530614 rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
615 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
616 rdmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
617 rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
Ingo Molnar241771e2008-12-03 10:39:53 +0100618
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530619 pr_info("\n");
620 pr_info("CPU#%d: ctrl: %016llx\n", cpu, ctrl);
621 pr_info("CPU#%d: status: %016llx\n", cpu, status);
622 pr_info("CPU#%d: overflow: %016llx\n", cpu, overflow);
623 pr_info("CPU#%d: fixed: %016llx\n", cpu, fixed);
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530624 }
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530625 pr_info("CPU#%d: used: %016llx\n", cpu, *(u64 *)cpuc->used);
Ingo Molnar241771e2008-12-03 10:39:53 +0100626
Ingo Molnar862a1a52008-12-17 13:09:20 +0100627 for (idx = 0; idx < nr_counters_generic; idx++) {
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530628 rdmsrl(pmc_ops->eventsel + idx, pmc_ctrl);
629 rdmsrl(pmc_ops->perfctr + idx, pmc_count);
Ingo Molnar241771e2008-12-03 10:39:53 +0100630
Ingo Molnaree060942008-12-13 09:00:03 +0100631 prev_left = per_cpu(prev_left[idx], cpu);
Ingo Molnar241771e2008-12-03 10:39:53 +0100632
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530633 pr_info("CPU#%d: gen-PMC%d ctrl: %016llx\n",
Ingo Molnar241771e2008-12-03 10:39:53 +0100634 cpu, idx, pmc_ctrl);
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530635 pr_info("CPU#%d: gen-PMC%d count: %016llx\n",
Ingo Molnar241771e2008-12-03 10:39:53 +0100636 cpu, idx, pmc_count);
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530637 pr_info("CPU#%d: gen-PMC%d left: %016llx\n",
Ingo Molnaree060942008-12-13 09:00:03 +0100638 cpu, idx, prev_left);
Ingo Molnar241771e2008-12-03 10:39:53 +0100639 }
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100640 for (idx = 0; idx < nr_counters_fixed; idx++) {
641 rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, pmc_count);
642
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530643 pr_info("CPU#%d: fixed-PMC%d count: %016llx\n",
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100644 cpu, idx, pmc_count);
645 }
Ingo Molnar241771e2008-12-03 10:39:53 +0100646 local_irq_enable();
647}
648
Ingo Molnareb2b8612008-12-17 09:09:13 +0100649static void pmc_generic_disable(struct perf_counter *counter)
Ingo Molnar241771e2008-12-03 10:39:53 +0100650{
651 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
652 struct hw_perf_counter *hwc = &counter->hw;
653 unsigned int idx = hwc->idx;
654
Ingo Molnareb2b8612008-12-17 09:09:13 +0100655 __pmc_generic_disable(counter, hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100656
657 clear_bit(idx, cpuc->used);
Ingo Molnar862a1a52008-12-17 13:09:20 +0100658 cpuc->counters[idx] = NULL;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100659 /*
660 * Make sure the cleared pointer becomes visible before we
661 * (potentially) free the counter:
662 */
663 smp_wmb();
Ingo Molnar241771e2008-12-03 10:39:53 +0100664
Ingo Molnaree060942008-12-13 09:00:03 +0100665 /*
666 * Drain the remaining delta count out of a counter
667 * that we are disabling:
668 */
669 x86_perf_counter_update(counter, hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100670}
671
672static void perf_store_irq_data(struct perf_counter *counter, u64 data)
673{
674 struct perf_data *irqdata = counter->irqdata;
675
676 if (irqdata->len > PERF_DATA_BUFLEN - sizeof(u64)) {
677 irqdata->overrun++;
678 } else {
679 u64 *p = (u64 *) &irqdata->data[irqdata->len];
680
681 *p = data;
682 irqdata->len += sizeof(u64);
683 }
684}
685
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100686/*
Ingo Molnaree060942008-12-13 09:00:03 +0100687 * Save and restart an expired counter. Called by NMI contexts,
688 * so it has to be careful about preempting normal counter ops:
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100689 */
Ingo Molnar241771e2008-12-03 10:39:53 +0100690static void perf_save_and_restart(struct perf_counter *counter)
691{
692 struct hw_perf_counter *hwc = &counter->hw;
693 int idx = hwc->idx;
Ingo Molnar241771e2008-12-03 10:39:53 +0100694
Ingo Molnaree060942008-12-13 09:00:03 +0100695 x86_perf_counter_update(counter, hwc, idx);
696 __hw_perf_counter_set_period(counter, hwc, idx);
Ingo Molnar7e2ae342008-12-09 11:40:46 +0100697
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100698 if (counter->state == PERF_COUNTER_STATE_ACTIVE)
Ingo Molnareb2b8612008-12-17 09:09:13 +0100699 __pmc_generic_enable(counter, hwc, idx);
Ingo Molnar241771e2008-12-03 10:39:53 +0100700}
701
702static void
Ingo Molnar04289bb2008-12-11 08:38:42 +0100703perf_handle_group(struct perf_counter *sibling, u64 *status, u64 *overflown)
Ingo Molnar241771e2008-12-03 10:39:53 +0100704{
Ingo Molnar04289bb2008-12-11 08:38:42 +0100705 struct perf_counter *counter, *group_leader = sibling->group_leader;
Ingo Molnar241771e2008-12-03 10:39:53 +0100706
Ingo Molnar04289bb2008-12-11 08:38:42 +0100707 /*
Ingo Molnaree060942008-12-13 09:00:03 +0100708 * Store sibling timestamps (if any):
Ingo Molnar04289bb2008-12-11 08:38:42 +0100709 */
710 list_for_each_entry(counter, &group_leader->sibling_list, list_entry) {
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100711
Ingo Molnaree060942008-12-13 09:00:03 +0100712 x86_perf_counter_update(counter, &counter->hw, counter->hw.idx);
Ingo Molnar04289bb2008-12-11 08:38:42 +0100713 perf_store_irq_data(sibling, counter->hw_event.type);
Ingo Molnaree060942008-12-13 09:00:03 +0100714 perf_store_irq_data(sibling, atomic64_read(&counter->count));
Ingo Molnar241771e2008-12-03 10:39:53 +0100715 }
716}
717
718/*
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100719 * Maximum interrupt frequency of 100KHz per CPU
720 */
Jaswinder Singh Rajput169e41e2009-02-28 18:37:49 +0530721#define PERFMON_MAX_INTERRUPTS (100000/HZ)
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100722
723/*
Ingo Molnar241771e2008-12-03 10:39:53 +0100724 * This handler is triggered by the local APIC, so the APIC IRQ handling
725 * rules apply:
726 */
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100727static int __smp_perf_counter_interrupt(struct pt_regs *regs, int nmi)
Ingo Molnar241771e2008-12-03 10:39:53 +0100728{
729 int bit, cpu = smp_processor_id();
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100730 u64 ack, status;
Mike Galbraith1b023a92009-01-23 10:13:01 +0100731 struct cpu_hw_counters *cpuc = &per_cpu(cpu_hw_counters, cpu);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100732 int ret = 0;
Ingo Molnar43874d22008-12-09 12:23:59 +0100733
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100734 cpuc->throttle_ctrl = hw_perf_save_disable();
Ingo Molnar241771e2008-12-03 10:39:53 +0100735
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100736 status = hw_perf_get_status(cpuc->throttle_ctrl);
Ingo Molnar87b9cf42008-12-08 14:20:16 +0100737 if (!status)
738 goto out;
739
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100740 ret = 1;
Ingo Molnar241771e2008-12-03 10:39:53 +0100741again:
Mike Galbraithd278c482009-02-09 07:38:50 +0100742 inc_irq_stat(apic_perf_irqs);
Ingo Molnar241771e2008-12-03 10:39:53 +0100743 ack = status;
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100744 for_each_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
Ingo Molnar862a1a52008-12-17 13:09:20 +0100745 struct perf_counter *counter = cpuc->counters[bit];
Ingo Molnar241771e2008-12-03 10:39:53 +0100746
747 clear_bit(bit, (unsigned long *) &status);
748 if (!counter)
749 continue;
750
751 perf_save_and_restart(counter);
752
Ingo Molnar9f66a382008-12-10 12:33:23 +0100753 switch (counter->hw_event.record_type) {
Ingo Molnar241771e2008-12-03 10:39:53 +0100754 case PERF_RECORD_SIMPLE:
755 continue;
756 case PERF_RECORD_IRQ:
757 perf_store_irq_data(counter, instruction_pointer(regs));
758 break;
759 case PERF_RECORD_GROUP:
Ingo Molnar241771e2008-12-03 10:39:53 +0100760 perf_handle_group(counter, &status, &ack);
761 break;
762 }
763 /*
764 * From NMI context we cannot call into the scheduler to
Ingo Molnareb2b8612008-12-17 09:09:13 +0100765 * do a task wakeup - but we mark these generic as
Ingo Molnar241771e2008-12-03 10:39:53 +0100766 * wakeup_pending and initate a wakeup callback:
767 */
768 if (nmi) {
769 counter->wakeup_pending = 1;
770 set_tsk_thread_flag(current, TIF_PERF_COUNTERS);
771 } else {
772 wake_up(&counter->waitq);
773 }
774 }
775
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100776 hw_perf_ack_status(ack);
Ingo Molnar241771e2008-12-03 10:39:53 +0100777
778 /*
779 * Repeat if there is more work to be done:
780 */
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100781 status = hw_perf_get_status(cpuc->throttle_ctrl);
Ingo Molnar241771e2008-12-03 10:39:53 +0100782 if (status)
783 goto again;
Ingo Molnar87b9cf42008-12-08 14:20:16 +0100784out:
Ingo Molnar241771e2008-12-03 10:39:53 +0100785 /*
Mike Galbraith1b023a92009-01-23 10:13:01 +0100786 * Restore - do not reenable when global enable is off or throttled:
Ingo Molnar241771e2008-12-03 10:39:53 +0100787 */
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100788 if (++cpuc->interrupts < PERFMON_MAX_INTERRUPTS)
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100789 hw_perf_restore(cpuc->throttle_ctrl);
790
791 return ret;
Mike Galbraith1b023a92009-01-23 10:13:01 +0100792}
793
794void perf_counter_unthrottle(void)
795{
796 struct cpu_hw_counters *cpuc;
797
798 if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
799 return;
800
801 if (unlikely(!perf_counters_initialized))
802 return;
803
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100804 cpuc = &__get_cpu_var(cpu_hw_counters);
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100805 if (cpuc->interrupts >= PERFMON_MAX_INTERRUPTS) {
Mike Galbraith1b023a92009-01-23 10:13:01 +0100806 if (printk_ratelimit())
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100807 printk(KERN_WARNING "PERFMON: max interrupts exceeded!\n");
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100808 hw_perf_restore(cpuc->throttle_ctrl);
Mike Galbraith1b023a92009-01-23 10:13:01 +0100809 }
Mike Galbraith4b39fd92009-01-23 14:36:16 +0100810 cpuc->interrupts = 0;
Ingo Molnar241771e2008-12-03 10:39:53 +0100811}
812
813void smp_perf_counter_interrupt(struct pt_regs *regs)
814{
815 irq_enter();
Ingo Molnar241771e2008-12-03 10:39:53 +0100816 apic_write(APIC_LVTPC, LOCAL_PERF_VECTOR);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100817 ack_APIC_irq();
Ingo Molnar241771e2008-12-03 10:39:53 +0100818 __smp_perf_counter_interrupt(regs, 0);
Ingo Molnar241771e2008-12-03 10:39:53 +0100819 irq_exit();
820}
821
822/*
823 * This handler is triggered by NMI contexts:
824 */
825void perf_counter_notify(struct pt_regs *regs)
826{
827 struct cpu_hw_counters *cpuc;
828 unsigned long flags;
829 int bit, cpu;
830
831 local_irq_save(flags);
832 cpu = smp_processor_id();
833 cpuc = &per_cpu(cpu_hw_counters, cpu);
834
Ingo Molnar862a1a52008-12-17 13:09:20 +0100835 for_each_bit(bit, cpuc->used, X86_PMC_IDX_MAX) {
836 struct perf_counter *counter = cpuc->counters[bit];
Ingo Molnar241771e2008-12-03 10:39:53 +0100837
838 if (!counter)
839 continue;
840
841 if (counter->wakeup_pending) {
842 counter->wakeup_pending = 0;
843 wake_up(&counter->waitq);
844 }
845 }
846
847 local_irq_restore(flags);
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
854 if (!perf_counters_initialized)
855 return;
856 /*
857 * Enable the performance counter vector in the APIC LVT:
858 */
859 apic_val = apic_read(APIC_LVTERR);
860
861 apic_write(APIC_LVTERR, apic_val | APIC_LVT_MASKED);
862 if (nmi)
863 apic_write(APIC_LVTPC, APIC_DM_NMI);
864 else
865 apic_write(APIC_LVTPC, LOCAL_PERF_VECTOR);
866 apic_write(APIC_LVTERR, apic_val);
867}
868
869static int __kprobes
870perf_counter_nmi_handler(struct notifier_block *self,
871 unsigned long cmd, void *__args)
872{
873 struct die_args *args = __args;
874 struct pt_regs *regs;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100875 int ret;
Ingo Molnar241771e2008-12-03 10:39:53 +0100876
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100877 switch (cmd) {
878 case DIE_NMI:
879 case DIE_NMI_IPI:
880 break;
881
882 default:
Ingo Molnar241771e2008-12-03 10:39:53 +0100883 return NOTIFY_DONE;
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100884 }
Ingo Molnar241771e2008-12-03 10:39:53 +0100885
886 regs = args->regs;
887
888 apic_write(APIC_LVTPC, APIC_DM_NMI);
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100889 ret = __smp_perf_counter_interrupt(regs, 1);
Ingo Molnar241771e2008-12-03 10:39:53 +0100890
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100891 return ret ? NOTIFY_STOP : NOTIFY_OK;
Ingo Molnar241771e2008-12-03 10:39:53 +0100892}
893
894static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
Mike Galbraith5b75af02009-02-04 17:11:34 +0100895 .notifier_call = perf_counter_nmi_handler,
896 .next = NULL,
897 .priority = 1
Ingo Molnar241771e2008-12-03 10:39:53 +0100898};
899
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530900static struct pmc_x86_ops pmc_intel_ops = {
901 .save_disable_all = pmc_intel_save_disable_all,
902 .restore_all = pmc_intel_restore_all,
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100903 .get_status = pmc_intel_get_status,
904 .ack_status = pmc_intel_ack_status,
905 .enable = pmc_intel_enable,
906 .disable = pmc_intel_disable,
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530907 .eventsel = MSR_ARCH_PERFMON_EVENTSEL0,
908 .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
909 .event_map = pmc_intel_event_map,
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100910 .raw_event = pmc_intel_raw_event,
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530911 .max_events = ARRAY_SIZE(intel_perfmon_event_map),
912};
913
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530914static struct pmc_x86_ops pmc_amd_ops = {
915 .save_disable_all = pmc_amd_save_disable_all,
916 .restore_all = pmc_amd_restore_all,
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100917 .get_status = pmc_amd_get_status,
918 .ack_status = pmc_amd_ack_status,
919 .enable = pmc_amd_enable,
920 .disable = pmc_amd_disable,
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530921 .eventsel = MSR_K7_EVNTSEL0,
922 .perfctr = MSR_K7_PERFCTR0,
923 .event_map = pmc_amd_event_map,
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100924 .raw_event = pmc_amd_raw_event,
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530925 .max_events = ARRAY_SIZE(amd_perfmon_event_map),
926};
927
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530928static struct pmc_x86_ops *pmc_intel_init(void)
Ingo Molnar241771e2008-12-03 10:39:53 +0100929{
930 union cpuid10_eax eax;
Ingo Molnar241771e2008-12-03 10:39:53 +0100931 unsigned int ebx;
Ingo Molnar703e9372008-12-17 10:51:15 +0100932 unsigned int unused;
933 union cpuid10_edx edx;
Ingo Molnar241771e2008-12-03 10:39:53 +0100934
Ingo Molnar241771e2008-12-03 10:39:53 +0100935 /*
936 * Check whether the Architectural PerfMon supports
937 * Branch Misses Retired Event or not.
938 */
Ingo Molnar703e9372008-12-17 10:51:15 +0100939 cpuid(10, &eax.full, &ebx, &unused, &edx.full);
Ingo Molnar241771e2008-12-03 10:39:53 +0100940 if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED)
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530941 return NULL;
Ingo Molnar241771e2008-12-03 10:39:53 +0100942
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530943 pr_info("Intel Performance Monitoring support detected.\n");
944 pr_info("... version: %d\n", eax.split.version_id);
945 pr_info("... bit width: %d\n", eax.split.bit_width);
946 pr_info("... mask length: %d\n", eax.split.mask_length);
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530947
Ingo Molnar862a1a52008-12-17 13:09:20 +0100948 nr_counters_generic = eax.split.num_counters;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530949 nr_counters_fixed = edx.split.num_counters_fixed;
950 counter_value_mask = (1ULL << eax.split.bit_width) - 1;
951
952 return &pmc_intel_ops;
953}
954
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530955static struct pmc_x86_ops *pmc_amd_init(void)
956{
Peter Zijlstrab0f3f282009-03-05 18:08:27 +0100957 u64 old;
958 int bits;
959
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530960 nr_counters_generic = 4;
961 nr_counters_fixed = 0;
Peter Zijlstrab5e8acf2009-03-05 20:34:21 +0100962 counter_value_mask = 0x0000FFFFFFFFFFFFULL;
963 counter_value_bits = 48;
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530964
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530965 pr_info("AMD Performance Monitoring support detected.\n");
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530966
967 return &pmc_amd_ops;
968}
969
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530970void __init init_hw_perf_counters(void)
971{
972 if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
973 return;
974
975 switch (boot_cpu_data.x86_vendor) {
976 case X86_VENDOR_INTEL:
977 pmc_ops = pmc_intel_init();
978 break;
Jaswinder Singh Rajputf87ad352009-02-27 20:15:14 +0530979 case X86_VENDOR_AMD:
980 pmc_ops = pmc_amd_init();
981 break;
Jaswinder Singh Rajputb56a3802009-02-27 18:09:09 +0530982 }
983 if (!pmc_ops)
984 return;
985
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530986 pr_info("... num counters: %d\n", nr_counters_generic);
Ingo Molnar862a1a52008-12-17 13:09:20 +0100987 if (nr_counters_generic > X86_PMC_MAX_GENERIC) {
988 nr_counters_generic = X86_PMC_MAX_GENERIC;
Ingo Molnar241771e2008-12-03 10:39:53 +0100989 WARN(1, KERN_ERR "hw perf counters %d > max(%d), clipping!",
Ingo Molnar862a1a52008-12-17 13:09:20 +0100990 nr_counters_generic, X86_PMC_MAX_GENERIC);
Ingo Molnar241771e2008-12-03 10:39:53 +0100991 }
Ingo Molnar862a1a52008-12-17 13:09:20 +0100992 perf_counter_mask = (1 << nr_counters_generic) - 1;
993 perf_max_counters = nr_counters_generic;
Ingo Molnar241771e2008-12-03 10:39:53 +0100994
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +0530995 pr_info("... value mask: %016Lx\n", counter_value_mask);
Ingo Molnar2f18d1e2008-12-22 11:10:42 +0100996
Ingo Molnar862a1a52008-12-17 13:09:20 +0100997 if (nr_counters_fixed > X86_PMC_MAX_FIXED) {
998 nr_counters_fixed = X86_PMC_MAX_FIXED;
Ingo Molnar703e9372008-12-17 10:51:15 +0100999 WARN(1, KERN_ERR "hw perf counters fixed %d > max(%d), clipping!",
Ingo Molnar862a1a52008-12-17 13:09:20 +01001000 nr_counters_fixed, X86_PMC_MAX_FIXED);
Ingo Molnar703e9372008-12-17 10:51:15 +01001001 }
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +05301002 pr_info("... fixed counters: %d\n", nr_counters_fixed);
Ingo Molnar241771e2008-12-03 10:39:53 +01001003
Ingo Molnar862a1a52008-12-17 13:09:20 +01001004 perf_counter_mask |= ((1LL << nr_counters_fixed)-1) << X86_PMC_IDX_FIXED;
1005
Jaswinder Singh Rajputa1ef58f2009-02-28 18:45:39 +05301006 pr_info("... counter mask: %016Lx\n", perf_counter_mask);
Ingo Molnar75f224c2008-12-14 21:58:46 +01001007 perf_counters_initialized = true;
1008
Ingo Molnar241771e2008-12-03 10:39:53 +01001009 perf_counters_lapic_init(0);
1010 register_die_notifier(&perf_counter_nmi_notifier);
Ingo Molnar241771e2008-12-03 10:39:53 +01001011}
Ingo Molnar621a01e2008-12-11 12:46:46 +01001012
Ingo Molnareb2b8612008-12-17 09:09:13 +01001013static void pmc_generic_read(struct perf_counter *counter)
Ingo Molnaree060942008-12-13 09:00:03 +01001014{
1015 x86_perf_counter_update(counter, &counter->hw, counter->hw.idx);
1016}
1017
Ingo Molnar5c92d122008-12-11 13:21:10 +01001018static const struct hw_perf_counter_ops x86_perf_counter_ops = {
Ingo Molnar76715812008-12-17 14:20:28 +01001019 .enable = pmc_generic_enable,
1020 .disable = pmc_generic_disable,
1021 .read = pmc_generic_read,
Ingo Molnar621a01e2008-12-11 12:46:46 +01001022};
1023
Ingo Molnar5c92d122008-12-11 13:21:10 +01001024const struct hw_perf_counter_ops *
1025hw_perf_counter_init(struct perf_counter *counter)
Ingo Molnar621a01e2008-12-11 12:46:46 +01001026{
1027 int err;
1028
1029 err = __hw_perf_counter_init(counter);
1030 if (err)
1031 return NULL;
1032
1033 return &x86_perf_counter_ops;
1034}