ia32_traps.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * IA-32 exception handlers
  3.  *
  4.  * Copyright (C) 2000 Asit K. Mallick <asit.k.mallick@intel.com>
  5.  * Copyright (C) 2001 Hewlett-Packard Co
  6.  * David Mosberger-Tang <davidm@hpl.hp.com>
  7.  *
  8.  * 06/16/00 A. Mallick added siginfo for most cases (close to IA32)
  9.  * 09/29/00 D. Mosberger added ia32_intercept()
  10.  */
  11. #include <linux/kernel.h>
  12. #include <linux/sched.h>
  13. #include <asm/ia32.h>
  14. #include <asm/ptrace.h>
  15. int
  16. ia32_intercept (struct pt_regs *regs, unsigned long isr)
  17. {
  18. switch ((isr >> 16) & 0xff) {
  19.       case 0: /* Instruction intercept fault */
  20.       case 3: /* Locked Data reference fault */
  21.       case 1: /* Gate intercept trap */
  22. return -1;
  23.       case 2: /* System flag trap */
  24. if (((isr >> 14) & 0x3) >= 2) {
  25. /* MOV SS, POP SS instructions */
  26. ia64_psr(regs)->id = 1;
  27. return 0;
  28. } else
  29. return -1;
  30. }
  31. return -1;
  32. }
  33. int
  34. ia32_exception (struct pt_regs *regs, unsigned long isr)
  35. {
  36. struct siginfo siginfo;
  37. siginfo.si_errno = 0;
  38. switch ((isr >> 16) & 0xff) {
  39.       case 1:
  40.       case 2:
  41. siginfo.si_signo = SIGTRAP;
  42. if (isr == 0)
  43. siginfo.si_code = TRAP_TRACE;
  44. else if (isr & 0x4)
  45. siginfo.si_code = TRAP_BRANCH;
  46. else
  47. siginfo.si_code = TRAP_BRKPT;
  48. break;
  49.       case 3:
  50. siginfo.si_signo = SIGTRAP;
  51. siginfo.si_code = TRAP_BRKPT;
  52. break;
  53.       case 0: /* Divide fault */
  54. siginfo.si_signo = SIGFPE;
  55. siginfo.si_code = FPE_INTDIV;
  56. break;
  57.       case 4: /* Overflow */
  58.       case 5: /* Bounds fault */
  59. siginfo.si_signo = SIGFPE;
  60. siginfo.si_code = 0;
  61. break;
  62.       case 6: /* Invalid Op-code */
  63. siginfo.si_signo = SIGILL;
  64. siginfo.si_code = ILL_ILLOPN;
  65. break;
  66.       case 7: /* FP DNA */
  67.       case 8: /* Double Fault */
  68.       case 9: /* Invalid TSS */
  69.       case 11: /* Segment not present */
  70.       case 12: /* Stack fault */
  71.       case 13: /* General Protection Fault */
  72. siginfo.si_signo = SIGSEGV;
  73. siginfo.si_code = 0;
  74. break;
  75.       case 16: /* Pending FP error */
  76. {
  77. unsigned long fsr, fcr;
  78. asm ("mov %0=ar.fsr;"
  79.      "mov %1=ar.fcr;"
  80.      : "=r"(fsr), "=r"(fcr));
  81. siginfo.si_signo = SIGFPE;
  82. /*
  83.  * (~cwd & swd) will mask out exceptions that are not set to unmasked
  84.  * status.  0x3f is the exception bits in these regs, 0x200 is the
  85.  * C1 reg you need in case of a stack fault, 0x040 is the stack
  86.  * fault bit.  We should only be taking one exception at a time,
  87.  * so if this combination doesn't produce any single exception,
  88.  * then we have a bad program that isn't syncronizing its FPU usage
  89.  * and it will suffer the consequences since we won't be able to
  90.  * fully reproduce the context of the exception
  91.  */
  92. switch(((~fcr) & (fsr & 0x3f)) | (fsr & 0x240)) {
  93. case 0x000:
  94. default:
  95. siginfo.si_code = 0;
  96. break;
  97. case 0x001: /* Invalid Op */
  98. case 0x040: /* Stack Fault */
  99. case 0x240: /* Stack Fault | Direction */
  100. siginfo.si_code = FPE_FLTINV;
  101. break;
  102. case 0x002: /* Denormalize */
  103. case 0x010: /* Underflow */
  104. siginfo.si_code = FPE_FLTUND;
  105. break;
  106. case 0x004: /* Zero Divide */
  107. siginfo.si_code = FPE_FLTDIV;
  108. break;
  109. case 0x008: /* Overflow */
  110. siginfo.si_code = FPE_FLTOVF;
  111. break;
  112. case 0x020: /* Precision */
  113. siginfo.si_code = FPE_FLTRES;
  114. break;
  115. }
  116. break;
  117. }
  118.       case 17: /* Alignment check */
  119. siginfo.si_signo = SIGSEGV;
  120. siginfo.si_code = BUS_ADRALN;
  121. break;
  122.       case 19: /* SSE Numeric error */
  123. siginfo.si_signo = SIGFPE;
  124. siginfo.si_code = 0;
  125. break;
  126.       default:
  127. return -1;
  128. }
  129. force_sig_info(siginfo.si_signo, &siginfo, current);
  130. return 0;
  131. }