pmu.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * Cell Broadband Engine Performance Monitor
  3. *
  4. * (C) Copyright IBM Corporation 2001,2006
  5. *
  6. * Author:
  7. * David Erb (djerb@us.ibm.com)
  8. * Kevin Corry (kevcorry@us.ibm.com)
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2, or (at your option)
  13. * any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23. */
  24. #include <linux/interrupt.h>
  25. #include <linux/types.h>
  26. #include <asm/io.h>
  27. #include <asm/irq_regs.h>
  28. #include <asm/machdep.h>
  29. #include <asm/pmc.h>
  30. #include <asm/reg.h>
  31. #include <asm/spu.h>
  32. #include <asm/cell-regs.h>
  33. #include "interrupt.h"
  34. /*
  35. * When writing to write-only mmio addresses, save a shadow copy. All of the
  36. * registers are 32-bit, but stored in the upper-half of a 64-bit field in
  37. * pmd_regs.
  38. */
  39. #define WRITE_WO_MMIO(reg, x) \
  40. do { \
  41. u32 _x = (x); \
  42. struct cbe_pmd_regs __iomem *pmd_regs; \
  43. struct cbe_pmd_shadow_regs *shadow_regs; \
  44. pmd_regs = cbe_get_cpu_pmd_regs(cpu); \
  45. shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \
  46. out_be64(&(pmd_regs->reg), (((u64)_x) << 32)); \
  47. shadow_regs->reg = _x; \
  48. } while (0)
  49. #define READ_SHADOW_REG(val, reg) \
  50. do { \
  51. struct cbe_pmd_shadow_regs *shadow_regs; \
  52. shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \
  53. (val) = shadow_regs->reg; \
  54. } while (0)
  55. #define READ_MMIO_UPPER32(val, reg) \
  56. do { \
  57. struct cbe_pmd_regs __iomem *pmd_regs; \
  58. pmd_regs = cbe_get_cpu_pmd_regs(cpu); \
  59. (val) = (u32)(in_be64(&pmd_regs->reg) >> 32); \
  60. } while (0)
  61. /*
  62. * Physical counter registers.
  63. * Each physical counter can act as one 32-bit counter or two 16-bit counters.
  64. */
  65. u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr)
  66. {
  67. u32 val_in_latch, val = 0;
  68. if (phys_ctr < NR_PHYS_CTRS) {
  69. READ_SHADOW_REG(val_in_latch, counter_value_in_latch);
  70. /* Read the latch or the actual counter, whichever is newer. */
  71. if (val_in_latch & (1 << phys_ctr)) {
  72. READ_SHADOW_REG(val, pm_ctr[phys_ctr]);
  73. } else {
  74. READ_MMIO_UPPER32(val, pm_ctr[phys_ctr]);
  75. }
  76. }
  77. return val;
  78. }
  79. EXPORT_SYMBOL_GPL(cbe_read_phys_ctr);
  80. void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val)
  81. {
  82. struct cbe_pmd_shadow_regs *shadow_regs;
  83. u32 pm_ctrl;
  84. if (phys_ctr < NR_PHYS_CTRS) {
  85. /* Writing to a counter only writes to a hardware latch.
  86. * The new value is not propagated to the actual counter
  87. * until the performance monitor is enabled.
  88. */
  89. WRITE_WO_MMIO(pm_ctr[phys_ctr], val);
  90. pm_ctrl = cbe_read_pm(cpu, pm_control);
  91. if (pm_ctrl & CBE_PM_ENABLE_PERF_MON) {
  92. /* The counters are already active, so we need to
  93. * rewrite the pm_control register to "re-enable"
  94. * the PMU.
  95. */
  96. cbe_write_pm(cpu, pm_control, pm_ctrl);
  97. } else {
  98. shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu);
  99. shadow_regs->counter_value_in_latch |= (1 << phys_ctr);
  100. }
  101. }
  102. }
  103. EXPORT_SYMBOL_GPL(cbe_write_phys_ctr);
  104. /*
  105. * "Logical" counter registers.
  106. * These will read/write 16-bits or 32-bits depending on the
  107. * current size of the counter. Counters 4 - 7 are always 16-bit.
  108. */
  109. u32 cbe_read_ctr(u32 cpu, u32 ctr)
  110. {
  111. u32 val;
  112. u32 phys_ctr = ctr & (NR_PHYS_CTRS - 1);
  113. val = cbe_read_phys_ctr(cpu, phys_ctr);
  114. if (cbe_get_ctr_size(cpu, phys_ctr) == 16)
  115. val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff);
  116. return val;
  117. }
  118. EXPORT_SYMBOL_GPL(cbe_read_ctr);
  119. void cbe_write_ctr(u32 cpu, u32 ctr, u32 val)
  120. {
  121. u32 phys_ctr;
  122. u32 phys_val;
  123. phys_ctr = ctr & (NR_PHYS_CTRS - 1);
  124. if (cbe_get_ctr_size(cpu, phys_ctr) == 16) {
  125. phys_val = cbe_read_phys_ctr(cpu, phys_ctr);
  126. if (ctr < NR_PHYS_CTRS)
  127. val = (val << 16) | (phys_val & 0xffff);
  128. else
  129. val = (val & 0xffff) | (phys_val & 0xffff0000);
  130. }
  131. cbe_write_phys_ctr(cpu, phys_ctr, val);
  132. }
  133. EXPORT_SYMBOL_GPL(cbe_write_ctr);
  134. /*
  135. * Counter-control registers.
  136. * Each "logical" counter has a corresponding control register.
  137. */
  138. u32 cbe_read_pm07_control(u32 cpu, u32 ctr)
  139. {
  140. u32 pm07_control = 0;
  141. if (ctr < NR_CTRS)
  142. READ_SHADOW_REG(pm07_control, pm07_control[ctr]);
  143. return pm07_control;
  144. }
  145. EXPORT_SYMBOL_GPL(cbe_read_pm07_control);
  146. void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val)
  147. {
  148. if (ctr < NR_CTRS)
  149. WRITE_WO_MMIO(pm07_control[ctr], val);
  150. }
  151. EXPORT_SYMBOL_GPL(cbe_write_pm07_control);
  152. /*
  153. * Other PMU control registers. Most of these are write-only.
  154. */
  155. u32 cbe_read_pm(u32 cpu, enum pm_reg_name reg)
  156. {
  157. u32 val = 0;
  158. switch (reg) {
  159. case group_control:
  160. READ_SHADOW_REG(val, group_control);
  161. break;
  162. case debug_bus_control:
  163. READ_SHADOW_REG(val, debug_bus_control);
  164. break;
  165. case trace_address:
  166. READ_MMIO_UPPER32(val, trace_address);
  167. break;
  168. case ext_tr_timer:
  169. READ_SHADOW_REG(val, ext_tr_timer);
  170. break;
  171. case pm_status:
  172. READ_MMIO_UPPER32(val, pm_status);
  173. break;
  174. case pm_control:
  175. READ_SHADOW_REG(val, pm_control);
  176. break;
  177. case pm_interval:
  178. READ_MMIO_UPPER32(val, pm_interval);
  179. break;
  180. case pm_start_stop:
  181. READ_SHADOW_REG(val, pm_start_stop);
  182. break;
  183. }
  184. return val;
  185. }
  186. EXPORT_SYMBOL_GPL(cbe_read_pm);
  187. void cbe_write_pm(u32 cpu, enum pm_reg_name reg, u32 val)
  188. {
  189. switch (reg) {
  190. case group_control:
  191. WRITE_WO_MMIO(group_control, val);
  192. break;
  193. case debug_bus_control:
  194. WRITE_WO_MMIO(debug_bus_control, val);
  195. break;
  196. case trace_address:
  197. WRITE_WO_MMIO(trace_address, val);
  198. break;
  199. case ext_tr_timer:
  200. WRITE_WO_MMIO(ext_tr_timer, val);
  201. break;
  202. case pm_status:
  203. WRITE_WO_MMIO(pm_status, val);
  204. break;
  205. case pm_control:
  206. WRITE_WO_MMIO(pm_control, val);
  207. break;
  208. case pm_interval:
  209. WRITE_WO_MMIO(pm_interval, val);
  210. break;
  211. case pm_start_stop:
  212. WRITE_WO_MMIO(pm_start_stop, val);
  213. break;
  214. }
  215. }
  216. EXPORT_SYMBOL_GPL(cbe_write_pm);
  217. /*
  218. * Get/set the size of a physical counter to either 16 or 32 bits.
  219. */
  220. u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr)
  221. {
  222. u32 pm_ctrl, size = 0;
  223. if (phys_ctr < NR_PHYS_CTRS) {
  224. pm_ctrl = cbe_read_pm(cpu, pm_control);
  225. size = (pm_ctrl & CBE_PM_16BIT_CTR(phys_ctr)) ? 16 : 32;
  226. }
  227. return size;
  228. }
  229. EXPORT_SYMBOL_GPL(cbe_get_ctr_size);
  230. void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size)
  231. {
  232. u32 pm_ctrl;
  233. if (phys_ctr < NR_PHYS_CTRS) {
  234. pm_ctrl = cbe_read_pm(cpu, pm_control);
  235. switch (ctr_size) {
  236. case 16:
  237. pm_ctrl |= CBE_PM_16BIT_CTR(phys_ctr);
  238. break;
  239. case 32:
  240. pm_ctrl &= ~CBE_PM_16BIT_CTR(phys_ctr);
  241. break;
  242. }
  243. cbe_write_pm(cpu, pm_control, pm_ctrl);
  244. }
  245. }
  246. EXPORT_SYMBOL_GPL(cbe_set_ctr_size);
  247. /*
  248. * Enable/disable the entire performance monitoring unit.
  249. * When we enable the PMU, all pending writes to counters get committed.
  250. */
  251. void cbe_enable_pm(u32 cpu)
  252. {
  253. struct cbe_pmd_shadow_regs *shadow_regs;
  254. u32 pm_ctrl;
  255. shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu);
  256. shadow_regs->counter_value_in_latch = 0;
  257. pm_ctrl = cbe_read_pm(cpu, pm_control) | CBE_PM_ENABLE_PERF_MON;
  258. cbe_write_pm(cpu, pm_control, pm_ctrl);
  259. }
  260. EXPORT_SYMBOL_GPL(cbe_enable_pm);
  261. void cbe_disable_pm(u32 cpu)
  262. {
  263. u32 pm_ctrl;
  264. pm_ctrl = cbe_read_pm(cpu, pm_control) & ~CBE_PM_ENABLE_PERF_MON;
  265. cbe_write_pm(cpu, pm_control, pm_ctrl);
  266. }
  267. EXPORT_SYMBOL_GPL(cbe_disable_pm);
  268. /*
  269. * Reading from the trace_buffer.
  270. * The trace buffer is two 64-bit registers. Reading from
  271. * the second half automatically increments the trace_address.
  272. */
  273. void cbe_read_trace_buffer(u32 cpu, u64 *buf)
  274. {
  275. struct cbe_pmd_regs __iomem *pmd_regs = cbe_get_cpu_pmd_regs(cpu);
  276. *buf++ = in_be64(&pmd_regs->trace_buffer_0_63);
  277. *buf++ = in_be64(&pmd_regs->trace_buffer_64_127);
  278. }
  279. EXPORT_SYMBOL_GPL(cbe_read_trace_buffer);
  280. /*
  281. * Enabling/disabling interrupts for the entire performance monitoring unit.
  282. */
  283. u32 cbe_get_and_clear_pm_interrupts(u32 cpu)
  284. {
  285. /* Reading pm_status clears the interrupt bits. */
  286. return cbe_read_pm(cpu, pm_status);
  287. }
  288. EXPORT_SYMBOL_GPL(cbe_get_and_clear_pm_interrupts);
  289. void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask)
  290. {
  291. /* Set which node and thread will handle the next interrupt. */
  292. iic_set_interrupt_routing(cpu, thread, 0);
  293. /* Enable the interrupt bits in the pm_status register. */
  294. if (mask)
  295. cbe_write_pm(cpu, pm_status, mask);
  296. }
  297. EXPORT_SYMBOL_GPL(cbe_enable_pm_interrupts);
  298. void cbe_disable_pm_interrupts(u32 cpu)
  299. {
  300. cbe_get_and_clear_pm_interrupts(cpu);
  301. cbe_write_pm(cpu, pm_status, 0);
  302. }
  303. EXPORT_SYMBOL_GPL(cbe_disable_pm_interrupts);
  304. static irqreturn_t cbe_pm_irq(int irq, void *dev_id)
  305. {
  306. perf_irq(get_irq_regs());
  307. return IRQ_HANDLED;
  308. }
  309. static int __init cbe_init_pm_irq(void)
  310. {
  311. unsigned int irq;
  312. int rc, node;
  313. for_each_node(node) {
  314. irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI |
  315. (node << IIC_IRQ_NODE_SHIFT));
  316. if (irq == NO_IRQ) {
  317. printk("ERROR: Unable to allocate irq for node %d\n",
  318. node);
  319. return -EINVAL;
  320. }
  321. rc = request_irq(irq, cbe_pm_irq,
  322. IRQF_DISABLED, "cbe-pmu-0", NULL);
  323. if (rc) {
  324. printk("ERROR: Request for irq on node %d failed\n",
  325. node);
  326. return rc;
  327. }
  328. }
  329. return 0;
  330. }
  331. machine_arch_initcall(cell, cbe_init_pm_irq);
  332. void cbe_sync_irq(int node)
  333. {
  334. unsigned int irq;
  335. irq = irq_find_mapping(NULL,
  336. IIC_IRQ_IOEX_PMI
  337. | (node << IIC_IRQ_NODE_SHIFT));
  338. if (irq == NO_IRQ) {
  339. printk(KERN_WARNING "ERROR, unable to get existing irq %d " \
  340. "for node %d\n", irq, node);
  341. return;
  342. }
  343. synchronize_irq(irq);
  344. }
  345. EXPORT_SYMBOL_GPL(cbe_sync_irq);