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>
31 #include <linux/kallsyms.h>
33 #include <asm/setup.h>
35 #include <asm/system.h>
36 #include <asm/uaccess.h>
37 #include <asm/traps.h>
38 #include <asm/pgtable.h>
39 #include <asm/machdep.h>
40 #include <asm/siginfo.h>
42 static char const * const vec_names[] = {
43 "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
44 "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
45 "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
46 "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
47 "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
48 "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
49 "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
50 "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
51 "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
52 "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
53 "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
54 "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
55 "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
56 "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
57 "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
58 "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
59 "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
60 "FPCP UNSUPPORTED OPERATION",
61 "MMU CONFIGURATION ERROR"
64 void __init trap_init(void)
68 void die_if_kernel(char *str, struct pt_regs *fp, int nr)
74 printk(KERN_EMERG "%s: %08x\n",str,nr);
75 printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n",
76 fp->pc, fp->sr, fp, fp->a2);
77 printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
78 fp->d0, fp->d1, fp->d2, fp->d3);
79 printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
80 fp->d4, fp->d5, fp->a0, fp->a1);
82 printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
83 current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
84 show_stack(NULL, (unsigned long *)(fp + 1));
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);
106 static void print_this_address(unsigned long addr, int i)
108 #ifdef CONFIG_KALLSYMS
109 printk(KERN_EMERG " [%08lx] ", addr);
110 print_symbol(KERN_CONT "%s\n", addr);
113 printk(KERN_CONT " [%08lx] ", addr);
115 printk(KERN_CONT "\n" KERN_EMERG " [%08lx] ", addr);
120 int kstack_depth_to_print = 48;
122 static void __show_stack(struct task_struct *task, unsigned long *stack)
124 unsigned long *endstack, addr;
125 #ifdef CONFIG_FRAME_POINTER
126 unsigned long *last_stack;
131 stack = (unsigned long *)task->thread.ksp;
133 addr = (unsigned long) stack;
134 endstack = (unsigned long *) PAGE_ALIGN(addr);
136 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
137 for (i = 0; i < kstack_depth_to_print; i++) {
138 if (stack + 1 + i > endstack)
141 printk("\n" KERN_EMERG " ");
142 printk(" %08lx", *(stack + i));
147 #ifdef CONFIG_FRAME_POINTER
148 printk(KERN_EMERG "Call Trace:\n");
150 last_stack = stack - 1;
151 while (stack <= endstack && stack > last_stack) {
154 print_this_address(addr, i);
158 stack = (unsigned long *)*stack;
162 printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
163 while (stack <= endstack) {
166 * If the address is either in the text segment of the kernel,
167 * or in a region which is occupied by a module then it *may*
168 * be the address of a calling routine; if so, print it so that
169 * someone tracing down the cause of the crash will be able to
170 * figure out the call path that was taken.
172 if (__kernel_text_address(addr)) {
173 print_this_address(addr, i);
177 printk(KERN_CONT "\n");
181 void bad_super_trap(struct frame *fp)
184 if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
185 printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
186 vec_names[(fp->ptregs.vector) >> 2],
189 printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
190 (fp->ptregs.vector) >> 2,
192 printk (KERN_WARNING "Current process id is %d\n", current->pid);
193 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
196 asmlinkage void trap_c(struct frame *fp)
201 if (fp->ptregs.sr & PS_S) {
202 if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
203 /* traced a trapping instruction */
204 current->ptrace |= PT_DTRACE;
210 /* send the appropriate signal to the user program */
211 switch ((fp->ptregs.vector) >> 2) {
213 info.si_code = BUS_ADRALN;
219 info.si_code = ILL_ILLOPC;
223 info.si_code = ILL_PRVOPC;
227 info.si_code = ILL_COPROC;
230 case VEC_TRAP1: /* gdbserver breakpoint */
232 info.si_code = TRAP_TRACE;
248 info.si_code = ILL_ILLTRP;
254 info.si_code = FPE_FLTINV;
258 info.si_code = FPE_FLTRES;
262 info.si_code = FPE_FLTDIV;
266 info.si_code = FPE_FLTUND;
270 info.si_code = FPE_FLTOVF;
274 info.si_code = FPE_INTDIV;
279 info.si_code = FPE_INTOVF;
282 case VEC_TRACE: /* ptrace single step */
283 info.si_code = TRAP_TRACE;
286 case VEC_TRAP15: /* breakpoint */
287 info.si_code = TRAP_BRKPT;
291 info.si_code = ILL_ILLOPC;
297 switch (fp->ptregs.format) {
299 info.si_addr = (void *) fp->ptregs.pc;
302 info.si_addr = (void *) fp->un.fmt2.iaddr;
305 info.si_addr = (void *) fp->un.fmt7.effaddr;
308 info.si_addr = (void *) fp->un.fmt9.iaddr;
311 info.si_addr = (void *) fp->un.fmta.daddr;
314 info.si_addr = (void *) fp->un.fmtb.daddr;
317 force_sig_info (sig, &info, current);
320 asmlinkage void set_esp0(unsigned long ssp)
322 current->thread.esp0 = ssp;
326 * The architecture-independent backtrace generator
328 void dump_stack(void)
331 * We need frame pointers for this little trick, which works as follows:
333 * +------------+ 0x00
334 * | Next SP | -> 0x0c
335 * +------------+ 0x04
337 * +------------+ 0x08
338 * | Local vars | -> our stack var
339 * +------------+ 0x0c
340 * | Next SP | -> 0x18, that is what we pass to show_stack()
341 * +------------+ 0x10
343 * +------------+ 0x14
345 * +------------+ 0x18
350 unsigned long *stack;
352 stack = (unsigned long *)&stack;
354 __show_stack(current, stack);
356 EXPORT_SYMBOL(dump_stack);
358 void show_stack(struct task_struct *task, unsigned long *stack)
363 __show_stack(task, stack);
366 #ifdef CONFIG_M68KFPU_EMU
367 asmlinkage void fpemu_signal(int signal, int code, void *addr)
371 info.si_signo = signal;
375 force_sig_info(signal, &info, current);