nmi_debug.c 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2007 Atmel Corporation
  4. */
  5. #include <linux/delay.h>
  6. #include <linux/kdebug.h>
  7. #include <linux/notifier.h>
  8. #include <linux/sched.h>
  9. #include <linux/sched/debug.h>
  10. #include <linux/hardirq.h>
  11. enum nmi_action {
  12. NMI_SHOW_STATE = 1 << 0,
  13. NMI_SHOW_REGS = 1 << 1,
  14. NMI_DIE = 1 << 2,
  15. NMI_DEBOUNCE = 1 << 3,
  16. };
  17. static unsigned long nmi_actions;
  18. static int nmi_debug_notify(struct notifier_block *self,
  19. unsigned long val, void *data)
  20. {
  21. struct die_args *args = data;
  22. if (likely(val != DIE_NMI))
  23. return NOTIFY_DONE;
  24. if (nmi_actions & NMI_SHOW_STATE)
  25. show_state();
  26. if (nmi_actions & NMI_SHOW_REGS)
  27. show_regs(args->regs);
  28. if (nmi_actions & NMI_DEBOUNCE)
  29. mdelay(10);
  30. if (nmi_actions & NMI_DIE)
  31. return NOTIFY_BAD;
  32. return NOTIFY_OK;
  33. }
  34. static struct notifier_block nmi_debug_nb = {
  35. .notifier_call = nmi_debug_notify,
  36. };
  37. static int __init nmi_debug_setup(char *str)
  38. {
  39. char *p, *sep;
  40. register_die_notifier(&nmi_debug_nb);
  41. if (*str != '=')
  42. return 1;
  43. for (p = str + 1; *p; p = sep + 1) {
  44. sep = strchr(p, ',');
  45. if (sep)
  46. *sep = 0;
  47. if (strcmp(p, "state") == 0)
  48. nmi_actions |= NMI_SHOW_STATE;
  49. else if (strcmp(p, "regs") == 0)
  50. nmi_actions |= NMI_SHOW_REGS;
  51. else if (strcmp(p, "debounce") == 0)
  52. nmi_actions |= NMI_DEBOUNCE;
  53. else if (strcmp(p, "die") == 0)
  54. nmi_actions |= NMI_DIE;
  55. else
  56. printk(KERN_WARNING "NMI: Unrecognized action `%s'\n",
  57. p);
  58. if (!sep)
  59. break;
  60. }
  61. return 1;
  62. }
  63. __setup("nmi_debug", nmi_debug_setup);