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