ARM: 6835/1: perf: ensure overflows aren't missed due to IRQ latency
[deliverable/linux.git] / arch / arm / kernel / perf_event_v7.c
1 /*
2 * ARMv7 Cortex-A8 and Cortex-A9 Performance Events handling code.
3 *
4 * ARMv7 support: Jean Pihet <jpihet@mvista.com>
5 * 2010 (c) MontaVista Software, LLC.
6 *
7 * Copied from ARMv6 code, with the low level code inspired
8 * by the ARMv7 Oprofile code.
9 *
10 * Cortex-A8 has up to 4 configurable performance counters and
11 * a single cycle counter.
12 * Cortex-A9 has up to 31 configurable performance counters and
13 * a single cycle counter.
14 *
15 * All counters can be enabled/disabled and IRQ masked separately. The cycle
16 * counter and all 4 performance counters together can be reset separately.
17 */
18
19 #ifdef CONFIG_CPU_V7
20 /* Common ARMv7 event types */
21 enum armv7_perf_types {
22 ARMV7_PERFCTR_PMNC_SW_INCR = 0x00,
23 ARMV7_PERFCTR_IFETCH_MISS = 0x01,
24 ARMV7_PERFCTR_ITLB_MISS = 0x02,
25 ARMV7_PERFCTR_DCACHE_REFILL = 0x03,
26 ARMV7_PERFCTR_DCACHE_ACCESS = 0x04,
27 ARMV7_PERFCTR_DTLB_REFILL = 0x05,
28 ARMV7_PERFCTR_DREAD = 0x06,
29 ARMV7_PERFCTR_DWRITE = 0x07,
30
31 ARMV7_PERFCTR_EXC_TAKEN = 0x09,
32 ARMV7_PERFCTR_EXC_EXECUTED = 0x0A,
33 ARMV7_PERFCTR_CID_WRITE = 0x0B,
34 /* ARMV7_PERFCTR_PC_WRITE is equivalent to HW_BRANCH_INSTRUCTIONS.
35 * It counts:
36 * - all branch instructions,
37 * - instructions that explicitly write the PC,
38 * - exception generating instructions.
39 */
40 ARMV7_PERFCTR_PC_WRITE = 0x0C,
41 ARMV7_PERFCTR_PC_IMM_BRANCH = 0x0D,
42 ARMV7_PERFCTR_UNALIGNED_ACCESS = 0x0F,
43 ARMV7_PERFCTR_PC_BRANCH_MIS_PRED = 0x10,
44 ARMV7_PERFCTR_CLOCK_CYCLES = 0x11,
45
46 ARMV7_PERFCTR_PC_BRANCH_MIS_USED = 0x12,
47
48 ARMV7_PERFCTR_CPU_CYCLES = 0xFF
49 };
50
51 /* ARMv7 Cortex-A8 specific event types */
52 enum armv7_a8_perf_types {
53 ARMV7_PERFCTR_INSTR_EXECUTED = 0x08,
54
55 ARMV7_PERFCTR_PC_PROC_RETURN = 0x0E,
56
57 ARMV7_PERFCTR_WRITE_BUFFER_FULL = 0x40,
58 ARMV7_PERFCTR_L2_STORE_MERGED = 0x41,
59 ARMV7_PERFCTR_L2_STORE_BUFF = 0x42,
60 ARMV7_PERFCTR_L2_ACCESS = 0x43,
61 ARMV7_PERFCTR_L2_CACH_MISS = 0x44,
62 ARMV7_PERFCTR_AXI_READ_CYCLES = 0x45,
63 ARMV7_PERFCTR_AXI_WRITE_CYCLES = 0x46,
64 ARMV7_PERFCTR_MEMORY_REPLAY = 0x47,
65 ARMV7_PERFCTR_UNALIGNED_ACCESS_REPLAY = 0x48,
66 ARMV7_PERFCTR_L1_DATA_MISS = 0x49,
67 ARMV7_PERFCTR_L1_INST_MISS = 0x4A,
68 ARMV7_PERFCTR_L1_DATA_COLORING = 0x4B,
69 ARMV7_PERFCTR_L1_NEON_DATA = 0x4C,
70 ARMV7_PERFCTR_L1_NEON_CACH_DATA = 0x4D,
71 ARMV7_PERFCTR_L2_NEON = 0x4E,
72 ARMV7_PERFCTR_L2_NEON_HIT = 0x4F,
73 ARMV7_PERFCTR_L1_INST = 0x50,
74 ARMV7_PERFCTR_PC_RETURN_MIS_PRED = 0x51,
75 ARMV7_PERFCTR_PC_BRANCH_FAILED = 0x52,
76 ARMV7_PERFCTR_PC_BRANCH_TAKEN = 0x53,
77 ARMV7_PERFCTR_PC_BRANCH_EXECUTED = 0x54,
78 ARMV7_PERFCTR_OP_EXECUTED = 0x55,
79 ARMV7_PERFCTR_CYCLES_INST_STALL = 0x56,
80 ARMV7_PERFCTR_CYCLES_INST = 0x57,
81 ARMV7_PERFCTR_CYCLES_NEON_DATA_STALL = 0x58,
82 ARMV7_PERFCTR_CYCLES_NEON_INST_STALL = 0x59,
83 ARMV7_PERFCTR_NEON_CYCLES = 0x5A,
84
85 ARMV7_PERFCTR_PMU0_EVENTS = 0x70,
86 ARMV7_PERFCTR_PMU1_EVENTS = 0x71,
87 ARMV7_PERFCTR_PMU_EVENTS = 0x72,
88 };
89
90 /* ARMv7 Cortex-A9 specific event types */
91 enum armv7_a9_perf_types {
92 ARMV7_PERFCTR_JAVA_HW_BYTECODE_EXEC = 0x40,
93 ARMV7_PERFCTR_JAVA_SW_BYTECODE_EXEC = 0x41,
94 ARMV7_PERFCTR_JAZELLE_BRANCH_EXEC = 0x42,
95
96 ARMV7_PERFCTR_COHERENT_LINE_MISS = 0x50,
97 ARMV7_PERFCTR_COHERENT_LINE_HIT = 0x51,
98
99 ARMV7_PERFCTR_ICACHE_DEP_STALL_CYCLES = 0x60,
100 ARMV7_PERFCTR_DCACHE_DEP_STALL_CYCLES = 0x61,
101 ARMV7_PERFCTR_TLB_MISS_DEP_STALL_CYCLES = 0x62,
102 ARMV7_PERFCTR_STREX_EXECUTED_PASSED = 0x63,
103 ARMV7_PERFCTR_STREX_EXECUTED_FAILED = 0x64,
104 ARMV7_PERFCTR_DATA_EVICTION = 0x65,
105 ARMV7_PERFCTR_ISSUE_STAGE_NO_INST = 0x66,
106 ARMV7_PERFCTR_ISSUE_STAGE_EMPTY = 0x67,
107 ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE = 0x68,
108
109 ARMV7_PERFCTR_PREDICTABLE_FUNCT_RETURNS = 0x6E,
110
111 ARMV7_PERFCTR_MAIN_UNIT_EXECUTED_INST = 0x70,
112 ARMV7_PERFCTR_SECOND_UNIT_EXECUTED_INST = 0x71,
113 ARMV7_PERFCTR_LD_ST_UNIT_EXECUTED_INST = 0x72,
114 ARMV7_PERFCTR_FP_EXECUTED_INST = 0x73,
115 ARMV7_PERFCTR_NEON_EXECUTED_INST = 0x74,
116
117 ARMV7_PERFCTR_PLD_FULL_DEP_STALL_CYCLES = 0x80,
118 ARMV7_PERFCTR_DATA_WR_DEP_STALL_CYCLES = 0x81,
119 ARMV7_PERFCTR_ITLB_MISS_DEP_STALL_CYCLES = 0x82,
120 ARMV7_PERFCTR_DTLB_MISS_DEP_STALL_CYCLES = 0x83,
121 ARMV7_PERFCTR_MICRO_ITLB_MISS_DEP_STALL_CYCLES = 0x84,
122 ARMV7_PERFCTR_MICRO_DTLB_MISS_DEP_STALL_CYCLES = 0x85,
123 ARMV7_PERFCTR_DMB_DEP_STALL_CYCLES = 0x86,
124
125 ARMV7_PERFCTR_INTGR_CLK_ENABLED_CYCLES = 0x8A,
126 ARMV7_PERFCTR_DATA_ENGINE_CLK_EN_CYCLES = 0x8B,
127
128 ARMV7_PERFCTR_ISB_INST = 0x90,
129 ARMV7_PERFCTR_DSB_INST = 0x91,
130 ARMV7_PERFCTR_DMB_INST = 0x92,
131 ARMV7_PERFCTR_EXT_INTERRUPTS = 0x93,
132
133 ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_COMPLETED = 0xA0,
134 ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_SKIPPED = 0xA1,
135 ARMV7_PERFCTR_PLE_FIFO_FLUSH = 0xA2,
136 ARMV7_PERFCTR_PLE_RQST_COMPLETED = 0xA3,
137 ARMV7_PERFCTR_PLE_FIFO_OVERFLOW = 0xA4,
138 ARMV7_PERFCTR_PLE_RQST_PROG = 0xA5
139 };
140
141 /*
142 * Cortex-A8 HW events mapping
143 *
144 * The hardware events that we support. We do support cache operations but
145 * we have harvard caches and no way to combine instruction and data
146 * accesses/misses in hardware.
147 */
148 static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = {
149 [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
150 [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
151 [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
152 [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
153 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
154 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
155 [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
156 };
157
158 static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
159 [PERF_COUNT_HW_CACHE_OP_MAX]
160 [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
161 [C(L1D)] = {
162 /*
163 * The performance counters don't differentiate between read
164 * and write accesses/misses so this isn't strictly correct,
165 * but it's the best we can do. Writes and reads get
166 * combined.
167 */
168 [C(OP_READ)] = {
169 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_DCACHE_ACCESS,
170 [C(RESULT_MISS)] = ARMV7_PERFCTR_DCACHE_REFILL,
171 },
172 [C(OP_WRITE)] = {
173 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_DCACHE_ACCESS,
174 [C(RESULT_MISS)] = ARMV7_PERFCTR_DCACHE_REFILL,
175 },
176 [C(OP_PREFETCH)] = {
177 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
178 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
179 },
180 },
181 [C(L1I)] = {
182 [C(OP_READ)] = {
183 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_INST,
184 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_INST_MISS,
185 },
186 [C(OP_WRITE)] = {
187 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_INST,
188 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_INST_MISS,
189 },
190 [C(OP_PREFETCH)] = {
191 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
192 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
193 },
194 },
195 [C(LL)] = {
196 [C(OP_READ)] = {
197 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L2_ACCESS,
198 [C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACH_MISS,
199 },
200 [C(OP_WRITE)] = {
201 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L2_ACCESS,
202 [C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACH_MISS,
203 },
204 [C(OP_PREFETCH)] = {
205 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
206 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
207 },
208 },
209 [C(DTLB)] = {
210 /*
211 * Only ITLB misses and DTLB refills are supported.
212 * If users want the DTLB refills misses a raw counter
213 * must be used.
214 */
215 [C(OP_READ)] = {
216 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
217 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
218 },
219 [C(OP_WRITE)] = {
220 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
221 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
222 },
223 [C(OP_PREFETCH)] = {
224 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
225 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
226 },
227 },
228 [C(ITLB)] = {
229 [C(OP_READ)] = {
230 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
231 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
232 },
233 [C(OP_WRITE)] = {
234 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
235 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
236 },
237 [C(OP_PREFETCH)] = {
238 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
239 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
240 },
241 },
242 [C(BPU)] = {
243 [C(OP_READ)] = {
244 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_WRITE,
245 [C(RESULT_MISS)]
246 = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
247 },
248 [C(OP_WRITE)] = {
249 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_WRITE,
250 [C(RESULT_MISS)]
251 = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
252 },
253 [C(OP_PREFETCH)] = {
254 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
255 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
256 },
257 },
258 };
259
260 /*
261 * Cortex-A9 HW events mapping
262 */
263 static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
264 [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
265 [PERF_COUNT_HW_INSTRUCTIONS] =
266 ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE,
267 [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_COHERENT_LINE_HIT,
268 [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_COHERENT_LINE_MISS,
269 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
270 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
271 [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
272 };
273
274 static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
275 [PERF_COUNT_HW_CACHE_OP_MAX]
276 [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
277 [C(L1D)] = {
278 /*
279 * The performance counters don't differentiate between read
280 * and write accesses/misses so this isn't strictly correct,
281 * but it's the best we can do. Writes and reads get
282 * combined.
283 */
284 [C(OP_READ)] = {
285 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_DCACHE_ACCESS,
286 [C(RESULT_MISS)] = ARMV7_PERFCTR_DCACHE_REFILL,
287 },
288 [C(OP_WRITE)] = {
289 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_DCACHE_ACCESS,
290 [C(RESULT_MISS)] = ARMV7_PERFCTR_DCACHE_REFILL,
291 },
292 [C(OP_PREFETCH)] = {
293 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
294 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
295 },
296 },
297 [C(L1I)] = {
298 [C(OP_READ)] = {
299 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
300 [C(RESULT_MISS)] = ARMV7_PERFCTR_IFETCH_MISS,
301 },
302 [C(OP_WRITE)] = {
303 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
304 [C(RESULT_MISS)] = ARMV7_PERFCTR_IFETCH_MISS,
305 },
306 [C(OP_PREFETCH)] = {
307 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
308 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
309 },
310 },
311 [C(LL)] = {
312 [C(OP_READ)] = {
313 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
314 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
315 },
316 [C(OP_WRITE)] = {
317 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
318 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
319 },
320 [C(OP_PREFETCH)] = {
321 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
322 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
323 },
324 },
325 [C(DTLB)] = {
326 /*
327 * Only ITLB misses and DTLB refills are supported.
328 * If users want the DTLB refills misses a raw counter
329 * must be used.
330 */
331 [C(OP_READ)] = {
332 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
333 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
334 },
335 [C(OP_WRITE)] = {
336 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
337 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
338 },
339 [C(OP_PREFETCH)] = {
340 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
341 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
342 },
343 },
344 [C(ITLB)] = {
345 [C(OP_READ)] = {
346 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
347 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
348 },
349 [C(OP_WRITE)] = {
350 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
351 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
352 },
353 [C(OP_PREFETCH)] = {
354 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
355 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
356 },
357 },
358 [C(BPU)] = {
359 [C(OP_READ)] = {
360 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_WRITE,
361 [C(RESULT_MISS)]
362 = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
363 },
364 [C(OP_WRITE)] = {
365 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_WRITE,
366 [C(RESULT_MISS)]
367 = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
368 },
369 [C(OP_PREFETCH)] = {
370 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
371 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
372 },
373 },
374 };
375
376 /*
377 * Perf Events counters
378 */
379 enum armv7_counters {
380 ARMV7_CYCLE_COUNTER = 1, /* Cycle counter */
381 ARMV7_COUNTER0 = 2, /* First event counter */
382 };
383
384 /*
385 * The cycle counter is ARMV7_CYCLE_COUNTER.
386 * The first event counter is ARMV7_COUNTER0.
387 * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1).
388 */
389 #define ARMV7_COUNTER_LAST (ARMV7_COUNTER0 + armpmu->num_events - 1)
390
391 /*
392 * ARMv7 low level PMNC access
393 */
394
395 /*
396 * Per-CPU PMNC: config reg
397 */
398 #define ARMV7_PMNC_E (1 << 0) /* Enable all counters */
399 #define ARMV7_PMNC_P (1 << 1) /* Reset all counters */
400 #define ARMV7_PMNC_C (1 << 2) /* Cycle counter reset */
401 #define ARMV7_PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */
402 #define ARMV7_PMNC_X (1 << 4) /* Export to ETM */
403 #define ARMV7_PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/
404 #define ARMV7_PMNC_N_SHIFT 11 /* Number of counters supported */
405 #define ARMV7_PMNC_N_MASK 0x1f
406 #define ARMV7_PMNC_MASK 0x3f /* Mask for writable bits */
407
408 /*
409 * Available counters
410 */
411 #define ARMV7_CNT0 0 /* First event counter */
412 #define ARMV7_CCNT 31 /* Cycle counter */
413
414 /* Perf Event to low level counters mapping */
415 #define ARMV7_EVENT_CNT_TO_CNTx (ARMV7_COUNTER0 - ARMV7_CNT0)
416
417 /*
418 * CNTENS: counters enable reg
419 */
420 #define ARMV7_CNTENS_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
421 #define ARMV7_CNTENS_C (1 << ARMV7_CCNT)
422
423 /*
424 * CNTENC: counters disable reg
425 */
426 #define ARMV7_CNTENC_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
427 #define ARMV7_CNTENC_C (1 << ARMV7_CCNT)
428
429 /*
430 * INTENS: counters overflow interrupt enable reg
431 */
432 #define ARMV7_INTENS_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
433 #define ARMV7_INTENS_C (1 << ARMV7_CCNT)
434
435 /*
436 * INTENC: counters overflow interrupt disable reg
437 */
438 #define ARMV7_INTENC_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
439 #define ARMV7_INTENC_C (1 << ARMV7_CCNT)
440
441 /*
442 * EVTSEL: Event selection reg
443 */
444 #define ARMV7_EVTSEL_MASK 0xff /* Mask for writable bits */
445
446 /*
447 * SELECT: Counter selection reg
448 */
449 #define ARMV7_SELECT_MASK 0x1f /* Mask for writable bits */
450
451 /*
452 * FLAG: counters overflow flag status reg
453 */
454 #define ARMV7_FLAG_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
455 #define ARMV7_FLAG_C (1 << ARMV7_CCNT)
456 #define ARMV7_FLAG_MASK 0xffffffff /* Mask for writable bits */
457 #define ARMV7_OVERFLOWED_MASK ARMV7_FLAG_MASK
458
459 static inline unsigned long armv7_pmnc_read(void)
460 {
461 u32 val;
462 asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
463 return val;
464 }
465
466 static inline void armv7_pmnc_write(unsigned long val)
467 {
468 val &= ARMV7_PMNC_MASK;
469 isb();
470 asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
471 }
472
473 static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
474 {
475 return pmnc & ARMV7_OVERFLOWED_MASK;
476 }
477
478 static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
479 enum armv7_counters counter)
480 {
481 int ret = 0;
482
483 if (counter == ARMV7_CYCLE_COUNTER)
484 ret = pmnc & ARMV7_FLAG_C;
485 else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST))
486 ret = pmnc & ARMV7_FLAG_P(counter);
487 else
488 pr_err("CPU%u checking wrong counter %d overflow status\n",
489 smp_processor_id(), counter);
490
491 return ret;
492 }
493
494 static inline int armv7_pmnc_select_counter(unsigned int idx)
495 {
496 u32 val;
497
498 if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
499 pr_err("CPU%u selecting wrong PMNC counter"
500 " %d\n", smp_processor_id(), idx);
501 return -1;
502 }
503
504 val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
505 asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
506 isb();
507
508 return idx;
509 }
510
511 static inline u32 armv7pmu_read_counter(int idx)
512 {
513 unsigned long value = 0;
514
515 if (idx == ARMV7_CYCLE_COUNTER)
516 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
517 else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
518 if (armv7_pmnc_select_counter(idx) == idx)
519 asm volatile("mrc p15, 0, %0, c9, c13, 2"
520 : "=r" (value));
521 } else
522 pr_err("CPU%u reading wrong counter %d\n",
523 smp_processor_id(), idx);
524
525 return value;
526 }
527
528 static inline void armv7pmu_write_counter(int idx, u32 value)
529 {
530 if (idx == ARMV7_CYCLE_COUNTER)
531 asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
532 else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
533 if (armv7_pmnc_select_counter(idx) == idx)
534 asm volatile("mcr p15, 0, %0, c9, c13, 2"
535 : : "r" (value));
536 } else
537 pr_err("CPU%u writing wrong counter %d\n",
538 smp_processor_id(), idx);
539 }
540
541 static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
542 {
543 if (armv7_pmnc_select_counter(idx) == idx) {
544 val &= ARMV7_EVTSEL_MASK;
545 asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
546 }
547 }
548
549 static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
550 {
551 u32 val;
552
553 if ((idx != ARMV7_CYCLE_COUNTER) &&
554 ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
555 pr_err("CPU%u enabling wrong PMNC counter"
556 " %d\n", smp_processor_id(), idx);
557 return -1;
558 }
559
560 if (idx == ARMV7_CYCLE_COUNTER)
561 val = ARMV7_CNTENS_C;
562 else
563 val = ARMV7_CNTENS_P(idx);
564
565 asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
566
567 return idx;
568 }
569
570 static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
571 {
572 u32 val;
573
574
575 if ((idx != ARMV7_CYCLE_COUNTER) &&
576 ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
577 pr_err("CPU%u disabling wrong PMNC counter"
578 " %d\n", smp_processor_id(), idx);
579 return -1;
580 }
581
582 if (idx == ARMV7_CYCLE_COUNTER)
583 val = ARMV7_CNTENC_C;
584 else
585 val = ARMV7_CNTENC_P(idx);
586
587 asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
588
589 return idx;
590 }
591
592 static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
593 {
594 u32 val;
595
596 if ((idx != ARMV7_CYCLE_COUNTER) &&
597 ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
598 pr_err("CPU%u enabling wrong PMNC counter"
599 " interrupt enable %d\n", smp_processor_id(), idx);
600 return -1;
601 }
602
603 if (idx == ARMV7_CYCLE_COUNTER)
604 val = ARMV7_INTENS_C;
605 else
606 val = ARMV7_INTENS_P(idx);
607
608 asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
609
610 return idx;
611 }
612
613 static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
614 {
615 u32 val;
616
617 if ((idx != ARMV7_CYCLE_COUNTER) &&
618 ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
619 pr_err("CPU%u disabling wrong PMNC counter"
620 " interrupt enable %d\n", smp_processor_id(), idx);
621 return -1;
622 }
623
624 if (idx == ARMV7_CYCLE_COUNTER)
625 val = ARMV7_INTENC_C;
626 else
627 val = ARMV7_INTENC_P(idx);
628
629 asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
630
631 return idx;
632 }
633
634 static inline u32 armv7_pmnc_getreset_flags(void)
635 {
636 u32 val;
637
638 /* Read */
639 asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
640
641 /* Write to clear flags */
642 val &= ARMV7_FLAG_MASK;
643 asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val));
644
645 return val;
646 }
647
648 #ifdef DEBUG
649 static void armv7_pmnc_dump_regs(void)
650 {
651 u32 val;
652 unsigned int cnt;
653
654 printk(KERN_INFO "PMNC registers dump:\n");
655
656 asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
657 printk(KERN_INFO "PMNC =0x%08x\n", val);
658
659 asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val));
660 printk(KERN_INFO "CNTENS=0x%08x\n", val);
661
662 asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val));
663 printk(KERN_INFO "INTENS=0x%08x\n", val);
664
665 asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
666 printk(KERN_INFO "FLAGS =0x%08x\n", val);
667
668 asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val));
669 printk(KERN_INFO "SELECT=0x%08x\n", val);
670
671 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
672 printk(KERN_INFO "CCNT =0x%08x\n", val);
673
674 for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) {
675 armv7_pmnc_select_counter(cnt);
676 asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
677 printk(KERN_INFO "CNT[%d] count =0x%08x\n",
678 cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
679 asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
680 printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
681 cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
682 }
683 }
684 #endif
685
686 static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
687 {
688 unsigned long flags;
689
690 /*
691 * Enable counter and interrupt, and set the counter to count
692 * the event that we're interested in.
693 */
694 raw_spin_lock_irqsave(&pmu_lock, flags);
695
696 /*
697 * Disable counter
698 */
699 armv7_pmnc_disable_counter(idx);
700
701 /*
702 * Set event (if destined for PMNx counters)
703 * We don't need to set the event if it's a cycle count
704 */
705 if (idx != ARMV7_CYCLE_COUNTER)
706 armv7_pmnc_write_evtsel(idx, hwc->config_base);
707
708 /*
709 * Enable interrupt for this counter
710 */
711 armv7_pmnc_enable_intens(idx);
712
713 /*
714 * Enable counter
715 */
716 armv7_pmnc_enable_counter(idx);
717
718 raw_spin_unlock_irqrestore(&pmu_lock, flags);
719 }
720
721 static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
722 {
723 unsigned long flags;
724
725 /*
726 * Disable counter and interrupt
727 */
728 raw_spin_lock_irqsave(&pmu_lock, flags);
729
730 /*
731 * Disable counter
732 */
733 armv7_pmnc_disable_counter(idx);
734
735 /*
736 * Disable interrupt for this counter
737 */
738 armv7_pmnc_disable_intens(idx);
739
740 raw_spin_unlock_irqrestore(&pmu_lock, flags);
741 }
742
743 static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
744 {
745 unsigned long pmnc;
746 struct perf_sample_data data;
747 struct cpu_hw_events *cpuc;
748 struct pt_regs *regs;
749 int idx;
750
751 /*
752 * Get and reset the IRQ flags
753 */
754 pmnc = armv7_pmnc_getreset_flags();
755
756 /*
757 * Did an overflow occur?
758 */
759 if (!armv7_pmnc_has_overflowed(pmnc))
760 return IRQ_NONE;
761
762 /*
763 * Handle the counter(s) overflow(s)
764 */
765 regs = get_irq_regs();
766
767 perf_sample_data_init(&data, 0);
768
769 cpuc = &__get_cpu_var(cpu_hw_events);
770 for (idx = 0; idx <= armpmu->num_events; ++idx) {
771 struct perf_event *event = cpuc->events[idx];
772 struct hw_perf_event *hwc;
773
774 if (!test_bit(idx, cpuc->active_mask))
775 continue;
776
777 /*
778 * We have a single interrupt for all counters. Check that
779 * each counter has overflowed before we process it.
780 */
781 if (!armv7_pmnc_counter_has_overflowed(pmnc, idx))
782 continue;
783
784 hwc = &event->hw;
785 armpmu_event_update(event, hwc, idx, 1);
786 data.period = event->hw.last_period;
787 if (!armpmu_event_set_period(event, hwc, idx))
788 continue;
789
790 if (perf_event_overflow(event, 0, &data, regs))
791 armpmu->disable(hwc, idx);
792 }
793
794 /*
795 * Handle the pending perf events.
796 *
797 * Note: this call *must* be run with interrupts disabled. For
798 * platforms that can have the PMU interrupts raised as an NMI, this
799 * will not work.
800 */
801 irq_work_run();
802
803 return IRQ_HANDLED;
804 }
805
806 static void armv7pmu_start(void)
807 {
808 unsigned long flags;
809
810 raw_spin_lock_irqsave(&pmu_lock, flags);
811 /* Enable all counters */
812 armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
813 raw_spin_unlock_irqrestore(&pmu_lock, flags);
814 }
815
816 static void armv7pmu_stop(void)
817 {
818 unsigned long flags;
819
820 raw_spin_lock_irqsave(&pmu_lock, flags);
821 /* Disable all counters */
822 armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
823 raw_spin_unlock_irqrestore(&pmu_lock, flags);
824 }
825
826 static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
827 struct hw_perf_event *event)
828 {
829 int idx;
830
831 /* Always place a cycle counter into the cycle counter. */
832 if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) {
833 if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask))
834 return -EAGAIN;
835
836 return ARMV7_CYCLE_COUNTER;
837 } else {
838 /*
839 * For anything other than a cycle counter, try and use
840 * the events counters
841 */
842 for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) {
843 if (!test_and_set_bit(idx, cpuc->used_mask))
844 return idx;
845 }
846
847 /* The counters are all in use. */
848 return -EAGAIN;
849 }
850 }
851
852 static void armv7pmu_reset(void *info)
853 {
854 u32 idx, nb_cnt = armpmu->num_events;
855
856 /* The counter and interrupt enable registers are unknown at reset. */
857 for (idx = 1; idx < nb_cnt; ++idx)
858 armv7pmu_disable_event(NULL, idx);
859
860 /* Initialize & Reset PMNC: C and P bits */
861 armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
862 }
863
864 static struct arm_pmu armv7pmu = {
865 .handle_irq = armv7pmu_handle_irq,
866 .enable = armv7pmu_enable_event,
867 .disable = armv7pmu_disable_event,
868 .read_counter = armv7pmu_read_counter,
869 .write_counter = armv7pmu_write_counter,
870 .get_event_idx = armv7pmu_get_event_idx,
871 .start = armv7pmu_start,
872 .stop = armv7pmu_stop,
873 .reset = armv7pmu_reset,
874 .raw_event_mask = 0xFF,
875 .max_period = (1LLU << 32) - 1,
876 };
877
878 static u32 __init armv7_read_num_pmnc_events(void)
879 {
880 u32 nb_cnt;
881
882 /* Read the nb of CNTx counters supported from PMNC */
883 nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
884
885 /* Add the CPU cycles counter and return */
886 return nb_cnt + 1;
887 }
888
889 static const struct arm_pmu *__init armv7_a8_pmu_init(void)
890 {
891 armv7pmu.id = ARM_PERF_PMU_ID_CA8;
892 armv7pmu.name = "ARMv7 Cortex-A8";
893 armv7pmu.cache_map = &armv7_a8_perf_cache_map;
894 armv7pmu.event_map = &armv7_a8_perf_map;
895 armv7pmu.num_events = armv7_read_num_pmnc_events();
896 return &armv7pmu;
897 }
898
899 static const struct arm_pmu *__init armv7_a9_pmu_init(void)
900 {
901 armv7pmu.id = ARM_PERF_PMU_ID_CA9;
902 armv7pmu.name = "ARMv7 Cortex-A9";
903 armv7pmu.cache_map = &armv7_a9_perf_cache_map;
904 armv7pmu.event_map = &armv7_a9_perf_map;
905 armv7pmu.num_events = armv7_read_num_pmnc_events();
906 return &armv7pmu;
907 }
908 #else
909 static const struct arm_pmu *__init armv7_a8_pmu_init(void)
910 {
911 return NULL;
912 }
913
914 static const struct arm_pmu *__init armv7_a9_pmu_init(void)
915 {
916 return NULL;
917 }
918 #endif /* CONFIG_CPU_V7 */
This page took 0.054544 seconds and 5 git commands to generate.