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 21 /* 22 * Common ARMv7 event types 23 * 24 * Note: An implementation may not be able to count all of these events 25 * but the encodings are considered to be `reserved' in the case that 26 * they are not available. 27 */ 28 enum armv7_perf_types { 29 ARMV7_PERFCTR_PMNC_SW_INCR = 0x00, 30 ARMV7_PERFCTR_L1_ICACHE_REFILL = 0x01, 31 ARMV7_PERFCTR_ITLB_REFILL = 0x02, 32 ARMV7_PERFCTR_L1_DCACHE_REFILL = 0x03, 33 ARMV7_PERFCTR_L1_DCACHE_ACCESS = 0x04, 34 ARMV7_PERFCTR_DTLB_REFILL = 0x05, 35 ARMV7_PERFCTR_MEM_READ = 0x06, 36 ARMV7_PERFCTR_MEM_WRITE = 0x07, 37 ARMV7_PERFCTR_INSTR_EXECUTED = 0x08, 38 ARMV7_PERFCTR_EXC_TAKEN = 0x09, 39 ARMV7_PERFCTR_EXC_EXECUTED = 0x0A, 40 ARMV7_PERFCTR_CID_WRITE = 0x0B, 41 42 /* 43 * ARMV7_PERFCTR_PC_WRITE is equivalent to HW_BRANCH_INSTRUCTIONS. 44 * It counts: 45 * - all (taken) branch instructions, 46 * - instructions that explicitly write the PC, 47 * - exception generating instructions. 48 */ 49 ARMV7_PERFCTR_PC_WRITE = 0x0C, 50 ARMV7_PERFCTR_PC_IMM_BRANCH = 0x0D, 51 ARMV7_PERFCTR_PC_PROC_RETURN = 0x0E, 52 ARMV7_PERFCTR_MEM_UNALIGNED_ACCESS = 0x0F, 53 ARMV7_PERFCTR_PC_BRANCH_MIS_PRED = 0x10, 54 ARMV7_PERFCTR_CLOCK_CYCLES = 0x11, 55 ARMV7_PERFCTR_PC_BRANCH_PRED = 0x12, 56 57 /* These events are defined by the PMUv2 supplement (ARM DDI 0457A). */ 58 ARMV7_PERFCTR_MEM_ACCESS = 0x13, 59 ARMV7_PERFCTR_L1_ICACHE_ACCESS = 0x14, 60 ARMV7_PERFCTR_L1_DCACHE_WB = 0x15, 61 ARMV7_PERFCTR_L2_CACHE_ACCESS = 0x16, 62 ARMV7_PERFCTR_L2_CACHE_REFILL = 0x17, 63 ARMV7_PERFCTR_L2_CACHE_WB = 0x18, 64 ARMV7_PERFCTR_BUS_ACCESS = 0x19, 65 ARMV7_PERFCTR_MEM_ERROR = 0x1A, 66 ARMV7_PERFCTR_INSTR_SPEC = 0x1B, 67 ARMV7_PERFCTR_TTBR_WRITE = 0x1C, 68 ARMV7_PERFCTR_BUS_CYCLES = 0x1D, 69 70 ARMV7_PERFCTR_CPU_CYCLES = 0xFF 71 }; 72 73 /* ARMv7 Cortex-A8 specific event types */ 74 enum armv7_a8_perf_types { 75 ARMV7_A8_PERFCTR_L2_CACHE_ACCESS = 0x43, 76 ARMV7_A8_PERFCTR_L2_CACHE_REFILL = 0x44, 77 ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS = 0x50, 78 ARMV7_A8_PERFCTR_STALL_ISIDE = 0x56, 79 }; 80 81 /* ARMv7 Cortex-A9 specific event types */ 82 enum armv7_a9_perf_types { 83 ARMV7_A9_PERFCTR_INSTR_CORE_RENAME = 0x68, 84 ARMV7_A9_PERFCTR_STALL_ICACHE = 0x60, 85 ARMV7_A9_PERFCTR_STALL_DISPATCH = 0x66, 86 }; 87 88 /* ARMv7 Cortex-A5 specific event types */ 89 enum armv7_a5_perf_types { 90 ARMV7_A5_PERFCTR_PREFETCH_LINEFILL = 0xc2, 91 ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP = 0xc3, 92 }; 93 94 /* ARMv7 Cortex-A15 specific event types */ 95 enum armv7_a15_perf_types { 96 ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_READ = 0x40, 97 ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_WRITE = 0x41, 98 ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_READ = 0x42, 99 ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_WRITE = 0x43, 100 101 ARMV7_A15_PERFCTR_DTLB_REFILL_L1_READ = 0x4C, 102 ARMV7_A15_PERFCTR_DTLB_REFILL_L1_WRITE = 0x4D, 103 104 ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_READ = 0x50, 105 ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_WRITE = 0x51, 106 ARMV7_A15_PERFCTR_L2_CACHE_REFILL_READ = 0x52, 107 ARMV7_A15_PERFCTR_L2_CACHE_REFILL_WRITE = 0x53, 108 109 ARMV7_A15_PERFCTR_PC_WRITE_SPEC = 0x76, 110 }; 111 112 /* 113 * Cortex-A8 HW events mapping 114 * 115 * The hardware events that we support. We do support cache operations but 116 * we have harvard caches and no way to combine instruction and data 117 * accesses/misses in hardware. 118 */ 119 static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = { 120 [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, 121 [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED, 122 [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 123 [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 124 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, 125 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 126 [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, 127 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV7_A8_PERFCTR_STALL_ISIDE, 128 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, 129 }; 130 131 static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] 132 [PERF_COUNT_HW_CACHE_OP_MAX] 133 [PERF_COUNT_HW_CACHE_RESULT_MAX] = { 134 [C(L1D)] = { 135 /* 136 * The performance counters don't differentiate between read 137 * and write accesses/misses so this isn't strictly correct, 138 * but it's the best we can do. Writes and reads get 139 * combined. 140 */ 141 [C(OP_READ)] = { 142 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 143 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 144 }, 145 [C(OP_WRITE)] = { 146 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 147 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 148 }, 149 [C(OP_PREFETCH)] = { 150 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 151 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 152 }, 153 }, 154 [C(L1I)] = { 155 [C(OP_READ)] = { 156 [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS, 157 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, 158 }, 159 [C(OP_WRITE)] = { 160 [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS, 161 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, 162 }, 163 [C(OP_PREFETCH)] = { 164 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 165 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 166 }, 167 }, 168 [C(LL)] = { 169 [C(OP_READ)] = { 170 [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L2_CACHE_ACCESS, 171 [C(RESULT_MISS)] = ARMV7_A8_PERFCTR_L2_CACHE_REFILL, 172 }, 173 [C(OP_WRITE)] = { 174 [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L2_CACHE_ACCESS, 175 [C(RESULT_MISS)] = ARMV7_A8_PERFCTR_L2_CACHE_REFILL, 176 }, 177 [C(OP_PREFETCH)] = { 178 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 179 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 180 }, 181 }, 182 [C(DTLB)] = { 183 [C(OP_READ)] = { 184 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 185 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, 186 }, 187 [C(OP_WRITE)] = { 188 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 189 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, 190 }, 191 [C(OP_PREFETCH)] = { 192 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 193 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 194 }, 195 }, 196 [C(ITLB)] = { 197 [C(OP_READ)] = { 198 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 199 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, 200 }, 201 [C(OP_WRITE)] = { 202 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 203 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, 204 }, 205 [C(OP_PREFETCH)] = { 206 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 207 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 208 }, 209 }, 210 [C(BPU)] = { 211 [C(OP_READ)] = { 212 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, 213 [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 214 }, 215 [C(OP_WRITE)] = { 216 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, 217 [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 218 }, 219 [C(OP_PREFETCH)] = { 220 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 221 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 222 }, 223 }, 224 [C(NODE)] = { 225 [C(OP_READ)] = { 226 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 227 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 228 }, 229 [C(OP_WRITE)] = { 230 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 231 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 232 }, 233 [C(OP_PREFETCH)] = { 234 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 235 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 236 }, 237 }, 238 }; 239 240 /* 241 * Cortex-A9 HW events mapping 242 */ 243 static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = { 244 [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, 245 [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_A9_PERFCTR_INSTR_CORE_RENAME, 246 [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 247 [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 248 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, 249 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 250 [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, 251 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV7_A9_PERFCTR_STALL_ICACHE, 252 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV7_A9_PERFCTR_STALL_DISPATCH, 253 }; 254 255 static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] 256 [PERF_COUNT_HW_CACHE_OP_MAX] 257 [PERF_COUNT_HW_CACHE_RESULT_MAX] = { 258 [C(L1D)] = { 259 /* 260 * The performance counters don't differentiate between read 261 * and write accesses/misses so this isn't strictly correct, 262 * but it's the best we can do. Writes and reads get 263 * combined. 264 */ 265 [C(OP_READ)] = { 266 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 267 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 268 }, 269 [C(OP_WRITE)] = { 270 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 271 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 272 }, 273 [C(OP_PREFETCH)] = { 274 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 275 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 276 }, 277 }, 278 [C(L1I)] = { 279 [C(OP_READ)] = { 280 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 281 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, 282 }, 283 [C(OP_WRITE)] = { 284 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 285 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, 286 }, 287 [C(OP_PREFETCH)] = { 288 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 289 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 290 }, 291 }, 292 [C(LL)] = { 293 [C(OP_READ)] = { 294 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 295 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 296 }, 297 [C(OP_WRITE)] = { 298 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 299 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 300 }, 301 [C(OP_PREFETCH)] = { 302 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 303 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 304 }, 305 }, 306 [C(DTLB)] = { 307 [C(OP_READ)] = { 308 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 309 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, 310 }, 311 [C(OP_WRITE)] = { 312 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 313 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, 314 }, 315 [C(OP_PREFETCH)] = { 316 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 317 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 318 }, 319 }, 320 [C(ITLB)] = { 321 [C(OP_READ)] = { 322 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 323 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, 324 }, 325 [C(OP_WRITE)] = { 326 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 327 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, 328 }, 329 [C(OP_PREFETCH)] = { 330 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 331 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 332 }, 333 }, 334 [C(BPU)] = { 335 [C(OP_READ)] = { 336 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, 337 [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 338 }, 339 [C(OP_WRITE)] = { 340 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, 341 [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 342 }, 343 [C(OP_PREFETCH)] = { 344 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 345 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 346 }, 347 }, 348 [C(NODE)] = { 349 [C(OP_READ)] = { 350 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 351 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 352 }, 353 [C(OP_WRITE)] = { 354 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 355 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 356 }, 357 [C(OP_PREFETCH)] = { 358 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 359 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 360 }, 361 }, 362 }; 363 364 /* 365 * Cortex-A5 HW events mapping 366 */ 367 static const unsigned armv7_a5_perf_map[PERF_COUNT_HW_MAX] = { 368 [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, 369 [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED, 370 [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 371 [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 372 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, 373 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 374 [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, 375 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED, 376 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, 377 }; 378 379 static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] 380 [PERF_COUNT_HW_CACHE_OP_MAX] 381 [PERF_COUNT_HW_CACHE_RESULT_MAX] = { 382 [C(L1D)] = { 383 [C(OP_READ)] = { 384 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 385 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 386 }, 387 [C(OP_WRITE)] = { 388 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 389 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 390 }, 391 [C(OP_PREFETCH)] = { 392 [C(RESULT_ACCESS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL, 393 [C(RESULT_MISS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP, 394 }, 395 }, 396 [C(L1I)] = { 397 [C(OP_READ)] = { 398 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, 399 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, 400 }, 401 [C(OP_WRITE)] = { 402 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, 403 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, 404 }, 405 /* 406 * The prefetch counters don't differentiate between the I 407 * side and the D side. 408 */ 409 [C(OP_PREFETCH)] = { 410 [C(RESULT_ACCESS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL, 411 [C(RESULT_MISS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP, 412 }, 413 }, 414 [C(LL)] = { 415 [C(OP_READ)] = { 416 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 417 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 418 }, 419 [C(OP_WRITE)] = { 420 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 421 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 422 }, 423 [C(OP_PREFETCH)] = { 424 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 425 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 426 }, 427 }, 428 [C(DTLB)] = { 429 [C(OP_READ)] = { 430 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 431 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, 432 }, 433 [C(OP_WRITE)] = { 434 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 435 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, 436 }, 437 [C(OP_PREFETCH)] = { 438 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 439 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 440 }, 441 }, 442 [C(ITLB)] = { 443 [C(OP_READ)] = { 444 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 445 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, 446 }, 447 [C(OP_WRITE)] = { 448 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 449 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, 450 }, 451 [C(OP_PREFETCH)] = { 452 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 453 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 454 }, 455 }, 456 [C(BPU)] = { 457 [C(OP_READ)] = { 458 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, 459 [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 460 }, 461 [C(OP_WRITE)] = { 462 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, 463 [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 464 }, 465 [C(OP_PREFETCH)] = { 466 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 467 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 468 }, 469 }, 470 [C(NODE)] = { 471 [C(OP_READ)] = { 472 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 473 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 474 }, 475 [C(OP_WRITE)] = { 476 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 477 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 478 }, 479 [C(OP_PREFETCH)] = { 480 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 481 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 482 }, 483 }, 484 }; 485 486 /* 487 * Cortex-A15 HW events mapping 488 */ 489 static const unsigned armv7_a15_perf_map[PERF_COUNT_HW_MAX] = { 490 [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, 491 [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED, 492 [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 493 [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 494 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_A15_PERFCTR_PC_WRITE_SPEC, 495 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 496 [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_BUS_CYCLES, 497 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED, 498 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, 499 }; 500 501 static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] 502 [PERF_COUNT_HW_CACHE_OP_MAX] 503 [PERF_COUNT_HW_CACHE_RESULT_MAX] = { 504 [C(L1D)] = { 505 [C(OP_READ)] = { 506 [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_READ, 507 [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_READ, 508 }, 509 [C(OP_WRITE)] = { 510 [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_WRITE, 511 [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_WRITE, 512 }, 513 [C(OP_PREFETCH)] = { 514 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 515 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 516 }, 517 }, 518 [C(L1I)] = { 519 /* 520 * Not all performance counters differentiate between read 521 * and write accesses/misses so we're not always strictly 522 * correct, but it's the best we can do. Writes and reads get 523 * combined in these cases. 524 */ 525 [C(OP_READ)] = { 526 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, 527 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, 528 }, 529 [C(OP_WRITE)] = { 530 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, 531 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, 532 }, 533 [C(OP_PREFETCH)] = { 534 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 535 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 536 }, 537 }, 538 [C(LL)] = { 539 [C(OP_READ)] = { 540 [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_READ, 541 [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L2_CACHE_REFILL_READ, 542 }, 543 [C(OP_WRITE)] = { 544 [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_WRITE, 545 [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L2_CACHE_REFILL_WRITE, 546 }, 547 [C(OP_PREFETCH)] = { 548 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 549 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 550 }, 551 }, 552 [C(DTLB)] = { 553 [C(OP_READ)] = { 554 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 555 [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_DTLB_REFILL_L1_READ, 556 }, 557 [C(OP_WRITE)] = { 558 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 559 [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_DTLB_REFILL_L1_WRITE, 560 }, 561 [C(OP_PREFETCH)] = { 562 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 563 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 564 }, 565 }, 566 [C(ITLB)] = { 567 [C(OP_READ)] = { 568 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 569 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, 570 }, 571 [C(OP_WRITE)] = { 572 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 573 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, 574 }, 575 [C(OP_PREFETCH)] = { 576 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 577 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 578 }, 579 }, 580 [C(BPU)] = { 581 [C(OP_READ)] = { 582 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, 583 [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 584 }, 585 [C(OP_WRITE)] = { 586 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, 587 [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 588 }, 589 [C(OP_PREFETCH)] = { 590 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 591 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 592 }, 593 }, 594 [C(NODE)] = { 595 [C(OP_READ)] = { 596 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 597 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 598 }, 599 [C(OP_WRITE)] = { 600 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 601 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 602 }, 603 [C(OP_PREFETCH)] = { 604 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 605 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 606 }, 607 }, 608 }; 609 610 /* 611 * Cortex-A7 HW events mapping 612 */ 613 static const unsigned armv7_a7_perf_map[PERF_COUNT_HW_MAX] = { 614 [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, 615 [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED, 616 [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 617 [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 618 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, 619 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 620 [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_BUS_CYCLES, 621 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED, 622 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, 623 }; 624 625 static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] 626 [PERF_COUNT_HW_CACHE_OP_MAX] 627 [PERF_COUNT_HW_CACHE_RESULT_MAX] = { 628 [C(L1D)] = { 629 /* 630 * The performance counters don't differentiate between read 631 * and write accesses/misses so this isn't strictly correct, 632 * but it's the best we can do. Writes and reads get 633 * combined. 634 */ 635 [C(OP_READ)] = { 636 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 637 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 638 }, 639 [C(OP_WRITE)] = { 640 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, 641 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, 642 }, 643 [C(OP_PREFETCH)] = { 644 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 645 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 646 }, 647 }, 648 [C(L1I)] = { 649 [C(OP_READ)] = { 650 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, 651 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, 652 }, 653 [C(OP_WRITE)] = { 654 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, 655 [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, 656 }, 657 [C(OP_PREFETCH)] = { 658 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 659 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 660 }, 661 }, 662 [C(LL)] = { 663 [C(OP_READ)] = { 664 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L2_CACHE_ACCESS, 665 [C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL, 666 }, 667 [C(OP_WRITE)] = { 668 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L2_CACHE_ACCESS, 669 [C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL, 670 }, 671 [C(OP_PREFETCH)] = { 672 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 673 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 674 }, 675 }, 676 [C(DTLB)] = { 677 [C(OP_READ)] = { 678 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 679 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, 680 }, 681 [C(OP_WRITE)] = { 682 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 683 [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, 684 }, 685 [C(OP_PREFETCH)] = { 686 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 687 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 688 }, 689 }, 690 [C(ITLB)] = { 691 [C(OP_READ)] = { 692 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 693 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, 694 }, 695 [C(OP_WRITE)] = { 696 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 697 [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, 698 }, 699 [C(OP_PREFETCH)] = { 700 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 701 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 702 }, 703 }, 704 [C(BPU)] = { 705 [C(OP_READ)] = { 706 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, 707 [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 708 }, 709 [C(OP_WRITE)] = { 710 [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, 711 [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, 712 }, 713 [C(OP_PREFETCH)] = { 714 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 715 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 716 }, 717 }, 718 [C(NODE)] = { 719 [C(OP_READ)] = { 720 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 721 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 722 }, 723 [C(OP_WRITE)] = { 724 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 725 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 726 }, 727 [C(OP_PREFETCH)] = { 728 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 729 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 730 }, 731 }, 732 }; 733 734 /* 735 * Perf Events' indices 736 */ 737 #define ARMV7_IDX_CYCLE_COUNTER 0 738 #define ARMV7_IDX_COUNTER0 1 739 #define ARMV7_IDX_COUNTER_LAST (ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1) 740 741 #define ARMV7_MAX_COUNTERS 32 742 #define ARMV7_COUNTER_MASK (ARMV7_MAX_COUNTERS - 1) 743 744 /* 745 * ARMv7 low level PMNC access 746 */ 747 748 /* 749 * Perf Event to low level counters mapping 750 */ 751 #define ARMV7_IDX_TO_COUNTER(x) \ 752 (((x) - ARMV7_IDX_COUNTER0) & ARMV7_COUNTER_MASK) 753 754 /* 755 * Per-CPU PMNC: config reg 756 */ 757 #define ARMV7_PMNC_E (1 << 0) /* Enable all counters */ 758 #define ARMV7_PMNC_P (1 << 1) /* Reset all counters */ 759 #define ARMV7_PMNC_C (1 << 2) /* Cycle counter reset */ 760 #define ARMV7_PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */ 761 #define ARMV7_PMNC_X (1 << 4) /* Export to ETM */ 762 #define ARMV7_PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ 763 #define ARMV7_PMNC_N_SHIFT 11 /* Number of counters supported */ 764 #define ARMV7_PMNC_N_MASK 0x1f 765 #define ARMV7_PMNC_MASK 0x3f /* Mask for writable bits */ 766 767 /* 768 * FLAG: counters overflow flag status reg 769 */ 770 #define ARMV7_FLAG_MASK 0xffffffff /* Mask for writable bits */ 771 #define ARMV7_OVERFLOWED_MASK ARMV7_FLAG_MASK 772 773 /* 774 * PMXEVTYPER: Event selection reg 775 */ 776 #define ARMV7_EVTYPE_MASK 0xc00000ff /* Mask for writable bits */ 777 #define ARMV7_EVTYPE_EVENT 0xff /* Mask for EVENT bits */ 778 779 /* 780 * Event filters for PMUv2 781 */ 782 #define ARMV7_EXCLUDE_PL1 (1 << 31) 783 #define ARMV7_EXCLUDE_USER (1 << 30) 784 #define ARMV7_INCLUDE_HYP (1 << 27) 785 786 static inline u32 armv7_pmnc_read(void) 787 { 788 u32 val; 789 asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val)); 790 return val; 791 } 792 793 static inline void armv7_pmnc_write(u32 val) 794 { 795 val &= ARMV7_PMNC_MASK; 796 isb(); 797 asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val)); 798 } 799 800 static inline int armv7_pmnc_has_overflowed(u32 pmnc) 801 { 802 return pmnc & ARMV7_OVERFLOWED_MASK; 803 } 804 805 static inline int armv7_pmnc_counter_valid(int idx) 806 { 807 return idx >= ARMV7_IDX_CYCLE_COUNTER && idx <= ARMV7_IDX_COUNTER_LAST; 808 } 809 810 static inline int armv7_pmnc_counter_has_overflowed(u32 pmnc, int idx) 811 { 812 int ret = 0; 813 u32 counter; 814 815 if (!armv7_pmnc_counter_valid(idx)) { 816 pr_err("CPU%u checking wrong counter %d overflow status\n", 817 smp_processor_id(), idx); 818 } else { 819 counter = ARMV7_IDX_TO_COUNTER(idx); 820 ret = pmnc & BIT(counter); 821 } 822 823 return ret; 824 } 825 826 static inline int armv7_pmnc_select_counter(int idx) 827 { 828 u32 counter; 829 830 if (!armv7_pmnc_counter_valid(idx)) { 831 pr_err("CPU%u selecting wrong PMNC counter %d\n", 832 smp_processor_id(), idx); 833 return -EINVAL; 834 } 835 836 counter = ARMV7_IDX_TO_COUNTER(idx); 837 asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (counter)); 838 isb(); 839 840 return idx; 841 } 842 843 static inline u32 armv7pmu_read_counter(int idx) 844 { 845 u32 value = 0; 846 847 if (!armv7_pmnc_counter_valid(idx)) 848 pr_err("CPU%u reading wrong counter %d\n", 849 smp_processor_id(), idx); 850 else if (idx == ARMV7_IDX_CYCLE_COUNTER) 851 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value)); 852 else if (armv7_pmnc_select_counter(idx) == idx) 853 asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (value)); 854 855 return value; 856 } 857 858 static inline void armv7pmu_write_counter(int idx, u32 value) 859 { 860 if (!armv7_pmnc_counter_valid(idx)) 861 pr_err("CPU%u writing wrong counter %d\n", 862 smp_processor_id(), idx); 863 else if (idx == ARMV7_IDX_CYCLE_COUNTER) 864 asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value)); 865 else if (armv7_pmnc_select_counter(idx) == idx) 866 asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value)); 867 } 868 869 static inline void armv7_pmnc_write_evtsel(int idx, u32 val) 870 { 871 if (armv7_pmnc_select_counter(idx) == idx) { 872 val &= ARMV7_EVTYPE_MASK; 873 asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val)); 874 } 875 } 876 877 static inline int armv7_pmnc_enable_counter(int idx) 878 { 879 u32 counter; 880 881 if (!armv7_pmnc_counter_valid(idx)) { 882 pr_err("CPU%u enabling wrong PMNC counter %d\n", 883 smp_processor_id(), idx); 884 return -EINVAL; 885 } 886 887 counter = ARMV7_IDX_TO_COUNTER(idx); 888 asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (BIT(counter))); 889 return idx; 890 } 891 892 static inline int armv7_pmnc_disable_counter(int idx) 893 { 894 u32 counter; 895 896 if (!armv7_pmnc_counter_valid(idx)) { 897 pr_err("CPU%u disabling wrong PMNC counter %d\n", 898 smp_processor_id(), idx); 899 return -EINVAL; 900 } 901 902 counter = ARMV7_IDX_TO_COUNTER(idx); 903 asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (BIT(counter))); 904 return idx; 905 } 906 907 static inline int armv7_pmnc_enable_intens(int idx) 908 { 909 u32 counter; 910 911 if (!armv7_pmnc_counter_valid(idx)) { 912 pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n", 913 smp_processor_id(), idx); 914 return -EINVAL; 915 } 916 917 counter = ARMV7_IDX_TO_COUNTER(idx); 918 asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (BIT(counter))); 919 return idx; 920 } 921 922 static inline int armv7_pmnc_disable_intens(int idx) 923 { 924 u32 counter; 925 926 if (!armv7_pmnc_counter_valid(idx)) { 927 pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n", 928 smp_processor_id(), idx); 929 return -EINVAL; 930 } 931 932 counter = ARMV7_IDX_TO_COUNTER(idx); 933 asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter))); 934 isb(); 935 /* Clear the overflow flag in case an interrupt is pending. */ 936 asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (BIT(counter))); 937 isb(); 938 939 return idx; 940 } 941 942 static inline u32 armv7_pmnc_getreset_flags(void) 943 { 944 u32 val; 945 946 /* Read */ 947 asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); 948 949 /* Write to clear flags */ 950 val &= ARMV7_FLAG_MASK; 951 asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val)); 952 953 return val; 954 } 955 956 #ifdef DEBUG 957 static void armv7_pmnc_dump_regs(void) 958 { 959 u32 val; 960 unsigned int cnt; 961 962 printk(KERN_INFO "PMNC registers dump:\n"); 963 964 asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); 965 printk(KERN_INFO "PMNC =0x%08x\n", val); 966 967 asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val)); 968 printk(KERN_INFO "CNTENS=0x%08x\n", val); 969 970 asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val)); 971 printk(KERN_INFO "INTENS=0x%08x\n", val); 972 973 asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); 974 printk(KERN_INFO "FLAGS =0x%08x\n", val); 975 976 asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val)); 977 printk(KERN_INFO "SELECT=0x%08x\n", val); 978 979 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); 980 printk(KERN_INFO "CCNT =0x%08x\n", val); 981 982 for (cnt = ARMV7_IDX_COUNTER0; cnt <= ARMV7_IDX_COUNTER_LAST; cnt++) { 983 armv7_pmnc_select_counter(cnt); 984 asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); 985 printk(KERN_INFO "CNT[%d] count =0x%08x\n", 986 ARMV7_IDX_TO_COUNTER(cnt), val); 987 asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val)); 988 printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n", 989 ARMV7_IDX_TO_COUNTER(cnt), val); 990 } 991 } 992 #endif 993 994 static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx) 995 { 996 unsigned long flags; 997 struct pmu_hw_events *events = cpu_pmu->get_hw_events(); 998 999 /* 1000 * Enable counter and interrupt, and set the counter to count 1001 * the event that we're interested in. 1002 */ 1003 raw_spin_lock_irqsave(&events->pmu_lock, flags); 1004 1005 /* 1006 * Disable counter 1007 */ 1008 armv7_pmnc_disable_counter(idx); 1009 1010 /* 1011 * Set event (if destined for PMNx counters) 1012 * We only need to set the event for the cycle counter if we 1013 * have the ability to perform event filtering. 1014 */ 1015 if (cpu_pmu->set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER) 1016 armv7_pmnc_write_evtsel(idx, hwc->config_base); 1017 1018 /* 1019 * Enable interrupt for this counter 1020 */ 1021 armv7_pmnc_enable_intens(idx); 1022 1023 /* 1024 * Enable counter 1025 */ 1026 armv7_pmnc_enable_counter(idx); 1027 1028 raw_spin_unlock_irqrestore(&events->pmu_lock, flags); 1029 } 1030 1031 static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx) 1032 { 1033 unsigned long flags; 1034 struct pmu_hw_events *events = cpu_pmu->get_hw_events(); 1035 1036 /* 1037 * Disable counter and interrupt 1038 */ 1039 raw_spin_lock_irqsave(&events->pmu_lock, flags); 1040 1041 /* 1042 * Disable counter 1043 */ 1044 armv7_pmnc_disable_counter(idx); 1045 1046 /* 1047 * Disable interrupt for this counter 1048 */ 1049 armv7_pmnc_disable_intens(idx); 1050 1051 raw_spin_unlock_irqrestore(&events->pmu_lock, flags); 1052 } 1053 1054 static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) 1055 { 1056 u32 pmnc; 1057 struct perf_sample_data data; 1058 struct pmu_hw_events *cpuc; 1059 struct pt_regs *regs; 1060 int idx; 1061 1062 /* 1063 * Get and reset the IRQ flags 1064 */ 1065 pmnc = armv7_pmnc_getreset_flags(); 1066 1067 /* 1068 * Did an overflow occur? 1069 */ 1070 if (!armv7_pmnc_has_overflowed(pmnc)) 1071 return IRQ_NONE; 1072 1073 /* 1074 * Handle the counter(s) overflow(s) 1075 */ 1076 regs = get_irq_regs(); 1077 1078 cpuc = &__get_cpu_var(cpu_hw_events); 1079 for (idx = 0; idx < cpu_pmu->num_events; ++idx) { 1080 struct perf_event *event = cpuc->events[idx]; 1081 struct hw_perf_event *hwc; 1082 1083 /* Ignore if we don't have an event. */ 1084 if (!event) 1085 continue; 1086 1087 /* 1088 * We have a single interrupt for all counters. Check that 1089 * each counter has overflowed before we process it. 1090 */ 1091 if (!armv7_pmnc_counter_has_overflowed(pmnc, idx)) 1092 continue; 1093 1094 hwc = &event->hw; 1095 armpmu_event_update(event, hwc, idx); 1096 perf_sample_data_init(&data, 0, hwc->last_period); 1097 if (!armpmu_event_set_period(event, hwc, idx)) 1098 continue; 1099 1100 if (perf_event_overflow(event, &data, regs)) 1101 cpu_pmu->disable(hwc, idx); 1102 } 1103 1104 /* 1105 * Handle the pending perf events. 1106 * 1107 * Note: this call *must* be run with interrupts disabled. For 1108 * platforms that can have the PMU interrupts raised as an NMI, this 1109 * will not work. 1110 */ 1111 irq_work_run(); 1112 1113 return IRQ_HANDLED; 1114 } 1115 1116 static void armv7pmu_start(void) 1117 { 1118 unsigned long flags; 1119 struct pmu_hw_events *events = cpu_pmu->get_hw_events(); 1120 1121 raw_spin_lock_irqsave(&events->pmu_lock, flags); 1122 /* Enable all counters */ 1123 armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E); 1124 raw_spin_unlock_irqrestore(&events->pmu_lock, flags); 1125 } 1126 1127 static void armv7pmu_stop(void) 1128 { 1129 unsigned long flags; 1130 struct pmu_hw_events *events = cpu_pmu->get_hw_events(); 1131 1132 raw_spin_lock_irqsave(&events->pmu_lock, flags); 1133 /* Disable all counters */ 1134 armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E); 1135 raw_spin_unlock_irqrestore(&events->pmu_lock, flags); 1136 } 1137 1138 static int armv7pmu_get_event_idx(struct pmu_hw_events *cpuc, 1139 struct hw_perf_event *event) 1140 { 1141 int idx; 1142 unsigned long evtype = event->config_base & ARMV7_EVTYPE_EVENT; 1143 1144 /* Always place a cycle counter into the cycle counter. */ 1145 if (evtype == ARMV7_PERFCTR_CPU_CYCLES) { 1146 if (test_and_set_bit(ARMV7_IDX_CYCLE_COUNTER, cpuc->used_mask)) 1147 return -EAGAIN; 1148 1149 return ARMV7_IDX_CYCLE_COUNTER; 1150 } 1151 1152 /* 1153 * For anything other than a cycle counter, try and use 1154 * the events counters 1155 */ 1156 for (idx = ARMV7_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) { 1157 if (!test_and_set_bit(idx, cpuc->used_mask)) 1158 return idx; 1159 } 1160 1161 /* The counters are all in use. */ 1162 return -EAGAIN; 1163 } 1164 1165 /* 1166 * Add an event filter to a given event. This will only work for PMUv2 PMUs. 1167 */ 1168 static int armv7pmu_set_event_filter(struct hw_perf_event *event, 1169 struct perf_event_attr *attr) 1170 { 1171 unsigned long config_base = 0; 1172 1173 if (attr->exclude_idle) 1174 return -EPERM; 1175 if (attr->exclude_user) 1176 config_base |= ARMV7_EXCLUDE_USER; 1177 if (attr->exclude_kernel) 1178 config_base |= ARMV7_EXCLUDE_PL1; 1179 if (!attr->exclude_hv) 1180 config_base |= ARMV7_INCLUDE_HYP; 1181 1182 /* 1183 * Install the filter into config_base as this is used to 1184 * construct the event type. 1185 */ 1186 event->config_base = config_base; 1187 1188 return 0; 1189 } 1190 1191 static void armv7pmu_reset(void *info) 1192 { 1193 u32 idx, nb_cnt = cpu_pmu->num_events; 1194 1195 /* The counter and interrupt enable registers are unknown at reset. */ 1196 for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) 1197 armv7pmu_disable_event(NULL, idx); 1198 1199 /* Initialize & Reset PMNC: C and P bits */ 1200 armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C); 1201 } 1202 1203 static int armv7_a8_map_event(struct perf_event *event) 1204 { 1205 return armpmu_map_event(event, &armv7_a8_perf_map, 1206 &armv7_a8_perf_cache_map, 0xFF); 1207 } 1208 1209 static int armv7_a9_map_event(struct perf_event *event) 1210 { 1211 return armpmu_map_event(event, &armv7_a9_perf_map, 1212 &armv7_a9_perf_cache_map, 0xFF); 1213 } 1214 1215 static int armv7_a5_map_event(struct perf_event *event) 1216 { 1217 return armpmu_map_event(event, &armv7_a5_perf_map, 1218 &armv7_a5_perf_cache_map, 0xFF); 1219 } 1220 1221 static int armv7_a15_map_event(struct perf_event *event) 1222 { 1223 return armpmu_map_event(event, &armv7_a15_perf_map, 1224 &armv7_a15_perf_cache_map, 0xFF); 1225 } 1226 1227 static int armv7_a7_map_event(struct perf_event *event) 1228 { 1229 return armpmu_map_event(event, &armv7_a7_perf_map, 1230 &armv7_a7_perf_cache_map, 0xFF); 1231 } 1232 1233 static void armv7pmu_init(struct arm_pmu *cpu_pmu) 1234 { 1235 cpu_pmu->handle_irq = armv7pmu_handle_irq; 1236 cpu_pmu->enable = armv7pmu_enable_event; 1237 cpu_pmu->disable = armv7pmu_disable_event; 1238 cpu_pmu->read_counter = armv7pmu_read_counter; 1239 cpu_pmu->write_counter = armv7pmu_write_counter; 1240 cpu_pmu->get_event_idx = armv7pmu_get_event_idx; 1241 cpu_pmu->start = armv7pmu_start; 1242 cpu_pmu->stop = armv7pmu_stop; 1243 cpu_pmu->reset = armv7pmu_reset; 1244 cpu_pmu->max_period = (1LLU << 32) - 1; 1245 }; 1246 1247 static u32 __devinit armv7_read_num_pmnc_events(void) 1248 { 1249 u32 nb_cnt; 1250 1251 /* Read the nb of CNTx counters supported from PMNC */ 1252 nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK; 1253 1254 /* Add the CPU cycles counter and return */ 1255 return nb_cnt + 1; 1256 } 1257 1258 static int __devinit armv7_a8_pmu_init(struct arm_pmu *cpu_pmu) 1259 { 1260 armv7pmu_init(cpu_pmu); 1261 cpu_pmu->name = "ARMv7 Cortex-A8"; 1262 cpu_pmu->map_event = armv7_a8_map_event; 1263 cpu_pmu->num_events = armv7_read_num_pmnc_events(); 1264 return 0; 1265 } 1266 1267 static int __devinit armv7_a9_pmu_init(struct arm_pmu *cpu_pmu) 1268 { 1269 armv7pmu_init(cpu_pmu); 1270 cpu_pmu->name = "ARMv7 Cortex-A9"; 1271 cpu_pmu->map_event = armv7_a9_map_event; 1272 cpu_pmu->num_events = armv7_read_num_pmnc_events(); 1273 return 0; 1274 } 1275 1276 static int __devinit armv7_a5_pmu_init(struct arm_pmu *cpu_pmu) 1277 { 1278 armv7pmu_init(cpu_pmu); 1279 cpu_pmu->name = "ARMv7 Cortex-A5"; 1280 cpu_pmu->map_event = armv7_a5_map_event; 1281 cpu_pmu->num_events = armv7_read_num_pmnc_events(); 1282 return 0; 1283 } 1284 1285 static int __devinit armv7_a15_pmu_init(struct arm_pmu *cpu_pmu) 1286 { 1287 armv7pmu_init(cpu_pmu); 1288 cpu_pmu->name = "ARMv7 Cortex-A15"; 1289 cpu_pmu->map_event = armv7_a15_map_event; 1290 cpu_pmu->num_events = armv7_read_num_pmnc_events(); 1291 cpu_pmu->set_event_filter = armv7pmu_set_event_filter; 1292 return 0; 1293 } 1294 1295 static int __devinit armv7_a7_pmu_init(struct arm_pmu *cpu_pmu) 1296 { 1297 armv7pmu_init(cpu_pmu); 1298 cpu_pmu->name = "ARMv7 Cortex-A7"; 1299 cpu_pmu->map_event = armv7_a7_map_event; 1300 cpu_pmu->num_events = armv7_read_num_pmnc_events(); 1301 cpu_pmu->set_event_filter = armv7pmu_set_event_filter; 1302 return 0; 1303 } 1304 #else 1305 static inline int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu) 1306 { 1307 return -ENODEV; 1308 } 1309 1310 static inline int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu) 1311 { 1312 return -ENODEV; 1313 } 1314 1315 static inline int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu) 1316 { 1317 return -ENODEV; 1318 } 1319 1320 static inline int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu) 1321 { 1322 return -ENODEV; 1323 } 1324 1325 static inline int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu) 1326 { 1327 return -ENODEV; 1328 } 1329 #endif /* CONFIG_CPU_V7 */ 1330