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 int kstack_depth_to_print
= 48;
108 static void __show_stack(struct task_struct
*task
, unsigned long *stack
)
110 unsigned long *endstack
, addr
;
111 unsigned long *last_stack
;
115 stack
= (unsigned long *)task
->thread
.ksp
;
117 addr
= (unsigned long) stack
;
118 endstack
= (unsigned long *) PAGE_ALIGN(addr
);
120 printk(KERN_EMERG
"Stack from %08lx:", (unsigned long)stack
);
121 for (i
= 0; i
< kstack_depth_to_print
; i
++) {
122 if (stack
+ 1 + i
> endstack
)
125 printk("\n" KERN_EMERG
" ");
126 printk(" %08lx", *(stack
+ i
));
130 #ifdef CONFIG_FRAME_POINTER
131 printk(KERN_EMERG
"Call Trace:\n");
133 last_stack
= stack
- 1;
134 while (stack
<= endstack
&& stack
> last_stack
) {
137 printk(KERN_EMERG
" [%08lx] ", addr
);
138 print_symbol(KERN_CONT
"%s\n", addr
);
141 stack
= (unsigned long *)*stack
;
145 printk(KERN_EMERG
"CONFIG_FRAME_POINTER disabled, no symbolic call trace\n");
149 void bad_super_trap(struct frame
*fp
)
152 if (fp
->ptregs
.vector
< 4 * ARRAY_SIZE(vec_names
))
153 printk (KERN_WARNING
"*** %s *** FORMAT=%X\n",
154 vec_names
[(fp
->ptregs
.vector
) >> 2],
157 printk (KERN_WARNING
"*** Exception %d *** FORMAT=%X\n",
158 (fp
->ptregs
.vector
) >> 2,
160 printk (KERN_WARNING
"Current process id is %d\n", current
->pid
);
161 die_if_kernel("BAD KERNEL TRAP", &fp
->ptregs
, 0);
164 asmlinkage
void trap_c(struct frame
*fp
)
169 if (fp
->ptregs
.sr
& PS_S
) {
170 if ((fp
->ptregs
.vector
>> 2) == VEC_TRACE
) {
171 /* traced a trapping instruction */
172 current
->ptrace
|= PT_DTRACE
;
178 /* send the appropriate signal to the user program */
179 switch ((fp
->ptregs
.vector
) >> 2) {
181 info
.si_code
= BUS_ADRALN
;
187 info
.si_code
= ILL_ILLOPC
;
191 info
.si_code
= ILL_PRVOPC
;
195 info
.si_code
= ILL_COPROC
;
198 case VEC_TRAP1
: /* gdbserver breakpoint */
200 info
.si_code
= TRAP_TRACE
;
216 info
.si_code
= ILL_ILLTRP
;
222 info
.si_code
= FPE_FLTINV
;
226 info
.si_code
= FPE_FLTRES
;
230 info
.si_code
= FPE_FLTDIV
;
234 info
.si_code
= FPE_FLTUND
;
238 info
.si_code
= FPE_FLTOVF
;
242 info
.si_code
= FPE_INTDIV
;
247 info
.si_code
= FPE_INTOVF
;
250 case VEC_TRACE
: /* ptrace single step */
251 info
.si_code
= TRAP_TRACE
;
254 case VEC_TRAP15
: /* breakpoint */
255 info
.si_code
= TRAP_BRKPT
;
259 info
.si_code
= ILL_ILLOPC
;
265 switch (fp
->ptregs
.format
) {
267 info
.si_addr
= (void *) fp
->ptregs
.pc
;
270 info
.si_addr
= (void *) fp
->un
.fmt2
.iaddr
;
273 info
.si_addr
= (void *) fp
->un
.fmt7
.effaddr
;
276 info
.si_addr
= (void *) fp
->un
.fmt9
.iaddr
;
279 info
.si_addr
= (void *) fp
->un
.fmta
.daddr
;
282 info
.si_addr
= (void *) fp
->un
.fmtb
.daddr
;
285 force_sig_info (sig
, &info
, current
);
288 asmlinkage
void set_esp0(unsigned long ssp
)
290 current
->thread
.esp0
= ssp
;
294 * The architecture-independent backtrace generator
296 void dump_stack(void)
299 * We need frame pointers for this little trick, which works as follows:
301 * +------------+ 0x00
302 * | Next SP | -> 0x0c
303 * +------------+ 0x04
305 * +------------+ 0x08
306 * | Local vars | -> our stack var
307 * +------------+ 0x0c
308 * | Next SP | -> 0x18, that is what we pass to show_stack()
309 * +------------+ 0x10
311 * +------------+ 0x14
313 * +------------+ 0x18
318 unsigned long *stack
;
320 stack
= (unsigned long *)&stack
;
322 __show_stack(current
, stack
);
324 EXPORT_SYMBOL(dump_stack
);
326 void show_stack(struct task_struct
*task
, unsigned long *stack
)
331 __show_stack(task
, stack
);
334 #ifdef CONFIG_M68KFPU_EMU
335 asmlinkage
void fpemu_signal(int signal
, int code
, void *addr
)
339 info
.si_signo
= signal
;
343 force_sig_info(signal
, &info
, current
);