1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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
166
167
168
169
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 console_verbose();
183 if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
184 printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
185 vec_names[(fp->ptregs.vector) >> 2],
186 fp->ptregs.format);
187 else
188 printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
189 (fp->ptregs.vector) >> 2,
190 fp->ptregs.format);
191 printk (KERN_WARNING "Current process id is %d\n", current->pid);
192 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
193}
194
195asmlinkage void trap_c(struct frame *fp)
196{
197 int sig;
198 siginfo_t info;
199
200 if (fp->ptregs.sr & PS_S) {
201 if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
202
203 } else
204 bad_super_trap(fp);
205 return;
206 }
207
208
209 switch ((fp->ptregs.vector) >> 2) {
210 case VEC_ADDRERR:
211 info.si_code = BUS_ADRALN;
212 sig = SIGBUS;
213 break;
214 case VEC_ILLEGAL:
215 case VEC_LINE10:
216 case VEC_LINE11:
217 info.si_code = ILL_ILLOPC;
218 sig = SIGILL;
219 break;
220 case VEC_PRIV:
221 info.si_code = ILL_PRVOPC;
222 sig = SIGILL;
223 break;
224 case VEC_COPROC:
225 info.si_code = ILL_COPROC;
226 sig = SIGILL;
227 break;
228 case VEC_TRAP1:
229 fp->ptregs.pc -= 2;
230 info.si_code = TRAP_TRACE;
231 sig = SIGTRAP;
232 break;
233 case VEC_TRAP2:
234 case VEC_TRAP3:
235 case VEC_TRAP4:
236 case VEC_TRAP5:
237 case VEC_TRAP6:
238 case VEC_TRAP7:
239 case VEC_TRAP8:
240 case VEC_TRAP9:
241 case VEC_TRAP10:
242 case VEC_TRAP11:
243 case VEC_TRAP12:
244 case VEC_TRAP13:
245 case VEC_TRAP14:
246 info.si_code = ILL_ILLTRP;
247 sig = SIGILL;
248 break;
249 case VEC_FPBRUC:
250 case VEC_FPOE:
251 case VEC_FPNAN:
252 info.si_code = FPE_FLTINV;
253 sig = SIGFPE;
254 break;
255 case VEC_FPIR:
256 info.si_code = FPE_FLTRES;
257 sig = SIGFPE;
258 break;
259 case VEC_FPDIVZ:
260 info.si_code = FPE_FLTDIV;
261 sig = SIGFPE;
262 break;
263 case VEC_FPUNDER:
264 info.si_code = FPE_FLTUND;
265 sig = SIGFPE;
266 break;
267 case VEC_FPOVER:
268 info.si_code = FPE_FLTOVF;
269 sig = SIGFPE;
270 break;
271 case VEC_ZERODIV:
272 info.si_code = FPE_INTDIV;
273 sig = SIGFPE;
274 break;
275 case VEC_CHK:
276 case VEC_TRAP:
277 info.si_code = FPE_INTOVF;
278 sig = SIGFPE;
279 break;
280 case VEC_TRACE:
281 info.si_code = TRAP_TRACE;
282 sig = SIGTRAP;
283 break;
284 case VEC_TRAP15:
285 info.si_code = TRAP_BRKPT;
286 sig = SIGTRAP;
287 break;
288 default:
289 info.si_code = ILL_ILLOPC;
290 sig = SIGILL;
291 break;
292 }
293 info.si_signo = sig;
294 info.si_errno = 0;
295 switch (fp->ptregs.format) {
296 default:
297 info.si_addr = (void *) fp->ptregs.pc;
298 break;
299 case 2:
300 info.si_addr = (void *) fp->un.fmt2.iaddr;
301 break;
302 case 7:
303 info.si_addr = (void *) fp->un.fmt7.effaddr;
304 break;
305 case 9:
306 info.si_addr = (void *) fp->un.fmt9.iaddr;
307 break;
308 case 10:
309 info.si_addr = (void *) fp->un.fmta.daddr;
310 break;
311 case 11:
312 info.si_addr = (void *) fp->un.fmtb.daddr;
313 break;
314 }
315 force_sig_info (sig, &info, current);
316}
317
318asmlinkage void set_esp0(unsigned long ssp)
319{
320 current->thread.esp0 = ssp;
321}
322
323
324
325
326void dump_stack(void)
327{
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348 unsigned long *stack;
349
350 stack = (unsigned long *)&stack;
351 stack++;
352 __show_stack(current, stack);
353}
354EXPORT_SYMBOL(dump_stack);
355
356void show_stack(struct task_struct *task, unsigned long *stack)
357{
358 if (!stack && !task)
359 dump_stack();
360 else
361 __show_stack(task, stack);
362}
363
364#ifdef CONFIG_M68KFPU_EMU
365asmlinkage void fpemu_signal(int signal, int code, void *addr)
366{
367 siginfo_t info;
368
369 info.si_signo = signal;
370 info.si_errno = 0;
371 info.si_code = code;
372 info.si_addr = addr;
373 force_sig_info(signal, &info, current);
374}
375#endif
376