perf_event_xscale.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. /*
  2. * ARMv5 [xscale] Performance counter handling code.
  3. *
  4. * Copyright (C) 2010, ARM Ltd., Will Deacon <will.deacon@arm.com>
  5. *
  6. * Based on the previous xscale OProfile code.
  7. *
  8. * There are two variants of the xscale PMU that we support:
  9. * - xscale1pmu: 2 event counters and a cycle counter
  10. * - xscale2pmu: 4 event counters and a cycle counter
  11. * The two variants share event definitions, but have different
  12. * PMU structures.
  13. */
  14. #ifdef CONFIG_CPU_XSCALE
  15. enum xscale_perf_types {
  16. XSCALE_PERFCTR_ICACHE_MISS = 0x00,
  17. XSCALE_PERFCTR_ICACHE_NO_DELIVER = 0x01,
  18. XSCALE_PERFCTR_DATA_STALL = 0x02,
  19. XSCALE_PERFCTR_ITLB_MISS = 0x03,
  20. XSCALE_PERFCTR_DTLB_MISS = 0x04,
  21. XSCALE_PERFCTR_BRANCH = 0x05,
  22. XSCALE_PERFCTR_BRANCH_MISS = 0x06,
  23. XSCALE_PERFCTR_INSTRUCTION = 0x07,
  24. XSCALE_PERFCTR_DCACHE_FULL_STALL = 0x08,
  25. XSCALE_PERFCTR_DCACHE_FULL_STALL_CONTIG = 0x09,
  26. XSCALE_PERFCTR_DCACHE_ACCESS = 0x0A,
  27. XSCALE_PERFCTR_DCACHE_MISS = 0x0B,
  28. XSCALE_PERFCTR_DCACHE_WRITE_BACK = 0x0C,
  29. XSCALE_PERFCTR_PC_CHANGED = 0x0D,
  30. XSCALE_PERFCTR_BCU_REQUEST = 0x10,
  31. XSCALE_PERFCTR_BCU_FULL = 0x11,
  32. XSCALE_PERFCTR_BCU_DRAIN = 0x12,
  33. XSCALE_PERFCTR_BCU_ECC_NO_ELOG = 0x14,
  34. XSCALE_PERFCTR_BCU_1_BIT_ERR = 0x15,
  35. XSCALE_PERFCTR_RMW = 0x16,
  36. /* XSCALE_PERFCTR_CCNT is not hardware defined */
  37. XSCALE_PERFCTR_CCNT = 0xFE,
  38. XSCALE_PERFCTR_UNUSED = 0xFF,
  39. };
  40. enum xscale_counters {
  41. XSCALE_CYCLE_COUNTER = 0,
  42. XSCALE_COUNTER0,
  43. XSCALE_COUNTER1,
  44. XSCALE_COUNTER2,
  45. XSCALE_COUNTER3,
  46. };
  47. static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = {
  48. PERF_MAP_ALL_UNSUPPORTED,
  49. [PERF_COUNT_HW_CPU_CYCLES] = XSCALE_PERFCTR_CCNT,
  50. [PERF_COUNT_HW_INSTRUCTIONS] = XSCALE_PERFCTR_INSTRUCTION,
  51. [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH,
  52. [PERF_COUNT_HW_BRANCH_MISSES] = XSCALE_PERFCTR_BRANCH_MISS,
  53. [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = XSCALE_PERFCTR_ICACHE_NO_DELIVER,
  54. };
  55. static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
  56. [PERF_COUNT_HW_CACHE_OP_MAX]
  57. [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
  58. PERF_CACHE_MAP_ALL_UNSUPPORTED,
  59. [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
  60. [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
  61. [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
  62. [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
  63. [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS,
  64. [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
  65. [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
  66. [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
  67. [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
  68. };
  69. #define XSCALE_PMU_ENABLE 0x001
  70. #define XSCALE_PMN_RESET 0x002
  71. #define XSCALE_CCNT_RESET 0x004
  72. #define XSCALE_PMU_RESET (CCNT_RESET | PMN_RESET)
  73. #define XSCALE_PMU_CNT64 0x008
  74. #define XSCALE1_OVERFLOWED_MASK 0x700
  75. #define XSCALE1_CCOUNT_OVERFLOW 0x400
  76. #define XSCALE1_COUNT0_OVERFLOW 0x100
  77. #define XSCALE1_COUNT1_OVERFLOW 0x200
  78. #define XSCALE1_CCOUNT_INT_EN 0x040
  79. #define XSCALE1_COUNT0_INT_EN 0x010
  80. #define XSCALE1_COUNT1_INT_EN 0x020
  81. #define XSCALE1_COUNT0_EVT_SHFT 12
  82. #define XSCALE1_COUNT0_EVT_MASK (0xff << XSCALE1_COUNT0_EVT_SHFT)
  83. #define XSCALE1_COUNT1_EVT_SHFT 20
  84. #define XSCALE1_COUNT1_EVT_MASK (0xff << XSCALE1_COUNT1_EVT_SHFT)
  85. static inline u32
  86. xscale1pmu_read_pmnc(void)
  87. {
  88. u32 val;
  89. asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
  90. return val;
  91. }
  92. static inline void
  93. xscale1pmu_write_pmnc(u32 val)
  94. {
  95. /* upper 4bits and 7, 11 are write-as-0 */
  96. val &= 0xffff77f;
  97. asm volatile("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
  98. }
  99. static inline int
  100. xscale1_pmnc_counter_has_overflowed(unsigned long pmnc,
  101. enum xscale_counters counter)
  102. {
  103. int ret = 0;
  104. switch (counter) {
  105. case XSCALE_CYCLE_COUNTER:
  106. ret = pmnc & XSCALE1_CCOUNT_OVERFLOW;
  107. break;
  108. case XSCALE_COUNTER0:
  109. ret = pmnc & XSCALE1_COUNT0_OVERFLOW;
  110. break;
  111. case XSCALE_COUNTER1:
  112. ret = pmnc & XSCALE1_COUNT1_OVERFLOW;
  113. break;
  114. default:
  115. WARN_ONCE(1, "invalid counter number (%d)\n", counter);
  116. }
  117. return ret;
  118. }
  119. static irqreturn_t
  120. xscale1pmu_handle_irq(int irq_num, void *dev)
  121. {
  122. unsigned long pmnc;
  123. struct perf_sample_data data;
  124. struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
  125. struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
  126. struct pt_regs *regs;
  127. int idx;
  128. /*
  129. * NOTE: there's an A stepping erratum that states if an overflow
  130. * bit already exists and another occurs, the previous
  131. * Overflow bit gets cleared. There's no workaround.
  132. * Fixed in B stepping or later.
  133. */
  134. pmnc = xscale1pmu_read_pmnc();
  135. /*
  136. * Write the value back to clear the overflow flags. Overflow
  137. * flags remain in pmnc for use below. We also disable the PMU
  138. * while we process the interrupt.
  139. */
  140. xscale1pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
  141. if (!(pmnc & XSCALE1_OVERFLOWED_MASK))
  142. return IRQ_NONE;
  143. regs = get_irq_regs();
  144. for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
  145. struct perf_event *event = cpuc->events[idx];
  146. struct hw_perf_event *hwc;
  147. if (!event)
  148. continue;
  149. if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
  150. continue;
  151. hwc = &event->hw;
  152. armpmu_event_update(event);
  153. perf_sample_data_init(&data, 0, hwc->last_period);
  154. if (!armpmu_event_set_period(event))
  155. continue;
  156. if (perf_event_overflow(event, &data, regs))
  157. cpu_pmu->disable(event);
  158. }
  159. irq_work_run();
  160. /*
  161. * Re-enable the PMU.
  162. */
  163. pmnc = xscale1pmu_read_pmnc() | XSCALE_PMU_ENABLE;
  164. xscale1pmu_write_pmnc(pmnc);
  165. return IRQ_HANDLED;
  166. }
  167. static void xscale1pmu_enable_event(struct perf_event *event)
  168. {
  169. unsigned long val, mask, evt, flags;
  170. struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
  171. struct hw_perf_event *hwc = &event->hw;
  172. struct pmu_hw_events *events = cpu_pmu->get_hw_events();
  173. int idx = hwc->idx;
  174. switch (idx) {
  175. case XSCALE_CYCLE_COUNTER:
  176. mask = 0;
  177. evt = XSCALE1_CCOUNT_INT_EN;
  178. break;
  179. case XSCALE_COUNTER0:
  180. mask = XSCALE1_COUNT0_EVT_MASK;
  181. evt = (hwc->config_base << XSCALE1_COUNT0_EVT_SHFT) |
  182. XSCALE1_COUNT0_INT_EN;
  183. break;
  184. case XSCALE_COUNTER1:
  185. mask = XSCALE1_COUNT1_EVT_MASK;
  186. evt = (hwc->config_base << XSCALE1_COUNT1_EVT_SHFT) |
  187. XSCALE1_COUNT1_INT_EN;
  188. break;
  189. default:
  190. WARN_ONCE(1, "invalid counter number (%d)\n", idx);
  191. return;
  192. }
  193. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  194. val = xscale1pmu_read_pmnc();
  195. val &= ~mask;
  196. val |= evt;
  197. xscale1pmu_write_pmnc(val);
  198. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  199. }
  200. static void xscale1pmu_disable_event(struct perf_event *event)
  201. {
  202. unsigned long val, mask, evt, flags;
  203. struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
  204. struct hw_perf_event *hwc = &event->hw;
  205. struct pmu_hw_events *events = cpu_pmu->get_hw_events();
  206. int idx = hwc->idx;
  207. switch (idx) {
  208. case XSCALE_CYCLE_COUNTER:
  209. mask = XSCALE1_CCOUNT_INT_EN;
  210. evt = 0;
  211. break;
  212. case XSCALE_COUNTER0:
  213. mask = XSCALE1_COUNT0_INT_EN | XSCALE1_COUNT0_EVT_MASK;
  214. evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT0_EVT_SHFT;
  215. break;
  216. case XSCALE_COUNTER1:
  217. mask = XSCALE1_COUNT1_INT_EN | XSCALE1_COUNT1_EVT_MASK;
  218. evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT1_EVT_SHFT;
  219. break;
  220. default:
  221. WARN_ONCE(1, "invalid counter number (%d)\n", idx);
  222. return;
  223. }
  224. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  225. val = xscale1pmu_read_pmnc();
  226. val &= ~mask;
  227. val |= evt;
  228. xscale1pmu_write_pmnc(val);
  229. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  230. }
  231. static int
  232. xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
  233. struct perf_event *event)
  234. {
  235. struct hw_perf_event *hwc = &event->hw;
  236. if (XSCALE_PERFCTR_CCNT == hwc->config_base) {
  237. if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask))
  238. return -EAGAIN;
  239. return XSCALE_CYCLE_COUNTER;
  240. } else {
  241. if (!test_and_set_bit(XSCALE_COUNTER1, cpuc->used_mask))
  242. return XSCALE_COUNTER1;
  243. if (!test_and_set_bit(XSCALE_COUNTER0, cpuc->used_mask))
  244. return XSCALE_COUNTER0;
  245. return -EAGAIN;
  246. }
  247. }
  248. static void xscale1pmu_start(struct arm_pmu *cpu_pmu)
  249. {
  250. unsigned long flags, val;
  251. struct pmu_hw_events *events = cpu_pmu->get_hw_events();
  252. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  253. val = xscale1pmu_read_pmnc();
  254. val |= XSCALE_PMU_ENABLE;
  255. xscale1pmu_write_pmnc(val);
  256. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  257. }
  258. static void xscale1pmu_stop(struct arm_pmu *cpu_pmu)
  259. {
  260. unsigned long flags, val;
  261. struct pmu_hw_events *events = cpu_pmu->get_hw_events();
  262. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  263. val = xscale1pmu_read_pmnc();
  264. val &= ~XSCALE_PMU_ENABLE;
  265. xscale1pmu_write_pmnc(val);
  266. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  267. }
  268. static inline u32 xscale1pmu_read_counter(struct perf_event *event)
  269. {
  270. struct hw_perf_event *hwc = &event->hw;
  271. int counter = hwc->idx;
  272. u32 val = 0;
  273. switch (counter) {
  274. case XSCALE_CYCLE_COUNTER:
  275. asm volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (val));
  276. break;
  277. case XSCALE_COUNTER0:
  278. asm volatile("mrc p14, 0, %0, c2, c0, 0" : "=r" (val));
  279. break;
  280. case XSCALE_COUNTER1:
  281. asm volatile("mrc p14, 0, %0, c3, c0, 0" : "=r" (val));
  282. break;
  283. }
  284. return val;
  285. }
  286. static inline void xscale1pmu_write_counter(struct perf_event *event, u32 val)
  287. {
  288. struct hw_perf_event *hwc = &event->hw;
  289. int counter = hwc->idx;
  290. switch (counter) {
  291. case XSCALE_CYCLE_COUNTER:
  292. asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val));
  293. break;
  294. case XSCALE_COUNTER0:
  295. asm volatile("mcr p14, 0, %0, c2, c0, 0" : : "r" (val));
  296. break;
  297. case XSCALE_COUNTER1:
  298. asm volatile("mcr p14, 0, %0, c3, c0, 0" : : "r" (val));
  299. break;
  300. }
  301. }
  302. static int xscale_map_event(struct perf_event *event)
  303. {
  304. return armpmu_map_event(event, &xscale_perf_map,
  305. &xscale_perf_cache_map, 0xFF);
  306. }
  307. static int xscale1pmu_init(struct arm_pmu *cpu_pmu)
  308. {
  309. cpu_pmu->name = "armv5_xscale1";
  310. cpu_pmu->handle_irq = xscale1pmu_handle_irq;
  311. cpu_pmu->enable = xscale1pmu_enable_event;
  312. cpu_pmu->disable = xscale1pmu_disable_event;
  313. cpu_pmu->read_counter = xscale1pmu_read_counter;
  314. cpu_pmu->write_counter = xscale1pmu_write_counter;
  315. cpu_pmu->get_event_idx = xscale1pmu_get_event_idx;
  316. cpu_pmu->start = xscale1pmu_start;
  317. cpu_pmu->stop = xscale1pmu_stop;
  318. cpu_pmu->map_event = xscale_map_event;
  319. cpu_pmu->num_events = 3;
  320. cpu_pmu->max_period = (1LLU << 32) - 1;
  321. return 0;
  322. }
  323. #define XSCALE2_OVERFLOWED_MASK 0x01f
  324. #define XSCALE2_CCOUNT_OVERFLOW 0x001
  325. #define XSCALE2_COUNT0_OVERFLOW 0x002
  326. #define XSCALE2_COUNT1_OVERFLOW 0x004
  327. #define XSCALE2_COUNT2_OVERFLOW 0x008
  328. #define XSCALE2_COUNT3_OVERFLOW 0x010
  329. #define XSCALE2_CCOUNT_INT_EN 0x001
  330. #define XSCALE2_COUNT0_INT_EN 0x002
  331. #define XSCALE2_COUNT1_INT_EN 0x004
  332. #define XSCALE2_COUNT2_INT_EN 0x008
  333. #define XSCALE2_COUNT3_INT_EN 0x010
  334. #define XSCALE2_COUNT0_EVT_SHFT 0
  335. #define XSCALE2_COUNT0_EVT_MASK (0xff << XSCALE2_COUNT0_EVT_SHFT)
  336. #define XSCALE2_COUNT1_EVT_SHFT 8
  337. #define XSCALE2_COUNT1_EVT_MASK (0xff << XSCALE2_COUNT1_EVT_SHFT)
  338. #define XSCALE2_COUNT2_EVT_SHFT 16
  339. #define XSCALE2_COUNT2_EVT_MASK (0xff << XSCALE2_COUNT2_EVT_SHFT)
  340. #define XSCALE2_COUNT3_EVT_SHFT 24
  341. #define XSCALE2_COUNT3_EVT_MASK (0xff << XSCALE2_COUNT3_EVT_SHFT)
  342. static inline u32
  343. xscale2pmu_read_pmnc(void)
  344. {
  345. u32 val;
  346. asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
  347. /* bits 1-2 and 4-23 are read-unpredictable */
  348. return val & 0xff000009;
  349. }
  350. static inline void
  351. xscale2pmu_write_pmnc(u32 val)
  352. {
  353. /* bits 4-23 are write-as-0, 24-31 are write ignored */
  354. val &= 0xf;
  355. asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
  356. }
  357. static inline u32
  358. xscale2pmu_read_overflow_flags(void)
  359. {
  360. u32 val;
  361. asm volatile("mrc p14, 0, %0, c5, c1, 0" : "=r" (val));
  362. return val;
  363. }
  364. static inline void
  365. xscale2pmu_write_overflow_flags(u32 val)
  366. {
  367. asm volatile("mcr p14, 0, %0, c5, c1, 0" : : "r" (val));
  368. }
  369. static inline u32
  370. xscale2pmu_read_event_select(void)
  371. {
  372. u32 val;
  373. asm volatile("mrc p14, 0, %0, c8, c1, 0" : "=r" (val));
  374. return val;
  375. }
  376. static inline void
  377. xscale2pmu_write_event_select(u32 val)
  378. {
  379. asm volatile("mcr p14, 0, %0, c8, c1, 0" : : "r"(val));
  380. }
  381. static inline u32
  382. xscale2pmu_read_int_enable(void)
  383. {
  384. u32 val;
  385. asm volatile("mrc p14, 0, %0, c4, c1, 0" : "=r" (val));
  386. return val;
  387. }
  388. static void
  389. xscale2pmu_write_int_enable(u32 val)
  390. {
  391. asm volatile("mcr p14, 0, %0, c4, c1, 0" : : "r" (val));
  392. }
  393. static inline int
  394. xscale2_pmnc_counter_has_overflowed(unsigned long of_flags,
  395. enum xscale_counters counter)
  396. {
  397. int ret = 0;
  398. switch (counter) {
  399. case XSCALE_CYCLE_COUNTER:
  400. ret = of_flags & XSCALE2_CCOUNT_OVERFLOW;
  401. break;
  402. case XSCALE_COUNTER0:
  403. ret = of_flags & XSCALE2_COUNT0_OVERFLOW;
  404. break;
  405. case XSCALE_COUNTER1:
  406. ret = of_flags & XSCALE2_COUNT1_OVERFLOW;
  407. break;
  408. case XSCALE_COUNTER2:
  409. ret = of_flags & XSCALE2_COUNT2_OVERFLOW;
  410. break;
  411. case XSCALE_COUNTER3:
  412. ret = of_flags & XSCALE2_COUNT3_OVERFLOW;
  413. break;
  414. default:
  415. WARN_ONCE(1, "invalid counter number (%d)\n", counter);
  416. }
  417. return ret;
  418. }
  419. static irqreturn_t
  420. xscale2pmu_handle_irq(int irq_num, void *dev)
  421. {
  422. unsigned long pmnc, of_flags;
  423. struct perf_sample_data data;
  424. struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
  425. struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
  426. struct pt_regs *regs;
  427. int idx;
  428. /* Disable the PMU. */
  429. pmnc = xscale2pmu_read_pmnc();
  430. xscale2pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
  431. /* Check the overflow flag register. */
  432. of_flags = xscale2pmu_read_overflow_flags();
  433. if (!(of_flags & XSCALE2_OVERFLOWED_MASK))
  434. return IRQ_NONE;
  435. /* Clear the overflow bits. */
  436. xscale2pmu_write_overflow_flags(of_flags);
  437. regs = get_irq_regs();
  438. for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
  439. struct perf_event *event = cpuc->events[idx];
  440. struct hw_perf_event *hwc;
  441. if (!event)
  442. continue;
  443. if (!xscale2_pmnc_counter_has_overflowed(of_flags, idx))
  444. continue;
  445. hwc = &event->hw;
  446. armpmu_event_update(event);
  447. perf_sample_data_init(&data, 0, hwc->last_period);
  448. if (!armpmu_event_set_period(event))
  449. continue;
  450. if (perf_event_overflow(event, &data, regs))
  451. cpu_pmu->disable(event);
  452. }
  453. irq_work_run();
  454. /*
  455. * Re-enable the PMU.
  456. */
  457. pmnc = xscale2pmu_read_pmnc() | XSCALE_PMU_ENABLE;
  458. xscale2pmu_write_pmnc(pmnc);
  459. return IRQ_HANDLED;
  460. }
  461. static void xscale2pmu_enable_event(struct perf_event *event)
  462. {
  463. unsigned long flags, ien, evtsel;
  464. struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
  465. struct hw_perf_event *hwc = &event->hw;
  466. struct pmu_hw_events *events = cpu_pmu->get_hw_events();
  467. int idx = hwc->idx;
  468. ien = xscale2pmu_read_int_enable();
  469. evtsel = xscale2pmu_read_event_select();
  470. switch (idx) {
  471. case XSCALE_CYCLE_COUNTER:
  472. ien |= XSCALE2_CCOUNT_INT_EN;
  473. break;
  474. case XSCALE_COUNTER0:
  475. ien |= XSCALE2_COUNT0_INT_EN;
  476. evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
  477. evtsel |= hwc->config_base << XSCALE2_COUNT0_EVT_SHFT;
  478. break;
  479. case XSCALE_COUNTER1:
  480. ien |= XSCALE2_COUNT1_INT_EN;
  481. evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
  482. evtsel |= hwc->config_base << XSCALE2_COUNT1_EVT_SHFT;
  483. break;
  484. case XSCALE_COUNTER2:
  485. ien |= XSCALE2_COUNT2_INT_EN;
  486. evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
  487. evtsel |= hwc->config_base << XSCALE2_COUNT2_EVT_SHFT;
  488. break;
  489. case XSCALE_COUNTER3:
  490. ien |= XSCALE2_COUNT3_INT_EN;
  491. evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
  492. evtsel |= hwc->config_base << XSCALE2_COUNT3_EVT_SHFT;
  493. break;
  494. default:
  495. WARN_ONCE(1, "invalid counter number (%d)\n", idx);
  496. return;
  497. }
  498. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  499. xscale2pmu_write_event_select(evtsel);
  500. xscale2pmu_write_int_enable(ien);
  501. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  502. }
  503. static void xscale2pmu_disable_event(struct perf_event *event)
  504. {
  505. unsigned long flags, ien, evtsel, of_flags;
  506. struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
  507. struct hw_perf_event *hwc = &event->hw;
  508. struct pmu_hw_events *events = cpu_pmu->get_hw_events();
  509. int idx = hwc->idx;
  510. ien = xscale2pmu_read_int_enable();
  511. evtsel = xscale2pmu_read_event_select();
  512. switch (idx) {
  513. case XSCALE_CYCLE_COUNTER:
  514. ien &= ~XSCALE2_CCOUNT_INT_EN;
  515. of_flags = XSCALE2_CCOUNT_OVERFLOW;
  516. break;
  517. case XSCALE_COUNTER0:
  518. ien &= ~XSCALE2_COUNT0_INT_EN;
  519. evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
  520. evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT;
  521. of_flags = XSCALE2_COUNT0_OVERFLOW;
  522. break;
  523. case XSCALE_COUNTER1:
  524. ien &= ~XSCALE2_COUNT1_INT_EN;
  525. evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
  526. evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT;
  527. of_flags = XSCALE2_COUNT1_OVERFLOW;
  528. break;
  529. case XSCALE_COUNTER2:
  530. ien &= ~XSCALE2_COUNT2_INT_EN;
  531. evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
  532. evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT;
  533. of_flags = XSCALE2_COUNT2_OVERFLOW;
  534. break;
  535. case XSCALE_COUNTER3:
  536. ien &= ~XSCALE2_COUNT3_INT_EN;
  537. evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
  538. evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT;
  539. of_flags = XSCALE2_COUNT3_OVERFLOW;
  540. break;
  541. default:
  542. WARN_ONCE(1, "invalid counter number (%d)\n", idx);
  543. return;
  544. }
  545. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  546. xscale2pmu_write_event_select(evtsel);
  547. xscale2pmu_write_int_enable(ien);
  548. xscale2pmu_write_overflow_flags(of_flags);
  549. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  550. }
  551. static int
  552. xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc,
  553. struct perf_event *event)
  554. {
  555. int idx = xscale1pmu_get_event_idx(cpuc, event);
  556. if (idx >= 0)
  557. goto out;
  558. if (!test_and_set_bit(XSCALE_COUNTER3, cpuc->used_mask))
  559. idx = XSCALE_COUNTER3;
  560. else if (!test_and_set_bit(XSCALE_COUNTER2, cpuc->used_mask))
  561. idx = XSCALE_COUNTER2;
  562. out:
  563. return idx;
  564. }
  565. static void xscale2pmu_start(struct arm_pmu *cpu_pmu)
  566. {
  567. unsigned long flags, val;
  568. struct pmu_hw_events *events = cpu_pmu->get_hw_events();
  569. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  570. val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
  571. val |= XSCALE_PMU_ENABLE;
  572. xscale2pmu_write_pmnc(val);
  573. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  574. }
  575. static void xscale2pmu_stop(struct arm_pmu *cpu_pmu)
  576. {
  577. unsigned long flags, val;
  578. struct pmu_hw_events *events = cpu_pmu->get_hw_events();
  579. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  580. val = xscale2pmu_read_pmnc();
  581. val &= ~XSCALE_PMU_ENABLE;
  582. xscale2pmu_write_pmnc(val);
  583. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  584. }
  585. static inline u32 xscale2pmu_read_counter(struct perf_event *event)
  586. {
  587. struct hw_perf_event *hwc = &event->hw;
  588. int counter = hwc->idx;
  589. u32 val = 0;
  590. switch (counter) {
  591. case XSCALE_CYCLE_COUNTER:
  592. asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (val));
  593. break;
  594. case XSCALE_COUNTER0:
  595. asm volatile("mrc p14, 0, %0, c0, c2, 0" : "=r" (val));
  596. break;
  597. case XSCALE_COUNTER1:
  598. asm volatile("mrc p14, 0, %0, c1, c2, 0" : "=r" (val));
  599. break;
  600. case XSCALE_COUNTER2:
  601. asm volatile("mrc p14, 0, %0, c2, c2, 0" : "=r" (val));
  602. break;
  603. case XSCALE_COUNTER3:
  604. asm volatile("mrc p14, 0, %0, c3, c2, 0" : "=r" (val));
  605. break;
  606. }
  607. return val;
  608. }
  609. static inline void xscale2pmu_write_counter(struct perf_event *event, u32 val)
  610. {
  611. struct hw_perf_event *hwc = &event->hw;
  612. int counter = hwc->idx;
  613. switch (counter) {
  614. case XSCALE_CYCLE_COUNTER:
  615. asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val));
  616. break;
  617. case XSCALE_COUNTER0:
  618. asm volatile("mcr p14, 0, %0, c0, c2, 0" : : "r" (val));
  619. break;
  620. case XSCALE_COUNTER1:
  621. asm volatile("mcr p14, 0, %0, c1, c2, 0" : : "r" (val));
  622. break;
  623. case XSCALE_COUNTER2:
  624. asm volatile("mcr p14, 0, %0, c2, c2, 0" : : "r" (val));
  625. break;
  626. case XSCALE_COUNTER3:
  627. asm volatile("mcr p14, 0, %0, c3, c2, 0" : : "r" (val));
  628. break;
  629. }
  630. }
  631. static int xscale2pmu_init(struct arm_pmu *cpu_pmu)
  632. {
  633. cpu_pmu->name = "armv5_xscale2";
  634. cpu_pmu->handle_irq = xscale2pmu_handle_irq;
  635. cpu_pmu->enable = xscale2pmu_enable_event;
  636. cpu_pmu->disable = xscale2pmu_disable_event;
  637. cpu_pmu->read_counter = xscale2pmu_read_counter;
  638. cpu_pmu->write_counter = xscale2pmu_write_counter;
  639. cpu_pmu->get_event_idx = xscale2pmu_get_event_idx;
  640. cpu_pmu->start = xscale2pmu_start;
  641. cpu_pmu->stop = xscale2pmu_stop;
  642. cpu_pmu->map_event = xscale_map_event;
  643. cpu_pmu->num_events = 5;
  644. cpu_pmu->max_period = (1LLU << 32) - 1;
  645. return 0;
  646. }
  647. #else
  648. static inline int xscale1pmu_init(struct arm_pmu *cpu_pmu)
  649. {
  650. return -ENODEV;
  651. }
  652. static inline int xscale2pmu_init(struct arm_pmu *cpu_pmu)
  653. {
  654. return -ENODEV;
  655. }
  656. #endif /* CONFIG_CPU_XSCALE */