perfmon.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /**
  2. * @file perfmon.c
  3. *
  4. * @remark Copyright 2003 OProfile authors
  5. * @remark Read the file COPYING
  6. *
  7. * @author John Levon <levon@movementarian.org>
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/config.h>
  11. #include <linux/oprofile.h>
  12. #include <linux/sched.h>
  13. #include <asm/perfmon.h>
  14. #include <asm/ptrace.h>
  15. #include <asm/errno.h>
  16. static int allow_ints;
  17. static int
  18. perfmon_handler(struct task_struct *task, void *buf, pfm_ovfl_arg_t *arg,
  19. struct pt_regs *regs, unsigned long stamp)
  20. {
  21. int event = arg->pmd_eventid;
  22. arg->ovfl_ctrl.bits.reset_ovfl_pmds = 1;
  23. /* the owner of the oprofile event buffer may have exited
  24. * without perfmon being shutdown (e.g. SIGSEGV)
  25. */
  26. if (allow_ints)
  27. oprofile_add_sample(regs, event);
  28. return 0;
  29. }
  30. static int perfmon_start(void)
  31. {
  32. allow_ints = 1;
  33. return 0;
  34. }
  35. static void perfmon_stop(void)
  36. {
  37. allow_ints = 0;
  38. }
  39. #define OPROFILE_FMT_UUID { \
  40. 0x77, 0x7a, 0x6e, 0x61, 0x20, 0x65, 0x73, 0x69, 0x74, 0x6e, 0x72, 0x20, 0x61, 0x65, 0x0a, 0x6c }
  41. static pfm_buffer_fmt_t oprofile_fmt = {
  42. .fmt_name = "oprofile_format",
  43. .fmt_uuid = OPROFILE_FMT_UUID,
  44. .fmt_handler = perfmon_handler,
  45. };
  46. static char * get_cpu_type(void)
  47. {
  48. __u8 family = local_cpu_data->family;
  49. switch (family) {
  50. case 0x07:
  51. return "ia64/itanium";
  52. case 0x1f:
  53. return "ia64/itanium2";
  54. default:
  55. return "ia64/ia64";
  56. }
  57. }
  58. /* all the ops are handled via userspace for IA64 perfmon */
  59. static int using_perfmon;
  60. int perfmon_init(struct oprofile_operations * ops)
  61. {
  62. int ret = pfm_register_buffer_fmt(&oprofile_fmt);
  63. if (ret)
  64. return -ENODEV;
  65. ops->cpu_type = get_cpu_type();
  66. ops->start = perfmon_start;
  67. ops->stop = perfmon_stop;
  68. using_perfmon = 1;
  69. printk(KERN_INFO "oprofile: using perfmon.\n");
  70. return 0;
  71. }
  72. void perfmon_exit(void)
  73. {
  74. if (!using_perfmon)
  75. return;
  76. pfm_unregister_buffer_fmt(oprofile_fmt.fmt_uuid);
  77. }