common.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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 <asm/cputable.h>
  19. #include "op_impl.h"
  20. extern struct op_ppc64_model op_model_rs64;
  21. extern struct op_ppc64_model op_model_power4;
  22. static struct op_ppc64_model *model;
  23. static struct op_counter_config ctr[OP_MAX_COUNTER];
  24. static struct op_system_config sys;
  25. static void op_handle_interrupt(struct pt_regs *regs)
  26. {
  27. model->handle_interrupt(regs, ctr);
  28. }
  29. static int op_ppc64_setup(void)
  30. {
  31. int err;
  32. /* Grab the hardware */
  33. err = reserve_pmc_hardware(op_handle_interrupt);
  34. if (err)
  35. return err;
  36. /* Pre-compute the values to stuff in the hardware registers. */
  37. model->reg_setup(ctr, &sys, model->num_counters);
  38. /* Configure the registers on all cpus. */
  39. on_each_cpu(model->cpu_setup, NULL, 0, 1);
  40. return 0;
  41. }
  42. static void op_ppc64_shutdown(void)
  43. {
  44. release_pmc_hardware();
  45. }
  46. static void op_ppc64_cpu_start(void *dummy)
  47. {
  48. model->start(ctr);
  49. }
  50. static int op_ppc64_start(void)
  51. {
  52. on_each_cpu(op_ppc64_cpu_start, NULL, 0, 1);
  53. return 0;
  54. }
  55. static inline void op_ppc64_cpu_stop(void *dummy)
  56. {
  57. model->stop();
  58. }
  59. static void op_ppc64_stop(void)
  60. {
  61. on_each_cpu(op_ppc64_cpu_stop, NULL, 0, 1);
  62. }
  63. static int op_ppc64_create_files(struct super_block *sb, struct dentry *root)
  64. {
  65. int i;
  66. /*
  67. * There is one mmcr0, mmcr1 and mmcra for setting the events for
  68. * all of the counters.
  69. */
  70. oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0);
  71. oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1);
  72. oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra);
  73. for (i = 0; i < model->num_counters; ++i) {
  74. struct dentry *dir;
  75. char buf[3];
  76. snprintf(buf, sizeof buf, "%d", i);
  77. dir = oprofilefs_mkdir(sb, root, buf);
  78. oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
  79. oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
  80. oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
  81. /*
  82. * We dont support per counter user/kernel selection, but
  83. * we leave the entries because userspace expects them
  84. */
  85. oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
  86. oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
  87. oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
  88. }
  89. oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
  90. oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
  91. oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
  92. &sys.backtrace_spinlocks);
  93. /* Default to tracing both kernel and user */
  94. sys.enable_kernel = 1;
  95. sys.enable_user = 1;
  96. /* Turn on backtracing through spinlocks by default */
  97. sys.backtrace_spinlocks = 1;
  98. return 0;
  99. }
  100. int __init oprofile_arch_init(struct oprofile_operations *ops)
  101. {
  102. unsigned int pvr;
  103. pvr = mfspr(SPRN_PVR);
  104. switch (PVR_VER(pvr)) {
  105. case PV_630:
  106. case PV_630p:
  107. model = &op_model_rs64;
  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. ops->cpu_type = "ppc64/rs64";
  116. break;
  117. case PV_POWER4:
  118. case PV_POWER4p:
  119. model = &op_model_power4;
  120. ops->cpu_type = "ppc64/power4";
  121. break;
  122. case PV_970:
  123. case PV_970FX:
  124. case PV_970MP:
  125. model = &op_model_power4;
  126. ops->cpu_type = "ppc64/970";
  127. break;
  128. case PV_POWER5:
  129. case PV_POWER5p:
  130. model = &op_model_power4;
  131. ops->cpu_type = "ppc64/power5";
  132. break;
  133. default:
  134. return -ENODEV;
  135. }
  136. model->num_counters = cur_cpu_spec->num_pmcs;
  137. ops->create_files = op_ppc64_create_files;
  138. ops->setup = op_ppc64_setup;
  139. ops->shutdown = op_ppc64_shutdown;
  140. ops->start = op_ppc64_start;
  141. ops->stop = op_ppc64_stop;
  142. printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
  143. ops->cpu_type);
  144. return 0;
  145. }
  146. void oprofile_arch_exit(void)
  147. {
  148. }