traps.c 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. unsigned short opcode;
  23. if (addr < PAGE_OFFSET)
  24. return 0;
  25. if (probe_kernel_address((u16 *)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. opcode_t insn = *(opcode_t *)instruction_pointer(regs);
  57. if (insn == TRAPA_BUG_OPCODE)
  58. handle_BUG(regs);
  59. }
  60. #endif
  61. force_sig(SIGTRAP, current);
  62. }