acer-wmi: replaced the hard coded bitmap by the communication devices bitmap from...
[pandora-kernel.git] / arch / m68k / kernel / traps_no.c
1 /*
2  *  linux/arch/m68knommu/kernel/traps.c
3  *
4  *  Copyright (C) 1993, 1994 by Hamish Macdonald
5  *
6  *  68040 fixes by Michael Rausch
7  *  68040 fixes by Martin Apel
8  *  68060 fixes by Roman Hodek
9  *  68060 fixes by Jesper Skov
10  *
11  * This file is subject to the terms and conditions of the GNU General Public
12  * License.  See the file COPYING in the main directory of this archive
13  * for more details.
14  */
15
16 /*
17  * Sets up all exception vectors
18  */
19 #include <linux/sched.h>
20 #include <linux/signal.h>
21 #include <linux/kernel.h>
22 #include <linux/mm.h>
23 #include <linux/module.h>
24 #include <linux/types.h>
25 #include <linux/user.h>
26 #include <linux/string.h>
27 #include <linux/linkage.h>
28 #include <linux/init.h>
29 #include <linux/ptrace.h>
30 #include <linux/kallsyms.h>
31
32 #include <asm/setup.h>
33 #include <asm/fpu.h>
34 #include <asm/system.h>
35 #include <asm/uaccess.h>
36 #include <asm/traps.h>
37 #include <asm/pgtable.h>
38 #include <asm/machdep.h>
39 #include <asm/siginfo.h>
40
41 static char const * const vec_names[] = {
42         "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
43         "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
44         "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
45         "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
46         "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
47         "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
48         "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
49         "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
50         "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
51         "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
52         "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
53         "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
54         "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
55         "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
56         "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
57         "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
58         "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
59         "FPCP UNSUPPORTED OPERATION",
60         "MMU CONFIGURATION ERROR"
61 };
62
63 void die_if_kernel(char *str, struct pt_regs *fp, int nr)
64 {
65         if (!(fp->sr & PS_S))
66                 return;
67
68         console_verbose();
69         printk(KERN_EMERG "%s: %08x\n",str,nr);
70         printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x  SP: %p  a2: %08lx\n",
71                fp->pc, fp->sr, fp, fp->a2);
72         printk(KERN_EMERG "d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
73                fp->d0, fp->d1, fp->d2, fp->d3);
74         printk(KERN_EMERG "d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
75                fp->d4, fp->d5, fp->a0, fp->a1);
76
77         printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
78                 current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
79         show_stack(NULL, (unsigned long *)(fp + 1));
80         add_taint(TAINT_DIE);
81         do_exit(SIGSEGV);
82 }
83
84 asmlinkage void buserr_c(struct frame *fp)
85 {
86         /* Only set esp0 if coming from user mode */
87         if (user_mode(&fp->ptregs))
88                 current->thread.esp0 = (unsigned long) fp;
89
90 #if defined(DEBUG)
91         printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
92 #endif
93
94         die_if_kernel("bad frame format",&fp->ptregs,0);
95 #if defined(DEBUG)
96         printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
97 #endif
98         force_sig(SIGSEGV, current);
99 }
100
101 static void print_this_address(unsigned long addr, int i)
102 {
103 #ifdef CONFIG_KALLSYMS
104         printk(KERN_EMERG " [%08lx] ", addr);
105         print_symbol(KERN_CONT "%s\n", addr);
106 #else
107         if (i % 5)
108                 printk(KERN_CONT " [%08lx] ", addr);
109         else
110                 printk(KERN_EMERG " [%08lx] ", addr);
111         i++;
112 #endif
113 }
114
115 int kstack_depth_to_print = 48;
116
117 static void __show_stack(struct task_struct *task, unsigned long *stack)
118 {
119         unsigned long *endstack, addr;
120 #ifdef CONFIG_FRAME_POINTER
121         unsigned long *last_stack;
122 #endif
123         int i;
124
125         if (!stack)
126                 stack = (unsigned long *)task->thread.ksp;
127
128         addr = (unsigned long) stack;
129         endstack = (unsigned long *) PAGE_ALIGN(addr);
130
131         printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
132         for (i = 0; i < kstack_depth_to_print; i++) {
133                 if (stack + 1 + i > endstack)
134                         break;
135                 if (i % 8 == 0)
136                         printk(KERN_EMERG "       ");
137                 printk(KERN_CONT " %08lx", *(stack + i));
138         }
139         printk("\n");
140         i = 0;
141
142 #ifdef CONFIG_FRAME_POINTER
143         printk(KERN_EMERG "Call Trace:\n");
144
145         last_stack = stack - 1;
146         while (stack <= endstack && stack > last_stack) {
147
148                 addr = *(stack + 1);
149                 print_this_address(addr, i);
150                 i++;
151
152                 last_stack = stack;
153                 stack = (unsigned long *)*stack;
154         }
155         printk("\n");
156 #else
157         printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
158         while (stack <= endstack) {
159                 addr = *stack++;
160                 /*
161                  * If the address is either in the text segment of the kernel,
162                  * or in a region which is occupied by a module then it *may*
163                  * be the address of a calling routine; if so, print it so that
164                  * someone tracing down the cause of the crash will be able to
165                  * figure out the call path that was taken.
166                  */
167                 if (__kernel_text_address(addr)) {
168                         print_this_address(addr, i);
169                         i++;
170                 }
171         }
172         printk(KERN_CONT "\n");
173 #endif
174 }
175
176 void bad_super_trap(struct frame *fp)
177 {
178         int vector = (fp->ptregs.vector >> 2) & 0xff;
179
180         console_verbose();
181         if (vector < ARRAY_SIZE(vec_names))
182                 printk (KERN_WARNING "*** %s ***   FORMAT=%X\n",
183                         vec_names[vector],
184                         fp->ptregs.format);
185         else
186                 printk (KERN_WARNING "*** Exception %d ***   FORMAT=%X\n",
187                         vector,
188                         fp->ptregs.format);
189         printk (KERN_WARNING "Current process id is %d\n", current->pid);
190         die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
191 }
192
193 asmlinkage void trap_c(struct frame *fp)
194 {
195         int sig;
196         int vector = (fp->ptregs.vector >> 2) & 0xff;
197         siginfo_t info;
198
199         if (fp->ptregs.sr & PS_S) {
200                 if (vector == VEC_TRACE) {
201                         /* traced a trapping instruction */
202                 } else
203                         bad_super_trap(fp);
204                 return;
205         }
206
207         /* send the appropriate signal to the user program */
208         switch (vector) {
209             case VEC_ADDRERR:
210                 info.si_code = BUS_ADRALN;
211                 sig = SIGBUS;
212                 break;
213             case VEC_ILLEGAL:
214             case VEC_LINE10:
215             case VEC_LINE11:
216                 info.si_code = ILL_ILLOPC;
217                 sig = SIGILL;
218                 break;
219             case VEC_PRIV:
220                 info.si_code = ILL_PRVOPC;
221                 sig = SIGILL;
222                 break;
223             case VEC_COPROC:
224                 info.si_code = ILL_COPROC;
225                 sig = SIGILL;
226                 break;
227             case VEC_TRAP1: /* gdbserver breakpoint */
228                 fp->ptregs.pc -= 2;
229                 info.si_code = TRAP_TRACE;
230                 sig = SIGTRAP;
231                 break;
232             case VEC_TRAP2:
233             case VEC_TRAP3:
234             case VEC_TRAP4:
235             case VEC_TRAP5:
236             case VEC_TRAP6:
237             case VEC_TRAP7:
238             case VEC_TRAP8:
239             case VEC_TRAP9:
240             case VEC_TRAP10:
241             case VEC_TRAP11:
242             case VEC_TRAP12:
243             case VEC_TRAP13:
244             case VEC_TRAP14:
245                 info.si_code = ILL_ILLTRP;
246                 sig = SIGILL;
247                 break;
248             case VEC_FPBRUC:
249             case VEC_FPOE:
250             case VEC_FPNAN:
251                 info.si_code = FPE_FLTINV;
252                 sig = SIGFPE;
253                 break;
254             case VEC_FPIR:
255                 info.si_code = FPE_FLTRES;
256                 sig = SIGFPE;
257                 break;
258             case VEC_FPDIVZ:
259                 info.si_code = FPE_FLTDIV;
260                 sig = SIGFPE;
261                 break;
262             case VEC_FPUNDER:
263                 info.si_code = FPE_FLTUND;
264                 sig = SIGFPE;
265                 break;
266             case VEC_FPOVER:
267                 info.si_code = FPE_FLTOVF;
268                 sig = SIGFPE;
269                 break;
270             case VEC_ZERODIV:
271                 info.si_code = FPE_INTDIV;
272                 sig = SIGFPE;
273                 break;
274             case VEC_CHK:
275             case VEC_TRAP:
276                 info.si_code = FPE_INTOVF;
277                 sig = SIGFPE;
278                 break;
279             case VEC_TRACE:             /* ptrace single step */
280                 info.si_code = TRAP_TRACE;
281                 sig = SIGTRAP;
282                 break;
283             case VEC_TRAP15:            /* breakpoint */
284                 info.si_code = TRAP_BRKPT;
285                 sig = SIGTRAP;
286                 break;
287             default:
288                 info.si_code = ILL_ILLOPC;
289                 sig = SIGILL;
290                 break;
291         }
292         info.si_signo = sig;
293         info.si_errno = 0;
294         switch (fp->ptregs.format) {
295             default:
296                 info.si_addr = (void *) fp->ptregs.pc;
297                 break;
298             case 2:
299                 info.si_addr = (void *) fp->un.fmt2.iaddr;
300                 break;
301             case 7:
302                 info.si_addr = (void *) fp->un.fmt7.effaddr;
303                 break;
304             case 9:
305                 info.si_addr = (void *) fp->un.fmt9.iaddr;
306                 break;
307             case 10:
308                 info.si_addr = (void *) fp->un.fmta.daddr;
309                 break;
310             case 11:
311                 info.si_addr = (void *) fp->un.fmtb.daddr;
312                 break;
313         }
314         force_sig_info (sig, &info, current);
315 }
316
317 asmlinkage void set_esp0(unsigned long ssp)
318 {
319         current->thread.esp0 = ssp;
320 }
321
322 /*
323  * The architecture-independent backtrace generator
324  */
325 void dump_stack(void)
326 {
327         /*
328          * We need frame pointers for this little trick, which works as follows:
329          *
330          * +------------+ 0x00
331          * | Next SP    |       -> 0x0c
332          * +------------+ 0x04
333          * | Caller     |
334          * +------------+ 0x08
335          * | Local vars |       -> our stack var
336          * +------------+ 0x0c
337          * | Next SP    |       -> 0x18, that is what we pass to show_stack()
338          * +------------+ 0x10
339          * | Caller     |
340          * +------------+ 0x14
341          * | Local vars |
342          * +------------+ 0x18
343          * | ...        |
344          * +------------+
345          */
346
347         unsigned long *stack;
348
349         stack = (unsigned long *)&stack;
350         stack++;
351         __show_stack(current, stack);
352 }
353 EXPORT_SYMBOL(dump_stack);
354
355 void show_stack(struct task_struct *task, unsigned long *stack)
356 {
357         if (!stack && !task)
358                 dump_stack();
359         else
360                 __show_stack(task, stack);
361 }