x86: Fix spelling error in the memcpy() source code comment
[pandora-kernel.git] / arch / m68knommu / kernel / traps.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 __init trap_init(void)
64 {
65 }
66
67 void die_if_kernel(char *str, struct pt_regs *fp, int nr)
68 {
69         if (!(fp->sr & PS_S))
70                 return;
71
72         console_verbose();
73         printk(KERN_EMERG "%s: %08x\n",str,nr);
74         printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x  SP: %p  a2: %08lx\n",
75                fp->pc, fp->sr, fp, fp->a2);
76         printk(KERN_EMERG "d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
77                fp->d0, fp->d1, fp->d2, fp->d3);
78         printk(KERN_EMERG "d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
79                fp->d4, fp->d5, fp->a0, fp->a1);
80
81         printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
82                 current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
83         show_stack(NULL, (unsigned long *)(fp + 1));
84         add_taint(TAINT_DIE);
85         do_exit(SIGSEGV);
86 }
87
88 asmlinkage void buserr_c(struct frame *fp)
89 {
90         /* Only set esp0 if coming from user mode */
91         if (user_mode(&fp->ptregs))
92                 current->thread.esp0 = (unsigned long) fp;
93
94 #if defined(DEBUG)
95         printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
96 #endif
97
98         die_if_kernel("bad frame format",&fp->ptregs,0);
99 #if defined(DEBUG)
100         printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
101 #endif
102         force_sig(SIGSEGV, current);
103 }
104
105 static void print_this_address(unsigned long addr, int i)
106 {
107 #ifdef CONFIG_KALLSYMS
108         printk(KERN_EMERG " [%08lx] ", addr);
109         print_symbol(KERN_CONT "%s\n", addr);
110 #else
111         if (i % 5)
112                 printk(KERN_CONT " [%08lx] ", addr);
113         else
114                 printk(KERN_EMERG " [%08lx] ", addr);
115         i++;
116 #endif
117 }
118
119 int kstack_depth_to_print = 48;
120
121 static void __show_stack(struct task_struct *task, unsigned long *stack)
122 {
123         unsigned long *endstack, addr;
124 #ifdef CONFIG_FRAME_POINTER
125         unsigned long *last_stack;
126 #endif
127         int i;
128
129         if (!stack)
130                 stack = (unsigned long *)task->thread.ksp;
131
132         addr = (unsigned long) stack;
133         endstack = (unsigned long *) PAGE_ALIGN(addr);
134
135         printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
136         for (i = 0; i < kstack_depth_to_print; i++) {
137                 if (stack + 1 + i > endstack)
138                         break;
139                 if (i % 8 == 0)
140                         printk(KERN_EMERG "       ");
141                 printk(KERN_CONT " %08lx", *(stack + i));
142         }
143         printk("\n");
144         i = 0;
145
146 #ifdef CONFIG_FRAME_POINTER
147         printk(KERN_EMERG "Call Trace:\n");
148
149         last_stack = stack - 1;
150         while (stack <= endstack && stack > last_stack) {
151
152                 addr = *(stack + 1);
153                 print_this_address(addr, i);
154                 i++;
155
156                 last_stack = stack;
157                 stack = (unsigned long *)*stack;
158         }
159         printk("\n");
160 #else
161         printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
162         while (stack <= endstack) {
163                 addr = *stack++;
164                 /*
165                  * If the address is either in the text segment of the kernel,
166                  * or in a region which is occupied by a module then it *may*
167                  * be the address of a calling routine; if so, print it so that
168                  * someone tracing down the cause of the crash will be able to
169                  * figure out the call path that was taken.
170                  */
171                 if (__kernel_text_address(addr)) {
172                         print_this_address(addr, i);
173                         i++;
174                 }
175         }
176         printk(KERN_CONT "\n");
177 #endif
178 }
179
180 void bad_super_trap(struct frame *fp)
181 {
182         int vector = (fp->ptregs.vector >> 2) & 0xff;
183
184         console_verbose();
185         if (vector < ARRAY_SIZE(vec_names))
186                 printk (KERN_WARNING "*** %s ***   FORMAT=%X\n",
187                         vec_names[vector],
188                         fp->ptregs.format);
189         else
190                 printk (KERN_WARNING "*** Exception %d ***   FORMAT=%X\n",
191                         vector,
192                         fp->ptregs.format);
193         printk (KERN_WARNING "Current process id is %d\n", current->pid);
194         die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
195 }
196
197 asmlinkage void trap_c(struct frame *fp)
198 {
199         int sig;
200         int vector = (fp->ptregs.vector >> 2) & 0xff;
201         siginfo_t info;
202
203         if (fp->ptregs.sr & PS_S) {
204                 if (vector == VEC_TRACE) {
205                         /* traced a trapping instruction */
206                 } else
207                         bad_super_trap(fp);
208                 return;
209         }
210
211         /* send the appropriate signal to the user program */
212         switch (vector) {
213             case VEC_ADDRERR:
214                 info.si_code = BUS_ADRALN;
215                 sig = SIGBUS;
216                 break;
217             case VEC_ILLEGAL:
218             case VEC_LINE10:
219             case VEC_LINE11:
220                 info.si_code = ILL_ILLOPC;
221                 sig = SIGILL;
222                 break;
223             case VEC_PRIV:
224                 info.si_code = ILL_PRVOPC;
225                 sig = SIGILL;
226                 break;
227             case VEC_COPROC:
228                 info.si_code = ILL_COPROC;
229                 sig = SIGILL;
230                 break;
231             case VEC_TRAP1: /* gdbserver breakpoint */
232                 fp->ptregs.pc -= 2;
233                 info.si_code = TRAP_TRACE;
234                 sig = SIGTRAP;
235                 break;
236             case VEC_TRAP2:
237             case VEC_TRAP3:
238             case VEC_TRAP4:
239             case VEC_TRAP5:
240             case VEC_TRAP6:
241             case VEC_TRAP7:
242             case VEC_TRAP8:
243             case VEC_TRAP9:
244             case VEC_TRAP10:
245             case VEC_TRAP11:
246             case VEC_TRAP12:
247             case VEC_TRAP13:
248             case VEC_TRAP14:
249                 info.si_code = ILL_ILLTRP;
250                 sig = SIGILL;
251                 break;
252             case VEC_FPBRUC:
253             case VEC_FPOE:
254             case VEC_FPNAN:
255                 info.si_code = FPE_FLTINV;
256                 sig = SIGFPE;
257                 break;
258             case VEC_FPIR:
259                 info.si_code = FPE_FLTRES;
260                 sig = SIGFPE;
261                 break;
262             case VEC_FPDIVZ:
263                 info.si_code = FPE_FLTDIV;
264                 sig = SIGFPE;
265                 break;
266             case VEC_FPUNDER:
267                 info.si_code = FPE_FLTUND;
268                 sig = SIGFPE;
269                 break;
270             case VEC_FPOVER:
271                 info.si_code = FPE_FLTOVF;
272                 sig = SIGFPE;
273                 break;
274             case VEC_ZERODIV:
275                 info.si_code = FPE_INTDIV;
276                 sig = SIGFPE;
277                 break;
278             case VEC_CHK:
279             case VEC_TRAP:
280                 info.si_code = FPE_INTOVF;
281                 sig = SIGFPE;
282                 break;
283             case VEC_TRACE:             /* ptrace single step */
284                 info.si_code = TRAP_TRACE;
285                 sig = SIGTRAP;
286                 break;
287             case VEC_TRAP15:            /* breakpoint */
288                 info.si_code = TRAP_BRKPT;
289                 sig = SIGTRAP;
290                 break;
291             default:
292                 info.si_code = ILL_ILLOPC;
293                 sig = SIGILL;
294                 break;
295         }
296         info.si_signo = sig;
297         info.si_errno = 0;
298         switch (fp->ptregs.format) {
299             default:
300                 info.si_addr = (void *) fp->ptregs.pc;
301                 break;
302             case 2:
303                 info.si_addr = (void *) fp->un.fmt2.iaddr;
304                 break;
305             case 7:
306                 info.si_addr = (void *) fp->un.fmt7.effaddr;
307                 break;
308             case 9:
309                 info.si_addr = (void *) fp->un.fmt9.iaddr;
310                 break;
311             case 10:
312                 info.si_addr = (void *) fp->un.fmta.daddr;
313                 break;
314             case 11:
315                 info.si_addr = (void *) fp->un.fmtb.daddr;
316                 break;
317         }
318         force_sig_info (sig, &info, current);
319 }
320
321 asmlinkage void set_esp0(unsigned long ssp)
322 {
323         current->thread.esp0 = ssp;
324 }
325
326 /*
327  * The architecture-independent backtrace generator
328  */
329 void dump_stack(void)
330 {
331         /*
332          * We need frame pointers for this little trick, which works as follows:
333          *
334          * +------------+ 0x00
335          * | Next SP    |       -> 0x0c
336          * +------------+ 0x04
337          * | Caller     |
338          * +------------+ 0x08
339          * | Local vars |       -> our stack var
340          * +------------+ 0x0c
341          * | Next SP    |       -> 0x18, that is what we pass to show_stack()
342          * +------------+ 0x10
343          * | Caller     |
344          * +------------+ 0x14
345          * | Local vars |
346          * +------------+ 0x18
347          * | ...        |
348          * +------------+
349          */
350
351         unsigned long *stack;
352
353         stack = (unsigned long *)&stack;
354         stack++;
355         __show_stack(current, stack);
356 }
357 EXPORT_SYMBOL(dump_stack);
358
359 void show_stack(struct task_struct *task, unsigned long *stack)
360 {
361         if (!stack && !task)
362                 dump_stack();
363         else
364                 __show_stack(task, stack);
365 }