traps.c 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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. static 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. return opcode == TRAPA_BUG_OPCODE;
  28. }
  29. #endif
  30. /*
  31. * Generic trap handler.
  32. */
  33. BUILD_TRAP_HANDLER(debug)
  34. {
  35. TRAP_HANDLER_DECL;
  36. /* Rewind */
  37. regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
  38. if (notify_die(DIE_TRAP, "debug trap", regs, 0, vec & 0xff,
  39. SIGTRAP) == NOTIFY_STOP)
  40. return;
  41. force_sig(SIGTRAP, current);
  42. }
  43. /*
  44. * Special handler for BUG() traps.
  45. */
  46. BUILD_TRAP_HANDLER(bug)
  47. {
  48. TRAP_HANDLER_DECL;
  49. /* Rewind */
  50. regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
  51. if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
  52. SIGTRAP) == NOTIFY_STOP)
  53. return;
  54. #ifdef CONFIG_BUG
  55. if (__kernel_text_address(instruction_pointer(regs))) {
  56. insn_size_t insn = *(insn_size_t *)instruction_pointer(regs);
  57. if (insn == TRAPA_BUG_OPCODE)
  58. handle_BUG(regs);
  59. return;
  60. }
  61. #endif
  62. force_sig(SIGTRAP, current);
  63. }