aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorDavid Daney <david.daney@cavium.com>2011-09-23 20:29:55 -0400
committerRalf Baechle <ralf@linux-mips.org>2011-10-24 18:34:26 -0400
commit82091564cfd7ab8def42777a9c662dbf655c5d25 (patch)
tree2e0328b9795a694aa64561958f397770610fab2b /arch/mips
parente5dcb58aa51090f462959b9789eb477286bd2279 (diff)
MIPS: perf: Add support for 64-bit perf counters.
The hard coded constants are moved to struct mips_pmu. All counter register access move to the read_counter and write_counter function pointers, which are set to either 32-bit or 64-bit access methods at initialization time. Many of the function pointers in struct mips_pmu were not needed as there was only a single implementation, these were removed. I couldn't figure out what made struct cpu_hw_events.msbs[] at all useful, so I removed it too. Some functions and other declarations were reordered to reduce the need for forward declarations. Signed-off-by: David Daney <david.daney@cavium.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Deng-Cheng Zhu <dengcheng.zhu@gmail.com> To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2792/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/kernel/perf_event_mipsxx.c858
1 files changed, 389 insertions, 469 deletions
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index eb74dce69c1..0c9549480c4 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -2,6 +2,7 @@
2 * Linux performance counter support for MIPS. 2 * Linux performance counter support for MIPS.
3 * 3 *
4 * Copyright (C) 2010 MIPS Technologies, Inc. 4 * Copyright (C) 2010 MIPS Technologies, Inc.
5 * Copyright (C) 2011 Cavium Networks, Inc.
5 * Author: Deng-Cheng Zhu 6 * Author: Deng-Cheng Zhu
6 * 7 *
7 * This code is based on the implementation for ARM, which is in turn 8 * This code is based on the implementation for ARM, which is in turn
@@ -26,12 +27,6 @@
26#include <asm/stacktrace.h> 27#include <asm/stacktrace.h>
27#include <asm/time.h> /* For perf_irq */ 28#include <asm/time.h> /* For perf_irq */
28 29
29/* These are for 32bit counters. For 64bit ones, define them accordingly. */
30#define MAX_PERIOD ((1ULL << 32) - 1)
31#define VALID_COUNT 0x7fffffff
32#define TOTAL_BITS 32
33#define HIGHEST_BIT 31
34
35#define MIPS_MAX_HWEVENTS 4 30#define MIPS_MAX_HWEVENTS 4
36 31
37struct cpu_hw_events { 32struct cpu_hw_events {
@@ -45,15 +40,6 @@ struct cpu_hw_events {
45 unsigned long used_mask[BITS_TO_LONGS(MIPS_MAX_HWEVENTS)]; 40 unsigned long used_mask[BITS_TO_LONGS(MIPS_MAX_HWEVENTS)];
46 41
47 /* 42 /*
48 * The borrowed MSB for the performance counter. A MIPS performance
49 * counter uses its bit 31 (for 32bit counters) or bit 63 (for 64bit
50 * counters) as a factor of determining whether a counter overflow
51 * should be signaled. So here we use a separate MSB for each
52 * counter to make things easy.
53 */
54 unsigned long msbs[BITS_TO_LONGS(MIPS_MAX_HWEVENTS)];
55
56 /*
57 * Software copy of the control register for each performance counter. 43 * Software copy of the control register for each performance counter.
58 * MIPS CPUs vary in performance counters. They use this differently, 44 * MIPS CPUs vary in performance counters. They use this differently,
59 * and even may not use it. 45 * and even may not use it.
@@ -75,6 +61,7 @@ struct mips_perf_event {
75 unsigned int cntr_mask; 61 unsigned int cntr_mask;
76 #define CNTR_EVEN 0x55555555 62 #define CNTR_EVEN 0x55555555
77 #define CNTR_ODD 0xaaaaaaaa 63 #define CNTR_ODD 0xaaaaaaaa
64 #define CNTR_ALL 0xffffffff
78#ifdef CONFIG_MIPS_MT_SMP 65#ifdef CONFIG_MIPS_MT_SMP
79 enum { 66 enum {
80 T = 0, 67 T = 0,
@@ -95,18 +82,13 @@ static DEFINE_MUTEX(raw_event_mutex);
95#define C(x) PERF_COUNT_HW_CACHE_##x 82#define C(x) PERF_COUNT_HW_CACHE_##x
96 83
97struct mips_pmu { 84struct mips_pmu {
85 u64 max_period;
86 u64 valid_count;
87 u64 overflow;
98 const char *name; 88 const char *name;
99 int irq; 89 int irq;
100 irqreturn_t (*handle_irq)(int irq, void *dev);
101 int (*handle_shared_irq)(void);
102 void (*start)(void);
103 void (*stop)(void);
104 int (*alloc_counter)(struct cpu_hw_events *cpuc,
105 struct hw_perf_event *hwc);
106 u64 (*read_counter)(unsigned int idx); 90 u64 (*read_counter)(unsigned int idx);
107 void (*write_counter)(unsigned int idx, u64 val); 91 void (*write_counter)(unsigned int idx, u64 val);
108 void (*enable_event)(struct hw_perf_event *evt, int idx);
109 void (*disable_event)(int idx);
110 const struct mips_perf_event *(*map_raw_event)(u64 config); 92 const struct mips_perf_event *(*map_raw_event)(u64 config);
111 const struct mips_perf_event (*general_event_map)[PERF_COUNT_HW_MAX]; 93 const struct mips_perf_event (*general_event_map)[PERF_COUNT_HW_MAX];
112 const struct mips_perf_event (*cache_event_map) 94 const struct mips_perf_event (*cache_event_map)
@@ -116,44 +98,302 @@ struct mips_pmu {
116 unsigned int num_counters; 98 unsigned int num_counters;
117}; 99};
118 100
119static const struct mips_pmu *mipspmu; 101static struct mips_pmu mipspmu;
102
103#define M_CONFIG1_PC (1 << 4)
104
105#define M_PERFCTL_EXL (1 << 0)
106#define M_PERFCTL_KERNEL (1 << 1)
107#define M_PERFCTL_SUPERVISOR (1 << 2)
108#define M_PERFCTL_USER (1 << 3)
109#define M_PERFCTL_INTERRUPT_ENABLE (1 << 4)
110#define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5)
111#define M_PERFCTL_VPEID(vpe) ((vpe) << 16)
112#define M_PERFCTL_MT_EN(filter) ((filter) << 20)
113#define M_TC_EN_ALL M_PERFCTL_MT_EN(0)
114#define M_TC_EN_VPE M_PERFCTL_MT_EN(1)
115#define M_TC_EN_TC M_PERFCTL_MT_EN(2)
116#define M_PERFCTL_TCID(tcid) ((tcid) << 22)
117#define M_PERFCTL_WIDE (1 << 30)
118#define M_PERFCTL_MORE (1 << 31)
119
120#define M_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \
121 M_PERFCTL_KERNEL | \
122 M_PERFCTL_USER | \
123 M_PERFCTL_SUPERVISOR | \
124 M_PERFCTL_INTERRUPT_ENABLE)
125
126#ifdef CONFIG_MIPS_MT_SMP
127#define M_PERFCTL_CONFIG_MASK 0x3fff801f
128#else
129#define M_PERFCTL_CONFIG_MASK 0x1f
130#endif
131#define M_PERFCTL_EVENT_MASK 0xfe0
132
133
134#ifdef CONFIG_MIPS_MT_SMP
135static int cpu_has_mipsmt_pertccounters;
136
137static DEFINE_RWLOCK(pmuint_rwlock);
138
139/*
140 * FIXME: For VSMP, vpe_id() is redefined for Perf-events, because
141 * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs.
142 */
143#if defined(CONFIG_HW_PERF_EVENTS)
144#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
145 0 : smp_processor_id())
146#else
147#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
148 0 : cpu_data[smp_processor_id()].vpe_id)
149#endif
150
151/* Copied from op_model_mipsxx.c */
152static unsigned int vpe_shift(void)
153{
154 if (num_possible_cpus() > 1)
155 return 1;
156
157 return 0;
158}
159
160static unsigned int counters_total_to_per_cpu(unsigned int counters)
161{
162 return counters >> vpe_shift();
163}
164
165static unsigned int counters_per_cpu_to_total(unsigned int counters)
166{
167 return counters << vpe_shift();
168}
169
170#else /* !CONFIG_MIPS_MT_SMP */
171#define vpe_id() 0
172
173#endif /* CONFIG_MIPS_MT_SMP */
174
175static void resume_local_counters(void);
176static void pause_local_counters(void);
177static irqreturn_t mipsxx_pmu_handle_irq(int, void *);
178static int mipsxx_pmu_handle_shared_irq(void);
179
180static unsigned int mipsxx_pmu_swizzle_perf_idx(unsigned int idx)
181{
182 if (vpe_id() == 1)
183 idx = (idx + 2) & 3;
184 return idx;
185}
186
187static u64 mipsxx_pmu_read_counter(unsigned int idx)
188{
189 idx = mipsxx_pmu_swizzle_perf_idx(idx);
190
191 switch (idx) {
192 case 0:
193 /*
194 * The counters are unsigned, we must cast to truncate
195 * off the high bits.
196 */
197 return (u32)read_c0_perfcntr0();
198 case 1:
199 return (u32)read_c0_perfcntr1();
200 case 2:
201 return (u32)read_c0_perfcntr2();
202 case 3:
203 return (u32)read_c0_perfcntr3();
204 default:
205 WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
206 return 0;
207 }
208}
209
210static u64 mipsxx_pmu_read_counter_64(unsigned int idx)
211{
212 idx = mipsxx_pmu_swizzle_perf_idx(idx);
213
214 switch (idx) {
215 case 0:
216 return read_c0_perfcntr0_64();
217 case 1:
218 return read_c0_perfcntr1_64();
219 case 2:
220 return read_c0_perfcntr2_64();
221 case 3:
222 return read_c0_perfcntr3_64();
223 default:
224 WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
225 return 0;
226 }
227}
228
229static void mipsxx_pmu_write_counter(unsigned int idx, u64 val)
230{
231 idx = mipsxx_pmu_swizzle_perf_idx(idx);
232
233 switch (idx) {
234 case 0:
235 write_c0_perfcntr0(val);
236 return;
237 case 1:
238 write_c0_perfcntr1(val);
239 return;
240 case 2:
241 write_c0_perfcntr2(val);
242 return;
243 case 3:
244 write_c0_perfcntr3(val);
245 return;
246 }
247}
248
249static void mipsxx_pmu_write_counter_64(unsigned int idx, u64 val)
250{
251 idx = mipsxx_pmu_swizzle_perf_idx(idx);
252
253 switch (idx) {
254 case 0:
255 write_c0_perfcntr0_64(val);
256 return;
257 case 1:
258 write_c0_perfcntr1_64(val);
259 return;
260 case 2:
261 write_c0_perfcntr2_64(val);
262 return;
263 case 3:
264 write_c0_perfcntr3_64(val);
265 return;
266 }
267}
268
269static unsigned int mipsxx_pmu_read_control(unsigned int idx)
270{
271 idx = mipsxx_pmu_swizzle_perf_idx(idx);
272
273 switch (idx) {
274 case 0:
275 return read_c0_perfctrl0();
276 case 1:
277 return read_c0_perfctrl1();
278 case 2:
279 return read_c0_perfctrl2();
280 case 3:
281 return read_c0_perfctrl3();
282 default:
283 WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
284 return 0;
285 }
286}
287
288static void mipsxx_pmu_write_control(unsigned int idx, unsigned int val)
289{
290 idx = mipsxx_pmu_swizzle_perf_idx(idx);
291
292 switch (idx) {
293 case 0:
294 write_c0_perfctrl0(val);
295 return;
296 case 1:
297 write_c0_perfctrl1(val);
298 return;
299 case 2:
300 write_c0_perfctrl2(val);
301 return;
302 case 3:
303 write_c0_perfctrl3(val);
304 return;
305 }
306}
307
308static int mipsxx_pmu_alloc_counter(struct cpu_hw_events *cpuc,
309 struct hw_perf_event *hwc)
310{
311 int i;
312
313 /*
314 * We only need to care the counter mask. The range has been
315 * checked definitely.
316 */
317 unsigned long cntr_mask = (hwc->event_base >> 8) & 0xffff;
318
319 for (i = mipspmu.num_counters - 1; i >= 0; i--) {
320 /*
321 * Note that some MIPS perf events can be counted by both
322 * even and odd counters, wheresas many other are only by
323 * even _or_ odd counters. This introduces an issue that
324 * when the former kind of event takes the counter the
325 * latter kind of event wants to use, then the "counter
326 * allocation" for the latter event will fail. In fact if
327 * they can be dynamically swapped, they both feel happy.
328 * But here we leave this issue alone for now.
329 */
330 if (test_bit(i, &cntr_mask) &&
331 !test_and_set_bit(i, cpuc->used_mask))
332 return i;
333 }
334
335 return -EAGAIN;
336}
337
338static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
339{
340 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
341
342 WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
343
344 cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(evt->event_base & 0xff) |
345 (evt->config_base & M_PERFCTL_CONFIG_MASK) |
346 /* Make sure interrupt enabled. */
347 M_PERFCTL_INTERRUPT_ENABLE;
348 /*
349 * We do not actually let the counter run. Leave it until start().
350 */
351}
352
353static void mipsxx_pmu_disable_event(int idx)
354{
355 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
356 unsigned long flags;
357
358 WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
359
360 local_irq_save(flags);
361 cpuc->saved_ctrl[idx] = mipsxx_pmu_read_control(idx) &
362 ~M_PERFCTL_COUNT_EVENT_WHENEVER;
363 mipsxx_pmu_write_control(idx, cpuc->saved_ctrl[idx]);
364 local_irq_restore(flags);
365}
120 366
121static int mipspmu_event_set_period(struct perf_event *event, 367static int mipspmu_event_set_period(struct perf_event *event,
122 struct hw_perf_event *hwc, 368 struct hw_perf_event *hwc,
123 int idx) 369 int idx)
124{ 370{
125 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 371 u64 left = local64_read(&hwc->period_left);
126 s64 left = local64_read(&hwc->period_left); 372 u64 period = hwc->sample_period;
127 s64 period = hwc->sample_period;
128 int ret = 0; 373 int ret = 0;
129 u64 uleft;
130 unsigned long flags;
131 374
132 if (unlikely(left <= -period)) { 375 if (unlikely((left + period) & (1ULL << 63))) {
376 /* left underflowed by more than period. */
133 left = period; 377 left = period;
134 local64_set(&hwc->period_left, left); 378 local64_set(&hwc->period_left, left);
135 hwc->last_period = period; 379 hwc->last_period = period;
136 ret = 1; 380 ret = 1;
137 } 381 } else if (unlikely((left + period) <= period)) {
138 382 /* left underflowed by less than period. */
139 if (unlikely(left <= 0)) {
140 left += period; 383 left += period;
141 local64_set(&hwc->period_left, left); 384 local64_set(&hwc->period_left, left);
142 hwc->last_period = period; 385 hwc->last_period = period;
143 ret = 1; 386 ret = 1;
144 } 387 }
145 388
146 if (left > (s64)MAX_PERIOD) 389 if (left > mipspmu.max_period) {
147 left = MAX_PERIOD; 390 left = mipspmu.max_period;
391 local64_set(&hwc->period_left, left);
392 }
148 393
149 local64_set(&hwc->prev_count, (u64)-left); 394 local64_set(&hwc->prev_count, mipspmu.overflow - left);
150 395
151 local_irq_save(flags); 396 mipspmu.write_counter(idx, mipspmu.overflow - left);
152 uleft = (u64)(-left) & MAX_PERIOD;
153 uleft > VALID_COUNT ?
154 set_bit(idx, cpuc->msbs) : clear_bit(idx, cpuc->msbs);
155 mipspmu->write_counter(idx, (u64)(-left) & VALID_COUNT);
156 local_irq_restore(flags);
157 397
158 perf_event_update_userpage(event); 398 perf_event_update_userpage(event);
159 399
@@ -164,30 +404,18 @@ static void mipspmu_event_update(struct perf_event *event,
164 struct hw_perf_event *hwc, 404 struct hw_perf_event *hwc,
165 int idx) 405 int idx)
166{ 406{
167 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 407 u64 prev_raw_count, new_raw_count;
168 unsigned long flags;
169 int shift = 64 - TOTAL_BITS;
170 s64 prev_raw_count, new_raw_count;
171 u64 delta; 408 u64 delta;
172 409
173again: 410again:
174 prev_raw_count = local64_read(&hwc->prev_count); 411 prev_raw_count = local64_read(&hwc->prev_count);
175 local_irq_save(flags); 412 new_raw_count = mipspmu.read_counter(idx);
176 /* Make the counter value be a "real" one. */
177 new_raw_count = mipspmu->read_counter(idx);
178 if (new_raw_count & (test_bit(idx, cpuc->msbs) << HIGHEST_BIT)) {
179 new_raw_count &= VALID_COUNT;
180 clear_bit(idx, cpuc->msbs);
181 } else
182 new_raw_count |= (test_bit(idx, cpuc->msbs) << HIGHEST_BIT);
183 local_irq_restore(flags);
184 413
185 if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, 414 if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
186 new_raw_count) != prev_raw_count) 415 new_raw_count) != prev_raw_count)
187 goto again; 416 goto again;
188 417
189 delta = (new_raw_count << shift) - (prev_raw_count << shift); 418 delta = new_raw_count - prev_raw_count;
190 delta >>= shift;
191 419
192 local64_add(delta, &event->count); 420 local64_add(delta, &event->count);
193 local64_sub(delta, &hwc->period_left); 421 local64_sub(delta, &hwc->period_left);
@@ -197,9 +425,6 @@ static void mipspmu_start(struct perf_event *event, int flags)
197{ 425{
198 struct hw_perf_event *hwc = &event->hw; 426 struct hw_perf_event *hwc = &event->hw;
199 427
200 if (!mipspmu)
201 return;
202
203 if (flags & PERF_EF_RELOAD) 428 if (flags & PERF_EF_RELOAD)
204 WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); 429 WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
205 430
@@ -209,19 +434,16 @@ static void mipspmu_start(struct perf_event *event, int flags)
209 mipspmu_event_set_period(event, hwc, hwc->idx); 434 mipspmu_event_set_period(event, hwc, hwc->idx);
210 435
211 /* Enable the event. */ 436 /* Enable the event. */
212 mipspmu->enable_event(hwc, hwc->idx); 437 mipsxx_pmu_enable_event(hwc, hwc->idx);
213} 438}
214 439
215static void mipspmu_stop(struct perf_event *event, int flags) 440static void mipspmu_stop(struct perf_event *event, int flags)
216{ 441{
217 struct hw_perf_event *hwc = &event->hw; 442 struct hw_perf_event *hwc = &event->hw;
218 443
219 if (!mipspmu)
220 return;
221
222 if (!(hwc->state & PERF_HES_STOPPED)) { 444 if (!(hwc->state & PERF_HES_STOPPED)) {
223 /* We are working on a local event. */ 445 /* We are working on a local event. */
224 mipspmu->disable_event(hwc->idx); 446 mipsxx_pmu_disable_event(hwc->idx);
225 barrier(); 447 barrier();
226 mipspmu_event_update(event, hwc, hwc->idx); 448 mipspmu_event_update(event, hwc, hwc->idx);
227 hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; 449 hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
@@ -238,7 +460,7 @@ static int mipspmu_add(struct perf_event *event, int flags)
238 perf_pmu_disable(event->pmu); 460 perf_pmu_disable(event->pmu);
239 461
240 /* To look for a free counter for this event. */ 462 /* To look for a free counter for this event. */
241 idx = mipspmu->alloc_counter(cpuc, hwc); 463 idx = mipsxx_pmu_alloc_counter(cpuc, hwc);
242 if (idx < 0) { 464 if (idx < 0) {
243 err = idx; 465 err = idx;
244 goto out; 466 goto out;
@@ -249,7 +471,7 @@ static int mipspmu_add(struct perf_event *event, int flags)
249 * make sure it is disabled. 471 * make sure it is disabled.
250 */ 472 */
251 event->hw.idx = idx; 473 event->hw.idx = idx;
252 mipspmu->disable_event(idx); 474 mipsxx_pmu_disable_event(idx);
253 cpuc->events[idx] = event; 475 cpuc->events[idx] = event;
254 476
255 hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; 477 hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
@@ -270,7 +492,7 @@ static void mipspmu_del(struct perf_event *event, int flags)
270 struct hw_perf_event *hwc = &event->hw; 492 struct hw_perf_event *hwc = &event->hw;
271 int idx = hwc->idx; 493 int idx = hwc->idx;
272 494
273 WARN_ON(idx < 0 || idx >= mipspmu->num_counters); 495 WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
274 496
275 mipspmu_stop(event, PERF_EF_UPDATE); 497 mipspmu_stop(event, PERF_EF_UPDATE);
276 cpuc->events[idx] = NULL; 498 cpuc->events[idx] = NULL;
@@ -292,14 +514,29 @@ static void mipspmu_read(struct perf_event *event)
292 514
293static void mipspmu_enable(struct pmu *pmu) 515static void mipspmu_enable(struct pmu *pmu)
294{ 516{
295 if (mipspmu) 517#ifdef CONFIG_MIPS_MT_SMP
296 mipspmu->start(); 518 write_unlock(&pmuint_rwlock);
519#endif
520 resume_local_counters();
297} 521}
298 522
523/*
524 * MIPS performance counters can be per-TC. The control registers can
525 * not be directly accessed accross CPUs. Hence if we want to do global
526 * control, we need cross CPU calls. on_each_cpu() can help us, but we
527 * can not make sure this function is called with interrupts enabled. So
528 * here we pause local counters and then grab a rwlock and leave the
529 * counters on other CPUs alone. If any counter interrupt raises while
530 * we own the write lock, simply pause local counters on that CPU and
531 * spin in the handler. Also we know we won't be switched to another
532 * CPU after pausing local counters and before grabbing the lock.
533 */
299static void mipspmu_disable(struct pmu *pmu) 534static void mipspmu_disable(struct pmu *pmu)
300{ 535{
301 if (mipspmu) 536 pause_local_counters();
302 mipspmu->stop(); 537#ifdef CONFIG_MIPS_MT_SMP
538 write_lock(&pmuint_rwlock);
539#endif
303} 540}
304 541
305static atomic_t active_events = ATOMIC_INIT(0); 542static atomic_t active_events = ATOMIC_INIT(0);
@@ -310,21 +547,21 @@ static int mipspmu_get_irq(void)
310{ 547{
311 int err; 548 int err;
312 549
313 if (mipspmu->irq >= 0) { 550 if (mipspmu.irq >= 0) {
314 /* Request my own irq handler. */ 551 /* Request my own irq handler. */
315 err = request_irq(mipspmu->irq, mipspmu->handle_irq, 552 err = request_irq(mipspmu.irq, mipsxx_pmu_handle_irq,
316 IRQF_DISABLED | IRQF_NOBALANCING, 553 IRQF_PERCPU | IRQF_NOBALANCING,
317 "mips_perf_pmu", NULL); 554 "mips_perf_pmu", NULL);
318 if (err) { 555 if (err) {
319 pr_warning("Unable to request IRQ%d for MIPS " 556 pr_warning("Unable to request IRQ%d for MIPS "
320 "performance counters!\n", mipspmu->irq); 557 "performance counters!\n", mipspmu.irq);
321 } 558 }
322 } else if (cp0_perfcount_irq < 0) { 559 } else if (cp0_perfcount_irq < 0) {
323 /* 560 /*
324 * We are sharing the irq number with the timer interrupt. 561 * We are sharing the irq number with the timer interrupt.
325 */ 562 */
326 save_perf_irq = perf_irq; 563 save_perf_irq = perf_irq;
327 perf_irq = mipspmu->handle_shared_irq; 564 perf_irq = mipsxx_pmu_handle_shared_irq;
328 err = 0; 565 err = 0;
329 } else { 566 } else {
330 pr_warning("The platform hasn't properly defined its " 567 pr_warning("The platform hasn't properly defined its "
@@ -337,8 +574,8 @@ static int mipspmu_get_irq(void)
337 574
338static void mipspmu_free_irq(void) 575static void mipspmu_free_irq(void)
339{ 576{
340 if (mipspmu->irq >= 0) 577 if (mipspmu.irq >= 0)
341 free_irq(mipspmu->irq, NULL); 578 free_irq(mipspmu.irq, NULL);
342 else if (cp0_perfcount_irq < 0) 579 else if (cp0_perfcount_irq < 0)
343 perf_irq = save_perf_irq; 580 perf_irq = save_perf_irq;
344} 581}
@@ -359,7 +596,7 @@ static void hw_perf_event_destroy(struct perf_event *event)
359 * disabled. 596 * disabled.
360 */ 597 */
361 on_each_cpu(reset_counters, 598 on_each_cpu(reset_counters,
362 (void *)(long)mipspmu->num_counters, 1); 599 (void *)(long)mipspmu.num_counters, 1);
363 mipspmu_free_irq(); 600 mipspmu_free_irq();
364 mutex_unlock(&pmu_reserve_mutex); 601 mutex_unlock(&pmu_reserve_mutex);
365 } 602 }
@@ -379,8 +616,8 @@ static int mipspmu_event_init(struct perf_event *event)
379 return -ENOENT; 616 return -ENOENT;
380 } 617 }
381 618
382 if (!mipspmu || event->cpu >= nr_cpumask_bits || 619 if (event->cpu >= nr_cpumask_bits ||
383 (event->cpu >= 0 && !cpu_online(event->cpu))) 620 (event->cpu >= 0 && !cpu_online(event->cpu)))
384 return -ENODEV; 621 return -ENODEV;
385 622
386 if (!atomic_inc_not_zero(&active_events)) { 623 if (!atomic_inc_not_zero(&active_events)) {
@@ -439,9 +676,9 @@ static const struct mips_perf_event *mipspmu_map_general_event(int idx)
439{ 676{
440 const struct mips_perf_event *pev; 677 const struct mips_perf_event *pev;
441 678
442 pev = ((*mipspmu->general_event_map)[idx].event_id == 679 pev = ((*mipspmu.general_event_map)[idx].event_id ==
443 UNSUPPORTED_PERF_EVENT_ID ? ERR_PTR(-EOPNOTSUPP) : 680 UNSUPPORTED_PERF_EVENT_ID ? ERR_PTR(-EOPNOTSUPP) :
444 &(*mipspmu->general_event_map)[idx]); 681 &(*mipspmu.general_event_map)[idx]);
445 682
446 return pev; 683 return pev;
447} 684}
@@ -463,7 +700,7 @@ static const struct mips_perf_event *mipspmu_map_cache_event(u64 config)
463 if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) 700 if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
464 return ERR_PTR(-EINVAL); 701 return ERR_PTR(-EINVAL);
465 702
466 pev = &((*mipspmu->cache_event_map) 703 pev = &((*mipspmu.cache_event_map)
467 [cache_type] 704 [cache_type]
468 [cache_op] 705 [cache_op]
469 [cache_result]); 706 [cache_result]);
@@ -484,7 +721,7 @@ static int validate_event(struct cpu_hw_events *cpuc,
484 if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF) 721 if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
485 return 1; 722 return 1;
486 723
487 return mipspmu->alloc_counter(cpuc, &fake_hwc) >= 0; 724 return mipsxx_pmu_alloc_counter(cpuc, &fake_hwc) >= 0;
488} 725}
489 726
490static int validate_group(struct perf_event *event) 727static int validate_group(struct perf_event *event)
@@ -522,123 +759,9 @@ static void handle_associated_event(struct cpu_hw_events *cpuc,
522 return; 759 return;
523 760
524 if (perf_event_overflow(event, data, regs)) 761 if (perf_event_overflow(event, data, regs))
525 mipspmu->disable_event(idx); 762 mipsxx_pmu_disable_event(idx);
526} 763}
527 764
528#define M_CONFIG1_PC (1 << 4)
529
530#define M_PERFCTL_EXL (1UL << 0)
531#define M_PERFCTL_KERNEL (1UL << 1)
532#define M_PERFCTL_SUPERVISOR (1UL << 2)
533#define M_PERFCTL_USER (1UL << 3)
534#define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4)
535#define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5)
536#define M_PERFCTL_VPEID(vpe) ((vpe) << 16)
537#define M_PERFCTL_MT_EN(filter) ((filter) << 20)
538#define M_TC_EN_ALL M_PERFCTL_MT_EN(0)
539#define M_TC_EN_VPE M_PERFCTL_MT_EN(1)
540#define M_TC_EN_TC M_PERFCTL_MT_EN(2)
541#define M_PERFCTL_TCID(tcid) ((tcid) << 22)
542#define M_PERFCTL_WIDE (1UL << 30)
543#define M_PERFCTL_MORE (1UL << 31)
544
545#define M_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \
546 M_PERFCTL_KERNEL | \
547 M_PERFCTL_USER | \
548 M_PERFCTL_SUPERVISOR | \
549 M_PERFCTL_INTERRUPT_ENABLE)
550
551#ifdef CONFIG_MIPS_MT_SMP
552#define M_PERFCTL_CONFIG_MASK 0x3fff801f
553#else
554#define M_PERFCTL_CONFIG_MASK 0x1f
555#endif
556#define M_PERFCTL_EVENT_MASK 0xfe0
557
558#define M_COUNTER_OVERFLOW (1UL << 31)
559
560#ifdef CONFIG_MIPS_MT_SMP
561static int cpu_has_mipsmt_pertccounters;
562
563/*
564 * FIXME: For VSMP, vpe_id() is redefined for Perf-events, because
565 * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs.
566 */
567#if defined(CONFIG_HW_PERF_EVENTS)
568#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
569 0 : smp_processor_id())
570#else
571#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
572 0 : cpu_data[smp_processor_id()].vpe_id)
573#endif
574
575/* Copied from op_model_mipsxx.c */
576static unsigned int vpe_shift(void)
577{
578 if (num_possible_cpus() > 1)
579 return 1;
580
581 return 0;
582}
583
584static unsigned int counters_total_to_per_cpu(unsigned int counters)
585{
586 return counters >> vpe_shift();
587}
588
589static unsigned int counters_per_cpu_to_total(unsigned int counters)
590{
591 return counters << vpe_shift();
592}
593
594#else /* !CONFIG_MIPS_MT_SMP */
595#define vpe_id() 0
596
597#endif /* CONFIG_MIPS_MT_SMP */
598
599#define __define_perf_accessors(r, n, np) \
600 \
601static unsigned int r_c0_ ## r ## n(void) \
602{ \
603 unsigned int cpu = vpe_id(); \
604 \
605 switch (cpu) { \
606 case 0: \
607 return read_c0_ ## r ## n(); \
608 case 1: \
609 return read_c0_ ## r ## np(); \
610 default: \
611 BUG(); \
612 } \
613 return 0; \
614} \
615 \
616static void w_c0_ ## r ## n(unsigned int value) \
617{ \
618 unsigned int cpu = vpe_id(); \
619 \
620 switch (cpu) { \
621 case 0: \
622 write_c0_ ## r ## n(value); \
623 return; \
624 case 1: \
625 write_c0_ ## r ## np(value); \
626 return; \
627 default: \
628 BUG(); \
629 } \
630 return; \
631} \
632
633__define_perf_accessors(perfcntr, 0, 2)
634__define_perf_accessors(perfcntr, 1, 3)
635__define_perf_accessors(perfcntr, 2, 0)
636__define_perf_accessors(perfcntr, 3, 1)
637
638__define_perf_accessors(perfctrl, 0, 2)
639__define_perf_accessors(perfctrl, 1, 3)
640__define_perf_accessors(perfctrl, 2, 0)
641__define_perf_accessors(perfctrl, 3, 1)
642 765
643static int __n_counters(void) 766static int __n_counters(void)
644{ 767{
@@ -680,94 +803,20 @@ static void reset_counters(void *arg)
680 int counters = (int)(long)arg; 803 int counters = (int)(long)arg;
681 switch (counters) { 804 switch (counters) {
682 case 4: 805 case 4:
683 w_c0_perfctrl3(0); 806 mipsxx_pmu_write_control(3, 0);
684 w_c0_perfcntr3(0); 807 mipspmu.write_counter(3, 0);
685 case 3:
686 w_c0_perfctrl2(0);
687 w_c0_perfcntr2(0);
688 case 2:
689 w_c0_perfctrl1(0);
690 w_c0_perfcntr1(0);
691 case 1:
692 w_c0_perfctrl0(0);
693 w_c0_perfcntr0(0);
694 }
695}
696
697static u64 mipsxx_pmu_read_counter(unsigned int idx)
698{
699 switch (idx) {
700 case 0:
701 return r_c0_perfcntr0();
702 case 1:
703 return r_c0_perfcntr1();
704 case 2:
705 return r_c0_perfcntr2();
706 case 3: 808 case 3:
707 return r_c0_perfcntr3(); 809 mipsxx_pmu_write_control(2, 0);
708 default: 810 mipspmu.write_counter(2, 0);
709 WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
710 return 0;
711 }
712}
713
714static void mipsxx_pmu_write_counter(unsigned int idx, u64 val)
715{
716 switch (idx) {
717 case 0:
718 w_c0_perfcntr0(val);
719 return;
720 case 1:
721 w_c0_perfcntr1(val);
722 return;
723 case 2: 811 case 2:
724 w_c0_perfcntr2(val); 812 mipsxx_pmu_write_control(1, 0);
725 return; 813 mipspmu.write_counter(1, 0);
726 case 3:
727 w_c0_perfcntr3(val);
728 return;
729 }
730}
731
732static unsigned int mipsxx_pmu_read_control(unsigned int idx)
733{
734 switch (idx) {
735 case 0:
736 return r_c0_perfctrl0();
737 case 1: 814 case 1:
738 return r_c0_perfctrl1(); 815 mipsxx_pmu_write_control(0, 0);
739 case 2: 816 mipspmu.write_counter(0, 0);
740 return r_c0_perfctrl2();
741 case 3:
742 return r_c0_perfctrl3();
743 default:
744 WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
745 return 0;
746 } 817 }
747} 818}
748 819
749static void mipsxx_pmu_write_control(unsigned int idx, unsigned int val)
750{
751 switch (idx) {
752 case 0:
753 w_c0_perfctrl0(val);
754 return;
755 case 1:
756 w_c0_perfctrl1(val);
757 return;
758 case 2:
759 w_c0_perfctrl2(val);
760 return;
761 case 3:
762 w_c0_perfctrl3(val);
763 return;
764 }
765}
766
767#ifdef CONFIG_MIPS_MT_SMP
768static DEFINE_RWLOCK(pmuint_rwlock);
769#endif
770
771/* 24K/34K/1004K cores can share the same event map. */ 820/* 24K/34K/1004K cores can share the same event map. */
772static const struct mips_perf_event mipsxxcore_event_map 821static const struct mips_perf_event mipsxxcore_event_map
773 [PERF_COUNT_HW_MAX] = { 822 [PERF_COUNT_HW_MAX] = {
@@ -1073,7 +1122,7 @@ static int __hw_perf_event_init(struct perf_event *event)
1073 } else if (PERF_TYPE_RAW == event->attr.type) { 1122 } else if (PERF_TYPE_RAW == event->attr.type) {
1074 /* We are working on the global raw event. */ 1123 /* We are working on the global raw event. */
1075 mutex_lock(&raw_event_mutex); 1124 mutex_lock(&raw_event_mutex);
1076 pev = mipspmu->map_raw_event(event->attr.config); 1125 pev = mipspmu.map_raw_event(event->attr.config);
1077 } else { 1126 } else {
1078 /* The event type is not (yet) supported. */ 1127 /* The event type is not (yet) supported. */
1079 return -EOPNOTSUPP; 1128 return -EOPNOTSUPP;
@@ -1118,7 +1167,7 @@ static int __hw_perf_event_init(struct perf_event *event)
1118 hwc->config = 0; 1167 hwc->config = 0;
1119 1168
1120 if (!hwc->sample_period) { 1169 if (!hwc->sample_period) {
1121 hwc->sample_period = MAX_PERIOD; 1170 hwc->sample_period = mipspmu.max_period;
1122 hwc->last_period = hwc->sample_period; 1171 hwc->last_period = hwc->sample_period;
1123 local64_set(&hwc->period_left, hwc->sample_period); 1172 local64_set(&hwc->period_left, hwc->sample_period);
1124 } 1173 }
@@ -1131,70 +1180,47 @@ static int __hw_perf_event_init(struct perf_event *event)
1131 } 1180 }
1132 1181
1133 event->destroy = hw_perf_event_destroy; 1182 event->destroy = hw_perf_event_destroy;
1134
1135 return err; 1183 return err;
1136} 1184}
1137 1185
1138static void pause_local_counters(void) 1186static void pause_local_counters(void)
1139{ 1187{
1140 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 1188 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1141 int counters = mipspmu->num_counters; 1189 int ctr = mipspmu.num_counters;
1142 unsigned long flags; 1190 unsigned long flags;
1143 1191
1144 local_irq_save(flags); 1192 local_irq_save(flags);
1145 switch (counters) { 1193 do {
1146 case 4: 1194 ctr--;
1147 cpuc->saved_ctrl[3] = r_c0_perfctrl3(); 1195 cpuc->saved_ctrl[ctr] = mipsxx_pmu_read_control(ctr);
1148 w_c0_perfctrl3(cpuc->saved_ctrl[3] & 1196 mipsxx_pmu_write_control(ctr, cpuc->saved_ctrl[ctr] &
1149 ~M_PERFCTL_COUNT_EVENT_WHENEVER); 1197 ~M_PERFCTL_COUNT_EVENT_WHENEVER);
1150 case 3: 1198 } while (ctr > 0);
1151 cpuc->saved_ctrl[2] = r_c0_perfctrl2();
1152 w_c0_perfctrl2(cpuc->saved_ctrl[2] &
1153 ~M_PERFCTL_COUNT_EVENT_WHENEVER);
1154 case 2:
1155 cpuc->saved_ctrl[1] = r_c0_perfctrl1();
1156 w_c0_perfctrl1(cpuc->saved_ctrl[1] &
1157 ~M_PERFCTL_COUNT_EVENT_WHENEVER);
1158 case 1:
1159 cpuc->saved_ctrl[0] = r_c0_perfctrl0();
1160 w_c0_perfctrl0(cpuc->saved_ctrl[0] &
1161 ~M_PERFCTL_COUNT_EVENT_WHENEVER);
1162 }
1163 local_irq_restore(flags); 1199 local_irq_restore(flags);
1164} 1200}
1165 1201
1166static void resume_local_counters(void) 1202static void resume_local_counters(void)
1167{ 1203{
1168 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 1204 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1169 int counters = mipspmu->num_counters; 1205 int ctr = mipspmu.num_counters;
1170 unsigned long flags;
1171 1206
1172 local_irq_save(flags); 1207 do {
1173 switch (counters) { 1208 ctr--;
1174 case 4: 1209 mipsxx_pmu_write_control(ctr, cpuc->saved_ctrl[ctr]);
1175 w_c0_perfctrl3(cpuc->saved_ctrl[3]); 1210 } while (ctr > 0);
1176 case 3:
1177 w_c0_perfctrl2(cpuc->saved_ctrl[2]);
1178 case 2:
1179 w_c0_perfctrl1(cpuc->saved_ctrl[1]);
1180 case 1:
1181 w_c0_perfctrl0(cpuc->saved_ctrl[0]);
1182 }
1183 local_irq_restore(flags);
1184} 1211}
1185 1212
1186static int mipsxx_pmu_handle_shared_irq(void) 1213static int mipsxx_pmu_handle_shared_irq(void)
1187{ 1214{
1188 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 1215 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1189 struct perf_sample_data data; 1216 struct perf_sample_data data;
1190 unsigned int counters = mipspmu->num_counters; 1217 unsigned int counters = mipspmu.num_counters;
1191 unsigned int counter; 1218 u64 counter;
1192 int handled = IRQ_NONE; 1219 int handled = IRQ_NONE;
1193 struct pt_regs *regs; 1220 struct pt_regs *regs;
1194 1221
1195 if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26))) 1222 if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26)))
1196 return handled; 1223 return handled;
1197
1198 /* 1224 /*
1199 * First we pause the local counters, so that when we are locked 1225 * First we pause the local counters, so that when we are locked
1200 * here, the counters are all paused. When it gets locked due to 1226 * here, the counters are all paused. When it gets locked due to
@@ -1215,13 +1241,9 @@ static int mipsxx_pmu_handle_shared_irq(void)
1215#define HANDLE_COUNTER(n) \ 1241#define HANDLE_COUNTER(n) \
1216 case n + 1: \ 1242 case n + 1: \
1217 if (test_bit(n, cpuc->used_mask)) { \ 1243 if (test_bit(n, cpuc->used_mask)) { \
1218 counter = r_c0_perfcntr ## n(); \ 1244 counter = mipspmu.read_counter(n); \
1219 if (counter & M_COUNTER_OVERFLOW) { \ 1245 if (counter & mipspmu.overflow) { \
1220 w_c0_perfcntr ## n(counter & \ 1246 handle_associated_event(cpuc, n, &data, regs); \
1221 VALID_COUNT); \
1222 if (test_and_change_bit(n, cpuc->msbs)) \
1223 handle_associated_event(cpuc, \
1224 n, &data, regs); \
1225 handled = IRQ_HANDLED; \ 1247 handled = IRQ_HANDLED; \
1226 } \ 1248 } \
1227 } 1249 }
@@ -1251,95 +1273,6 @@ static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
1251 return mipsxx_pmu_handle_shared_irq(); 1273 return mipsxx_pmu_handle_shared_irq();
1252} 1274}
1253 1275
1254static void mipsxx_pmu_start(void)
1255{
1256#ifdef CONFIG_MIPS_MT_SMP
1257 write_unlock(&pmuint_rwlock);
1258#endif
1259 resume_local_counters();
1260}
1261
1262/*
1263 * MIPS performance counters can be per-TC. The control registers can
1264 * not be directly accessed across CPUs. Hence if we want to do global
1265 * control, we need cross CPU calls. on_each_cpu() can help us, but we
1266 * can not make sure this function is called with interrupts enabled. So
1267 * here we pause local counters and then grab a rwlock and leave the
1268 * counters on other CPUs alone. If any counter interrupt raises while
1269 * we own the write lock, simply pause local counters on that CPU and
1270 * spin in the handler. Also we know we won't be switched to another
1271 * CPU after pausing local counters and before grabbing the lock.
1272 */
1273static void mipsxx_pmu_stop(void)
1274{
1275 pause_local_counters();
1276#ifdef CONFIG_MIPS_MT_SMP
1277 write_lock(&pmuint_rwlock);
1278#endif
1279}
1280
1281static int mipsxx_pmu_alloc_counter(struct cpu_hw_events *cpuc,
1282 struct hw_perf_event *hwc)
1283{
1284 int i;
1285
1286 /*
1287 * We only need to care the counter mask. The range has been
1288 * checked definitely.
1289 */
1290 unsigned long cntr_mask = (hwc->event_base >> 8) & 0xffff;
1291
1292 for (i = mipspmu->num_counters - 1; i >= 0; i--) {
1293 /*
1294 * Note that some MIPS perf events can be counted by both
1295 * even and odd counters, wheresas many other are only by
1296 * even _or_ odd counters. This introduces an issue that
1297 * when the former kind of event takes the counter the
1298 * latter kind of event wants to use, then the "counter
1299 * allocation" for the latter event will fail. In fact if
1300 * they can be dynamically swapped, they both feel happy.
1301 * But here we leave this issue alone for now.
1302 */
1303 if (test_bit(i, &cntr_mask) &&
1304 !test_and_set_bit(i, cpuc->used_mask))
1305 return i;
1306 }
1307
1308 return -EAGAIN;
1309}
1310
1311static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
1312{
1313 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1314 unsigned long flags;
1315
1316 WARN_ON(idx < 0 || idx >= mipspmu->num_counters);
1317
1318 local_irq_save(flags);
1319 cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(evt->event_base & 0xff) |
1320 (evt->config_base & M_PERFCTL_CONFIG_MASK) |
1321 /* Make sure interrupt enabled. */
1322 M_PERFCTL_INTERRUPT_ENABLE;
1323 /*
1324 * We do not actually let the counter run. Leave it until start().
1325 */
1326 local_irq_restore(flags);
1327}
1328
1329static void mipsxx_pmu_disable_event(int idx)
1330{
1331 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1332 unsigned long flags;
1333
1334 WARN_ON(idx < 0 || idx >= mipspmu->num_counters);
1335
1336 local_irq_save(flags);
1337 cpuc->saved_ctrl[idx] = mipsxx_pmu_read_control(idx) &
1338 ~M_PERFCTL_COUNT_EVENT_WHENEVER;
1339 mipsxx_pmu_write_control(idx, cpuc->saved_ctrl[idx]);
1340 local_irq_restore(flags);
1341}
1342
1343/* 24K */ 1276/* 24K */
1344#define IS_UNSUPPORTED_24K_EVENT(r, b) \ 1277#define IS_UNSUPPORTED_24K_EVENT(r, b) \
1345 ((b) == 12 || (r) == 151 || (r) == 152 || (b) == 26 || \ 1278 ((b) == 12 || (r) == 151 || (r) == 152 || (b) == 26 || \
@@ -1478,40 +1411,11 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
1478 return &raw_event; 1411 return &raw_event;
1479} 1412}
1480 1413
1481static struct mips_pmu mipsxxcore_pmu = {
1482 .handle_irq = mipsxx_pmu_handle_irq,
1483 .handle_shared_irq = mipsxx_pmu_handle_shared_irq,
1484 .start = mipsxx_pmu_start,
1485 .stop = mipsxx_pmu_stop,
1486 .alloc_counter = mipsxx_pmu_alloc_counter,
1487 .read_counter = mipsxx_pmu_read_counter,
1488 .write_counter = mipsxx_pmu_write_counter,
1489 .enable_event = mipsxx_pmu_enable_event,
1490 .disable_event = mipsxx_pmu_disable_event,
1491 .map_raw_event = mipsxx_pmu_map_raw_event,
1492 .general_event_map = &mipsxxcore_event_map,
1493 .cache_event_map = &mipsxxcore_cache_map,
1494};
1495
1496static struct mips_pmu mipsxx74Kcore_pmu = {
1497 .handle_irq = mipsxx_pmu_handle_irq,
1498 .handle_shared_irq = mipsxx_pmu_handle_shared_irq,
1499 .start = mipsxx_pmu_start,
1500 .stop = mipsxx_pmu_stop,
1501 .alloc_counter = mipsxx_pmu_alloc_counter,
1502 .read_counter = mipsxx_pmu_read_counter,
1503 .write_counter = mipsxx_pmu_write_counter,
1504 .enable_event = mipsxx_pmu_enable_event,
1505 .disable_event = mipsxx_pmu_disable_event,
1506 .map_raw_event = mipsxx_pmu_map_raw_event,
1507 .general_event_map = &mipsxx74Kcore_event_map,
1508 .cache_event_map = &mipsxx74Kcore_cache_map,
1509};
1510
1511static int __init 1414static int __init
1512init_hw_perf_events(void) 1415init_hw_perf_events(void)
1513{ 1416{
1514 int counters, irq; 1417 int counters, irq;
1418 int counter_bits;
1515 1419
1516 pr_info("Performance counters: "); 1420 pr_info("Performance counters: ");
1517 1421
@@ -1543,32 +1447,28 @@ init_hw_perf_events(void)
1543 } 1447 }
1544#endif 1448#endif
1545 1449
1546 on_each_cpu(reset_counters, (void *)(long)counters, 1); 1450 mipspmu.map_raw_event = mipsxx_pmu_map_raw_event;
1547 1451
1548 switch (current_cpu_type()) { 1452 switch (current_cpu_type()) {
1549 case CPU_24K: 1453 case CPU_24K:
1550 mipsxxcore_pmu.name = "mips/24K"; 1454 mipspmu.name = "mips/24K";
1551 mipsxxcore_pmu.num_counters = counters; 1455 mipspmu.general_event_map = &mipsxxcore_event_map;
1552 mipsxxcore_pmu.irq = irq; 1456 mipspmu.cache_event_map = &mipsxxcore_cache_map;
1553 mipspmu = &mipsxxcore_pmu;
1554 break; 1457 break;
1555 case CPU_34K: 1458 case CPU_34K:
1556 mipsxxcore_pmu.name = "mips/34K"; 1459 mipspmu.name = "mips/34K";
1557 mipsxxcore_pmu.num_counters = counters; 1460 mipspmu.general_event_map = &mipsxxcore_event_map;
1558 mipsxxcore_pmu.irq = irq; 1461 mipspmu.cache_event_map = &mipsxxcore_cache_map;
1559 mipspmu = &mipsxxcore_pmu;
1560 break; 1462 break;
1561 case CPU_74K: 1463 case CPU_74K:
1562 mipsxx74Kcore_pmu.name = "mips/74K"; 1464 mipspmu.name = "mips/74K";
1563 mipsxx74Kcore_pmu.num_counters = counters; 1465 mipspmu.general_event_map = &mipsxx74Kcore_event_map;
1564 mipsxx74Kcore_pmu.irq = irq; 1466 mipspmu.cache_event_map = &mipsxx74Kcore_cache_map;
1565 mipspmu = &mipsxx74Kcore_pmu;
1566 break; 1467 break;
1567 case CPU_1004K: 1468 case CPU_1004K:
1568 mipsxxcore_pmu.name = "mips/1004K"; 1469 mipspmu.name = "mips/1004K";
1569 mipsxxcore_pmu.num_counters = counters; 1470 mipspmu.general_event_map = &mipsxxcore_event_map;
1570 mipsxxcore_pmu.irq = irq; 1471 mipspmu.cache_event_map = &mipsxxcore_cache_map;
1571 mipspmu = &mipsxxcore_pmu;
1572 break; 1472 break;
1573 default: 1473 default:
1574 pr_cont("Either hardware does not support performance " 1474 pr_cont("Either hardware does not support performance "
@@ -1576,10 +1476,30 @@ init_hw_perf_events(void)
1576 return -ENODEV; 1476 return -ENODEV;
1577 } 1477 }
1578 1478
1579 if (mipspmu) 1479 mipspmu.num_counters = counters;
1580 pr_cont("%s PMU enabled, %d counters available to each " 1480 mipspmu.irq = irq;
1581 "CPU, irq %d%s\n", mipspmu->name, counters, irq, 1481
1582 irq < 0 ? " (share with timer interrupt)" : ""); 1482 if (read_c0_perfctrl0() & M_PERFCTL_WIDE) {
1483 mipspmu.max_period = (1ULL << 63) - 1;
1484 mipspmu.valid_count = (1ULL << 63) - 1;
1485 mipspmu.overflow = 1ULL << 63;
1486 mipspmu.read_counter = mipsxx_pmu_read_counter_64;
1487 mipspmu.write_counter = mipsxx_pmu_write_counter_64;
1488 counter_bits = 64;
1489 } else {
1490 mipspmu.max_period = (1ULL << 31) - 1;
1491 mipspmu.valid_count = (1ULL << 31) - 1;
1492 mipspmu.overflow = 1ULL << 31;
1493 mipspmu.read_counter = mipsxx_pmu_read_counter;
1494 mipspmu.write_counter = mipsxx_pmu_write_counter;
1495 counter_bits = 32;
1496 }
1497
1498 on_each_cpu(reset_counters, (void *)(long)counters, 1);
1499
1500 pr_cont("%s PMU enabled, %d %d-bit counters available to each "
1501 "CPU, irq %d%s\n", mipspmu.name, counters, counter_bits, irq,
1502 irq < 0 ? " (share with timer interrupt)" : "");
1583 1503
1584 perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); 1504 perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
1585 1505