2 * linux/arch/m68knommu/kernel/traps.c
4 * Copyright (C) 1993, 1994 by Hamish Macdonald
6 * 68040 fixes by Michael Rausch
7 * 68040 fixes by Martin Apel
8 * 68060 fixes by Roman Hodek
9 * 68060 fixes by Jesper Skov
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
17 * Sets up all exception vectors
19 #include <linux/sched.h>
20 #include <linux/signal.h>
21 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/types.h>
25 #include <linux/a.out.h>
26 #include <linux/user.h>
27 #include <linux/string.h>
28 #include <linux/linkage.h>
29 #include <linux/init.h>
30 #include <linux/ptrace.h>
32 #include <asm/setup.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>
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"
63 void __init trap_init(void)
69 void die_if_kernel(char *str, struct pt_regs *fp, int nr)
75 printk(KERN_EMERG "%s: %08x\n",str,nr);
76 printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n",
77 fp->pc, fp->sr, fp, fp->a2);
78 printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
79 fp->d0, fp->d1, fp->d2, fp->d3);
80 printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
81 fp->d4, fp->d5, fp->a0, fp->a1);
83 printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
84 current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
85 show_stack(NULL, (unsigned long *)fp);
89 asmlinkage void buserr_c(struct frame *fp)
91 /* Only set esp0 if coming from user mode */
92 if (user_mode(&fp->ptregs))
93 current->thread.esp0 = (unsigned long) fp;
96 printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
99 die_if_kernel("bad frame format",&fp->ptregs,0);
101 printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
103 force_sig(SIGSEGV, current);
107 int kstack_depth_to_print = 48;
109 void show_stack(struct task_struct *task, unsigned long *stack)
111 unsigned long *endstack, addr;
112 extern char _start, _etext;
117 stack = (unsigned long *)task->thread.ksp;
119 stack = (unsigned long *)&stack;
122 addr = (unsigned long) stack;
123 endstack = (unsigned long *) PAGE_ALIGN(addr);
125 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
126 for (i = 0; i < kstack_depth_to_print; i++) {
127 if (stack + 1 > endstack)
130 printk("\n" KERN_EMERG " ");
131 printk(" %08lx", *stack++);
135 printk(KERN_EMERG "Call Trace:");
137 while (stack + 1 <= endstack) {
140 * If the address is either in the text segment of the
141 * kernel, or in the region which contains vmalloc'ed
142 * memory, it *may* be the address of a calling
143 * routine; if so, print it so that someone tracing
144 * down the cause of the crash will be able to figure
145 * out the call path that was taken.
147 if (((addr >= (unsigned long) &_start) &&
148 (addr <= (unsigned long) &_etext))) {
150 printk("\n" KERN_EMERG " ");
151 printk(" [<%08lx>]", addr);
158 void bad_super_trap(struct frame *fp)
161 if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
162 printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
163 vec_names[(fp->ptregs.vector) >> 2],
166 printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
167 (fp->ptregs.vector) >> 2,
169 printk (KERN_WARNING "Current process id is %d\n", current->pid);
170 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
173 asmlinkage void trap_c(struct frame *fp)
178 if (fp->ptregs.sr & PS_S) {
179 if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
180 /* traced a trapping instruction */
181 current->ptrace |= PT_DTRACE;
187 /* send the appropriate signal to the user program */
188 switch ((fp->ptregs.vector) >> 2) {
190 info.si_code = BUS_ADRALN;
196 info.si_code = ILL_ILLOPC;
200 info.si_code = ILL_PRVOPC;
204 info.si_code = ILL_COPROC;
207 case VEC_TRAP1: /* gdbserver breakpoint */
209 info.si_code = TRAP_TRACE;
225 info.si_code = ILL_ILLTRP;
231 info.si_code = FPE_FLTINV;
235 info.si_code = FPE_FLTRES;
239 info.si_code = FPE_FLTDIV;
243 info.si_code = FPE_FLTUND;
247 info.si_code = FPE_FLTOVF;
251 info.si_code = FPE_INTDIV;
256 info.si_code = FPE_INTOVF;
259 case VEC_TRACE: /* ptrace single step */
260 info.si_code = TRAP_TRACE;
263 case VEC_TRAP15: /* breakpoint */
264 info.si_code = TRAP_BRKPT;
268 info.si_code = ILL_ILLOPC;
274 switch (fp->ptregs.format) {
276 info.si_addr = (void *) fp->ptregs.pc;
279 info.si_addr = (void *) fp->un.fmt2.iaddr;
282 info.si_addr = (void *) fp->un.fmt7.effaddr;
285 info.si_addr = (void *) fp->un.fmt9.iaddr;
288 info.si_addr = (void *) fp->un.fmta.daddr;
291 info.si_addr = (void *) fp->un.fmtb.daddr;
294 force_sig_info (sig, &info, current);
297 asmlinkage void set_esp0(unsigned long ssp)
299 current->thread.esp0 = ssp;
304 * The architecture-independent backtrace generator
306 void dump_stack(void)
310 show_stack(current, &stack);
313 EXPORT_SYMBOL(dump_stack);
315 #ifdef CONFIG_M68KFPU_EMU
316 asmlinkage void fpemu_signal(int signal, int code, void *addr)
320 info.si_signo = signal;
324 force_sig_info(signal, &info, current);