common.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * PPC 64 oprofile support:
  3. * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
  4. * PPC 32 oprofile support: (based on PPC 64 support)
  5. * Copyright (C) Freescale Semiconductor, Inc 2004
  6. * Author: Andy Fleming
  7. *
  8. * Based on alpha version.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version
  13. * 2 of the License, or (at your option) any later version.
  14. */
  15. #include <linux/oprofile.h>
  16. #include <linux/init.h>
  17. #include <linux/smp.h>
  18. #include <linux/errno.h>
  19. #include <asm/ptrace.h>
  20. #include <asm/pmc.h>
  21. #include <asm/cputable.h>
  22. #include <asm/oprofile_impl.h>
  23. #include <asm/firmware.h>
  24. static struct op_powerpc_model *model;
  25. static struct op_counter_config ctr[OP_MAX_COUNTER];
  26. static struct op_system_config sys;
  27. static int op_per_cpu_rc;
  28. static void op_handle_interrupt(struct pt_regs *regs)
  29. {
  30. model->handle_interrupt(regs, ctr);
  31. }
  32. static void op_powerpc_cpu_setup(void *dummy)
  33. {
  34. int ret;
  35. ret = model->cpu_setup(ctr);
  36. if (ret != 0)
  37. op_per_cpu_rc = ret;
  38. }
  39. static int op_powerpc_setup(void)
  40. {
  41. int err;
  42. op_per_cpu_rc = 0;
  43. /* Grab the hardware */
  44. err = reserve_pmc_hardware(op_handle_interrupt);
  45. if (err)
  46. return err;
  47. /* Pre-compute the values to stuff in the hardware registers. */
  48. op_per_cpu_rc = model->reg_setup(ctr, &sys, model->num_counters);
  49. if (op_per_cpu_rc)
  50. goto out;
  51. /* Configure the registers on all cpus. If an error occurs on one
  52. * of the cpus, op_per_cpu_rc will be set to the error */
  53. on_each_cpu(op_powerpc_cpu_setup, NULL, 1);
  54. out: if (op_per_cpu_rc) {
  55. /* error on setup release the performance counter hardware */
  56. release_pmc_hardware();
  57. }
  58. return op_per_cpu_rc;
  59. }
  60. static void op_powerpc_shutdown(void)
  61. {
  62. release_pmc_hardware();
  63. }
  64. static void op_powerpc_cpu_start(void *dummy)
  65. {
  66. /* If any of the cpus have return an error, set the
  67. * global flag to the error so it can be returned
  68. * to the generic OProfile caller.
  69. */
  70. int ret;
  71. ret = model->start(ctr);
  72. if (ret != 0)
  73. op_per_cpu_rc = ret;
  74. }
  75. static int op_powerpc_start(void)
  76. {
  77. op_per_cpu_rc = 0;
  78. if (model->global_start)
  79. return model->global_start(ctr);
  80. if (model->start) {
  81. on_each_cpu(op_powerpc_cpu_start, NULL, 1);
  82. return op_per_cpu_rc;
  83. }
  84. return -EIO; /* No start function is defined for this
  85. power architecture */
  86. }
  87. static inline void op_powerpc_cpu_stop(void *dummy)
  88. {
  89. model->stop();
  90. }
  91. static void op_powerpc_stop(void)
  92. {
  93. if (model->stop)
  94. on_each_cpu(op_powerpc_cpu_stop, NULL, 1);
  95. if (model->global_stop)
  96. model->global_stop();
  97. }
  98. static int op_powerpc_create_files(struct dentry *root)
  99. {
  100. int i;
  101. #ifdef CONFIG_PPC64
  102. /*
  103. * There is one mmcr0, mmcr1 and mmcra for setting the events for
  104. * all of the counters.
  105. */
  106. oprofilefs_create_ulong(root, "mmcr0", &sys.mmcr0);
  107. oprofilefs_create_ulong(root, "mmcr1", &sys.mmcr1);
  108. oprofilefs_create_ulong(root, "mmcra", &sys.mmcra);
  109. #ifdef CONFIG_OPROFILE_CELL
  110. /* create a file the user tool can check to see what level of profiling
  111. * support exits with this kernel. Initialize bit mask to indicate
  112. * what support the kernel has:
  113. * bit 0 - Supports SPU event profiling in addition to PPU
  114. * event and cycles; and SPU cycle profiling
  115. * bits 1-31 - Currently unused.
  116. *
  117. * If the file does not exist, then the kernel only supports SPU
  118. * cycle profiling, PPU event and cycle profiling.
  119. */
  120. oprofilefs_create_ulong(root, "cell_support", &sys.cell_support);
  121. sys.cell_support = 0x1; /* Note, the user OProfile tool must check
  122. * that this bit is set before attempting to
  123. * user SPU event profiling. Older kernels
  124. * will not have this file, hence the user
  125. * tool is not allowed to do SPU event
  126. * profiling on older kernels. Older kernels
  127. * will accept SPU events but collected data
  128. * is garbage.
  129. */
  130. #endif
  131. #endif
  132. for (i = 0; i < model->num_counters; ++i) {
  133. struct dentry *dir;
  134. char buf[4];
  135. snprintf(buf, sizeof buf, "%d", i);
  136. dir = oprofilefs_mkdir(root, buf);
  137. oprofilefs_create_ulong(dir, "enabled", &ctr[i].enabled);
  138. oprofilefs_create_ulong(dir, "event", &ctr[i].event);
  139. oprofilefs_create_ulong(dir, "count", &ctr[i].count);
  140. /*
  141. * Classic PowerPC doesn't support per-counter
  142. * control like this, but the options are
  143. * expected, so they remain. For Freescale
  144. * Book-E style performance monitors, we do
  145. * support them.
  146. */
  147. oprofilefs_create_ulong(dir, "kernel", &ctr[i].kernel);
  148. oprofilefs_create_ulong(dir, "user", &ctr[i].user);
  149. oprofilefs_create_ulong(dir, "unit_mask", &ctr[i].unit_mask);
  150. }
  151. oprofilefs_create_ulong(root, "enable_kernel", &sys.enable_kernel);
  152. oprofilefs_create_ulong(root, "enable_user", &sys.enable_user);
  153. /* Default to tracing both kernel and user */
  154. sys.enable_kernel = 1;
  155. sys.enable_user = 1;
  156. return 0;
  157. }
  158. int __init oprofile_arch_init(struct oprofile_operations *ops)
  159. {
  160. if (!cur_cpu_spec->oprofile_cpu_type)
  161. return -ENODEV;
  162. switch (cur_cpu_spec->oprofile_type) {
  163. #ifdef CONFIG_PPC_BOOK3S_64
  164. #ifdef CONFIG_OPROFILE_CELL
  165. case PPC_OPROFILE_CELL:
  166. if (firmware_has_feature(FW_FEATURE_LPAR))
  167. return -ENODEV;
  168. model = &op_model_cell;
  169. ops->sync_start = model->sync_start;
  170. ops->sync_stop = model->sync_stop;
  171. break;
  172. #endif
  173. case PPC_OPROFILE_POWER4:
  174. model = &op_model_power4;
  175. break;
  176. case PPC_OPROFILE_PA6T:
  177. model = &op_model_pa6t;
  178. break;
  179. #endif
  180. #ifdef CONFIG_6xx
  181. case PPC_OPROFILE_G4:
  182. model = &op_model_7450;
  183. break;
  184. #endif
  185. #if defined(CONFIG_FSL_EMB_PERFMON)
  186. case PPC_OPROFILE_FSL_EMB:
  187. model = &op_model_fsl_emb;
  188. break;
  189. #endif
  190. default:
  191. return -ENODEV;
  192. }
  193. model->num_counters = cur_cpu_spec->num_pmcs;
  194. ops->cpu_type = cur_cpu_spec->oprofile_cpu_type;
  195. ops->create_files = op_powerpc_create_files;
  196. ops->setup = op_powerpc_setup;
  197. ops->shutdown = op_powerpc_shutdown;
  198. ops->start = op_powerpc_start;
  199. ops->stop = op_powerpc_stop;
  200. ops->backtrace = op_powerpc_backtrace;
  201. printk(KERN_DEBUG "oprofile: using %s performance monitoring.\n",
  202. ops->cpu_type);
  203. return 0;
  204. }
  205. void oprofile_arch_exit(void)
  206. {
  207. }