init.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /**
  2. * @file init.c
  3. *
  4. * @remark Copyright 2002 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/oprofile.h>
  11. #include <linux/errno.h>
  12. #include <linux/init.h>
  13. #include <linux/param.h> /* for HZ */
  14. #ifdef CONFIG_SPARC64
  15. #include <linux/notifier.h>
  16. #include <linux/rcupdate.h>
  17. #include <linux/kdebug.h>
  18. #include <asm/nmi.h>
  19. static int profile_timer_exceptions_notify(struct notifier_block *self,
  20. unsigned long val, void *data)
  21. {
  22. struct die_args *args = data;
  23. int ret = NOTIFY_DONE;
  24. switch (val) {
  25. case DIE_NMI:
  26. oprofile_add_sample(args->regs, 0);
  27. ret = NOTIFY_STOP;
  28. break;
  29. default:
  30. break;
  31. }
  32. return ret;
  33. }
  34. static struct notifier_block profile_timer_exceptions_nb = {
  35. .notifier_call = profile_timer_exceptions_notify,
  36. };
  37. static int timer_start(void)
  38. {
  39. if (register_die_notifier(&profile_timer_exceptions_nb))
  40. return 1;
  41. nmi_adjust_hz(HZ);
  42. return 0;
  43. }
  44. static void timer_stop(void)
  45. {
  46. nmi_adjust_hz(1);
  47. unregister_die_notifier(&profile_timer_exceptions_nb);
  48. synchronize_rcu(); /* Allow already-started NMIs to complete. */
  49. }
  50. static int op_nmi_timer_init(struct oprofile_operations *ops)
  51. {
  52. if (atomic_read(&nmi_active) <= 0)
  53. return -ENODEV;
  54. ops->start = timer_start;
  55. ops->stop = timer_stop;
  56. ops->cpu_type = "timer";
  57. printk(KERN_INFO "oprofile: Using perfctr NMI timer interrupt.\n");
  58. return 0;
  59. }
  60. #endif
  61. int __init oprofile_arch_init(struct oprofile_operations *ops)
  62. {
  63. int ret = -ENODEV;
  64. #ifdef CONFIG_SPARC64
  65. ret = op_nmi_timer_init(ops);
  66. if (!ret)
  67. return ret;
  68. #endif
  69. return ret;
  70. }
  71. void oprofile_arch_exit(void)
  72. {
  73. }