Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / m68knommu / kernel / traps.c
blobad7dc6347f19092ec56f5fdf3a546ccda5a7836d
1 /*
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
13 * for more details.
17 * Sets up all exception vectors
19 #include <linux/config.h>
20 #include <linux/sched.h>
21 #include <linux/signal.h>
22 #include <linux/kernel.h>
23 #include <linux/mm.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>
33 #include <asm/fpu.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 *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)
65 if (mach_trap_init)
66 mach_trap_init();
69 void die_if_kernel(char *str, struct pt_regs *fp, int nr)
71 if (!(fp->sr & PS_S))
72 return;
74 console_verbose();
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);
86 do_exit(SIGSEGV);
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;
95 #if DEBUG
96 printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
97 #endif
99 die_if_kernel("bad frame format",&fp->ptregs,0);
100 #if DEBUG
101 printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
102 #endif
103 force_sig(SIGSEGV, current);
107 int kstack_depth_to_print = 48;
109 void show_stack(struct task_struct *task, unsigned long *esp)
111 unsigned long *stack, *endstack, addr;
112 extern char _start, _etext;
113 int i;
115 if (esp == NULL)
116 esp = (unsigned long *) &esp;
118 stack = esp;
119 addr = (unsigned long) esp;
120 endstack = (unsigned long *) PAGE_ALIGN(addr);
122 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
123 for (i = 0; i < kstack_depth_to_print; i++) {
124 if (stack + 1 > endstack)
125 break;
126 if (i % 8 == 0)
127 printk(KERN_EMERG "\n ");
128 printk(KERN_EMERG " %08lx", *stack++);
131 printk(KERN_EMERG "\nCall Trace:");
132 i = 0;
133 while (stack + 1 <= endstack) {
134 addr = *stack++;
136 * If the address is either in the text segment of the
137 * kernel, or in the region which contains vmalloc'ed
138 * memory, it *may* be the address of a calling
139 * routine; if so, print it so that someone tracing
140 * down the cause of the crash will be able to figure
141 * out the call path that was taken.
143 if (((addr >= (unsigned long) &_start) &&
144 (addr <= (unsigned long) &_etext))) {
145 if (i % 4 == 0)
146 printk(KERN_EMERG "\n ");
147 printk(KERN_EMERG " [<%08lx>]", addr);
148 i++;
151 printk(KERN_EMERG "\n");
154 void bad_super_trap(struct frame *fp)
156 console_verbose();
157 if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
158 printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
159 vec_names[(fp->ptregs.vector) >> 2],
160 fp->ptregs.format);
161 else
162 printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
163 (fp->ptregs.vector) >> 2,
164 fp->ptregs.format);
165 printk (KERN_WARNING "Current process id is %d\n", current->pid);
166 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
169 asmlinkage void trap_c(struct frame *fp)
171 int sig;
172 siginfo_t info;
174 if (fp->ptregs.sr & PS_S) {
175 if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
176 /* traced a trapping instruction */
177 current->ptrace |= PT_DTRACE;
178 } else
179 bad_super_trap(fp);
180 return;
183 /* send the appropriate signal to the user program */
184 switch ((fp->ptregs.vector) >> 2) {
185 case VEC_ADDRERR:
186 info.si_code = BUS_ADRALN;
187 sig = SIGBUS;
188 break;
189 case VEC_ILLEGAL:
190 case VEC_LINE10:
191 case VEC_LINE11:
192 info.si_code = ILL_ILLOPC;
193 sig = SIGILL;
194 break;
195 case VEC_PRIV:
196 info.si_code = ILL_PRVOPC;
197 sig = SIGILL;
198 break;
199 case VEC_COPROC:
200 info.si_code = ILL_COPROC;
201 sig = SIGILL;
202 break;
203 case VEC_TRAP1: /* gdbserver breakpoint */
204 fp->ptregs.pc -= 2;
205 info.si_code = TRAP_TRACE;
206 sig = SIGTRAP;
207 break;
208 case VEC_TRAP2:
209 case VEC_TRAP3:
210 case VEC_TRAP4:
211 case VEC_TRAP5:
212 case VEC_TRAP6:
213 case VEC_TRAP7:
214 case VEC_TRAP8:
215 case VEC_TRAP9:
216 case VEC_TRAP10:
217 case VEC_TRAP11:
218 case VEC_TRAP12:
219 case VEC_TRAP13:
220 case VEC_TRAP14:
221 info.si_code = ILL_ILLTRP;
222 sig = SIGILL;
223 break;
224 case VEC_FPBRUC:
225 case VEC_FPOE:
226 case VEC_FPNAN:
227 info.si_code = FPE_FLTINV;
228 sig = SIGFPE;
229 break;
230 case VEC_FPIR:
231 info.si_code = FPE_FLTRES;
232 sig = SIGFPE;
233 break;
234 case VEC_FPDIVZ:
235 info.si_code = FPE_FLTDIV;
236 sig = SIGFPE;
237 break;
238 case VEC_FPUNDER:
239 info.si_code = FPE_FLTUND;
240 sig = SIGFPE;
241 break;
242 case VEC_FPOVER:
243 info.si_code = FPE_FLTOVF;
244 sig = SIGFPE;
245 break;
246 case VEC_ZERODIV:
247 info.si_code = FPE_INTDIV;
248 sig = SIGFPE;
249 break;
250 case VEC_CHK:
251 case VEC_TRAP:
252 info.si_code = FPE_INTOVF;
253 sig = SIGFPE;
254 break;
255 case VEC_TRACE: /* ptrace single step */
256 info.si_code = TRAP_TRACE;
257 sig = SIGTRAP;
258 break;
259 case VEC_TRAP15: /* breakpoint */
260 info.si_code = TRAP_BRKPT;
261 sig = SIGTRAP;
262 break;
263 default:
264 info.si_code = ILL_ILLOPC;
265 sig = SIGILL;
266 break;
268 info.si_signo = sig;
269 info.si_errno = 0;
270 switch (fp->ptregs.format) {
271 default:
272 info.si_addr = (void *) fp->ptregs.pc;
273 break;
274 case 2:
275 info.si_addr = (void *) fp->un.fmt2.iaddr;
276 break;
277 case 7:
278 info.si_addr = (void *) fp->un.fmt7.effaddr;
279 break;
280 case 9:
281 info.si_addr = (void *) fp->un.fmt9.iaddr;
282 break;
283 case 10:
284 info.si_addr = (void *) fp->un.fmta.daddr;
285 break;
286 case 11:
287 info.si_addr = (void *) fp->un.fmtb.daddr;
288 break;
290 force_sig_info (sig, &info, current);
293 asmlinkage void set_esp0(unsigned long ssp)
295 current->thread.esp0 = ssp;
300 * The architecture-independent backtrace generator
302 void dump_stack(void)
304 unsigned long stack;
306 show_stack(current, &stack);
309 #ifdef CONFIG_M68KFPU_EMU
310 asmlinkage void fpemu_signal(int signal, int code, void *addr)
312 siginfo_t info;
314 info.si_signo = signal;
315 info.si_errno = 0;
316 info.si_code = code;
317 info.si_addr = addr;
318 force_sig_info(signal, &info, current);
320 #endif