ia32_traps.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

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-2002 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 4: /* 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. /* initialize these fields to avoid leaking kernel bits to user space: */
  38. siginfo.si_errno = 0;
  39. siginfo.si_flags = 0;
  40. siginfo.si_isr = 0;
  41. siginfo.si_imm = 0;
  42. switch ((isr >> 16) & 0xff) {
  43.       case 1:
  44.       case 2:
  45. siginfo.si_signo = SIGTRAP;
  46. if (isr == 0)
  47. siginfo.si_code = TRAP_TRACE;
  48. else if (isr & 0x4)
  49. siginfo.si_code = TRAP_BRANCH;
  50. else
  51. siginfo.si_code = TRAP_BRKPT;
  52. break;
  53.       case 3:
  54. siginfo.si_signo = SIGTRAP;
  55. siginfo.si_code = TRAP_BRKPT;
  56. break;
  57.       case 0: /* Divide fault */
  58. siginfo.si_signo = SIGFPE;
  59. siginfo.si_code = FPE_INTDIV;
  60. break;
  61.       case 4: /* Overflow */
  62.       case 5: /* Bounds fault */
  63. siginfo.si_signo = SIGFPE;
  64. siginfo.si_code = 0;
  65. break;
  66.       case 6: /* Invalid Op-code */
  67. siginfo.si_signo = SIGILL;
  68. siginfo.si_code = ILL_ILLOPN;
  69. break;
  70.       case 7: /* FP DNA */
  71.       case 8: /* Double Fault */
  72.       case 9: /* Invalid TSS */
  73.       case 11: /* Segment not present */
  74.       case 12: /* Stack fault */
  75.       case 13: /* General Protection Fault */
  76. siginfo.si_signo = SIGSEGV;
  77. siginfo.si_code = 0;
  78. break;
  79.       case 16: /* Pending FP error */
  80. {
  81. unsigned long fsr, fcr;
  82. asm ("mov %0=ar.fsr;"
  83.      "mov %1=ar.fcr;"
  84.      : "=r"(fsr), "=r"(fcr));
  85. siginfo.si_signo = SIGFPE;
  86. /*
  87.  * (~cwd & swd) will mask out exceptions that are not set to unmasked
  88.  * status.  0x3f is the exception bits in these regs, 0x200 is the
  89.  * C1 reg you need in case of a stack fault, 0x040 is the stack
  90.  * fault bit.  We should only be taking one exception at a time,
  91.  * so if this combination doesn't produce any single exception,
  92.  * then we have a bad program that isn't syncronizing its FPU usage
  93.  * and it will suffer the consequences since we won't be able to
  94.  * fully reproduce the context of the exception
  95.  */
  96. siginfo.si_isr = isr;
  97. siginfo.si_flags = __ISR_VALID;
  98. switch(((~fcr) & (fsr & 0x3f)) | (fsr & 0x240)) {
  99. case 0x000:
  100. default:
  101. siginfo.si_code = 0;
  102. break;
  103. case 0x001: /* Invalid Op */
  104. case 0x040: /* Stack Fault */
  105. case 0x240: /* Stack Fault | Direction */
  106. siginfo.si_code = FPE_FLTINV;
  107. break;
  108. case 0x002: /* Denormalize */
  109. case 0x010: /* Underflow */
  110. siginfo.si_code = FPE_FLTUND;
  111. break;
  112. case 0x004: /* Zero Divide */
  113. siginfo.si_code = FPE_FLTDIV;
  114. break;
  115. case 0x008: /* Overflow */
  116. siginfo.si_code = FPE_FLTOVF;
  117. break;
  118. case 0x020: /* Precision */
  119. siginfo.si_code = FPE_FLTRES;
  120. break;
  121. }
  122. break;
  123. }
  124.       case 17: /* Alignment check */
  125. siginfo.si_signo = SIGSEGV;
  126. siginfo.si_code = BUS_ADRALN;
  127. break;
  128.       case 19: /* SSE Numeric error */
  129. siginfo.si_signo = SIGFPE;
  130. siginfo.si_code = 0;
  131. break;
  132.       default:
  133. return -1;
  134. }
  135. force_sig_info(siginfo.si_signo, &siginfo, current);
  136. return 0;
  137. }