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);
90 asmlinkage void buserr_c(struct frame *fp)
92 /* Only set esp0 if coming from user mode */
93 if (user_mode(&fp->ptregs))
94 current->thread.esp0 = (unsigned long) fp;
97 printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
100 die_if_kernel("bad frame format",&fp->ptregs,0);
102 printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
104 force_sig(SIGSEGV, current);
108 int kstack_depth_to_print = 48;
110 void show_stack(struct task_struct *task, unsigned long *stack)
112 unsigned long *endstack, addr;
113 extern char _start, _etext;
118 stack = (unsigned long *)task->thread.ksp;
120 stack = (unsigned long *)&stack;
123 addr = (unsigned long) stack;
124 endstack = (unsigned long *) PAGE_ALIGN(addr);
126 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
127 for (i = 0; i < kstack_depth_to_print; i++) {
128 if (stack + 1 > endstack)
131 printk("\n" KERN_EMERG " ");
132 printk(" %08lx", *stack++);
136 printk(KERN_EMERG "Call Trace:");
138 while (stack + 1 <= endstack) {
141 * If the address is either in the text segment of the
142 * kernel, or in the region which contains vmalloc'ed
143 * memory, it *may* be the address of a calling
144 * routine; if so, print it so that someone tracing
145 * down the cause of the crash will be able to figure
146 * out the call path that was taken.
148 if (((addr >= (unsigned long) &_start) &&
149 (addr <= (unsigned long) &_etext))) {
151 printk("\n" KERN_EMERG " ");
152 printk(" [<%08lx>]", addr);
159 void bad_super_trap(struct frame *fp)
162 if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
163 printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
164 vec_names[(fp->ptregs.vector) >> 2],
167 printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
168 (fp->ptregs.vector) >> 2,
170 printk (KERN_WARNING "Current process id is %d\n", current->pid);
171 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
174 asmlinkage void trap_c(struct frame *fp)
179 if (fp->ptregs.sr & PS_S) {
180 if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
181 /* traced a trapping instruction */
182 current->ptrace |= PT_DTRACE;
188 /* send the appropriate signal to the user program */
189 switch ((fp->ptregs.vector) >> 2) {
191 info.si_code = BUS_ADRALN;
197 info.si_code = ILL_ILLOPC;
201 info.si_code = ILL_PRVOPC;
205 info.si_code = ILL_COPROC;
208 case VEC_TRAP1: /* gdbserver breakpoint */
210 info.si_code = TRAP_TRACE;
226 info.si_code = ILL_ILLTRP;
232 info.si_code = FPE_FLTINV;
236 info.si_code = FPE_FLTRES;
240 info.si_code = FPE_FLTDIV;
244 info.si_code = FPE_FLTUND;
248 info.si_code = FPE_FLTOVF;
252 info.si_code = FPE_INTDIV;
257 info.si_code = FPE_INTOVF;
260 case VEC_TRACE: /* ptrace single step */
261 info.si_code = TRAP_TRACE;
264 case VEC_TRAP15: /* breakpoint */
265 info.si_code = TRAP_BRKPT;
269 info.si_code = ILL_ILLOPC;
275 switch (fp->ptregs.format) {
277 info.si_addr = (void *) fp->ptregs.pc;
280 info.si_addr = (void *) fp->un.fmt2.iaddr;
283 info.si_addr = (void *) fp->un.fmt7.effaddr;
286 info.si_addr = (void *) fp->un.fmt9.iaddr;
289 info.si_addr = (void *) fp->un.fmta.daddr;
292 info.si_addr = (void *) fp->un.fmtb.daddr;
295 force_sig_info (sig, &info, current);
298 asmlinkage void set_esp0(unsigned long ssp)
300 current->thread.esp0 = ssp;
305 * The architecture-independent backtrace generator
307 void dump_stack(void)
311 show_stack(current, &stack);
314 EXPORT_SYMBOL(dump_stack);
316 #ifdef CONFIG_M68KFPU_EMU
317 asmlinkage void fpemu_signal(int signal, int code, void *addr)
321 info.si_signo = signal;
325 force_sig_info(signal, &info, current);