traps.c 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #include <linux/bug.h>
  2. #include <linux/io.h>
  3. #include <linux/types.h>
  4. #include <linux/kdebug.h>
  5. #include <linux/signal.h>
  6. #include <linux/sched.h>
  7. #include <linux/uaccess.h>
  8. #include <asm/system.h>
  9. #ifdef CONFIG_BUG
  10. void handle_BUG(struct pt_regs *regs)
  11. {
  12. enum bug_trap_type tt;
  13. tt = report_bug(regs->pc, regs);
  14. if (tt == BUG_TRAP_TYPE_WARN) {
  15. regs->pc += instruction_size(regs->pc);
  16. return;
  17. }
  18. die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
  19. }
  20. int is_valid_bugaddr(unsigned long addr)
  21. {
  22. insn_size_t opcode;
  23. if (addr < PAGE_OFFSET)
  24. return 0;
  25. if (probe_kernel_address((insn_size_t *)addr, opcode))
  26. return 0;
  27. if (opcode == TRAPA_BUG_OPCODE || opcode == TRAPA_UNWINDER_BUG_OPCODE)
  28. return 1;
  29. return 0;
  30. }
  31. #endif
  32. /*
  33. * Generic trap handler.
  34. */
  35. BUILD_TRAP_HANDLER(debug)
  36. {
  37. TRAP_HANDLER_DECL;
  38. /* Rewind */
  39. regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
  40. if (notify_die(DIE_TRAP, "debug trap", regs, 0, vec & 0xff,
  41. SIGTRAP) == NOTIFY_STOP)
  42. return;
  43. force_sig(SIGTRAP, current);
  44. }
  45. /*
  46. * Special handler for BUG() traps.
  47. */
  48. BUILD_TRAP_HANDLER(bug)
  49. {
  50. TRAP_HANDLER_DECL;
  51. /* Rewind */
  52. regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
  53. if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
  54. SIGTRAP) == NOTIFY_STOP)
  55. return;
  56. #ifdef CONFIG_BUG
  57. if (__kernel_text_address(instruction_pointer(regs))) {
  58. insn_size_t insn = *(insn_size_t *)instruction_pointer(regs);
  59. if (insn == TRAPA_BUG_OPCODE)
  60. handle_BUG(regs);
  61. return;
  62. }
  63. #endif
  64. force_sig(SIGTRAP, current);
  65. }