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