1
2
3
4
5
6
7
8
9
10
11
12#include <linux/sched.h>
13#include <linux/signal.h>
14#include <linux/kernel.h>
15#include <linux/mm.h>
16#include <linux/types.h>
17#include <linux/user.h>
18#include <linux/string.h>
19#include <linux/linkage.h>
20#include <linux/init.h>
21#include <linux/module.h>
22
23#include <asm/asm-offsets.h>
24#include <asm/setup.h>
25#include <asm/fpu.h>
26#include <asm/system.h>
27#include <asm/uaccess.h>
28#include <asm/pgtable.h>
29#include <asm/siginfo.h>
30#include <asm/unaligned.h>
31
32void show_backtrace(struct pt_regs *, unsigned long);
33
34extern asmlinkage void __break_hijack_kernel_event(void);
35
36
37
38
39
40asmlinkage void insn_access_error(unsigned long esfr1, unsigned long epcr0, unsigned long esr0)
41{
42 siginfo_t info;
43
44 die_if_kernel("-- Insn Access Error --\n"
45 "EPCR0 : %08lx\n"
46 "ESR0 : %08lx\n",
47 epcr0, esr0);
48
49 info.si_signo = SIGSEGV;
50 info.si_code = SEGV_ACCERR;
51 info.si_errno = 0;
52 info.si_addr = (void *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc);
53
54 force_sig_info(info.si_signo, &info, current);
55}
56
57
58
59
60
61
62
63
64
65asmlinkage void illegal_instruction(unsigned long esfr1, unsigned long epcr0, unsigned long esr0)
66{
67 siginfo_t info;
68
69 die_if_kernel("-- Illegal Instruction --\n"
70 "EPCR0 : %08lx\n"
71 "ESR0 : %08lx\n"
72 "ESFR1 : %08lx\n",
73 epcr0, esr0, esfr1);
74
75 info.si_errno = 0;
76 info.si_addr = (void *) ((epcr0 & EPCR0_PC) ? (epcr0 & EPCR0_PC) : __frame->pc);
77
78 switch (__frame->tbr & TBR_TT) {
79 case TBR_TT_ILLEGAL_INSTR:
80 info.si_signo = SIGILL;
81 info.si_code = ILL_ILLOPC;
82 break;
83 case TBR_TT_PRIV_INSTR:
84 info.si_signo = SIGILL;
85 info.si_code = ILL_PRVOPC;
86 break;
87 case TBR_TT_TRAP2 ... TBR_TT_TRAP126:
88 info.si_signo = SIGILL;
89 info.si_code = ILL_ILLTRP;
90 break;
91
92 case TBR_TT_TRAP1:
93 case TBR_TT_BREAK:
94 info.si_signo = SIGTRAP;
95 info.si_code =
96 (__frame->__status & REG__STATUS_STEPPED) ? TRAP_TRACE : TRAP_BRKPT;
97 break;
98 }
99
100 force_sig_info(info.si_signo, &info, current);
101}
102
103
104
105
106
107asmlinkage void media_exception(unsigned long msr0, unsigned long msr1)
108{
109 siginfo_t info;
110
111 die_if_kernel("-- Media Exception --\n"
112 "MSR0 : %08lx\n"
113 "MSR1 : %08lx\n",
114 msr0, msr1);
115
116 info.si_signo = SIGFPE;
117 info.si_code = FPE_MDAOVF;
118 info.si_errno = 0;
119 info.si_addr = (void *) __frame->pc;
120
121 force_sig_info(info.si_signo, &info, current);
122}
123
124
125
126
127
128asmlinkage void memory_access_exception(unsigned long esr0,
129 unsigned long ear0,
130 unsigned long epcr0)
131{
132 siginfo_t info;
133
134#ifdef CONFIG_MMU
135 unsigned long fixup;
136
137 if ((esr0 & ESRx_EC) == ESRx_EC_DATA_ACCESS)
138 if (handle_misalignment(esr0, ear0, epcr0) == 0)
139 return;
140
141 if ((fixup = search_exception_table(__frame->pc)) != 0) {
142 __frame->pc = fixup;
143 return;
144 }
145#endif
146
147 die_if_kernel("-- Memory Access Exception --\n"
148 "ESR0 : %08lx\n"
149 "EAR0 : %08lx\n"
150 "EPCR0 : %08lx\n",
151 esr0, ear0, epcr0);
152
153 info.si_signo = SIGSEGV;
154 info.si_code = SEGV_ACCERR;
155 info.si_errno = 0;
156 info.si_addr = NULL;
157
158 if ((esr0 & (ESRx_VALID | ESR0_EAV)) == (ESRx_VALID | ESR0_EAV))
159 info.si_addr = (void *) ear0;
160
161 force_sig_info(info.si_signo, &info, current);
162
163}
164
165
166
167
168
169
170
171
172
173
174
175
176asmlinkage void data_access_error(unsigned long esfr1, unsigned long esr15, unsigned long ear15)
177{
178 siginfo_t info;
179
180 die_if_kernel("-- Data Access Error --\n"
181 "ESR15 : %08lx\n"
182 "EAR15 : %08lx\n",
183 esr15, ear15);
184
185 info.si_signo = SIGSEGV;
186 info.si_code = SEGV_ACCERR;
187 info.si_errno = 0;
188 info.si_addr = (void *)
189 (((esr15 & (ESRx_VALID|ESR15_EAV)) == (ESRx_VALID|ESR15_EAV)) ? ear15 : 0);
190
191 force_sig_info(info.si_signo, &info, current);
192}
193
194
195
196
197
198asmlinkage void data_store_error(unsigned long esfr1, unsigned long esr15)
199{
200 die_if_kernel("-- Data Store Error --\n"
201 "ESR15 : %08lx\n",
202 esr15);
203 BUG();
204}
205
206
207
208
209
210asmlinkage void division_exception(unsigned long esfr1, unsigned long esr0, unsigned long isr)
211{
212 siginfo_t info;
213
214 die_if_kernel("-- Division Exception --\n"
215 "ESR0 : %08lx\n"
216 "ISR : %08lx\n",
217 esr0, isr);
218
219 info.si_signo = SIGFPE;
220 info.si_code = FPE_INTDIV;
221 info.si_errno = 0;
222 info.si_addr = (void *) __frame->pc;
223
224 force_sig_info(info.si_signo, &info, current);
225}
226
227
228
229
230
231asmlinkage void compound_exception(unsigned long esfr1,
232 unsigned long esr0, unsigned long esr14, unsigned long esr15,
233 unsigned long msr0, unsigned long msr1)
234{
235 die_if_kernel("-- Compound Exception --\n"
236 "ESR0 : %08lx\n"
237 "ESR15 : %08lx\n"
238 "ESR15 : %08lx\n"
239 "MSR0 : %08lx\n"
240 "MSR1 : %08lx\n",
241 esr0, esr14, esr15, msr0, msr1);
242 BUG();
243}
244
245
246
247
248
249void dump_stack(void)
250{
251 show_stack(NULL, NULL);
252}
253
254EXPORT_SYMBOL(dump_stack);
255
256void show_stack(struct task_struct *task, unsigned long *sp)
257{
258}
259
260void show_trace_task(struct task_struct *tsk)
261{
262 printk("CONTEXT: stack=0x%lx frame=0x%p LR=0x%lx RET=0x%lx\n",
263 tsk->thread.sp, tsk->thread.frame, tsk->thread.lr, tsk->thread.sched_lr);
264}
265
266static const char *regnames[] = {
267 "PSR ", "ISR ", "CCR ", "CCCR",
268 "LR ", "LCR ", "PC ", "_stt",
269 "sys ", "GR8*", "GNE0", "GNE1",
270 "IACH", "IACL",
271 "TBR ", "SP ", "FP ", "GR3 ",
272 "GR4 ", "GR5 ", "GR6 ", "GR7 ",
273 "GR8 ", "GR9 ", "GR10", "GR11",
274 "GR12", "GR13", "GR14", "GR15",
275 "GR16", "GR17", "GR18", "GR19",
276 "GR20", "GR21", "GR22", "GR23",
277 "GR24", "GR25", "GR26", "GR27",
278 "EFRM", "CURR", "GR30", "BFRM"
279};
280
281void show_regs(struct pt_regs *regs)
282{
283 unsigned long *reg;
284 int loop;
285
286 printk("\n");
287
288 printk("Frame: @%08lx [%s]\n",
289 (unsigned long) regs,
290 regs->psr & PSR_S ? "kernel" : "user");
291
292 reg = (unsigned long *) regs;
293 for (loop = 0; loop < NR_PT_REGS; loop++) {
294 printk("%s %08lx", regnames[loop + 0], reg[loop + 0]);
295
296 if (loop == NR_PT_REGS - 1 || loop % 5 == 4)
297 printk("\n");
298 else
299 printk(" | ");
300 }
301
302 printk("Process %s (pid: %d)\n", current->comm, current->pid);
303}
304
305void die_if_kernel(const char *str, ...)
306{
307 char buffer[256];
308 va_list va;
309
310 if (user_mode(__frame))
311 return;
312
313 va_start(va, str);
314 vsprintf(buffer, str, va);
315 va_end(va);
316
317 console_verbose();
318 printk("\n===================================\n");
319 printk("%s\n", buffer);
320 show_backtrace(__frame, 0);
321
322 __break_hijack_kernel_event();
323 do_exit(SIGSEGV);
324}
325
326
327
328
329
330static void show_backtrace_regs(struct pt_regs *frame)
331{
332 unsigned long *reg;
333 int loop;
334
335
336 printk("<-- %s Frame: @%p -->\n",
337 frame->psr & PSR_S ? "Kernel Mode" : "User Mode",
338 frame);
339
340 reg = (unsigned long *) frame;
341 for (loop = 0; loop < NR_PT_REGS; loop++) {
342 printk("%s %08lx", regnames[loop + 0], reg[loop + 0]);
343
344 if (loop == NR_PT_REGS - 1 || loop % 5 == 4)
345 printk("\n");
346 else
347 printk(" | ");
348 }
349
350 printk("--------\n");
351}
352
353
354
355
356
357void show_backtrace(struct pt_regs *frame, unsigned long sp)
358{
359 struct pt_regs *frame0;
360 unsigned long tos = 0, stop = 0, base;
361 int format;
362
363 base = ((((unsigned long) frame) + 8191) & ~8191) - sizeof(struct user_context);
364 frame0 = (struct pt_regs *) base;
365
366 if (sp) {
367 tos = sp;
368 stop = (unsigned long) frame;
369 }
370
371 printk("\nProcess %s (pid: %d)\n\n", current->comm, current->pid);
372
373 for (;;) {
374
375
376 format = 0;
377 while (tos < stop) {
378 if (format == 0)
379 printk(" %04lx :", tos & 0xffff);
380
381 printk(" %08lx", *(unsigned long *) tos);
382
383 tos += 4;
384 format++;
385 if (format == 8) {
386 printk("\n");
387 format = 0;
388 }
389 }
390
391 if (format > 0)
392 printk("\n");
393
394
395 if (frame == frame0)
396 break;
397
398 tos = frame->sp;
399 if (((unsigned long) frame) + sizeof(*frame) != tos) {
400 printk("-- TOS %08lx does not follow frame %p --\n",
401 tos, frame);
402 break;
403 }
404
405 show_backtrace_regs(frame);
406
407
408 stop = (unsigned long) frame->next_frame;
409 if (stop != base &&
410 (stop < tos ||
411 stop > base ||
412 (stop < base && stop + sizeof(*frame) > base) ||
413 stop & 3)) {
414 printk("-- next_frame %08lx is invalid (range %08lx-%08lx) --\n",
415 stop, tos, base);
416 break;
417 }
418
419
420 frame = frame->next_frame;
421 }
422
423
424 show_backtrace_regs(frame0);
425
426}
427
428
429
430
431
432void __init trap_init (void)
433{
434}
435