diff options
Diffstat (limited to 'arch/mips/kernel/perf_event_mipsxx.c')
-rw-r--r-- | arch/mips/kernel/perf_event_mipsxx.c | 1241 |
1 files changed, 907 insertions, 334 deletions
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index e5ad09a9baf7..4f2971bcf8e5 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c | |||
@@ -1,13 +1,112 @@ | |||
1 | #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) || \ | 1 | /* |
2 | defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_SB1) | 2 | * Linux performance counter support for MIPS. |
3 | * | ||
4 | * Copyright (C) 2010 MIPS Technologies, Inc. | ||
5 | * Copyright (C) 2011 Cavium Networks, Inc. | ||
6 | * Author: Deng-Cheng Zhu | ||
7 | * | ||
8 | * This code is based on the implementation for ARM, which is in turn | ||
9 | * based on the sparc64 perf event code and the x86 code. Performance | ||
10 | * counter access is based on the MIPS Oprofile code. And the callchain | ||
11 | * support references the code of MIPS stacktrace.c. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/cpumask.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/smp.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/perf_event.h> | ||
23 | #include <linux/uaccess.h> | ||
24 | |||
25 | #include <asm/irq.h> | ||
26 | #include <asm/irq_regs.h> | ||
27 | #include <asm/stacktrace.h> | ||
28 | #include <asm/time.h> /* For perf_irq */ | ||
29 | |||
30 | #define MIPS_MAX_HWEVENTS 4 | ||
31 | |||
32 | struct cpu_hw_events { | ||
33 | /* Array of events on this cpu. */ | ||
34 | struct perf_event *events[MIPS_MAX_HWEVENTS]; | ||
35 | |||
36 | /* | ||
37 | * Set the bit (indexed by the counter number) when the counter | ||
38 | * is used for an event. | ||
39 | */ | ||
40 | unsigned long used_mask[BITS_TO_LONGS(MIPS_MAX_HWEVENTS)]; | ||
41 | |||
42 | /* | ||
43 | * Software copy of the control register for each performance counter. | ||
44 | * MIPS CPUs vary in performance counters. They use this differently, | ||
45 | * and even may not use it. | ||
46 | */ | ||
47 | unsigned int saved_ctrl[MIPS_MAX_HWEVENTS]; | ||
48 | }; | ||
49 | DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { | ||
50 | .saved_ctrl = {0}, | ||
51 | }; | ||
52 | |||
53 | /* The description of MIPS performance events. */ | ||
54 | struct mips_perf_event { | ||
55 | unsigned int event_id; | ||
56 | /* | ||
57 | * MIPS performance counters are indexed starting from 0. | ||
58 | * CNTR_EVEN indicates the indexes of the counters to be used are | ||
59 | * even numbers. | ||
60 | */ | ||
61 | unsigned int cntr_mask; | ||
62 | #define CNTR_EVEN 0x55555555 | ||
63 | #define CNTR_ODD 0xaaaaaaaa | ||
64 | #define CNTR_ALL 0xffffffff | ||
65 | #ifdef CONFIG_MIPS_MT_SMP | ||
66 | enum { | ||
67 | T = 0, | ||
68 | V = 1, | ||
69 | P = 2, | ||
70 | } range; | ||
71 | #else | ||
72 | #define T | ||
73 | #define V | ||
74 | #define P | ||
75 | #endif | ||
76 | }; | ||
77 | |||
78 | static struct mips_perf_event raw_event; | ||
79 | static DEFINE_MUTEX(raw_event_mutex); | ||
80 | |||
81 | #define UNSUPPORTED_PERF_EVENT_ID 0xffffffff | ||
82 | #define C(x) PERF_COUNT_HW_CACHE_##x | ||
83 | |||
84 | struct mips_pmu { | ||
85 | u64 max_period; | ||
86 | u64 valid_count; | ||
87 | u64 overflow; | ||
88 | const char *name; | ||
89 | int irq; | ||
90 | u64 (*read_counter)(unsigned int idx); | ||
91 | void (*write_counter)(unsigned int idx, u64 val); | ||
92 | const struct mips_perf_event *(*map_raw_event)(u64 config); | ||
93 | const struct mips_perf_event (*general_event_map)[PERF_COUNT_HW_MAX]; | ||
94 | const struct mips_perf_event (*cache_event_map) | ||
95 | [PERF_COUNT_HW_CACHE_MAX] | ||
96 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
97 | [PERF_COUNT_HW_CACHE_RESULT_MAX]; | ||
98 | unsigned int num_counters; | ||
99 | }; | ||
100 | |||
101 | static struct mips_pmu mipspmu; | ||
3 | 102 | ||
4 | #define M_CONFIG1_PC (1 << 4) | 103 | #define M_CONFIG1_PC (1 << 4) |
5 | 104 | ||
6 | #define M_PERFCTL_EXL (1UL << 0) | 105 | #define M_PERFCTL_EXL (1 << 0) |
7 | #define M_PERFCTL_KERNEL (1UL << 1) | 106 | #define M_PERFCTL_KERNEL (1 << 1) |
8 | #define M_PERFCTL_SUPERVISOR (1UL << 2) | 107 | #define M_PERFCTL_SUPERVISOR (1 << 2) |
9 | #define M_PERFCTL_USER (1UL << 3) | 108 | #define M_PERFCTL_USER (1 << 3) |
10 | #define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4) | 109 | #define M_PERFCTL_INTERRUPT_ENABLE (1 << 4) |
11 | #define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5) | 110 | #define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5) |
12 | #define M_PERFCTL_VPEID(vpe) ((vpe) << 16) | 111 | #define M_PERFCTL_VPEID(vpe) ((vpe) << 16) |
13 | #define M_PERFCTL_MT_EN(filter) ((filter) << 20) | 112 | #define M_PERFCTL_MT_EN(filter) ((filter) << 20) |
@@ -15,8 +114,8 @@ | |||
15 | #define M_TC_EN_VPE M_PERFCTL_MT_EN(1) | 114 | #define M_TC_EN_VPE M_PERFCTL_MT_EN(1) |
16 | #define M_TC_EN_TC M_PERFCTL_MT_EN(2) | 115 | #define M_TC_EN_TC M_PERFCTL_MT_EN(2) |
17 | #define M_PERFCTL_TCID(tcid) ((tcid) << 22) | 116 | #define M_PERFCTL_TCID(tcid) ((tcid) << 22) |
18 | #define M_PERFCTL_WIDE (1UL << 30) | 117 | #define M_PERFCTL_WIDE (1 << 30) |
19 | #define M_PERFCTL_MORE (1UL << 31) | 118 | #define M_PERFCTL_MORE (1 << 31) |
20 | 119 | ||
21 | #define M_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \ | 120 | #define M_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \ |
22 | M_PERFCTL_KERNEL | \ | 121 | M_PERFCTL_KERNEL | \ |
@@ -31,11 +130,12 @@ | |||
31 | #endif | 130 | #endif |
32 | #define M_PERFCTL_EVENT_MASK 0xfe0 | 131 | #define M_PERFCTL_EVENT_MASK 0xfe0 |
33 | 132 | ||
34 | #define M_COUNTER_OVERFLOW (1UL << 31) | ||
35 | 133 | ||
36 | #ifdef CONFIG_MIPS_MT_SMP | 134 | #ifdef CONFIG_MIPS_MT_SMP |
37 | static int cpu_has_mipsmt_pertccounters; | 135 | static int cpu_has_mipsmt_pertccounters; |
38 | 136 | ||
137 | static DEFINE_RWLOCK(pmuint_rwlock); | ||
138 | |||
39 | /* | 139 | /* |
40 | * FIXME: For VSMP, vpe_id() is redefined for Perf-events, because | 140 | * FIXME: For VSMP, vpe_id() is redefined for Perf-events, because |
41 | * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs. | 141 | * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs. |
@@ -49,209 +149,673 @@ static int cpu_has_mipsmt_pertccounters; | |||
49 | #endif | 149 | #endif |
50 | 150 | ||
51 | /* Copied from op_model_mipsxx.c */ | 151 | /* Copied from op_model_mipsxx.c */ |
52 | static inline unsigned int vpe_shift(void) | 152 | static unsigned int vpe_shift(void) |
53 | { | 153 | { |
54 | if (num_possible_cpus() > 1) | 154 | if (num_possible_cpus() > 1) |
55 | return 1; | 155 | return 1; |
56 | 156 | ||
57 | return 0; | 157 | return 0; |
58 | } | 158 | } |
59 | #else /* !CONFIG_MIPS_MT_SMP */ | ||
60 | #define vpe_id() 0 | ||
61 | 159 | ||
62 | static inline unsigned int vpe_shift(void) | 160 | static unsigned int counters_total_to_per_cpu(unsigned int counters) |
63 | { | ||
64 | return 0; | ||
65 | } | ||
66 | #endif /* CONFIG_MIPS_MT_SMP */ | ||
67 | |||
68 | static inline unsigned int | ||
69 | counters_total_to_per_cpu(unsigned int counters) | ||
70 | { | 161 | { |
71 | return counters >> vpe_shift(); | 162 | return counters >> vpe_shift(); |
72 | } | 163 | } |
73 | 164 | ||
74 | static inline unsigned int | 165 | static unsigned int counters_per_cpu_to_total(unsigned int counters) |
75 | counters_per_cpu_to_total(unsigned int counters) | ||
76 | { | 166 | { |
77 | return counters << vpe_shift(); | 167 | return counters << vpe_shift(); |
78 | } | 168 | } |
79 | 169 | ||
80 | #define __define_perf_accessors(r, n, np) \ | 170 | #else /* !CONFIG_MIPS_MT_SMP */ |
81 | \ | 171 | #define vpe_id() 0 |
82 | static inline unsigned int r_c0_ ## r ## n(void) \ | ||
83 | { \ | ||
84 | unsigned int cpu = vpe_id(); \ | ||
85 | \ | ||
86 | switch (cpu) { \ | ||
87 | case 0: \ | ||
88 | return read_c0_ ## r ## n(); \ | ||
89 | case 1: \ | ||
90 | return read_c0_ ## r ## np(); \ | ||
91 | default: \ | ||
92 | BUG(); \ | ||
93 | } \ | ||
94 | return 0; \ | ||
95 | } \ | ||
96 | \ | ||
97 | static inline void w_c0_ ## r ## n(unsigned int value) \ | ||
98 | { \ | ||
99 | unsigned int cpu = vpe_id(); \ | ||
100 | \ | ||
101 | switch (cpu) { \ | ||
102 | case 0: \ | ||
103 | write_c0_ ## r ## n(value); \ | ||
104 | return; \ | ||
105 | case 1: \ | ||
106 | write_c0_ ## r ## np(value); \ | ||
107 | return; \ | ||
108 | default: \ | ||
109 | BUG(); \ | ||
110 | } \ | ||
111 | return; \ | ||
112 | } \ | ||
113 | |||
114 | __define_perf_accessors(perfcntr, 0, 2) | ||
115 | __define_perf_accessors(perfcntr, 1, 3) | ||
116 | __define_perf_accessors(perfcntr, 2, 0) | ||
117 | __define_perf_accessors(perfcntr, 3, 1) | ||
118 | |||
119 | __define_perf_accessors(perfctrl, 0, 2) | ||
120 | __define_perf_accessors(perfctrl, 1, 3) | ||
121 | __define_perf_accessors(perfctrl, 2, 0) | ||
122 | __define_perf_accessors(perfctrl, 3, 1) | ||
123 | |||
124 | static inline int __n_counters(void) | ||
125 | { | ||
126 | if (!(read_c0_config1() & M_CONFIG1_PC)) | ||
127 | return 0; | ||
128 | if (!(read_c0_perfctrl0() & M_PERFCTL_MORE)) | ||
129 | return 1; | ||
130 | if (!(read_c0_perfctrl1() & M_PERFCTL_MORE)) | ||
131 | return 2; | ||
132 | if (!(read_c0_perfctrl2() & M_PERFCTL_MORE)) | ||
133 | return 3; | ||
134 | 172 | ||
135 | return 4; | 173 | #endif /* CONFIG_MIPS_MT_SMP */ |
136 | } | ||
137 | 174 | ||
138 | static inline int n_counters(void) | 175 | static void resume_local_counters(void); |
139 | { | 176 | static void pause_local_counters(void); |
140 | int counters; | 177 | static irqreturn_t mipsxx_pmu_handle_irq(int, void *); |
178 | static int mipsxx_pmu_handle_shared_irq(void); | ||
141 | 179 | ||
142 | switch (current_cpu_type()) { | 180 | static unsigned int mipsxx_pmu_swizzle_perf_idx(unsigned int idx) |
143 | case CPU_R10000: | 181 | { |
144 | counters = 2; | 182 | if (vpe_id() == 1) |
145 | break; | 183 | idx = (idx + 2) & 3; |
184 | return idx; | ||
185 | } | ||
146 | 186 | ||
147 | case CPU_R12000: | 187 | static u64 mipsxx_pmu_read_counter(unsigned int idx) |
148 | case CPU_R14000: | 188 | { |
149 | counters = 4; | 189 | idx = mipsxx_pmu_swizzle_perf_idx(idx); |
150 | break; | ||
151 | 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(); | ||
152 | default: | 204 | default: |
153 | counters = __n_counters(); | 205 | WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx); |
206 | return 0; | ||
154 | } | 207 | } |
155 | |||
156 | return counters; | ||
157 | } | 208 | } |
158 | 209 | ||
159 | static void reset_counters(void *arg) | 210 | static u64 mipsxx_pmu_read_counter_64(unsigned int idx) |
160 | { | 211 | { |
161 | int counters = (int)(long)arg; | 212 | idx = mipsxx_pmu_swizzle_perf_idx(idx); |
162 | switch (counters) { | 213 | |
163 | case 4: | 214 | switch (idx) { |
164 | w_c0_perfctrl3(0); | 215 | case 0: |
165 | w_c0_perfcntr3(0); | 216 | return read_c0_perfcntr0_64(); |
166 | case 3: | ||
167 | w_c0_perfctrl2(0); | ||
168 | w_c0_perfcntr2(0); | ||
169 | case 2: | ||
170 | w_c0_perfctrl1(0); | ||
171 | w_c0_perfcntr1(0); | ||
172 | case 1: | 217 | case 1: |
173 | w_c0_perfctrl0(0); | 218 | return read_c0_perfcntr1_64(); |
174 | w_c0_perfcntr0(0); | 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; | ||
175 | } | 226 | } |
176 | } | 227 | } |
177 | 228 | ||
178 | static inline u64 | 229 | static void mipsxx_pmu_write_counter(unsigned int idx, u64 val) |
179 | mipsxx_pmu_read_counter(unsigned int idx) | ||
180 | { | 230 | { |
231 | idx = mipsxx_pmu_swizzle_perf_idx(idx); | ||
232 | |||
181 | switch (idx) { | 233 | switch (idx) { |
182 | case 0: | 234 | case 0: |
183 | return r_c0_perfcntr0(); | 235 | write_c0_perfcntr0(val); |
236 | return; | ||
184 | case 1: | 237 | case 1: |
185 | return r_c0_perfcntr1(); | 238 | write_c0_perfcntr1(val); |
239 | return; | ||
186 | case 2: | 240 | case 2: |
187 | return r_c0_perfcntr2(); | 241 | write_c0_perfcntr2(val); |
242 | return; | ||
188 | case 3: | 243 | case 3: |
189 | return r_c0_perfcntr3(); | 244 | write_c0_perfcntr3(val); |
190 | default: | 245 | return; |
191 | WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx); | ||
192 | return 0; | ||
193 | } | 246 | } |
194 | } | 247 | } |
195 | 248 | ||
196 | static inline void | 249 | static void mipsxx_pmu_write_counter_64(unsigned int idx, u64 val) |
197 | mipsxx_pmu_write_counter(unsigned int idx, u64 val) | ||
198 | { | 250 | { |
251 | idx = mipsxx_pmu_swizzle_perf_idx(idx); | ||
252 | |||
199 | switch (idx) { | 253 | switch (idx) { |
200 | case 0: | 254 | case 0: |
201 | w_c0_perfcntr0(val); | 255 | write_c0_perfcntr0_64(val); |
202 | return; | 256 | return; |
203 | case 1: | 257 | case 1: |
204 | w_c0_perfcntr1(val); | 258 | write_c0_perfcntr1_64(val); |
205 | return; | 259 | return; |
206 | case 2: | 260 | case 2: |
207 | w_c0_perfcntr2(val); | 261 | write_c0_perfcntr2_64(val); |
208 | return; | 262 | return; |
209 | case 3: | 263 | case 3: |
210 | w_c0_perfcntr3(val); | 264 | write_c0_perfcntr3_64(val); |
211 | return; | 265 | return; |
212 | } | 266 | } |
213 | } | 267 | } |
214 | 268 | ||
215 | static inline unsigned int | 269 | static unsigned int mipsxx_pmu_read_control(unsigned int idx) |
216 | mipsxx_pmu_read_control(unsigned int idx) | ||
217 | { | 270 | { |
271 | idx = mipsxx_pmu_swizzle_perf_idx(idx); | ||
272 | |||
218 | switch (idx) { | 273 | switch (idx) { |
219 | case 0: | 274 | case 0: |
220 | return r_c0_perfctrl0(); | 275 | return read_c0_perfctrl0(); |
221 | case 1: | 276 | case 1: |
222 | return r_c0_perfctrl1(); | 277 | return read_c0_perfctrl1(); |
223 | case 2: | 278 | case 2: |
224 | return r_c0_perfctrl2(); | 279 | return read_c0_perfctrl2(); |
225 | case 3: | 280 | case 3: |
226 | return r_c0_perfctrl3(); | 281 | return read_c0_perfctrl3(); |
227 | default: | 282 | default: |
228 | WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx); | 283 | WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx); |
229 | return 0; | 284 | return 0; |
230 | } | 285 | } |
231 | } | 286 | } |
232 | 287 | ||
233 | static inline void | 288 | static void mipsxx_pmu_write_control(unsigned int idx, unsigned int val) |
234 | mipsxx_pmu_write_control(unsigned int idx, unsigned int val) | ||
235 | { | 289 | { |
290 | idx = mipsxx_pmu_swizzle_perf_idx(idx); | ||
291 | |||
236 | switch (idx) { | 292 | switch (idx) { |
237 | case 0: | 293 | case 0: |
238 | w_c0_perfctrl0(val); | 294 | write_c0_perfctrl0(val); |
239 | return; | 295 | return; |
240 | case 1: | 296 | case 1: |
241 | w_c0_perfctrl1(val); | 297 | write_c0_perfctrl1(val); |
242 | return; | 298 | return; |
243 | case 2: | 299 | case 2: |
244 | w_c0_perfctrl2(val); | 300 | write_c0_perfctrl2(val); |
245 | return; | 301 | return; |
246 | case 3: | 302 | case 3: |
247 | w_c0_perfctrl3(val); | 303 | write_c0_perfctrl3(val); |
304 | return; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | static 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 | |||
338 | static 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 | |||
353 | static 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 | } | ||
366 | |||
367 | static int mipspmu_event_set_period(struct perf_event *event, | ||
368 | struct hw_perf_event *hwc, | ||
369 | int idx) | ||
370 | { | ||
371 | u64 left = local64_read(&hwc->period_left); | ||
372 | u64 period = hwc->sample_period; | ||
373 | int ret = 0; | ||
374 | |||
375 | if (unlikely((left + period) & (1ULL << 63))) { | ||
376 | /* left underflowed by more than period. */ | ||
377 | left = period; | ||
378 | local64_set(&hwc->period_left, left); | ||
379 | hwc->last_period = period; | ||
380 | ret = 1; | ||
381 | } else if (unlikely((left + period) <= period)) { | ||
382 | /* left underflowed by less than period. */ | ||
383 | left += period; | ||
384 | local64_set(&hwc->period_left, left); | ||
385 | hwc->last_period = period; | ||
386 | ret = 1; | ||
387 | } | ||
388 | |||
389 | if (left > mipspmu.max_period) { | ||
390 | left = mipspmu.max_period; | ||
391 | local64_set(&hwc->period_left, left); | ||
392 | } | ||
393 | |||
394 | local64_set(&hwc->prev_count, mipspmu.overflow - left); | ||
395 | |||
396 | mipspmu.write_counter(idx, mipspmu.overflow - left); | ||
397 | |||
398 | perf_event_update_userpage(event); | ||
399 | |||
400 | return ret; | ||
401 | } | ||
402 | |||
403 | static void mipspmu_event_update(struct perf_event *event, | ||
404 | struct hw_perf_event *hwc, | ||
405 | int idx) | ||
406 | { | ||
407 | u64 prev_raw_count, new_raw_count; | ||
408 | u64 delta; | ||
409 | |||
410 | again: | ||
411 | prev_raw_count = local64_read(&hwc->prev_count); | ||
412 | new_raw_count = mipspmu.read_counter(idx); | ||
413 | |||
414 | if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, | ||
415 | new_raw_count) != prev_raw_count) | ||
416 | goto again; | ||
417 | |||
418 | delta = new_raw_count - prev_raw_count; | ||
419 | |||
420 | local64_add(delta, &event->count); | ||
421 | local64_sub(delta, &hwc->period_left); | ||
422 | } | ||
423 | |||
424 | static void mipspmu_start(struct perf_event *event, int flags) | ||
425 | { | ||
426 | struct hw_perf_event *hwc = &event->hw; | ||
427 | |||
428 | if (flags & PERF_EF_RELOAD) | ||
429 | WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); | ||
430 | |||
431 | hwc->state = 0; | ||
432 | |||
433 | /* Set the period for the event. */ | ||
434 | mipspmu_event_set_period(event, hwc, hwc->idx); | ||
435 | |||
436 | /* Enable the event. */ | ||
437 | mipsxx_pmu_enable_event(hwc, hwc->idx); | ||
438 | } | ||
439 | |||
440 | static void mipspmu_stop(struct perf_event *event, int flags) | ||
441 | { | ||
442 | struct hw_perf_event *hwc = &event->hw; | ||
443 | |||
444 | if (!(hwc->state & PERF_HES_STOPPED)) { | ||
445 | /* We are working on a local event. */ | ||
446 | mipsxx_pmu_disable_event(hwc->idx); | ||
447 | barrier(); | ||
448 | mipspmu_event_update(event, hwc, hwc->idx); | ||
449 | hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | static int mipspmu_add(struct perf_event *event, int flags) | ||
454 | { | ||
455 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
456 | struct hw_perf_event *hwc = &event->hw; | ||
457 | int idx; | ||
458 | int err = 0; | ||
459 | |||
460 | perf_pmu_disable(event->pmu); | ||
461 | |||
462 | /* To look for a free counter for this event. */ | ||
463 | idx = mipsxx_pmu_alloc_counter(cpuc, hwc); | ||
464 | if (idx < 0) { | ||
465 | err = idx; | ||
466 | goto out; | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | * If there is an event in the counter we are going to use then | ||
471 | * make sure it is disabled. | ||
472 | */ | ||
473 | event->hw.idx = idx; | ||
474 | mipsxx_pmu_disable_event(idx); | ||
475 | cpuc->events[idx] = event; | ||
476 | |||
477 | hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; | ||
478 | if (flags & PERF_EF_START) | ||
479 | mipspmu_start(event, PERF_EF_RELOAD); | ||
480 | |||
481 | /* Propagate our changes to the userspace mapping. */ | ||
482 | perf_event_update_userpage(event); | ||
483 | |||
484 | out: | ||
485 | perf_pmu_enable(event->pmu); | ||
486 | return err; | ||
487 | } | ||
488 | |||
489 | static void mipspmu_del(struct perf_event *event, int flags) | ||
490 | { | ||
491 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
492 | struct hw_perf_event *hwc = &event->hw; | ||
493 | int idx = hwc->idx; | ||
494 | |||
495 | WARN_ON(idx < 0 || idx >= mipspmu.num_counters); | ||
496 | |||
497 | mipspmu_stop(event, PERF_EF_UPDATE); | ||
498 | cpuc->events[idx] = NULL; | ||
499 | clear_bit(idx, cpuc->used_mask); | ||
500 | |||
501 | perf_event_update_userpage(event); | ||
502 | } | ||
503 | |||
504 | static void mipspmu_read(struct perf_event *event) | ||
505 | { | ||
506 | struct hw_perf_event *hwc = &event->hw; | ||
507 | |||
508 | /* Don't read disabled counters! */ | ||
509 | if (hwc->idx < 0) | ||
248 | return; | 510 | return; |
511 | |||
512 | mipspmu_event_update(event, hwc, hwc->idx); | ||
513 | } | ||
514 | |||
515 | static void mipspmu_enable(struct pmu *pmu) | ||
516 | { | ||
517 | #ifdef CONFIG_MIPS_MT_SMP | ||
518 | write_unlock(&pmuint_rwlock); | ||
519 | #endif | ||
520 | resume_local_counters(); | ||
521 | } | ||
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 | */ | ||
534 | static void mipspmu_disable(struct pmu *pmu) | ||
535 | { | ||
536 | pause_local_counters(); | ||
537 | #ifdef CONFIG_MIPS_MT_SMP | ||
538 | write_lock(&pmuint_rwlock); | ||
539 | #endif | ||
540 | } | ||
541 | |||
542 | static atomic_t active_events = ATOMIC_INIT(0); | ||
543 | static DEFINE_MUTEX(pmu_reserve_mutex); | ||
544 | static int (*save_perf_irq)(void); | ||
545 | |||
546 | static int mipspmu_get_irq(void) | ||
547 | { | ||
548 | int err; | ||
549 | |||
550 | if (mipspmu.irq >= 0) { | ||
551 | /* Request my own irq handler. */ | ||
552 | err = request_irq(mipspmu.irq, mipsxx_pmu_handle_irq, | ||
553 | IRQF_PERCPU | IRQF_NOBALANCING, | ||
554 | "mips_perf_pmu", NULL); | ||
555 | if (err) { | ||
556 | pr_warning("Unable to request IRQ%d for MIPS " | ||
557 | "performance counters!\n", mipspmu.irq); | ||
558 | } | ||
559 | } else if (cp0_perfcount_irq < 0) { | ||
560 | /* | ||
561 | * We are sharing the irq number with the timer interrupt. | ||
562 | */ | ||
563 | save_perf_irq = perf_irq; | ||
564 | perf_irq = mipsxx_pmu_handle_shared_irq; | ||
565 | err = 0; | ||
566 | } else { | ||
567 | pr_warning("The platform hasn't properly defined its " | ||
568 | "interrupt controller.\n"); | ||
569 | err = -ENOENT; | ||
249 | } | 570 | } |
571 | |||
572 | return err; | ||
573 | } | ||
574 | |||
575 | static void mipspmu_free_irq(void) | ||
576 | { | ||
577 | if (mipspmu.irq >= 0) | ||
578 | free_irq(mipspmu.irq, NULL); | ||
579 | else if (cp0_perfcount_irq < 0) | ||
580 | perf_irq = save_perf_irq; | ||
250 | } | 581 | } |
251 | 582 | ||
583 | /* | ||
584 | * mipsxx/rm9000/loongson2 have different performance counters, they have | ||
585 | * specific low-level init routines. | ||
586 | */ | ||
587 | static void reset_counters(void *arg); | ||
588 | static int __hw_perf_event_init(struct perf_event *event); | ||
589 | |||
590 | static void hw_perf_event_destroy(struct perf_event *event) | ||
591 | { | ||
592 | if (atomic_dec_and_mutex_lock(&active_events, | ||
593 | &pmu_reserve_mutex)) { | ||
594 | /* | ||
595 | * We must not call the destroy function with interrupts | ||
596 | * disabled. | ||
597 | */ | ||
598 | on_each_cpu(reset_counters, | ||
599 | (void *)(long)mipspmu.num_counters, 1); | ||
600 | mipspmu_free_irq(); | ||
601 | mutex_unlock(&pmu_reserve_mutex); | ||
602 | } | ||
603 | } | ||
604 | |||
605 | static int mipspmu_event_init(struct perf_event *event) | ||
606 | { | ||
607 | int err = 0; | ||
608 | |||
609 | switch (event->attr.type) { | ||
610 | case PERF_TYPE_RAW: | ||
611 | case PERF_TYPE_HARDWARE: | ||
612 | case PERF_TYPE_HW_CACHE: | ||
613 | break; | ||
614 | |||
615 | default: | ||
616 | return -ENOENT; | ||
617 | } | ||
618 | |||
619 | if (event->cpu >= nr_cpumask_bits || | ||
620 | (event->cpu >= 0 && !cpu_online(event->cpu))) | ||
621 | return -ENODEV; | ||
622 | |||
623 | if (!atomic_inc_not_zero(&active_events)) { | ||
624 | if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) { | ||
625 | atomic_dec(&active_events); | ||
626 | return -ENOSPC; | ||
627 | } | ||
628 | |||
629 | mutex_lock(&pmu_reserve_mutex); | ||
630 | if (atomic_read(&active_events) == 0) | ||
631 | err = mipspmu_get_irq(); | ||
632 | |||
633 | if (!err) | ||
634 | atomic_inc(&active_events); | ||
635 | mutex_unlock(&pmu_reserve_mutex); | ||
636 | } | ||
637 | |||
638 | if (err) | ||
639 | return err; | ||
640 | |||
641 | err = __hw_perf_event_init(event); | ||
642 | if (err) | ||
643 | hw_perf_event_destroy(event); | ||
644 | |||
645 | return err; | ||
646 | } | ||
647 | |||
648 | static struct pmu pmu = { | ||
649 | .pmu_enable = mipspmu_enable, | ||
650 | .pmu_disable = mipspmu_disable, | ||
651 | .event_init = mipspmu_event_init, | ||
652 | .add = mipspmu_add, | ||
653 | .del = mipspmu_del, | ||
654 | .start = mipspmu_start, | ||
655 | .stop = mipspmu_stop, | ||
656 | .read = mipspmu_read, | ||
657 | }; | ||
658 | |||
659 | static unsigned int mipspmu_perf_event_encode(const struct mips_perf_event *pev) | ||
660 | { | ||
661 | /* | ||
662 | * Top 8 bits for range, next 16 bits for cntr_mask, lowest 8 bits for | ||
663 | * event_id. | ||
664 | */ | ||
252 | #ifdef CONFIG_MIPS_MT_SMP | 665 | #ifdef CONFIG_MIPS_MT_SMP |
253 | static DEFINE_RWLOCK(pmuint_rwlock); | 666 | return ((unsigned int)pev->range << 24) | |
667 | (pev->cntr_mask & 0xffff00) | | ||
668 | (pev->event_id & 0xff); | ||
669 | #else | ||
670 | return (pev->cntr_mask & 0xffff00) | | ||
671 | (pev->event_id & 0xff); | ||
254 | #endif | 672 | #endif |
673 | } | ||
674 | |||
675 | static const struct mips_perf_event *mipspmu_map_general_event(int idx) | ||
676 | { | ||
677 | const struct mips_perf_event *pev; | ||
678 | |||
679 | pev = ((*mipspmu.general_event_map)[idx].event_id == | ||
680 | UNSUPPORTED_PERF_EVENT_ID ? ERR_PTR(-EOPNOTSUPP) : | ||
681 | &(*mipspmu.general_event_map)[idx]); | ||
682 | |||
683 | return pev; | ||
684 | } | ||
685 | |||
686 | static const struct mips_perf_event *mipspmu_map_cache_event(u64 config) | ||
687 | { | ||
688 | unsigned int cache_type, cache_op, cache_result; | ||
689 | const struct mips_perf_event *pev; | ||
690 | |||
691 | cache_type = (config >> 0) & 0xff; | ||
692 | if (cache_type >= PERF_COUNT_HW_CACHE_MAX) | ||
693 | return ERR_PTR(-EINVAL); | ||
694 | |||
695 | cache_op = (config >> 8) & 0xff; | ||
696 | if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX) | ||
697 | return ERR_PTR(-EINVAL); | ||
698 | |||
699 | cache_result = (config >> 16) & 0xff; | ||
700 | if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) | ||
701 | return ERR_PTR(-EINVAL); | ||
702 | |||
703 | pev = &((*mipspmu.cache_event_map) | ||
704 | [cache_type] | ||
705 | [cache_op] | ||
706 | [cache_result]); | ||
707 | |||
708 | if (pev->event_id == UNSUPPORTED_PERF_EVENT_ID) | ||
709 | return ERR_PTR(-EOPNOTSUPP); | ||
710 | |||
711 | return pev; | ||
712 | |||
713 | } | ||
714 | |||
715 | static int validate_event(struct cpu_hw_events *cpuc, | ||
716 | struct perf_event *event) | ||
717 | { | ||
718 | struct hw_perf_event fake_hwc = event->hw; | ||
719 | |||
720 | /* Allow mixed event group. So return 1 to pass validation. */ | ||
721 | if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF) | ||
722 | return 1; | ||
723 | |||
724 | return mipsxx_pmu_alloc_counter(cpuc, &fake_hwc) >= 0; | ||
725 | } | ||
726 | |||
727 | static int validate_group(struct perf_event *event) | ||
728 | { | ||
729 | struct perf_event *sibling, *leader = event->group_leader; | ||
730 | struct cpu_hw_events fake_cpuc; | ||
731 | |||
732 | memset(&fake_cpuc, 0, sizeof(fake_cpuc)); | ||
733 | |||
734 | if (!validate_event(&fake_cpuc, leader)) | ||
735 | return -ENOSPC; | ||
736 | |||
737 | list_for_each_entry(sibling, &leader->sibling_list, group_entry) { | ||
738 | if (!validate_event(&fake_cpuc, sibling)) | ||
739 | return -ENOSPC; | ||
740 | } | ||
741 | |||
742 | if (!validate_event(&fake_cpuc, event)) | ||
743 | return -ENOSPC; | ||
744 | |||
745 | return 0; | ||
746 | } | ||
747 | |||
748 | /* This is needed by specific irq handlers in perf_event_*.c */ | ||
749 | static void handle_associated_event(struct cpu_hw_events *cpuc, | ||
750 | int idx, struct perf_sample_data *data, | ||
751 | struct pt_regs *regs) | ||
752 | { | ||
753 | struct perf_event *event = cpuc->events[idx]; | ||
754 | struct hw_perf_event *hwc = &event->hw; | ||
755 | |||
756 | mipspmu_event_update(event, hwc, idx); | ||
757 | data->period = event->hw.last_period; | ||
758 | if (!mipspmu_event_set_period(event, hwc, idx)) | ||
759 | return; | ||
760 | |||
761 | if (perf_event_overflow(event, data, regs)) | ||
762 | mipsxx_pmu_disable_event(idx); | ||
763 | } | ||
764 | |||
765 | |||
766 | static int __n_counters(void) | ||
767 | { | ||
768 | if (!(read_c0_config1() & M_CONFIG1_PC)) | ||
769 | return 0; | ||
770 | if (!(read_c0_perfctrl0() & M_PERFCTL_MORE)) | ||
771 | return 1; | ||
772 | if (!(read_c0_perfctrl1() & M_PERFCTL_MORE)) | ||
773 | return 2; | ||
774 | if (!(read_c0_perfctrl2() & M_PERFCTL_MORE)) | ||
775 | return 3; | ||
776 | |||
777 | return 4; | ||
778 | } | ||
779 | |||
780 | static int n_counters(void) | ||
781 | { | ||
782 | int counters; | ||
783 | |||
784 | switch (current_cpu_type()) { | ||
785 | case CPU_R10000: | ||
786 | counters = 2; | ||
787 | break; | ||
788 | |||
789 | case CPU_R12000: | ||
790 | case CPU_R14000: | ||
791 | counters = 4; | ||
792 | break; | ||
793 | |||
794 | default: | ||
795 | counters = __n_counters(); | ||
796 | } | ||
797 | |||
798 | return counters; | ||
799 | } | ||
800 | |||
801 | static void reset_counters(void *arg) | ||
802 | { | ||
803 | int counters = (int)(long)arg; | ||
804 | switch (counters) { | ||
805 | case 4: | ||
806 | mipsxx_pmu_write_control(3, 0); | ||
807 | mipspmu.write_counter(3, 0); | ||
808 | case 3: | ||
809 | mipsxx_pmu_write_control(2, 0); | ||
810 | mipspmu.write_counter(2, 0); | ||
811 | case 2: | ||
812 | mipsxx_pmu_write_control(1, 0); | ||
813 | mipspmu.write_counter(1, 0); | ||
814 | case 1: | ||
815 | mipsxx_pmu_write_control(0, 0); | ||
816 | mipspmu.write_counter(0, 0); | ||
817 | } | ||
818 | } | ||
255 | 819 | ||
256 | /* 24K/34K/1004K cores can share the same event map. */ | 820 | /* 24K/34K/1004K cores can share the same event map. */ |
257 | static const struct mips_perf_event mipsxxcore_event_map | 821 | static const struct mips_perf_event mipsxxcore_event_map |
@@ -277,6 +841,16 @@ static const struct mips_perf_event mipsxx74Kcore_event_map | |||
277 | [PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID }, | 841 | [PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID }, |
278 | }; | 842 | }; |
279 | 843 | ||
844 | static const struct mips_perf_event octeon_event_map[PERF_COUNT_HW_MAX] = { | ||
845 | [PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL }, | ||
846 | [PERF_COUNT_HW_INSTRUCTIONS] = { 0x03, CNTR_ALL }, | ||
847 | [PERF_COUNT_HW_CACHE_REFERENCES] = { 0x2b, CNTR_ALL }, | ||
848 | [PERF_COUNT_HW_CACHE_MISSES] = { 0x2e, CNTR_ALL }, | ||
849 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x08, CNTR_ALL }, | ||
850 | [PERF_COUNT_HW_BRANCH_MISSES] = { 0x09, CNTR_ALL }, | ||
851 | [PERF_COUNT_HW_BUS_CYCLES] = { 0x25, CNTR_ALL }, | ||
852 | }; | ||
853 | |||
280 | /* 24K/34K/1004K cores can share the same cache event map. */ | 854 | /* 24K/34K/1004K cores can share the same cache event map. */ |
281 | static const struct mips_perf_event mipsxxcore_cache_map | 855 | static const struct mips_perf_event mipsxxcore_cache_map |
282 | [PERF_COUNT_HW_CACHE_MAX] | 856 | [PERF_COUNT_HW_CACHE_MAX] |
@@ -510,10 +1084,105 @@ static const struct mips_perf_event mipsxx74Kcore_cache_map | |||
510 | }, | 1084 | }, |
511 | }; | 1085 | }; |
512 | 1086 | ||
1087 | |||
1088 | static const struct mips_perf_event octeon_cache_map | ||
1089 | [PERF_COUNT_HW_CACHE_MAX] | ||
1090 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
1091 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = { | ||
1092 | [C(L1D)] = { | ||
1093 | [C(OP_READ)] = { | ||
1094 | [C(RESULT_ACCESS)] = { 0x2b, CNTR_ALL }, | ||
1095 | [C(RESULT_MISS)] = { 0x2e, CNTR_ALL }, | ||
1096 | }, | ||
1097 | [C(OP_WRITE)] = { | ||
1098 | [C(RESULT_ACCESS)] = { 0x30, CNTR_ALL }, | ||
1099 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1100 | }, | ||
1101 | [C(OP_PREFETCH)] = { | ||
1102 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1103 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1104 | }, | ||
1105 | }, | ||
1106 | [C(L1I)] = { | ||
1107 | [C(OP_READ)] = { | ||
1108 | [C(RESULT_ACCESS)] = { 0x18, CNTR_ALL }, | ||
1109 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1110 | }, | ||
1111 | [C(OP_WRITE)] = { | ||
1112 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1113 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1114 | }, | ||
1115 | [C(OP_PREFETCH)] = { | ||
1116 | [C(RESULT_ACCESS)] = { 0x19, CNTR_ALL }, | ||
1117 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1118 | }, | ||
1119 | }, | ||
1120 | [C(LL)] = { | ||
1121 | [C(OP_READ)] = { | ||
1122 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1123 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1124 | }, | ||
1125 | [C(OP_WRITE)] = { | ||
1126 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1127 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1128 | }, | ||
1129 | [C(OP_PREFETCH)] = { | ||
1130 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1131 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1132 | }, | ||
1133 | }, | ||
1134 | [C(DTLB)] = { | ||
1135 | /* | ||
1136 | * Only general DTLB misses are counted use the same event for | ||
1137 | * read and write. | ||
1138 | */ | ||
1139 | [C(OP_READ)] = { | ||
1140 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1141 | [C(RESULT_MISS)] = { 0x35, CNTR_ALL }, | ||
1142 | }, | ||
1143 | [C(OP_WRITE)] = { | ||
1144 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1145 | [C(RESULT_MISS)] = { 0x35, CNTR_ALL }, | ||
1146 | }, | ||
1147 | [C(OP_PREFETCH)] = { | ||
1148 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1149 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1150 | }, | ||
1151 | }, | ||
1152 | [C(ITLB)] = { | ||
1153 | [C(OP_READ)] = { | ||
1154 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1155 | [C(RESULT_MISS)] = { 0x37, CNTR_ALL }, | ||
1156 | }, | ||
1157 | [C(OP_WRITE)] = { | ||
1158 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1159 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1160 | }, | ||
1161 | [C(OP_PREFETCH)] = { | ||
1162 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1163 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1164 | }, | ||
1165 | }, | ||
1166 | [C(BPU)] = { | ||
1167 | /* Using the same code for *HW_BRANCH* */ | ||
1168 | [C(OP_READ)] = { | ||
1169 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1170 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1171 | }, | ||
1172 | [C(OP_WRITE)] = { | ||
1173 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1174 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1175 | }, | ||
1176 | [C(OP_PREFETCH)] = { | ||
1177 | [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1178 | [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID }, | ||
1179 | }, | ||
1180 | }, | ||
1181 | }; | ||
1182 | |||
513 | #ifdef CONFIG_MIPS_MT_SMP | 1183 | #ifdef CONFIG_MIPS_MT_SMP |
514 | static void | 1184 | static void check_and_calc_range(struct perf_event *event, |
515 | check_and_calc_range(struct perf_event *event, | 1185 | const struct mips_perf_event *pev) |
516 | const struct mips_perf_event *pev) | ||
517 | { | 1186 | { |
518 | struct hw_perf_event *hwc = &event->hw; | 1187 | struct hw_perf_event *hwc = &event->hw; |
519 | 1188 | ||
@@ -536,9 +1205,8 @@ check_and_calc_range(struct perf_event *event, | |||
536 | hwc->config_base |= M_TC_EN_ALL; | 1205 | hwc->config_base |= M_TC_EN_ALL; |
537 | } | 1206 | } |
538 | #else | 1207 | #else |
539 | static void | 1208 | static void check_and_calc_range(struct perf_event *event, |
540 | check_and_calc_range(struct perf_event *event, | 1209 | const struct mips_perf_event *pev) |
541 | const struct mips_perf_event *pev) | ||
542 | { | 1210 | { |
543 | } | 1211 | } |
544 | #endif | 1212 | #endif |
@@ -560,7 +1228,7 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
560 | } else if (PERF_TYPE_RAW == event->attr.type) { | 1228 | } else if (PERF_TYPE_RAW == event->attr.type) { |
561 | /* We are working on the global raw event. */ | 1229 | /* We are working on the global raw event. */ |
562 | mutex_lock(&raw_event_mutex); | 1230 | mutex_lock(&raw_event_mutex); |
563 | pev = mipspmu->map_raw_event(event->attr.config); | 1231 | pev = mipspmu.map_raw_event(event->attr.config); |
564 | } else { | 1232 | } else { |
565 | /* The event type is not (yet) supported. */ | 1233 | /* The event type is not (yet) supported. */ |
566 | return -EOPNOTSUPP; | 1234 | return -EOPNOTSUPP; |
@@ -605,7 +1273,7 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
605 | hwc->config = 0; | 1273 | hwc->config = 0; |
606 | 1274 | ||
607 | if (!hwc->sample_period) { | 1275 | if (!hwc->sample_period) { |
608 | hwc->sample_period = MAX_PERIOD; | 1276 | hwc->sample_period = mipspmu.max_period; |
609 | hwc->last_period = hwc->sample_period; | 1277 | hwc->last_period = hwc->sample_period; |
610 | local64_set(&hwc->period_left, hwc->sample_period); | 1278 | local64_set(&hwc->period_left, hwc->sample_period); |
611 | } | 1279 | } |
@@ -618,70 +1286,47 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
618 | } | 1286 | } |
619 | 1287 | ||
620 | event->destroy = hw_perf_event_destroy; | 1288 | event->destroy = hw_perf_event_destroy; |
621 | |||
622 | return err; | 1289 | return err; |
623 | } | 1290 | } |
624 | 1291 | ||
625 | static void pause_local_counters(void) | 1292 | static void pause_local_counters(void) |
626 | { | 1293 | { |
627 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1294 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
628 | int counters = mipspmu->num_counters; | 1295 | int ctr = mipspmu.num_counters; |
629 | unsigned long flags; | 1296 | unsigned long flags; |
630 | 1297 | ||
631 | local_irq_save(flags); | 1298 | local_irq_save(flags); |
632 | switch (counters) { | 1299 | do { |
633 | case 4: | 1300 | ctr--; |
634 | cpuc->saved_ctrl[3] = r_c0_perfctrl3(); | 1301 | cpuc->saved_ctrl[ctr] = mipsxx_pmu_read_control(ctr); |
635 | w_c0_perfctrl3(cpuc->saved_ctrl[3] & | 1302 | mipsxx_pmu_write_control(ctr, cpuc->saved_ctrl[ctr] & |
636 | ~M_PERFCTL_COUNT_EVENT_WHENEVER); | 1303 | ~M_PERFCTL_COUNT_EVENT_WHENEVER); |
637 | case 3: | 1304 | } while (ctr > 0); |
638 | cpuc->saved_ctrl[2] = r_c0_perfctrl2(); | ||
639 | w_c0_perfctrl2(cpuc->saved_ctrl[2] & | ||
640 | ~M_PERFCTL_COUNT_EVENT_WHENEVER); | ||
641 | case 2: | ||
642 | cpuc->saved_ctrl[1] = r_c0_perfctrl1(); | ||
643 | w_c0_perfctrl1(cpuc->saved_ctrl[1] & | ||
644 | ~M_PERFCTL_COUNT_EVENT_WHENEVER); | ||
645 | case 1: | ||
646 | cpuc->saved_ctrl[0] = r_c0_perfctrl0(); | ||
647 | w_c0_perfctrl0(cpuc->saved_ctrl[0] & | ||
648 | ~M_PERFCTL_COUNT_EVENT_WHENEVER); | ||
649 | } | ||
650 | local_irq_restore(flags); | 1305 | local_irq_restore(flags); |
651 | } | 1306 | } |
652 | 1307 | ||
653 | static void resume_local_counters(void) | 1308 | static void resume_local_counters(void) |
654 | { | 1309 | { |
655 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1310 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
656 | int counters = mipspmu->num_counters; | 1311 | int ctr = mipspmu.num_counters; |
657 | unsigned long flags; | ||
658 | 1312 | ||
659 | local_irq_save(flags); | 1313 | do { |
660 | switch (counters) { | 1314 | ctr--; |
661 | case 4: | 1315 | mipsxx_pmu_write_control(ctr, cpuc->saved_ctrl[ctr]); |
662 | w_c0_perfctrl3(cpuc->saved_ctrl[3]); | 1316 | } while (ctr > 0); |
663 | case 3: | ||
664 | w_c0_perfctrl2(cpuc->saved_ctrl[2]); | ||
665 | case 2: | ||
666 | w_c0_perfctrl1(cpuc->saved_ctrl[1]); | ||
667 | case 1: | ||
668 | w_c0_perfctrl0(cpuc->saved_ctrl[0]); | ||
669 | } | ||
670 | local_irq_restore(flags); | ||
671 | } | 1317 | } |
672 | 1318 | ||
673 | static int mipsxx_pmu_handle_shared_irq(void) | 1319 | static int mipsxx_pmu_handle_shared_irq(void) |
674 | { | 1320 | { |
675 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1321 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
676 | struct perf_sample_data data; | 1322 | struct perf_sample_data data; |
677 | unsigned int counters = mipspmu->num_counters; | 1323 | unsigned int counters = mipspmu.num_counters; |
678 | unsigned int counter; | 1324 | u64 counter; |
679 | int handled = IRQ_NONE; | 1325 | int handled = IRQ_NONE; |
680 | struct pt_regs *regs; | 1326 | struct pt_regs *regs; |
681 | 1327 | ||
682 | if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26))) | 1328 | if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26))) |
683 | return handled; | 1329 | return handled; |
684 | |||
685 | /* | 1330 | /* |
686 | * First we pause the local counters, so that when we are locked | 1331 | * First we pause the local counters, so that when we are locked |
687 | * here, the counters are all paused. When it gets locked due to | 1332 | * here, the counters are all paused. When it gets locked due to |
@@ -702,13 +1347,9 @@ static int mipsxx_pmu_handle_shared_irq(void) | |||
702 | #define HANDLE_COUNTER(n) \ | 1347 | #define HANDLE_COUNTER(n) \ |
703 | case n + 1: \ | 1348 | case n + 1: \ |
704 | if (test_bit(n, cpuc->used_mask)) { \ | 1349 | if (test_bit(n, cpuc->used_mask)) { \ |
705 | counter = r_c0_perfcntr ## n(); \ | 1350 | counter = mipspmu.read_counter(n); \ |
706 | if (counter & M_COUNTER_OVERFLOW) { \ | 1351 | if (counter & mipspmu.overflow) { \ |
707 | w_c0_perfcntr ## n(counter & \ | 1352 | handle_associated_event(cpuc, n, &data, regs); \ |
708 | VALID_COUNT); \ | ||
709 | if (test_and_change_bit(n, cpuc->msbs)) \ | ||
710 | handle_associated_event(cpuc, \ | ||
711 | n, &data, regs); \ | ||
712 | handled = IRQ_HANDLED; \ | 1353 | handled = IRQ_HANDLED; \ |
713 | } \ | 1354 | } \ |
714 | } | 1355 | } |
@@ -733,104 +1374,11 @@ static int mipsxx_pmu_handle_shared_irq(void) | |||
733 | return handled; | 1374 | return handled; |
734 | } | 1375 | } |
735 | 1376 | ||
736 | static irqreturn_t | 1377 | static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev) |
737 | mipsxx_pmu_handle_irq(int irq, void *dev) | ||
738 | { | 1378 | { |
739 | return mipsxx_pmu_handle_shared_irq(); | 1379 | return mipsxx_pmu_handle_shared_irq(); |
740 | } | 1380 | } |
741 | 1381 | ||
742 | static void mipsxx_pmu_start(void) | ||
743 | { | ||
744 | #ifdef CONFIG_MIPS_MT_SMP | ||
745 | write_unlock(&pmuint_rwlock); | ||
746 | #endif | ||
747 | resume_local_counters(); | ||
748 | } | ||
749 | |||
750 | /* | ||
751 | * MIPS performance counters can be per-TC. The control registers can | ||
752 | * not be directly accessed across CPUs. Hence if we want to do global | ||
753 | * control, we need cross CPU calls. on_each_cpu() can help us, but we | ||
754 | * can not make sure this function is called with interrupts enabled. So | ||
755 | * here we pause local counters and then grab a rwlock and leave the | ||
756 | * counters on other CPUs alone. If any counter interrupt raises while | ||
757 | * we own the write lock, simply pause local counters on that CPU and | ||
758 | * spin in the handler. Also we know we won't be switched to another | ||
759 | * CPU after pausing local counters and before grabbing the lock. | ||
760 | */ | ||
761 | static void mipsxx_pmu_stop(void) | ||
762 | { | ||
763 | pause_local_counters(); | ||
764 | #ifdef CONFIG_MIPS_MT_SMP | ||
765 | write_lock(&pmuint_rwlock); | ||
766 | #endif | ||
767 | } | ||
768 | |||
769 | static int | ||
770 | mipsxx_pmu_alloc_counter(struct cpu_hw_events *cpuc, | ||
771 | struct hw_perf_event *hwc) | ||
772 | { | ||
773 | int i; | ||
774 | |||
775 | /* | ||
776 | * We only need to care the counter mask. The range has been | ||
777 | * checked definitely. | ||
778 | */ | ||
779 | unsigned long cntr_mask = (hwc->event_base >> 8) & 0xffff; | ||
780 | |||
781 | for (i = mipspmu->num_counters - 1; i >= 0; i--) { | ||
782 | /* | ||
783 | * Note that some MIPS perf events can be counted by both | ||
784 | * even and odd counters, wheresas many other are only by | ||
785 | * even _or_ odd counters. This introduces an issue that | ||
786 | * when the former kind of event takes the counter the | ||
787 | * latter kind of event wants to use, then the "counter | ||
788 | * allocation" for the latter event will fail. In fact if | ||
789 | * they can be dynamically swapped, they both feel happy. | ||
790 | * But here we leave this issue alone for now. | ||
791 | */ | ||
792 | if (test_bit(i, &cntr_mask) && | ||
793 | !test_and_set_bit(i, cpuc->used_mask)) | ||
794 | return i; | ||
795 | } | ||
796 | |||
797 | return -EAGAIN; | ||
798 | } | ||
799 | |||
800 | static void | ||
801 | mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx) | ||
802 | { | ||
803 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
804 | unsigned long flags; | ||
805 | |||
806 | WARN_ON(idx < 0 || idx >= mipspmu->num_counters); | ||
807 | |||
808 | local_irq_save(flags); | ||
809 | cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(evt->event_base & 0xff) | | ||
810 | (evt->config_base & M_PERFCTL_CONFIG_MASK) | | ||
811 | /* Make sure interrupt enabled. */ | ||
812 | M_PERFCTL_INTERRUPT_ENABLE; | ||
813 | /* | ||
814 | * We do not actually let the counter run. Leave it until start(). | ||
815 | */ | ||
816 | local_irq_restore(flags); | ||
817 | } | ||
818 | |||
819 | static void | ||
820 | mipsxx_pmu_disable_event(int idx) | ||
821 | { | ||
822 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
823 | unsigned long flags; | ||
824 | |||
825 | WARN_ON(idx < 0 || idx >= mipspmu->num_counters); | ||
826 | |||
827 | local_irq_save(flags); | ||
828 | cpuc->saved_ctrl[idx] = mipsxx_pmu_read_control(idx) & | ||
829 | ~M_PERFCTL_COUNT_EVENT_WHENEVER; | ||
830 | mipsxx_pmu_write_control(idx, cpuc->saved_ctrl[idx]); | ||
831 | local_irq_restore(flags); | ||
832 | } | ||
833 | |||
834 | /* 24K */ | 1382 | /* 24K */ |
835 | #define IS_UNSUPPORTED_24K_EVENT(r, b) \ | 1383 | #define IS_UNSUPPORTED_24K_EVENT(r, b) \ |
836 | ((b) == 12 || (r) == 151 || (r) == 152 || (b) == 26 || \ | 1384 | ((b) == 12 || (r) == 151 || (r) == 152 || (b) == 26 || \ |
@@ -892,8 +1440,7 @@ mipsxx_pmu_disable_event(int idx) | |||
892 | * then 128 needs to be added to 15 as the input for the event config, | 1440 | * then 128 needs to be added to 15 as the input for the event config, |
893 | * i.e., 143 (0x8F) to be used. | 1441 | * i.e., 143 (0x8F) to be used. |
894 | */ | 1442 | */ |
895 | static const struct mips_perf_event * | 1443 | static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config) |
896 | mipsxx_pmu_map_raw_event(u64 config) | ||
897 | { | 1444 | { |
898 | unsigned int raw_id = config & 0xff; | 1445 | unsigned int raw_id = config & 0xff; |
899 | unsigned int base_id = raw_id & 0x7f; | 1446 | unsigned int base_id = raw_id & 0x7f; |
@@ -970,40 +1517,44 @@ mipsxx_pmu_map_raw_event(u64 config) | |||
970 | return &raw_event; | 1517 | return &raw_event; |
971 | } | 1518 | } |
972 | 1519 | ||
973 | static struct mips_pmu mipsxxcore_pmu = { | 1520 | static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config) |
974 | .handle_irq = mipsxx_pmu_handle_irq, | 1521 | { |
975 | .handle_shared_irq = mipsxx_pmu_handle_shared_irq, | 1522 | unsigned int raw_id = config & 0xff; |
976 | .start = mipsxx_pmu_start, | 1523 | unsigned int base_id = raw_id & 0x7f; |
977 | .stop = mipsxx_pmu_stop, | ||
978 | .alloc_counter = mipsxx_pmu_alloc_counter, | ||
979 | .read_counter = mipsxx_pmu_read_counter, | ||
980 | .write_counter = mipsxx_pmu_write_counter, | ||
981 | .enable_event = mipsxx_pmu_enable_event, | ||
982 | .disable_event = mipsxx_pmu_disable_event, | ||
983 | .map_raw_event = mipsxx_pmu_map_raw_event, | ||
984 | .general_event_map = &mipsxxcore_event_map, | ||
985 | .cache_event_map = &mipsxxcore_cache_map, | ||
986 | }; | ||
987 | 1524 | ||
988 | static struct mips_pmu mipsxx74Kcore_pmu = { | 1525 | |
989 | .handle_irq = mipsxx_pmu_handle_irq, | 1526 | raw_event.cntr_mask = CNTR_ALL; |
990 | .handle_shared_irq = mipsxx_pmu_handle_shared_irq, | 1527 | raw_event.event_id = base_id; |
991 | .start = mipsxx_pmu_start, | 1528 | |
992 | .stop = mipsxx_pmu_stop, | 1529 | if (current_cpu_type() == CPU_CAVIUM_OCTEON2) { |
993 | .alloc_counter = mipsxx_pmu_alloc_counter, | 1530 | if (base_id > 0x42) |
994 | .read_counter = mipsxx_pmu_read_counter, | 1531 | return ERR_PTR(-EOPNOTSUPP); |
995 | .write_counter = mipsxx_pmu_write_counter, | 1532 | } else { |
996 | .enable_event = mipsxx_pmu_enable_event, | 1533 | if (base_id > 0x3a) |
997 | .disable_event = mipsxx_pmu_disable_event, | 1534 | return ERR_PTR(-EOPNOTSUPP); |
998 | .map_raw_event = mipsxx_pmu_map_raw_event, | 1535 | } |
999 | .general_event_map = &mipsxx74Kcore_event_map, | 1536 | |
1000 | .cache_event_map = &mipsxx74Kcore_cache_map, | 1537 | switch (base_id) { |
1001 | }; | 1538 | case 0x00: |
1539 | case 0x0f: | ||
1540 | case 0x1e: | ||
1541 | case 0x1f: | ||
1542 | case 0x2f: | ||
1543 | case 0x34: | ||
1544 | case 0x3b ... 0x3f: | ||
1545 | return ERR_PTR(-EOPNOTSUPP); | ||
1546 | default: | ||
1547 | break; | ||
1548 | } | ||
1549 | |||
1550 | return &raw_event; | ||
1551 | } | ||
1002 | 1552 | ||
1003 | static int __init | 1553 | static int __init |
1004 | init_hw_perf_events(void) | 1554 | init_hw_perf_events(void) |
1005 | { | 1555 | { |
1006 | int counters, irq; | 1556 | int counters, irq; |
1557 | int counter_bits; | ||
1007 | 1558 | ||
1008 | pr_info("Performance counters: "); | 1559 | pr_info("Performance counters: "); |
1009 | 1560 | ||
@@ -1035,32 +1586,36 @@ init_hw_perf_events(void) | |||
1035 | } | 1586 | } |
1036 | #endif | 1587 | #endif |
1037 | 1588 | ||
1038 | on_each_cpu(reset_counters, (void *)(long)counters, 1); | 1589 | mipspmu.map_raw_event = mipsxx_pmu_map_raw_event; |
1039 | 1590 | ||
1040 | switch (current_cpu_type()) { | 1591 | switch (current_cpu_type()) { |
1041 | case CPU_24K: | 1592 | case CPU_24K: |
1042 | mipsxxcore_pmu.name = "mips/24K"; | 1593 | mipspmu.name = "mips/24K"; |
1043 | mipsxxcore_pmu.num_counters = counters; | 1594 | mipspmu.general_event_map = &mipsxxcore_event_map; |
1044 | mipsxxcore_pmu.irq = irq; | 1595 | mipspmu.cache_event_map = &mipsxxcore_cache_map; |
1045 | mipspmu = &mipsxxcore_pmu; | ||
1046 | break; | 1596 | break; |
1047 | case CPU_34K: | 1597 | case CPU_34K: |
1048 | mipsxxcore_pmu.name = "mips/34K"; | 1598 | mipspmu.name = "mips/34K"; |
1049 | mipsxxcore_pmu.num_counters = counters; | 1599 | mipspmu.general_event_map = &mipsxxcore_event_map; |
1050 | mipsxxcore_pmu.irq = irq; | 1600 | mipspmu.cache_event_map = &mipsxxcore_cache_map; |
1051 | mipspmu = &mipsxxcore_pmu; | ||
1052 | break; | 1601 | break; |
1053 | case CPU_74K: | 1602 | case CPU_74K: |
1054 | mipsxx74Kcore_pmu.name = "mips/74K"; | 1603 | mipspmu.name = "mips/74K"; |
1055 | mipsxx74Kcore_pmu.num_counters = counters; | 1604 | mipspmu.general_event_map = &mipsxx74Kcore_event_map; |
1056 | mipsxx74Kcore_pmu.irq = irq; | 1605 | mipspmu.cache_event_map = &mipsxx74Kcore_cache_map; |
1057 | mipspmu = &mipsxx74Kcore_pmu; | ||
1058 | break; | 1606 | break; |
1059 | case CPU_1004K: | 1607 | case CPU_1004K: |
1060 | mipsxxcore_pmu.name = "mips/1004K"; | 1608 | mipspmu.name = "mips/1004K"; |
1061 | mipsxxcore_pmu.num_counters = counters; | 1609 | mipspmu.general_event_map = &mipsxxcore_event_map; |
1062 | mipsxxcore_pmu.irq = irq; | 1610 | mipspmu.cache_event_map = &mipsxxcore_cache_map; |
1063 | mipspmu = &mipsxxcore_pmu; | 1611 | break; |
1612 | case CPU_CAVIUM_OCTEON: | ||
1613 | case CPU_CAVIUM_OCTEON_PLUS: | ||
1614 | case CPU_CAVIUM_OCTEON2: | ||
1615 | mipspmu.name = "octeon"; | ||
1616 | mipspmu.general_event_map = &octeon_event_map; | ||
1617 | mipspmu.cache_event_map = &octeon_cache_map; | ||
1618 | mipspmu.map_raw_event = octeon_pmu_map_raw_event; | ||
1064 | break; | 1619 | break; |
1065 | default: | 1620 | default: |
1066 | pr_cont("Either hardware does not support performance " | 1621 | pr_cont("Either hardware does not support performance " |
@@ -1068,15 +1623,33 @@ init_hw_perf_events(void) | |||
1068 | return -ENODEV; | 1623 | return -ENODEV; |
1069 | } | 1624 | } |
1070 | 1625 | ||
1071 | if (mipspmu) | 1626 | mipspmu.num_counters = counters; |
1072 | pr_cont("%s PMU enabled, %d counters available to each " | 1627 | mipspmu.irq = irq; |
1073 | "CPU, irq %d%s\n", mipspmu->name, counters, irq, | 1628 | |
1074 | irq < 0 ? " (share with timer interrupt)" : ""); | 1629 | if (read_c0_perfctrl0() & M_PERFCTL_WIDE) { |
1630 | mipspmu.max_period = (1ULL << 63) - 1; | ||
1631 | mipspmu.valid_count = (1ULL << 63) - 1; | ||
1632 | mipspmu.overflow = 1ULL << 63; | ||
1633 | mipspmu.read_counter = mipsxx_pmu_read_counter_64; | ||
1634 | mipspmu.write_counter = mipsxx_pmu_write_counter_64; | ||
1635 | counter_bits = 64; | ||
1636 | } else { | ||
1637 | mipspmu.max_period = (1ULL << 31) - 1; | ||
1638 | mipspmu.valid_count = (1ULL << 31) - 1; | ||
1639 | mipspmu.overflow = 1ULL << 31; | ||
1640 | mipspmu.read_counter = mipsxx_pmu_read_counter; | ||
1641 | mipspmu.write_counter = mipsxx_pmu_write_counter; | ||
1642 | counter_bits = 32; | ||
1643 | } | ||
1644 | |||
1645 | on_each_cpu(reset_counters, (void *)(long)counters, 1); | ||
1646 | |||
1647 | pr_cont("%s PMU enabled, %d %d-bit counters available to each " | ||
1648 | "CPU, irq %d%s\n", mipspmu.name, counters, counter_bits, irq, | ||
1649 | irq < 0 ? " (share with timer interrupt)" : ""); | ||
1075 | 1650 | ||
1076 | perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); | 1651 | perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); |
1077 | 1652 | ||
1078 | return 0; | 1653 | return 0; |
1079 | } | 1654 | } |
1080 | early_initcall(init_hw_perf_events); | 1655 | early_initcall(init_hw_perf_events); |
1081 | |||
1082 | #endif /* defined(CONFIG_CPU_MIPS32)... */ | ||