perf_event_v7.c 24 KB

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