xref: /openbmc/linux/arch/arm/kernel/perf_event_v7.c (revision 81d67439)
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 	[C(NODE)] = {
259 		[C(OP_READ)] = {
260 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
261 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
262 		},
263 		[C(OP_WRITE)] = {
264 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
265 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
266 		},
267 		[C(OP_PREFETCH)] = {
268 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
269 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
270 		},
271 	},
272 };
273 
274 /*
275  * Cortex-A9 HW events mapping
276  */
277 static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
278 	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
279 	[PERF_COUNT_HW_INSTRUCTIONS]	    =
280 					ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE,
281 	[PERF_COUNT_HW_CACHE_REFERENCES]    = ARMV7_PERFCTR_COHERENT_LINE_HIT,
282 	[PERF_COUNT_HW_CACHE_MISSES]	    = ARMV7_PERFCTR_COHERENT_LINE_MISS,
283 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
284 	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
285 	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
286 };
287 
288 static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
289 					  [PERF_COUNT_HW_CACHE_OP_MAX]
290 					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
291 	[C(L1D)] = {
292 		/*
293 		 * The performance counters don't differentiate between read
294 		 * and write accesses/misses so this isn't strictly correct,
295 		 * but it's the best we can do. Writes and reads get
296 		 * combined.
297 		 */
298 		[C(OP_READ)] = {
299 			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
300 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
301 		},
302 		[C(OP_WRITE)] = {
303 			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS,
304 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL,
305 		},
306 		[C(OP_PREFETCH)] = {
307 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
308 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
309 		},
310 	},
311 	[C(L1I)] = {
312 		[C(OP_READ)] = {
313 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
314 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
315 		},
316 		[C(OP_WRITE)] = {
317 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
318 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
319 		},
320 		[C(OP_PREFETCH)] = {
321 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
322 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
323 		},
324 	},
325 	[C(LL)] = {
326 		[C(OP_READ)] = {
327 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
328 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
329 		},
330 		[C(OP_WRITE)] = {
331 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
332 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
333 		},
334 		[C(OP_PREFETCH)] = {
335 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
336 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
337 		},
338 	},
339 	[C(DTLB)] = {
340 		/*
341 		 * Only ITLB misses and DTLB refills are supported.
342 		 * If users want the DTLB refills misses a raw counter
343 		 * must be used.
344 		 */
345 		[C(OP_READ)] = {
346 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
347 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
348 		},
349 		[C(OP_WRITE)] = {
350 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
351 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
352 		},
353 		[C(OP_PREFETCH)] = {
354 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
355 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
356 		},
357 	},
358 	[C(ITLB)] = {
359 		[C(OP_READ)] = {
360 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
361 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
362 		},
363 		[C(OP_WRITE)] = {
364 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
365 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
366 		},
367 		[C(OP_PREFETCH)] = {
368 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
369 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
370 		},
371 	},
372 	[C(BPU)] = {
373 		[C(OP_READ)] = {
374 			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE,
375 			[C(RESULT_MISS)]
376 					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
377 		},
378 		[C(OP_WRITE)] = {
379 			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE,
380 			[C(RESULT_MISS)]
381 					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
382 		},
383 		[C(OP_PREFETCH)] = {
384 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
385 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
386 		},
387 	},
388 	[C(NODE)] = {
389 		[C(OP_READ)] = {
390 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
391 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
392 		},
393 		[C(OP_WRITE)] = {
394 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
395 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
396 		},
397 		[C(OP_PREFETCH)] = {
398 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
399 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
400 		},
401 	},
402 };
403 
404 /*
405  * Perf Events counters
406  */
407 enum armv7_counters {
408 	ARMV7_CYCLE_COUNTER		= 1,	/* Cycle counter */
409 	ARMV7_COUNTER0			= 2,	/* First event counter */
410 };
411 
412 /*
413  * The cycle counter is ARMV7_CYCLE_COUNTER.
414  * The first event counter is ARMV7_COUNTER0.
415  * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1).
416  */
417 #define	ARMV7_COUNTER_LAST	(ARMV7_COUNTER0 + armpmu->num_events - 1)
418 
419 /*
420  * ARMv7 low level PMNC access
421  */
422 
423 /*
424  * Per-CPU PMNC: config reg
425  */
426 #define ARMV7_PMNC_E		(1 << 0) /* Enable all counters */
427 #define ARMV7_PMNC_P		(1 << 1) /* Reset all counters */
428 #define ARMV7_PMNC_C		(1 << 2) /* Cycle counter reset */
429 #define ARMV7_PMNC_D		(1 << 3) /* CCNT counts every 64th cpu cycle */
430 #define ARMV7_PMNC_X		(1 << 4) /* Export to ETM */
431 #define ARMV7_PMNC_DP		(1 << 5) /* Disable CCNT if non-invasive debug*/
432 #define	ARMV7_PMNC_N_SHIFT	11	 /* Number of counters supported */
433 #define	ARMV7_PMNC_N_MASK	0x1f
434 #define	ARMV7_PMNC_MASK		0x3f	 /* Mask for writable bits */
435 
436 /*
437  * Available counters
438  */
439 #define ARMV7_CNT0		0	/* First event counter */
440 #define ARMV7_CCNT		31	/* Cycle counter */
441 
442 /* Perf Event to low level counters mapping */
443 #define ARMV7_EVENT_CNT_TO_CNTx	(ARMV7_COUNTER0 - ARMV7_CNT0)
444 
445 /*
446  * CNTENS: counters enable reg
447  */
448 #define ARMV7_CNTENS_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
449 #define ARMV7_CNTENS_C		(1 << ARMV7_CCNT)
450 
451 /*
452  * CNTENC: counters disable reg
453  */
454 #define ARMV7_CNTENC_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
455 #define ARMV7_CNTENC_C		(1 << ARMV7_CCNT)
456 
457 /*
458  * INTENS: counters overflow interrupt enable reg
459  */
460 #define ARMV7_INTENS_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
461 #define ARMV7_INTENS_C		(1 << ARMV7_CCNT)
462 
463 /*
464  * INTENC: counters overflow interrupt disable reg
465  */
466 #define ARMV7_INTENC_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
467 #define ARMV7_INTENC_C		(1 << ARMV7_CCNT)
468 
469 /*
470  * EVTSEL: Event selection reg
471  */
472 #define	ARMV7_EVTSEL_MASK	0xff		/* Mask for writable bits */
473 
474 /*
475  * SELECT: Counter selection reg
476  */
477 #define	ARMV7_SELECT_MASK	0x1f		/* Mask for writable bits */
478 
479 /*
480  * FLAG: counters overflow flag status reg
481  */
482 #define ARMV7_FLAG_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
483 #define ARMV7_FLAG_C		(1 << ARMV7_CCNT)
484 #define	ARMV7_FLAG_MASK		0xffffffff	/* Mask for writable bits */
485 #define	ARMV7_OVERFLOWED_MASK	ARMV7_FLAG_MASK
486 
487 static inline unsigned long armv7_pmnc_read(void)
488 {
489 	u32 val;
490 	asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
491 	return val;
492 }
493 
494 static inline void armv7_pmnc_write(unsigned long val)
495 {
496 	val &= ARMV7_PMNC_MASK;
497 	isb();
498 	asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
499 }
500 
501 static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
502 {
503 	return pmnc & ARMV7_OVERFLOWED_MASK;
504 }
505 
506 static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
507 					enum armv7_counters counter)
508 {
509 	int ret = 0;
510 
511 	if (counter == ARMV7_CYCLE_COUNTER)
512 		ret = pmnc & ARMV7_FLAG_C;
513 	else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST))
514 		ret = pmnc & ARMV7_FLAG_P(counter);
515 	else
516 		pr_err("CPU%u checking wrong counter %d overflow status\n",
517 			smp_processor_id(), counter);
518 
519 	return ret;
520 }
521 
522 static inline int armv7_pmnc_select_counter(unsigned int idx)
523 {
524 	u32 val;
525 
526 	if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
527 		pr_err("CPU%u selecting wrong PMNC counter"
528 			" %d\n", smp_processor_id(), idx);
529 		return -1;
530 	}
531 
532 	val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
533 	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
534 	isb();
535 
536 	return idx;
537 }
538 
539 static inline u32 armv7pmu_read_counter(int idx)
540 {
541 	unsigned long value = 0;
542 
543 	if (idx == ARMV7_CYCLE_COUNTER)
544 		asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
545 	else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
546 		if (armv7_pmnc_select_counter(idx) == idx)
547 			asm volatile("mrc p15, 0, %0, c9, c13, 2"
548 				     : "=r" (value));
549 	} else
550 		pr_err("CPU%u reading wrong counter %d\n",
551 			smp_processor_id(), idx);
552 
553 	return value;
554 }
555 
556 static inline void armv7pmu_write_counter(int idx, u32 value)
557 {
558 	if (idx == ARMV7_CYCLE_COUNTER)
559 		asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
560 	else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
561 		if (armv7_pmnc_select_counter(idx) == idx)
562 			asm volatile("mcr p15, 0, %0, c9, c13, 2"
563 				     : : "r" (value));
564 	} else
565 		pr_err("CPU%u writing wrong counter %d\n",
566 			smp_processor_id(), idx);
567 }
568 
569 static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
570 {
571 	if (armv7_pmnc_select_counter(idx) == idx) {
572 		val &= ARMV7_EVTSEL_MASK;
573 		asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
574 	}
575 }
576 
577 static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
578 {
579 	u32 val;
580 
581 	if ((idx != ARMV7_CYCLE_COUNTER) &&
582 	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
583 		pr_err("CPU%u enabling wrong PMNC counter"
584 			" %d\n", smp_processor_id(), idx);
585 		return -1;
586 	}
587 
588 	if (idx == ARMV7_CYCLE_COUNTER)
589 		val = ARMV7_CNTENS_C;
590 	else
591 		val = ARMV7_CNTENS_P(idx);
592 
593 	asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
594 
595 	return idx;
596 }
597 
598 static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
599 {
600 	u32 val;
601 
602 
603 	if ((idx != ARMV7_CYCLE_COUNTER) &&
604 	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
605 		pr_err("CPU%u disabling wrong PMNC counter"
606 			" %d\n", smp_processor_id(), idx);
607 		return -1;
608 	}
609 
610 	if (idx == ARMV7_CYCLE_COUNTER)
611 		val = ARMV7_CNTENC_C;
612 	else
613 		val = ARMV7_CNTENC_P(idx);
614 
615 	asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
616 
617 	return idx;
618 }
619 
620 static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
621 {
622 	u32 val;
623 
624 	if ((idx != ARMV7_CYCLE_COUNTER) &&
625 	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
626 		pr_err("CPU%u enabling wrong PMNC counter"
627 			" interrupt enable %d\n", smp_processor_id(), idx);
628 		return -1;
629 	}
630 
631 	if (idx == ARMV7_CYCLE_COUNTER)
632 		val = ARMV7_INTENS_C;
633 	else
634 		val = ARMV7_INTENS_P(idx);
635 
636 	asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
637 
638 	return idx;
639 }
640 
641 static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
642 {
643 	u32 val;
644 
645 	if ((idx != ARMV7_CYCLE_COUNTER) &&
646 	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
647 		pr_err("CPU%u disabling wrong PMNC counter"
648 			" interrupt enable %d\n", smp_processor_id(), idx);
649 		return -1;
650 	}
651 
652 	if (idx == ARMV7_CYCLE_COUNTER)
653 		val = ARMV7_INTENC_C;
654 	else
655 		val = ARMV7_INTENC_P(idx);
656 
657 	asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
658 
659 	return idx;
660 }
661 
662 static inline u32 armv7_pmnc_getreset_flags(void)
663 {
664 	u32 val;
665 
666 	/* Read */
667 	asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
668 
669 	/* Write to clear flags */
670 	val &= ARMV7_FLAG_MASK;
671 	asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val));
672 
673 	return val;
674 }
675 
676 #ifdef DEBUG
677 static void armv7_pmnc_dump_regs(void)
678 {
679 	u32 val;
680 	unsigned int cnt;
681 
682 	printk(KERN_INFO "PMNC registers dump:\n");
683 
684 	asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
685 	printk(KERN_INFO "PMNC  =0x%08x\n", val);
686 
687 	asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val));
688 	printk(KERN_INFO "CNTENS=0x%08x\n", val);
689 
690 	asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val));
691 	printk(KERN_INFO "INTENS=0x%08x\n", val);
692 
693 	asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
694 	printk(KERN_INFO "FLAGS =0x%08x\n", val);
695 
696 	asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val));
697 	printk(KERN_INFO "SELECT=0x%08x\n", val);
698 
699 	asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
700 	printk(KERN_INFO "CCNT  =0x%08x\n", val);
701 
702 	for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) {
703 		armv7_pmnc_select_counter(cnt);
704 		asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
705 		printk(KERN_INFO "CNT[%d] count =0x%08x\n",
706 			cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
707 		asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
708 		printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
709 			cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
710 	}
711 }
712 #endif
713 
714 static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
715 {
716 	unsigned long flags;
717 
718 	/*
719 	 * Enable counter and interrupt, and set the counter to count
720 	 * the event that we're interested in.
721 	 */
722 	raw_spin_lock_irqsave(&pmu_lock, flags);
723 
724 	/*
725 	 * Disable counter
726 	 */
727 	armv7_pmnc_disable_counter(idx);
728 
729 	/*
730 	 * Set event (if destined for PMNx counters)
731 	 * We don't need to set the event if it's a cycle count
732 	 */
733 	if (idx != ARMV7_CYCLE_COUNTER)
734 		armv7_pmnc_write_evtsel(idx, hwc->config_base);
735 
736 	/*
737 	 * Enable interrupt for this counter
738 	 */
739 	armv7_pmnc_enable_intens(idx);
740 
741 	/*
742 	 * Enable counter
743 	 */
744 	armv7_pmnc_enable_counter(idx);
745 
746 	raw_spin_unlock_irqrestore(&pmu_lock, flags);
747 }
748 
749 static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
750 {
751 	unsigned long flags;
752 
753 	/*
754 	 * Disable counter and interrupt
755 	 */
756 	raw_spin_lock_irqsave(&pmu_lock, flags);
757 
758 	/*
759 	 * Disable counter
760 	 */
761 	armv7_pmnc_disable_counter(idx);
762 
763 	/*
764 	 * Disable interrupt for this counter
765 	 */
766 	armv7_pmnc_disable_intens(idx);
767 
768 	raw_spin_unlock_irqrestore(&pmu_lock, flags);
769 }
770 
771 static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
772 {
773 	unsigned long pmnc;
774 	struct perf_sample_data data;
775 	struct cpu_hw_events *cpuc;
776 	struct pt_regs *regs;
777 	int idx;
778 
779 	/*
780 	 * Get and reset the IRQ flags
781 	 */
782 	pmnc = armv7_pmnc_getreset_flags();
783 
784 	/*
785 	 * Did an overflow occur?
786 	 */
787 	if (!armv7_pmnc_has_overflowed(pmnc))
788 		return IRQ_NONE;
789 
790 	/*
791 	 * Handle the counter(s) overflow(s)
792 	 */
793 	regs = get_irq_regs();
794 
795 	perf_sample_data_init(&data, 0);
796 
797 	cpuc = &__get_cpu_var(cpu_hw_events);
798 	for (idx = 0; idx <= armpmu->num_events; ++idx) {
799 		struct perf_event *event = cpuc->events[idx];
800 		struct hw_perf_event *hwc;
801 
802 		if (!test_bit(idx, cpuc->active_mask))
803 			continue;
804 
805 		/*
806 		 * We have a single interrupt for all counters. Check that
807 		 * each counter has overflowed before we process it.
808 		 */
809 		if (!armv7_pmnc_counter_has_overflowed(pmnc, idx))
810 			continue;
811 
812 		hwc = &event->hw;
813 		armpmu_event_update(event, hwc, idx, 1);
814 		data.period = event->hw.last_period;
815 		if (!armpmu_event_set_period(event, hwc, idx))
816 			continue;
817 
818 		if (perf_event_overflow(event, &data, regs))
819 			armpmu->disable(hwc, idx);
820 	}
821 
822 	/*
823 	 * Handle the pending perf events.
824 	 *
825 	 * Note: this call *must* be run with interrupts disabled. For
826 	 * platforms that can have the PMU interrupts raised as an NMI, this
827 	 * will not work.
828 	 */
829 	irq_work_run();
830 
831 	return IRQ_HANDLED;
832 }
833 
834 static void armv7pmu_start(void)
835 {
836 	unsigned long flags;
837 
838 	raw_spin_lock_irqsave(&pmu_lock, flags);
839 	/* Enable all counters */
840 	armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
841 	raw_spin_unlock_irqrestore(&pmu_lock, flags);
842 }
843 
844 static void armv7pmu_stop(void)
845 {
846 	unsigned long flags;
847 
848 	raw_spin_lock_irqsave(&pmu_lock, flags);
849 	/* Disable all counters */
850 	armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
851 	raw_spin_unlock_irqrestore(&pmu_lock, flags);
852 }
853 
854 static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
855 				  struct hw_perf_event *event)
856 {
857 	int idx;
858 
859 	/* Always place a cycle counter into the cycle counter. */
860 	if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) {
861 		if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask))
862 			return -EAGAIN;
863 
864 		return ARMV7_CYCLE_COUNTER;
865 	} else {
866 		/*
867 		 * For anything other than a cycle counter, try and use
868 		 * the events counters
869 		 */
870 		for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) {
871 			if (!test_and_set_bit(idx, cpuc->used_mask))
872 				return idx;
873 		}
874 
875 		/* The counters are all in use. */
876 		return -EAGAIN;
877 	}
878 }
879 
880 static void armv7pmu_reset(void *info)
881 {
882 	u32 idx, nb_cnt = armpmu->num_events;
883 
884 	/* The counter and interrupt enable registers are unknown at reset. */
885 	for (idx = 1; idx < nb_cnt; ++idx)
886 		armv7pmu_disable_event(NULL, idx);
887 
888 	/* Initialize & Reset PMNC: C and P bits */
889 	armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
890 }
891 
892 static struct arm_pmu armv7pmu = {
893 	.handle_irq		= armv7pmu_handle_irq,
894 	.enable			= armv7pmu_enable_event,
895 	.disable		= armv7pmu_disable_event,
896 	.read_counter		= armv7pmu_read_counter,
897 	.write_counter		= armv7pmu_write_counter,
898 	.get_event_idx		= armv7pmu_get_event_idx,
899 	.start			= armv7pmu_start,
900 	.stop			= armv7pmu_stop,
901 	.reset			= armv7pmu_reset,
902 	.raw_event_mask		= 0xFF,
903 	.max_period		= (1LLU << 32) - 1,
904 };
905 
906 static u32 __init armv7_read_num_pmnc_events(void)
907 {
908 	u32 nb_cnt;
909 
910 	/* Read the nb of CNTx counters supported from PMNC */
911 	nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
912 
913 	/* Add the CPU cycles counter and return */
914 	return nb_cnt + 1;
915 }
916 
917 static const struct arm_pmu *__init armv7_a8_pmu_init(void)
918 {
919 	armv7pmu.id		= ARM_PERF_PMU_ID_CA8;
920 	armv7pmu.name		= "ARMv7 Cortex-A8";
921 	armv7pmu.cache_map	= &armv7_a8_perf_cache_map;
922 	armv7pmu.event_map	= &armv7_a8_perf_map;
923 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
924 	return &armv7pmu;
925 }
926 
927 static const struct arm_pmu *__init armv7_a9_pmu_init(void)
928 {
929 	armv7pmu.id		= ARM_PERF_PMU_ID_CA9;
930 	armv7pmu.name		= "ARMv7 Cortex-A9";
931 	armv7pmu.cache_map	= &armv7_a9_perf_cache_map;
932 	armv7pmu.event_map	= &armv7_a9_perf_map;
933 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
934 	return &armv7pmu;
935 }
936 #else
937 static const struct arm_pmu *__init armv7_a8_pmu_init(void)
938 {
939 	return NULL;
940 }
941 
942 static const struct arm_pmu *__init armv7_a9_pmu_init(void)
943 {
944 	return NULL;
945 }
946 #endif	/* CONFIG_CPU_V7 */
947