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)
67 void die_if_kernel(char *str, struct pt_regs *fp, int nr)
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);
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));
88 asmlinkage void buserr_c(struct frame *fp)
90 /* Only set esp0 if coming from user mode */
91 if (user_mode(&fp->ptregs))
92 current->thread.esp0 = (unsigned long) fp;
95 printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
98 die_if_kernel("bad frame format",&fp->ptregs,0);
100 printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
102 force_sig(SIGSEGV, current);
106 int kstack_depth_to_print = 48;
108 void show_stack(struct task_struct *task, unsigned long *stack)
110 unsigned long *endstack, addr;
111 extern char _start, _etext;
116 stack = (unsigned long *)task->thread.ksp;
118 stack = (unsigned long *)&stack;
121 addr = (unsigned long) stack;
122 endstack = (unsigned long *) PAGE_ALIGN(addr);
124 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
125 for (i = 0; i < kstack_depth_to_print; i++) {
126 if (stack + 1 > endstack)
129 printk("\n" KERN_EMERG " ");
130 printk(" %08lx", *stack++);
134 printk(KERN_EMERG "Call Trace:");
136 while (stack + 1 <= endstack) {
139 * If the address is either in the text segment of the
140 * kernel, or in the region which contains vmalloc'ed
141 * memory, it *may* be the address of a calling
142 * routine; if so, print it so that someone tracing
143 * down the cause of the crash will be able to figure
144 * out the call path that was taken.
146 if (((addr >= (unsigned long) &_start) &&
147 (addr <= (unsigned long) &_etext))) {
149 printk("\n" KERN_EMERG " ");
150 printk(" [<%08lx>]", addr);
157 void bad_super_trap(struct frame *fp)
160 if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
161 printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
162 vec_names[(fp->ptregs.vector) >> 2],
165 printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
166 (fp->ptregs.vector) >> 2,
168 printk (KERN_WARNING "Current process id is %d\n", current->pid);
169 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
172 asmlinkage void trap_c(struct frame *fp)
177 if (fp->ptregs.sr & PS_S) {
178 if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
179 /* traced a trapping instruction */
180 current->ptrace |= PT_DTRACE;
186 /* send the appropriate signal to the user program */
187 switch ((fp->ptregs.vector) >> 2) {
189 info.si_code = BUS_ADRALN;
195 info.si_code = ILL_ILLOPC;
199 info.si_code = ILL_PRVOPC;
203 info.si_code = ILL_COPROC;
206 case VEC_TRAP1: /* gdbserver breakpoint */
208 info.si_code = TRAP_TRACE;
224 info.si_code = ILL_ILLTRP;
230 info.si_code = FPE_FLTINV;
234 info.si_code = FPE_FLTRES;
238 info.si_code = FPE_FLTDIV;
242 info.si_code = FPE_FLTUND;
246 info.si_code = FPE_FLTOVF;
250 info.si_code = FPE_INTDIV;
255 info.si_code = FPE_INTOVF;
258 case VEC_TRACE: /* ptrace single step */
259 info.si_code = TRAP_TRACE;
262 case VEC_TRAP15: /* breakpoint */
263 info.si_code = TRAP_BRKPT;
267 info.si_code = ILL_ILLOPC;
273 switch (fp->ptregs.format) {
275 info.si_addr = (void *) fp->ptregs.pc;
278 info.si_addr = (void *) fp->un.fmt2.iaddr;
281 info.si_addr = (void *) fp->un.fmt7.effaddr;
284 info.si_addr = (void *) fp->un.fmt9.iaddr;
287 info.si_addr = (void *) fp->un.fmta.daddr;
290 info.si_addr = (void *) fp->un.fmtb.daddr;
293 force_sig_info (sig, &info, current);
296 asmlinkage void set_esp0(unsigned long ssp)
298 current->thread.esp0 = ssp;
303 * The architecture-independent backtrace generator
305 void dump_stack(void)
309 show_stack(current, &stack);
312 EXPORT_SYMBOL(dump_stack);
314 #ifdef CONFIG_M68KFPU_EMU
315 asmlinkage void fpemu_signal(int signal, int code, void *addr)
319 info.si_signo = signal;
323 force_sig_info(signal, &info, current);