common.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
  3. *
  4. * Based on alpha version.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/oprofile.h>
  12. #include <linux/init.h>
  13. #include <linux/smp.h>
  14. #include <linux/errno.h>
  15. #include <asm/ptrace.h>
  16. #include <asm/system.h>
  17. #include <asm/pmc.h>
  18. #include "op_impl.h"
  19. extern struct op_ppc64_model op_model_rs64;
  20. extern struct op_ppc64_model op_model_power4;
  21. static struct op_ppc64_model *model;
  22. static struct op_counter_config ctr[OP_MAX_COUNTER];
  23. static struct op_system_config sys;
  24. static void op_handle_interrupt(struct pt_regs *regs)
  25. {
  26. model->handle_interrupt(regs, ctr);
  27. }
  28. static int op_ppc64_setup(void)
  29. {
  30. int err;
  31. /* Grab the hardware */
  32. err = reserve_pmc_hardware(op_handle_interrupt);
  33. if (err)
  34. return err;
  35. /* Pre-compute the values to stuff in the hardware registers. */
  36. model->reg_setup(ctr, &sys, model->num_counters);
  37. /* Configure the registers on all cpus. */
  38. on_each_cpu(model->cpu_setup, NULL, 0, 1);
  39. return 0;
  40. }
  41. static void op_ppc64_shutdown(void)
  42. {
  43. release_pmc_hardware();
  44. }
  45. static void op_ppc64_cpu_start(void *dummy)
  46. {
  47. model->start(ctr);
  48. }
  49. static int op_ppc64_start(void)
  50. {
  51. on_each_cpu(op_ppc64_cpu_start, NULL, 0, 1);
  52. return 0;
  53. }
  54. static inline void op_ppc64_cpu_stop(void *dummy)
  55. {
  56. model->stop();
  57. }
  58. static void op_ppc64_stop(void)
  59. {
  60. on_each_cpu(op_ppc64_cpu_stop, NULL, 0, 1);
  61. }
  62. static int op_ppc64_create_files(struct super_block *sb, struct dentry *root)
  63. {
  64. int i;
  65. /*
  66. * There is one mmcr0, mmcr1 and mmcra for setting the events for
  67. * all of the counters.
  68. */
  69. oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0);
  70. oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1);
  71. oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra);
  72. for (i = 0; i < model->num_counters; ++i) {
  73. struct dentry *dir;
  74. char buf[3];
  75. snprintf(buf, sizeof buf, "%d", i);
  76. dir = oprofilefs_mkdir(sb, root, buf);
  77. oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
  78. oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
  79. oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
  80. /*
  81. * We dont support per counter user/kernel selection, but
  82. * we leave the entries because userspace expects them
  83. */
  84. oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
  85. oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
  86. oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
  87. }
  88. oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
  89. oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
  90. oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
  91. &sys.backtrace_spinlocks);
  92. /* Default to tracing both kernel and user */
  93. sys.enable_kernel = 1;
  94. sys.enable_user = 1;
  95. /* Turn on backtracing through spinlocks by default */
  96. sys.backtrace_spinlocks = 1;
  97. return 0;
  98. }
  99. int __init oprofile_arch_init(struct oprofile_operations *ops)
  100. {
  101. unsigned int pvr;
  102. pvr = mfspr(SPRN_PVR);
  103. switch (PVR_VER(pvr)) {
  104. case PV_630:
  105. case PV_630p:
  106. model = &op_model_rs64;
  107. model->num_counters = 8;
  108. ops->cpu_type = "ppc64/power3";
  109. break;
  110. case PV_NORTHSTAR:
  111. case PV_PULSAR:
  112. case PV_ICESTAR:
  113. case PV_SSTAR:
  114. model = &op_model_rs64;
  115. model->num_counters = 8;
  116. ops->cpu_type = "ppc64/rs64";
  117. break;
  118. case PV_POWER4:
  119. case PV_POWER4p:
  120. model = &op_model_power4;
  121. model->num_counters = 8;
  122. ops->cpu_type = "ppc64/power4";
  123. break;
  124. case PV_970:
  125. case PV_970FX:
  126. case PV_970MP:
  127. model = &op_model_power4;
  128. model->num_counters = 8;
  129. ops->cpu_type = "ppc64/970";
  130. break;
  131. case PV_POWER5:
  132. case PV_POWER5p:
  133. model = &op_model_power4;
  134. model->num_counters = 6;
  135. ops->cpu_type = "ppc64/power5";
  136. break;
  137. default:
  138. return -ENODEV;
  139. }
  140. ops->create_files = op_ppc64_create_files;
  141. ops->setup = op_ppc64_setup;
  142. ops->shutdown = op_ppc64_shutdown;
  143. ops->start = op_ppc64_start;
  144. ops->stop = op_ppc64_stop;
  145. printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
  146. ops->cpu_type);
  147. return 0;
  148. }
  149. void oprofile_arch_exit(void)
  150. {
  151. }