pmu.c 9.5 KB

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