Linux 2.6.31.6
[linux/fpc-iii.git] / arch / ia64 / ia32 / ia32_traps.c
blobe486042672f102f54ce3b847824bbd6ebf1a2412
1 /*
2 * IA-32 exception handlers
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>
8 * 06/16/00 A. Mallick added siginfo for most cases (close to IA32)
9 * 09/29/00 D. Mosberger added ia32_intercept()
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
15 #include "ia32priv.h"
17 #include <asm/intrinsics.h>
18 #include <asm/ptrace.h>
20 int
21 ia32_intercept (struct pt_regs *regs, unsigned long isr)
23 switch ((isr >> 16) & 0xff) {
24 case 0: /* Instruction intercept fault */
25 case 4: /* Locked Data reference fault */
26 case 1: /* Gate intercept trap */
27 return -1;
29 case 2: /* System flag trap */
30 if (((isr >> 14) & 0x3) >= 2) {
31 /* MOV SS, POP SS instructions */
32 ia64_psr(regs)->id = 1;
33 return 0;
34 } else
35 return -1;
37 return -1;
40 int
41 ia32_exception (struct pt_regs *regs, unsigned long isr)
43 struct siginfo siginfo;
45 /* initialize these fields to avoid leaking kernel bits to user space: */
46 siginfo.si_errno = 0;
47 siginfo.si_flags = 0;
48 siginfo.si_isr = 0;
49 siginfo.si_imm = 0;
50 switch ((isr >> 16) & 0xff) {
51 case 1:
52 case 2:
53 siginfo.si_signo = SIGTRAP;
54 if (isr == 0)
55 siginfo.si_code = TRAP_TRACE;
56 else if (isr & 0x4)
57 siginfo.si_code = TRAP_BRANCH;
58 else
59 siginfo.si_code = TRAP_BRKPT;
60 break;
62 case 3:
63 siginfo.si_signo = SIGTRAP;
64 siginfo.si_code = TRAP_BRKPT;
65 break;
67 case 0: /* Divide fault */
68 siginfo.si_signo = SIGFPE;
69 siginfo.si_code = FPE_INTDIV;
70 break;
72 case 4: /* Overflow */
73 case 5: /* Bounds fault */
74 siginfo.si_signo = SIGFPE;
75 siginfo.si_code = 0;
76 break;
78 case 6: /* Invalid Op-code */
79 siginfo.si_signo = SIGILL;
80 siginfo.si_code = ILL_ILLOPN;
81 break;
83 case 7: /* FP DNA */
84 case 8: /* Double Fault */
85 case 9: /* Invalid TSS */
86 case 11: /* Segment not present */
87 case 12: /* Stack fault */
88 case 13: /* General Protection Fault */
89 siginfo.si_signo = SIGSEGV;
90 siginfo.si_code = 0;
91 break;
93 case 16: /* Pending FP error */
95 unsigned long fsr, fcr;
97 fsr = ia64_getreg(_IA64_REG_AR_FSR);
98 fcr = ia64_getreg(_IA64_REG_AR_FCR);
100 siginfo.si_signo = SIGFPE;
102 * (~cwd & swd) will mask out exceptions that are not set to unmasked
103 * status. 0x3f is the exception bits in these regs, 0x200 is the
104 * C1 reg you need in case of a stack fault, 0x040 is the stack
105 * fault bit. We should only be taking one exception at a time,
106 * so if this combination doesn't produce any single exception,
107 * then we have a bad program that isn't synchronizing its FPU usage
108 * and it will suffer the consequences since we won't be able to
109 * fully reproduce the context of the exception
111 siginfo.si_isr = isr;
112 siginfo.si_flags = __ISR_VALID;
113 switch(((~fcr) & (fsr & 0x3f)) | (fsr & 0x240)) {
114 case 0x000:
115 default:
116 siginfo.si_code = 0;
117 break;
118 case 0x001: /* Invalid Op */
119 case 0x040: /* Stack Fault */
120 case 0x240: /* Stack Fault | Direction */
121 siginfo.si_code = FPE_FLTINV;
122 break;
123 case 0x002: /* Denormalize */
124 case 0x010: /* Underflow */
125 siginfo.si_code = FPE_FLTUND;
126 break;
127 case 0x004: /* Zero Divide */
128 siginfo.si_code = FPE_FLTDIV;
129 break;
130 case 0x008: /* Overflow */
131 siginfo.si_code = FPE_FLTOVF;
132 break;
133 case 0x020: /* Precision */
134 siginfo.si_code = FPE_FLTRES;
135 break;
138 break;
141 case 17: /* Alignment check */
142 siginfo.si_signo = SIGSEGV;
143 siginfo.si_code = BUS_ADRALN;
144 break;
146 case 19: /* SSE Numeric error */
147 siginfo.si_signo = SIGFPE;
148 siginfo.si_code = 0;
149 break;
151 default:
152 return -1;
154 force_sig_info(siginfo.si_signo, &siginfo, current);
155 return 0;