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/user.h>
26 #include <linux/string.h>
27 #include <linux/linkage.h>
28 #include <linux/init.h>
29 #include <linux/ptrace.h>
30 #include <linux/kallsyms.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 die_if_kernel(char *str
, struct pt_regs
*fp
, int nr
)
69 printk(KERN_EMERG
"%s: %08x\n",str
,nr
);
70 printk(KERN_EMERG
"PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n",
71 fp
->pc
, fp
->sr
, fp
, fp
->a2
);
72 printk(KERN_EMERG
"d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
73 fp
->d0
, fp
->d1
, fp
->d2
, fp
->d3
);
74 printk(KERN_EMERG
"d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
75 fp
->d4
, fp
->d5
, fp
->a0
, fp
->a1
);
77 printk(KERN_EMERG
"Process %s (pid: %d, stackpage=%08lx)\n",
78 current
->comm
, current
->pid
, PAGE_SIZE
+(unsigned long)current
);
79 show_stack(NULL
, (unsigned long *)(fp
+ 1));
84 asmlinkage
void buserr_c(struct frame
*fp
)
86 /* Only set esp0 if coming from user mode */
87 if (user_mode(&fp
->ptregs
))
88 current
->thread
.esp0
= (unsigned long) fp
;
91 printk (KERN_DEBUG
"*** Bus Error *** Format is %x\n", fp
->ptregs
.format
);
94 die_if_kernel("bad frame format",&fp
->ptregs
,0);
96 printk(KERN_DEBUG
"Unknown SIGSEGV - 4\n");
98 force_sig(SIGSEGV
, current
);
101 static void print_this_address(unsigned long addr
, int i
)
103 #ifdef CONFIG_KALLSYMS
104 printk(KERN_EMERG
" [%08lx] ", addr
);
105 print_symbol(KERN_CONT
"%s\n", addr
);
108 printk(KERN_CONT
" [%08lx] ", addr
);
110 printk(KERN_EMERG
" [%08lx] ", addr
);
115 int kstack_depth_to_print
= 48;
117 static void __show_stack(struct task_struct
*task
, unsigned long *stack
)
119 unsigned long *endstack
, addr
;
120 #ifdef CONFIG_FRAME_POINTER
121 unsigned long *last_stack
;
126 stack
= (unsigned long *)task
->thread
.ksp
;
128 addr
= (unsigned long) stack
;
129 endstack
= (unsigned long *) PAGE_ALIGN(addr
);
131 printk(KERN_EMERG
"Stack from %08lx:", (unsigned long)stack
);
132 for (i
= 0; i
< kstack_depth_to_print
; i
++) {
133 if (stack
+ 1 + i
> endstack
)
136 printk(KERN_EMERG
" ");
137 printk(KERN_CONT
" %08lx", *(stack
+ i
));
142 #ifdef CONFIG_FRAME_POINTER
143 printk(KERN_EMERG
"Call Trace:\n");
145 last_stack
= stack
- 1;
146 while (stack
<= endstack
&& stack
> last_stack
) {
149 print_this_address(addr
, i
);
153 stack
= (unsigned long *)*stack
;
157 printk(KERN_EMERG
"Call Trace with CONFIG_FRAME_POINTER disabled:\n");
158 while (stack
<= endstack
) {
161 * If the address is either in the text segment of the kernel,
162 * or in a region which is occupied by a module then it *may*
163 * be the address of a calling routine; if so, print it so that
164 * someone tracing down the cause of the crash will be able to
165 * figure out the call path that was taken.
167 if (__kernel_text_address(addr
)) {
168 print_this_address(addr
, i
);
172 printk(KERN_CONT
"\n");
176 void bad_super_trap(struct frame
*fp
)
178 int vector
= (fp
->ptregs
.vector
>> 2) & 0xff;
181 if (vector
< ARRAY_SIZE(vec_names
))
182 printk (KERN_WARNING
"*** %s *** FORMAT=%X\n",
186 printk (KERN_WARNING
"*** Exception %d *** FORMAT=%X\n",
189 printk (KERN_WARNING
"Current process id is %d\n", current
->pid
);
190 die_if_kernel("BAD KERNEL TRAP", &fp
->ptregs
, 0);
193 asmlinkage
void trap_c(struct frame
*fp
)
196 int vector
= (fp
->ptregs
.vector
>> 2) & 0xff;
199 if (fp
->ptregs
.sr
& PS_S
) {
200 if (vector
== VEC_TRACE
) {
201 /* traced a trapping instruction */
207 /* send the appropriate signal to the user program */
210 info
.si_code
= BUS_ADRALN
;
216 info
.si_code
= ILL_ILLOPC
;
220 info
.si_code
= ILL_PRVOPC
;
224 info
.si_code
= ILL_COPROC
;
227 case VEC_TRAP1
: /* gdbserver breakpoint */
229 info
.si_code
= TRAP_TRACE
;
245 info
.si_code
= ILL_ILLTRP
;
251 info
.si_code
= FPE_FLTINV
;
255 info
.si_code
= FPE_FLTRES
;
259 info
.si_code
= FPE_FLTDIV
;
263 info
.si_code
= FPE_FLTUND
;
267 info
.si_code
= FPE_FLTOVF
;
271 info
.si_code
= FPE_INTDIV
;
276 info
.si_code
= FPE_INTOVF
;
279 case VEC_TRACE
: /* ptrace single step */
280 info
.si_code
= TRAP_TRACE
;
283 case VEC_TRAP15
: /* breakpoint */
284 info
.si_code
= TRAP_BRKPT
;
288 info
.si_code
= ILL_ILLOPC
;
294 switch (fp
->ptregs
.format
) {
296 info
.si_addr
= (void *) fp
->ptregs
.pc
;
299 info
.si_addr
= (void *) fp
->un
.fmt2
.iaddr
;
302 info
.si_addr
= (void *) fp
->un
.fmt7
.effaddr
;
305 info
.si_addr
= (void *) fp
->un
.fmt9
.iaddr
;
308 info
.si_addr
= (void *) fp
->un
.fmta
.daddr
;
311 info
.si_addr
= (void *) fp
->un
.fmtb
.daddr
;
314 force_sig_info (sig
, &info
, current
);
317 asmlinkage
void set_esp0(unsigned long ssp
)
319 current
->thread
.esp0
= ssp
;
323 * The architecture-independent backtrace generator
325 void dump_stack(void)
328 * We need frame pointers for this little trick, which works as follows:
330 * +------------+ 0x00
331 * | Next SP | -> 0x0c
332 * +------------+ 0x04
334 * +------------+ 0x08
335 * | Local vars | -> our stack var
336 * +------------+ 0x0c
337 * | Next SP | -> 0x18, that is what we pass to show_stack()
338 * +------------+ 0x10
340 * +------------+ 0x14
342 * +------------+ 0x18
347 unsigned long *stack
;
349 stack
= (unsigned long *)&stack
;
351 __show_stack(current
, stack
);
353 EXPORT_SYMBOL(dump_stack
);
355 void show_stack(struct task_struct
*task
, unsigned long *stack
)
360 __show_stack(task
, stack
);