common.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2004, 2005 Ralf Baechle
  7. * Copyright (C) 2005 MIPS Technologies, Inc.
  8. */
  9. #include <linux/compiler.h>
  10. #include <linux/errno.h>
  11. #include <linux/init.h>
  12. #include <linux/oprofile.h>
  13. #include <linux/smp.h>
  14. #include <asm/cpu-info.h>
  15. #include <asm/cpu-type.h>
  16. #include "op_impl.h"
  17. extern struct op_mips_model op_model_mipsxx_ops __weak;
  18. extern struct op_mips_model op_model_loongson2_ops __weak;
  19. extern struct op_mips_model op_model_loongson3_ops __weak;
  20. static struct op_mips_model *model;
  21. static struct op_counter_config ctr[20];
  22. static int op_mips_setup(void)
  23. {
  24. /* Pre-compute the values to stuff in the hardware registers. */
  25. model->reg_setup(ctr);
  26. /* Configure the registers on all cpus. */
  27. on_each_cpu(model->cpu_setup, NULL, 1);
  28. return 0;
  29. }
  30. static int op_mips_create_files(struct dentry *root)
  31. {
  32. int i;
  33. for (i = 0; i < model->num_counters; ++i) {
  34. struct dentry *dir;
  35. char buf[4];
  36. snprintf(buf, sizeof buf, "%d", i);
  37. dir = oprofilefs_mkdir(root, buf);
  38. oprofilefs_create_ulong(dir, "enabled", &ctr[i].enabled);
  39. oprofilefs_create_ulong(dir, "event", &ctr[i].event);
  40. oprofilefs_create_ulong(dir, "count", &ctr[i].count);
  41. oprofilefs_create_ulong(dir, "kernel", &ctr[i].kernel);
  42. oprofilefs_create_ulong(dir, "user", &ctr[i].user);
  43. oprofilefs_create_ulong(dir, "exl", &ctr[i].exl);
  44. /* Dummy. */
  45. oprofilefs_create_ulong(dir, "unit_mask", &ctr[i].unit_mask);
  46. }
  47. return 0;
  48. }
  49. static int op_mips_start(void)
  50. {
  51. on_each_cpu(model->cpu_start, NULL, 1);
  52. return 0;
  53. }
  54. static void op_mips_stop(void)
  55. {
  56. /* Disable performance monitoring for all counters. */
  57. on_each_cpu(model->cpu_stop, NULL, 1);
  58. }
  59. int __init oprofile_arch_init(struct oprofile_operations *ops)
  60. {
  61. struct op_mips_model *lmodel = NULL;
  62. int res;
  63. switch (current_cpu_type()) {
  64. case CPU_5KC:
  65. case CPU_M14KC:
  66. case CPU_M14KEC:
  67. case CPU_20KC:
  68. case CPU_24K:
  69. case CPU_25KF:
  70. case CPU_34K:
  71. case CPU_1004K:
  72. case CPU_74K:
  73. case CPU_1074K:
  74. case CPU_INTERAPTIV:
  75. case CPU_PROAPTIV:
  76. case CPU_P5600:
  77. case CPU_M5150:
  78. case CPU_LOONGSON1:
  79. case CPU_SB1:
  80. case CPU_SB1A:
  81. case CPU_R10000:
  82. case CPU_R12000:
  83. case CPU_R14000:
  84. case CPU_R16000:
  85. case CPU_XLR:
  86. lmodel = &op_model_mipsxx_ops;
  87. break;
  88. case CPU_LOONGSON2:
  89. lmodel = &op_model_loongson2_ops;
  90. break;
  91. case CPU_LOONGSON3:
  92. lmodel = &op_model_loongson3_ops;
  93. break;
  94. };
  95. /*
  96. * Always set the backtrace. This allows unsupported CPU types to still
  97. * use timer-based oprofile.
  98. */
  99. ops->backtrace = op_mips_backtrace;
  100. if (!lmodel)
  101. return -ENODEV;
  102. res = lmodel->init();
  103. if (res)
  104. return res;
  105. model = lmodel;
  106. ops->create_files = op_mips_create_files;
  107. ops->setup = op_mips_setup;
  108. //ops->shutdown = op_mips_shutdown;
  109. ops->start = op_mips_start;
  110. ops->stop = op_mips_stop;
  111. ops->cpu_type = lmodel->cpu_type;
  112. printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
  113. lmodel->cpu_type);
  114. return 0;
  115. }
  116. void oprofile_arch_exit(void)
  117. {
  118. if (model)
  119. model->exit();
  120. }