relayd: move the interface fixup to the right place
[oweals/openwrt.git] / target / linux / coldfire / files-2.6.31 / arch / m68k / coldfire / common / traps.c
1 /*
2  *  linux/arch/m68knommu/kernel/traps.c
3  *
4  *  Copyright Freescale Semiconductor, Inc. 2008-2009
5  *  Jason Jin Jason.Jin@freescale.com
6  *  Shrek Wu B16972@freescale.com
7  *
8  *  This file is subject to the terms and conditions of the GNU General Public
9  *  License.  See the file COPYING in the main directory of this archive
10  *  for more details.
11  */
12
13 /*
14  * Sets up all exception vectors
15  */
16 #include <linux/sched.h>
17 #include <linux/signal.h>
18 #include <linux/kernel.h>
19 #include <linux/mm.h>
20 #include <linux/module.h>
21 #include <linux/types.h>
22 #include <linux/a.out.h>
23 #include <linux/user.h>
24 #include <linux/string.h>
25 #include <linux/linkage.h>
26 #include <linux/init.h>
27 #include <linux/ptrace.h>
28 #include <linux/kallsyms.h>
29
30 #include <asm/setup.h>
31 #include <asm/fpu.h>
32 #include <asm/system.h>
33 #include <asm/uaccess.h>
34 #include <asm/traps.h>
35 #include <asm/pgtable.h>
36 #include <asm/machdep.h>
37 #include <asm/siginfo.h>
38
39 static char const * const vec_names[] = {
40         "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
41         "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
42         "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
43         "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
44         "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
45         "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
46         "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
47         "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
48         "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
49         "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
50         "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
51         "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
52         "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
53         "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
54         "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
55         "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
56         "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
57         "FPCP UNSUPPORTED OPERATION",
58         "MMU CONFIGURATION ERROR"
59 };
60
61 asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
62                              unsigned long error_code);
63 asmlinkage void trap_c(struct frame *fp);
64 extern void __init coldfire_trap_init(void);
65
66 void __init trap_init(void)
67 {
68         coldfire_trap_init();
69 }
70
71 /* The following table converts the FS encoding of a ColdFire
72    exception stack frame into the error_code value needed by
73    do_fault. */
74
75 static const unsigned char fs_err_code[] = {
76         0,  /* 0000 */
77         0,  /* 0001 */
78         0,  /* 0010 */
79         0,  /* 0011 */
80         1,  /* 0100 */
81         0,  /* 0101 */
82         0,  /* 0110 */
83         0,  /* 0111 */
84         2,  /* 1000 */
85         3,  /* 1001 */
86         2,  /* 1010 */
87         0,  /* 1011 */
88         1,  /* 1100 */
89         1,  /* 1101 */
90         0,  /* 1110 */
91         0   /* 1111 */
92 };
93
94 #ifdef DEBUG
95 static const char *fs_err_msg[16] = {
96         "Normal",
97         "Reserved",
98         "Interrupt during debug service routine",
99         "Reserved",
100         "X Protection",
101         "TLB X miss (opword)",
102         "TLB X miss (ext. word)",
103         "IFP in emulator mode",
104         "W Protection",
105         "Write error",
106         "TLB W miss",
107         "Reserved",
108         "R Protection",
109         "R/RMW Protection",
110         "TLB R miss",
111         "OEP in emulator mode",
112 };
113 #endif
114
115 static inline void access_errorCF(struct frame *fp)
116 {
117         unsigned long int mmusr, complainingAddress;
118         unsigned int err_code, fs;
119         int need_page_fault;
120
121         mmusr = fp->ptregs.mmusr;
122         complainingAddress = fp->ptregs.mmuar;
123 #ifdef DEBUG
124         printk(KERN_DEBUG "pc %#lx, mmusr %#lx, complainingAddress %#lx\n", \
125                 fp->ptregs.pc, mmusr, complainingAddress);
126 #endif
127
128         /*
129          * error_code:
130          *      bit 0 == 0 means no page found, 1 means protection fault
131          *      bit 1 == 0 means read, 1 means write
132          */
133
134         fs = (fp->ptregs.fs2 << 2) | fp->ptregs.fs1;
135         switch (fs) {
136         case  5:  /* 0101 TLB opword X miss */
137                 need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 0);
138                 complainingAddress = fp->ptregs.pc;
139                 break;
140         case  6:  /* 0110 TLB extension word X miss */
141                 need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 1);
142                 complainingAddress = fp->ptregs.pc + sizeof(long);
143                 break;
144         case 10:  /* 1010 TLB W miss */
145                 need_page_fault = cf_tlb_miss(&fp->ptregs, 1, 1, 0);
146                 break;
147         case 14: /* 1110 TLB R miss */
148                 need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 1, 0);
149                 break;
150         default:
151                 /* 0000 Normal  */
152                 /* 0001 Reserved */
153                 /* 0010 Interrupt during debug service routine */
154                 /* 0011 Reserved */
155                 /* 0100 X Protection */
156                 /* 0111 IFP in emulator mode */
157                 /* 1000 W Protection*/
158                 /* 1001 Write error*/
159                 /* 1011 Reserved*/
160                 /* 1100 R Protection*/
161                 /* 1101 R Protection*/
162                 /* 1111 OEP in emulator mode*/
163                 need_page_fault = 1;
164                 break;
165         }
166
167         if (need_page_fault) {
168                 err_code = fs_err_code[fs];
169                 if ((fs == 13) && (mmusr & MMUSR_WF)) /* rd-mod-wr access */
170                         err_code |= 2; /* bit1 - write, bit0 - protection */
171                 do_page_fault(&fp->ptregs, complainingAddress, err_code);
172         }
173 }
174
175 void die_if_kernel(char *str, struct pt_regs *fp, int nr)
176 {
177         if (!(fp->sr & PS_S))
178                 return;
179
180         console_verbose();
181         printk(KERN_EMERG "%s: %08x\n", str, nr);
182         printk(KERN_EMERG "PC: [<%08lx>]", fp->pc);
183         print_symbol(" %s", fp->pc);
184         printk(KERN_EMERG "\nSR: %04x  SP: %p  a2: %08lx\n",
185                fp->sr, fp, fp->a2);
186         printk(KERN_EMERG "d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
187                fp->d0, fp->d1, fp->d2, fp->d3);
188         printk(KERN_EMERG "d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
189                fp->d4, fp->d5, fp->a0, fp->a1);
190
191         printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
192                 current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
193         show_stack(NULL, (unsigned long *)fp);
194         do_exit(SIGSEGV);
195 }
196
197 asmlinkage void buserr_c(struct frame *fp)
198 {
199         unsigned int fs;
200
201         /* Only set esp0 if coming from user mode */
202         if (user_mode(&fp->ptregs))
203                 current->thread.esp0 = (unsigned long) fp;
204
205         fs = (fp->ptregs.fs2 << 2) | fp->ptregs.fs1;
206 #if defined(DEBUG)
207         printk(KERN_DEBUG "*** Bus Error *** (%x)%s\n", fs,
208                 fs_err_msg[fs & 0xf]);
209 #endif
210         switch (fs) {
211         case 0x5:
212         case 0x6:
213         case 0x7:
214         case 0x9:
215         case 0xa:
216         case 0xd:
217         case 0xe:
218         case 0xf:
219                 access_errorCF(fp);
220                 break;
221         default:
222                 die_if_kernel("bad frame format", &fp->ptregs, 0);
223 #if defined(DEBUG)
224                 printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
225 #endif
226                 force_sig(SIGSEGV, current);
227         }
228 }
229
230 void show_trace(unsigned long *stack)
231 {
232         unsigned long *endstack;
233         unsigned long addr;
234         int i;
235
236         printk("Call Trace:");
237         addr = (unsigned long)stack + THREAD_SIZE - 1;
238         endstack = (unsigned long *)(addr & -THREAD_SIZE);
239         i = 0;
240         while (stack + 1 <= endstack) {
241                 addr = *stack++;
242                 /*
243                  * If the address is either in the text segment of the
244                  * kernel, or in the region which contains vmalloc'ed
245                  * memory, it *may* be the address of a calling
246                  * routine; if so, print it so that someone tracing
247                  * down the cause of the crash will be able to figure
248                  * out the call path that was taken.
249                  */
250                 if (__kernel_text_address(addr)) {
251 #ifndef CONFIG_KALLSYMS
252                         if (i % 5 == 0)
253                                 printk("\n       ");
254 #endif
255                         printk(" [<%08lx>] %pS\n", addr, (void *)addr);
256                         i++;
257                 }
258         }
259         printk("\n");
260 }
261
262 int kstack_depth_to_print = 48;
263 void show_stack(struct task_struct *task, unsigned long *stack)
264 {
265         unsigned long *p;
266         unsigned long *endstack;
267         int i;
268
269         if (!stack) {
270                 if (task)
271                         stack = (unsigned long *)task->thread.esp0;
272                 else
273                         stack = (unsigned long *)&stack;
274         }
275         endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
276
277         printk("Stack from %08lx:", (unsigned long)stack);
278         p = stack;
279         for (i = 0; i < kstack_depth_to_print; i++) {
280                 if (p + 1 > endstack)
281                         break;
282                 if (i % 8 == 0)
283                         printk("\n       ");
284                 printk(" %08lx", *p++);
285         }
286         printk("\n");
287         show_trace(stack);
288 }
289
290 void bad_super_trap(struct frame *fp)
291 {
292         console_verbose();
293         if (fp->ptregs.vector < sizeof(vec_names)/sizeof(vec_names[0]))
294                 printk(KERN_WARNING "*** %s ***   FORMAT=%X\n",
295                         vec_names[fp->ptregs.vector],
296                         fp->ptregs.format);
297         else
298                 printk(KERN_WARNING "*** Exception %d ***   FORMAT=%X\n",
299                         fp->ptregs.vector,
300                         fp->ptregs.format);
301         printk(KERN_WARNING "Current process id is %d\n", current->pid);
302         die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
303 }
304
305 asmlinkage void trap_c(struct frame *fp)
306 {
307         int sig;
308         siginfo_t info;
309
310         if (fp->ptregs.sr & PS_S) {
311                 if (fp->ptregs.vector == VEC_TRACE) {
312                         /* traced a trapping instruction */
313                         current->ptrace |= PT_DTRACE;
314                 } else
315                         bad_super_trap(fp);
316                 return;
317         }
318
319         /* send the appropriate signal to the user program */
320         switch (fp->ptregs.vector) {
321         case VEC_ADDRERR:
322                 info.si_code = BUS_ADRALN;
323                 sig = SIGBUS;
324                 break;
325         case VEC_ILLEGAL:
326         case VEC_LINE10:
327         case VEC_LINE11:
328                 info.si_code = ILL_ILLOPC;
329                 sig = SIGILL;
330                 break;
331         case VEC_PRIV:
332                 info.si_code = ILL_PRVOPC;
333                 sig = SIGILL;
334                 break;
335         case VEC_COPROC:
336                 info.si_code = ILL_COPROC;
337                 sig = SIGILL;
338                 break;
339         case VEC_TRAP1: /* gdbserver breakpoint */
340                 fp->ptregs.pc -= 2;
341                 info.si_code = TRAP_TRACE;
342                 sig = SIGTRAP;
343                 break;
344         case VEC_TRAP2:
345         case VEC_TRAP3:
346         case VEC_TRAP4:
347         case VEC_TRAP5:
348         case VEC_TRAP6:
349         case VEC_TRAP7:
350         case VEC_TRAP8:
351         case VEC_TRAP9:
352         case VEC_TRAP10:
353         case VEC_TRAP11:
354         case VEC_TRAP12:
355         case VEC_TRAP13:
356         case VEC_TRAP14:
357                 info.si_code = ILL_ILLTRP;
358                 sig = SIGILL;
359                 break;
360         case VEC_FPBRUC:
361         case VEC_FPOE:
362         case VEC_FPNAN:
363                 info.si_code = FPE_FLTINV;
364                 sig = SIGFPE;
365                 break;
366         case VEC_FPIR:
367                 info.si_code = FPE_FLTRES;
368                 sig = SIGFPE;
369                 break;
370         case VEC_FPDIVZ:
371                 info.si_code = FPE_FLTDIV;
372                 sig = SIGFPE;
373                 break;
374         case VEC_FPUNDER:
375                 info.si_code = FPE_FLTUND;
376                 sig = SIGFPE;
377                 break;
378         case VEC_FPOVER:
379                 info.si_code = FPE_FLTOVF;
380                 sig = SIGFPE;
381                 break;
382         case VEC_ZERODIV:
383                 info.si_code = FPE_INTDIV;
384                 sig = SIGFPE;
385                 break;
386         case VEC_CHK:
387         case VEC_TRAP:
388                 info.si_code = FPE_INTOVF;
389                 sig = SIGFPE;
390                 break;
391         case VEC_TRACE:         /* ptrace single step */
392                 info.si_code = TRAP_TRACE;
393                 sig = SIGTRAP;
394                 break;
395         case VEC_TRAP15:                /* breakpoint */
396                 info.si_code = TRAP_BRKPT;
397                 sig = SIGTRAP;
398                 break;
399         default:
400                 info.si_code = ILL_ILLOPC;
401                 sig = SIGILL;
402                 break;
403         }
404         info.si_signo = sig;
405         info.si_errno = 0;
406         switch (fp->ptregs.format) {
407         default:
408                 info.si_addr = (void *) fp->ptregs.pc;
409                 break;
410         case 2:
411                 info.si_addr = (void *) fp->un.fmt2.iaddr;
412                 break;
413         case 7:
414                 info.si_addr = (void *) fp->un.fmt7.effaddr;
415                 break;
416         case 9:
417                 info.si_addr = (void *) fp->un.fmt9.iaddr;
418                 break;
419         case 10:
420                 info.si_addr = (void *) fp->un.fmta.daddr;
421                 break;
422         case 11:
423                 info.si_addr = (void *) fp->un.fmtb.daddr;
424                 break;
425         }
426         force_sig_info(sig, &info, current);
427 }
428
429 asmlinkage void set_esp0(unsigned long ssp)
430 {
431         current->thread.esp0 = ssp;
432 }
433
434 /*
435  * The architecture-independent backtrace generator
436  */
437 void dump_stack(void)
438 {
439         unsigned long stack;
440
441         show_stack(current, &stack);
442 }
443 EXPORT_SYMBOL(dump_stack);
444
445 #ifdef CONFIG_M68KFPU_EMU
446 asmlinkage void fpemu_signal(int signal, int code, void *addr)
447 {
448         siginfo_t info;
449
450         info.si_signo = signal;
451         info.si_errno = 0;
452         info.si_code = code;
453         info.si_addr = addr;
454         force_sig_info(signal, &info, current);
455 }
456 #endif