aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/kernel/traps_no.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/kernel/traps_no.c')
-rw-r--r--arch/m68k/kernel/traps_no.c365
1 files changed, 365 insertions, 0 deletions
diff --git a/arch/m68k/kernel/traps_no.c b/arch/m68k/kernel/traps_no.c
new file mode 100644
index 00000000000..a768008dfd0
--- /dev/null
+++ b/arch/m68k/kernel/traps_no.c
@@ -0,0 +1,365 @@
1/*
2 * linux/arch/m68knommu/kernel/traps.c
3 *
4 * Copyright (C) 1993, 1994 by Hamish Macdonald
5 *
6 * 68040 fixes by Michael Rausch
7 * 68040 fixes by Martin Apel
8 * 68060 fixes by Roman Hodek
9 * 68060 fixes by Jesper Skov
10 *
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.
14 */
15
16/*
17 * Sets up all exception vectors
18 */
19#include <linux/sched.h>
20#include <linux/signal.h>
21#include <linux/kernel.h>
22#include <linux/mm.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>
31
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>
40
41static 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"
61};
62
63void __init trap_init(void)
64{
65}
66
67void die_if_kernel(char *str, struct pt_regs *fp, int nr)
68{
69 if (!(fp->sr & PS_S))
70 return;
71
72 console_verbose();
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);
80
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));
84 add_taint(TAINT_DIE);
85 do_exit(SIGSEGV);
86}
87
88asmlinkage void buserr_c(struct frame *fp)
89{
90 /* Only set esp0 if coming from user mode */
91 if (user_mode(&fp->ptregs))
92 current->thread.esp0 = (unsigned long) fp;
93
94#if defined(DEBUG)
95 printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
96#endif
97
98 die_if_kernel("bad frame format",&fp->ptregs,0);
99#if defined(DEBUG)
100 printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
101#endif
102 force_sig(SIGSEGV, current);
103}
104
105static void print_this_address(unsigned long addr, int i)
106{
107#ifdef CONFIG_KALLSYMS
108 printk(KERN_EMERG " [%08lx] ", addr);
109 print_symbol(KERN_CONT "%s\n", addr);
110#else
111 if (i % 5)
112 printk(KERN_CONT " [%08lx] ", addr);
113 else
114 printk(KERN_EMERG " [%08lx] ", addr);
115 i++;
116#endif
117}
118
119int kstack_depth_to_print = 48;
120
121static void __show_stack(struct task_struct *task, unsigned long *stack)
122{
123 unsigned long *endstack, addr;
124#ifdef CONFIG_FRAME_POINTER
125 unsigned long *last_stack;
126#endif
127 int i;
128
129 if (!stack)
130 stack = (unsigned long *)task->thread.ksp;
131
132 addr = (unsigned long) stack;
133 endstack = (unsigned long *) PAGE_ALIGN(addr);
134
135 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
136 for (i = 0; i < kstack_depth_to_print; i++) {
137 if (stack + 1 + i > endstack)
138 break;
139 if (i % 8 == 0)
140 printk(KERN_EMERG " ");
141 printk(KERN_CONT " %08lx", *(stack + i));
142 }
143 printk("\n");
144 i = 0;
145
146#ifdef CONFIG_FRAME_POINTER
147 printk(KERN_EMERG "Call Trace:\n");
148
149 last_stack = stack - 1;
150 while (stack <= endstack && stack > last_stack) {
151
152 addr = *(stack + 1);
153 print_this_address(addr, i);
154 i++;
155
156 last_stack = stack;
157 stack = (unsigned long *)*stack;
158 }
159 printk("\n");
160#else
161 printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
162 while (stack <= endstack) {
163 addr = *stack++;
164 /*
165 * If the address is either in the text segment of the kernel,
166 * or in a region which is occupied by a module then it *may*
167 * be the address of a calling routine; if so, print it so that
168 * someone tracing down the cause of the crash will be able to
169 * figure out the call path that was taken.
170 */
171 if (__kernel_text_address(addr)) {
172 print_this_address(addr, i);
173 i++;
174 }
175 }
176 printk(KERN_CONT "\n");
177#endif
178}
179
180void bad_super_trap(struct frame *fp)
181{
182 int vector = (fp->ptregs.vector >> 2) & 0xff;
183
184 console_verbose();
185 if (vector < ARRAY_SIZE(vec_names))
186 printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
187 vec_names[vector],
188 fp->ptregs.format);
189 else
190 printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
191 vector,
192 fp->ptregs.format);
193 printk (KERN_WARNING "Current process id is %d\n", current->pid);
194 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
195}
196
197asmlinkage void trap_c(struct frame *fp)
198{
199 int sig;
200 int vector = (fp->ptregs.vector >> 2) & 0xff;
201 siginfo_t info;
202
203 if (fp->ptregs.sr & PS_S) {
204 if (vector == VEC_TRACE) {
205 /* traced a trapping instruction */
206 } else
207 bad_super_trap(fp);
208 return;
209 }
210
211 /* send the appropriate signal to the user program */
212 switch (vector) {
213 case VEC_ADDRERR:
214 info.si_code = BUS_ADRALN;
215 sig = SIGBUS;
216 break;
217 case VEC_ILLEGAL:
218 case VEC_LINE10:
219 case VEC_LINE11:
220 info.si_code = ILL_ILLOPC;
221 sig = SIGILL;
222 break;
223 case VEC_PRIV:
224 info.si_code = ILL_PRVOPC;
225 sig = SIGILL;
226 break;
227 case VEC_COPROC:
228 info.si_code = ILL_COPROC;
229 sig = SIGILL;
230 break;
231 case VEC_TRAP1: /* gdbserver breakpoint */
232 fp->ptregs.pc -= 2;
233 info.si_code = TRAP_TRACE;
234 sig = SIGTRAP;
235 break;
236 case VEC_TRAP2:
237 case VEC_TRAP3:
238 case VEC_TRAP4:
239 case VEC_TRAP5:
240 case VEC_TRAP6:
241 case VEC_TRAP7:
242 case VEC_TRAP8:
243 case VEC_TRAP9:
244 case VEC_TRAP10:
245 case VEC_TRAP11:
246 case VEC_TRAP12:
247 case VEC_TRAP13:
248 case VEC_TRAP14:
249 info.si_code = ILL_ILLTRP;
250 sig = SIGILL;
251 break;
252 case VEC_FPBRUC:
253 case VEC_FPOE:
254 case VEC_FPNAN:
255 info.si_code = FPE_FLTINV;
256 sig = SIGFPE;
257 break;
258 case VEC_FPIR:
259 info.si_code = FPE_FLTRES;
260 sig = SIGFPE;
261 break;
262 case VEC_FPDIVZ:
263 info.si_code = FPE_FLTDIV;
264 sig = SIGFPE;
265 break;
266 case VEC_FPUNDER:
267 info.si_code = FPE_FLTUND;
268 sig = SIGFPE;
269 break;
270 case VEC_FPOVER:
271 info.si_code = FPE_FLTOVF;
272 sig = SIGFPE;
273 break;
274 case VEC_ZERODIV:
275 info.si_code = FPE_INTDIV;
276 sig = SIGFPE;
277 break;
278 case VEC_CHK:
279 case VEC_TRAP:
280 info.si_code = FPE_INTOVF;
281 sig = SIGFPE;
282 break;
283 case VEC_TRACE: /* ptrace single step */
284 info.si_code = TRAP_TRACE;
285 sig = SIGTRAP;
286 break;
287 case VEC_TRAP15: /* breakpoint */
288 info.si_code = TRAP_BRKPT;
289 sig = SIGTRAP;
290 break;
291 default:
292 info.si_code = ILL_ILLOPC;
293 sig = SIGILL;
294 break;
295 }
296 info.si_signo = sig;
297 info.si_errno = 0;
298 switch (fp->ptregs.format) {
299 default:
300 info.si_addr = (void *) fp->ptregs.pc;
301 break;
302 case 2:
303 info.si_addr = (void *) fp->un.fmt2.iaddr;
304 break;
305 case 7:
306 info.si_addr = (void *) fp->un.fmt7.effaddr;
307 break;
308 case 9:
309 info.si_addr = (void *) fp->un.fmt9.iaddr;
310 break;
311 case 10:
312 info.si_addr = (void *) fp->un.fmta.daddr;
313 break;
314 case 11:
315 info.si_addr = (void *) fp->un.fmtb.daddr;
316 break;
317 }
318 force_sig_info (sig, &info, current);
319}
320
321asmlinkage void set_esp0(unsigned long ssp)
322{
323 current->thread.esp0 = ssp;
324}
325
326/*
327 * The architecture-independent backtrace generator
328 */
329void dump_stack(void)
330{
331 /*
332 * We need frame pointers for this little trick, which works as follows:
333 *
334 * +------------+ 0x00
335 * | Next SP | -> 0x0c
336 * +------------+ 0x04
337 * | Caller |
338 * +------------+ 0x08
339 * | Local vars | -> our stack var
340 * +------------+ 0x0c
341 * | Next SP | -> 0x18, that is what we pass to show_stack()
342 * +------------+ 0x10
343 * | Caller |
344 * +------------+ 0x14
345 * | Local vars |
346 * +------------+ 0x18
347 * | ... |
348 * +------------+
349 */
350
351 unsigned long *stack;
352
353 stack = (unsigned long *)&stack;
354 stack++;
355 __show_stack(current, stack);
356}
357EXPORT_SYMBOL(dump_stack);
358
359void show_stack(struct task_struct *task, unsigned long *stack)
360{
361 if (!stack && !task)
362 dump_stack();
363 else
364 __show_stack(task, stack);
365}