Commit | Line | Data |
---|---|---|
1394f032 | 1 | /* |
2a12c463 RG |
2 | * Main exception handling logic. |
3 | * | |
4 | * Copyright 2004-2010 Analog Devices Inc. | |
1394f032 | 5 | * |
96f1050d | 6 | * Licensed under the GPL-2 or later |
1394f032 BW |
7 | */ |
8 | ||
70f12567 | 9 | #include <linux/bug.h> |
1f83b8f1 | 10 | #include <linux/uaccess.h> |
1f83b8f1 | 11 | #include <linux/module.h> |
1394f032 | 12 | #include <asm/traps.h> |
f4585a08 | 13 | #include <asm/cplb.h> |
1394f032 | 14 | #include <asm/blackfin.h> |
1394f032 | 15 | #include <asm/irq_handler.h> |
d8f66c8c | 16 | #include <linux/irq.h> |
669b792c | 17 | #include <asm/trace.h> |
226eb1ef | 18 | #include <asm/fixed_code.h> |
6ce3e9c2 | 19 | #include <asm/pseudo_instructions.h> |
3bed8d67 | 20 | #include <asm/pda.h> |
ede45dd3 | 21 | #include <asm/asm-offsets.h> |
1394f032 BW |
22 | |
23 | #ifdef CONFIG_KGDB | |
1394f032 | 24 | # include <linux/kgdb.h> |
226eb1ef RG |
25 | |
26 | # define CHK_DEBUGGER_TRAP() \ | |
27 | do { \ | |
a5ac0129 | 28 | kgdb_handle_exception(trapnr, sig, info.si_code, fp); \ |
226eb1ef RG |
29 | } while (0) |
30 | # define CHK_DEBUGGER_TRAP_MAYBE() \ | |
31 | do { \ | |
32 | if (kgdb_connected) \ | |
33 | CHK_DEBUGGER_TRAP(); \ | |
34 | } while (0) | |
35 | #else | |
36 | # define CHK_DEBUGGER_TRAP() do { } while (0) | |
37 | # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) | |
1394f032 BW |
38 | #endif |
39 | ||
9f06c38f | 40 | |
4ee1c453 | 41 | #ifdef CONFIG_DEBUG_VERBOSE |
9f06c38f RG |
42 | #define verbose_printk(fmt, arg...) \ |
43 | printk(fmt, ##arg) | |
44 | #else | |
45 | #define verbose_printk(fmt, arg...) \ | |
46 | ({ if (0) printk(fmt, ##arg); 0; }) | |
47 | #endif | |
48 | ||
81f7f456 RG |
49 | #if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE) |
50 | u32 last_seqstat; | |
51 | #ifdef CONFIG_DEBUG_MMRS_MODULE | |
52 | EXPORT_SYMBOL(last_seqstat); | |
53 | #endif | |
54 | #endif | |
55 | ||
1394f032 BW |
56 | /* Initiate the event table handler */ |
57 | void __init trap_init(void) | |
58 | { | |
59 | CSYNC(); | |
60 | bfin_write_EVT3(trap); | |
61 | CSYNC(); | |
62 | } | |
63 | ||
82bd1d7d MF |
64 | static int kernel_mode_regs(struct pt_regs *regs) |
65 | { | |
66 | return regs->ipend & 0xffc0; | |
67 | } | |
68 | ||
c4baebf2 | 69 | asmlinkage notrace void trap_c(struct pt_regs *fp) |
1394f032 | 70 | { |
518039bc RG |
71 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON |
72 | int j; | |
6ce3e9c2 RG |
73 | #endif |
74 | #ifdef CONFIG_BFIN_PSEUDODBG_INSNS | |
75 | int opcode; | |
8f65873e | 76 | #endif |
b6dbde27 | 77 | unsigned int cpu = raw_smp_processor_id(); |
82bd1d7d | 78 | const char *strerror = NULL; |
518039bc | 79 | int sig = 0; |
1394f032 BW |
80 | siginfo_t info; |
81 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; | |
82 | ||
226eb1ef | 83 | trace_buffer_save(j); |
81f7f456 RG |
84 | #if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE) |
85 | last_seqstat = (u32)fp->seqstat; | |
86 | #endif | |
226eb1ef RG |
87 | |
88 | /* Important - be very careful dereferncing pointers - will lead to | |
89 | * double faults if the stack has become corrupt | |
90 | */ | |
91 | ||
1394f032 BW |
92 | /* trap_c() will be called for exceptions. During exceptions |
93 | * processing, the pc value should be set with retx value. | |
94 | * With this change we can cleanup some code in signal.c- TODO | |
95 | */ | |
96 | fp->orig_pc = fp->retx; | |
97 | /* printk("exception: 0x%x, ipend=%x, reti=%x, retx=%x\n", | |
98 | trapnr, fp->ipend, fp->pc, fp->retx); */ | |
99 | ||
100 | /* send the appropriate signal to the user program */ | |
101 | switch (trapnr) { | |
102 | ||
25985edc | 103 | /* This table works in conjunction with the one in ./mach-common/entry.S |
1394f032 BW |
104 | * Some exceptions are handled there (in assembly, in exception space) |
105 | * Some are handled here, (in C, in interrupt space) | |
106 | * Some, like CPLB, are handled in both, where the normal path is | |
107 | * handled in assembly/exception space, and the error path is handled | |
108 | * here | |
109 | */ | |
110 | ||
111 | /* 0x00 - Linux Syscall, getting here is an error */ | |
112 | /* 0x01 - userspace gdb breakpoint, handled here */ | |
113 | case VEC_EXCPT01: | |
114 | info.si_code = TRAP_ILLTRAP; | |
115 | sig = SIGTRAP; | |
116 | CHK_DEBUGGER_TRAP_MAYBE(); | |
117 | /* Check if this is a breakpoint in kernel space */ | |
82bd1d7d | 118 | if (kernel_mode_regs(fp)) |
6510a20e | 119 | goto traps_done; |
1394f032 BW |
120 | else |
121 | break; | |
9401e618 | 122 | /* 0x03 - User Defined, userspace stack overflow */ |
1394f032 BW |
123 | case VEC_EXCPT03: |
124 | info.si_code = SEGV_STACKFLOW; | |
125 | sig = SIGSEGV; | |
82bd1d7d | 126 | strerror = KERN_NOTICE EXC_0x03(KERN_NOTICE); |
a5ac0129 | 127 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 | 128 | break; |
27707d3e SZ |
129 | /* 0x02 - KGDB initial connection and break signal trap */ |
130 | case VEC_EXCPT02: | |
131 | #ifdef CONFIG_KGDB | |
132 | info.si_code = TRAP_ILLTRAP; | |
133 | sig = SIGTRAP; | |
134 | CHK_DEBUGGER_TRAP(); | |
6510a20e | 135 | goto traps_done; |
27707d3e | 136 | #endif |
5c64e0d5 RG |
137 | /* 0x04 - User Defined */ |
138 | /* 0x05 - User Defined */ | |
139 | /* 0x06 - User Defined */ | |
140 | /* 0x07 - User Defined */ | |
141 | /* 0x08 - User Defined */ | |
142 | /* 0x09 - User Defined */ | |
143 | /* 0x0A - User Defined */ | |
144 | /* 0x0B - User Defined */ | |
145 | /* 0x0C - User Defined */ | |
146 | /* 0x0D - User Defined */ | |
147 | /* 0x0E - User Defined */ | |
148 | /* 0x0F - User Defined */ | |
27707d3e | 149 | /* If we got here, it is most likely that someone was trying to use a |
5c64e0d5 RG |
150 | * custom exception handler, and it is not actually installed properly |
151 | */ | |
152 | case VEC_EXCPT04 ... VEC_EXCPT15: | |
153 | info.si_code = ILL_ILLPARAOP; | |
154 | sig = SIGILL; | |
82bd1d7d | 155 | strerror = KERN_NOTICE EXC_0x04(KERN_NOTICE); |
5c64e0d5 RG |
156 | CHK_DEBUGGER_TRAP_MAYBE(); |
157 | break; | |
1394f032 BW |
158 | /* 0x10 HW Single step, handled here */ |
159 | case VEC_STEP: | |
160 | info.si_code = TRAP_STEP; | |
161 | sig = SIGTRAP; | |
162 | CHK_DEBUGGER_TRAP_MAYBE(); | |
163 | /* Check if this is a single step in kernel space */ | |
82bd1d7d | 164 | if (kernel_mode_regs(fp)) |
6510a20e | 165 | goto traps_done; |
1394f032 BW |
166 | else |
167 | break; | |
168 | /* 0x11 - Trace Buffer Full, handled here */ | |
169 | case VEC_OVFLOW: | |
170 | info.si_code = TRAP_TRACEFLOW; | |
171 | sig = SIGTRAP; | |
82bd1d7d | 172 | strerror = KERN_NOTICE EXC_0x11(KERN_NOTICE); |
a5ac0129 | 173 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
174 | break; |
175 | /* 0x12 - Reserved, Caught by default */ | |
176 | /* 0x13 - Reserved, Caught by default */ | |
177 | /* 0x14 - Reserved, Caught by default */ | |
178 | /* 0x15 - Reserved, Caught by default */ | |
179 | /* 0x16 - Reserved, Caught by default */ | |
180 | /* 0x17 - Reserved, Caught by default */ | |
181 | /* 0x18 - Reserved, Caught by default */ | |
182 | /* 0x19 - Reserved, Caught by default */ | |
183 | /* 0x1A - Reserved, Caught by default */ | |
184 | /* 0x1B - Reserved, Caught by default */ | |
185 | /* 0x1C - Reserved, Caught by default */ | |
186 | /* 0x1D - Reserved, Caught by default */ | |
187 | /* 0x1E - Reserved, Caught by default */ | |
188 | /* 0x1F - Reserved, Caught by default */ | |
189 | /* 0x20 - Reserved, Caught by default */ | |
190 | /* 0x21 - Undefined Instruction, handled here */ | |
191 | case VEC_UNDEF_I: | |
70f12567 MF |
192 | #ifdef CONFIG_BUG |
193 | if (kernel_mode_regs(fp)) { | |
194 | switch (report_bug(fp->pc, fp)) { | |
195 | case BUG_TRAP_TYPE_NONE: | |
196 | break; | |
197 | case BUG_TRAP_TYPE_WARN: | |
198 | dump_bfin_trace_buffer(); | |
199 | fp->pc += 2; | |
200 | goto traps_done; | |
201 | case BUG_TRAP_TYPE_BUG: | |
202 | /* call to panic() will dump trace, and it is | |
203 | * off at this point, so it won't be clobbered | |
204 | */ | |
205 | panic("BUG()"); | |
206 | } | |
207 | } | |
6ce3e9c2 RG |
208 | #endif |
209 | #ifdef CONFIG_BFIN_PSEUDODBG_INSNS | |
210 | /* | |
211 | * Support for the fake instructions, if the instruction fails, | |
212 | * then just execute a illegal opcode failure (like normal). | |
213 | * Don't support these instructions inside the kernel | |
214 | */ | |
215 | if (!kernel_mode_regs(fp) && get_instruction(&opcode, (unsigned short *)fp->pc)) { | |
216 | if (execute_pseudodbg_assert(fp, opcode)) | |
217 | goto traps_done; | |
dc89d97f RG |
218 | if (execute_pseudodbg(fp, opcode)) |
219 | goto traps_done; | |
6ce3e9c2 | 220 | } |
70f12567 | 221 | #endif |
1394f032 BW |
222 | info.si_code = ILL_ILLOPC; |
223 | sig = SIGILL; | |
82bd1d7d | 224 | strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE); |
a5ac0129 | 225 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
226 | break; |
227 | /* 0x22 - Illegal Instruction Combination, handled here */ | |
228 | case VEC_ILGAL_I: | |
229 | info.si_code = ILL_ILLPARAOP; | |
230 | sig = SIGILL; | |
82bd1d7d | 231 | strerror = KERN_NOTICE EXC_0x22(KERN_NOTICE); |
a5ac0129 | 232 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 | 233 | break; |
f26fbc48 | 234 | /* 0x23 - Data CPLB protection violation, handled here */ |
1394f032 BW |
235 | case VEC_CPLB_VL: |
236 | info.si_code = ILL_CPLB_VI; | |
36b84128 | 237 | sig = SIGSEGV; |
82bd1d7d | 238 | strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE); |
a5ac0129 | 239 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
240 | break; |
241 | /* 0x24 - Data access misaligned, handled here */ | |
242 | case VEC_MISALI_D: | |
243 | info.si_code = BUS_ADRALN; | |
244 | sig = SIGBUS; | |
82bd1d7d | 245 | strerror = KERN_NOTICE EXC_0x24(KERN_NOTICE); |
a5ac0129 | 246 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
247 | break; |
248 | /* 0x25 - Unrecoverable Event, handled here */ | |
249 | case VEC_UNCOV: | |
250 | info.si_code = ILL_ILLEXCPT; | |
251 | sig = SIGILL; | |
82bd1d7d | 252 | strerror = KERN_NOTICE EXC_0x25(KERN_NOTICE); |
a5ac0129 | 253 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
254 | break; |
255 | /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, | |
256 | error case is handled here */ | |
257 | case VEC_CPLB_M: | |
258 | info.si_code = BUS_ADRALN; | |
259 | sig = SIGBUS; | |
82bd1d7d | 260 | strerror = KERN_NOTICE EXC_0x26(KERN_NOTICE); |
1394f032 BW |
261 | break; |
262 | /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ | |
263 | case VEC_CPLB_MHIT: | |
264 | info.si_code = ILL_CPLB_MULHIT; | |
1394f032 | 265 | sig = SIGSEGV; |
c6c6f75d | 266 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
8f65873e | 267 | if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START) |
82bd1d7d | 268 | strerror = KERN_NOTICE "NULL pointer access\n"; |
c6c6f75d | 269 | else |
1394f032 | 270 | #endif |
82bd1d7d | 271 | strerror = KERN_NOTICE EXC_0x27(KERN_NOTICE); |
a5ac0129 | 272 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
273 | break; |
274 | /* 0x28 - Emulation Watchpoint, handled here */ | |
275 | case VEC_WATCH: | |
276 | info.si_code = TRAP_WATCHPT; | |
277 | sig = SIGTRAP; | |
569a50ca | 278 | pr_debug(EXC_0x28(KERN_DEBUG)); |
1394f032 BW |
279 | CHK_DEBUGGER_TRAP_MAYBE(); |
280 | /* Check if this is a watchpoint in kernel space */ | |
82bd1d7d | 281 | if (kernel_mode_regs(fp)) |
6510a20e | 282 | goto traps_done; |
1394f032 BW |
283 | else |
284 | break; | |
285 | #ifdef CONFIG_BF535 | |
286 | /* 0x29 - Instruction fetch access error (535 only) */ | |
287 | case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ | |
288 | info.si_code = BUS_OPFETCH; | |
289 | sig = SIGBUS; | |
82bd1d7d | 290 | strerror = KERN_NOTICE "BF535: VEC_ISTRU_VL\n"; |
a5ac0129 | 291 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
292 | break; |
293 | #else | |
294 | /* 0x29 - Reserved, Caught by default */ | |
295 | #endif | |
296 | /* 0x2A - Instruction fetch misaligned, handled here */ | |
297 | case VEC_MISALI_I: | |
298 | info.si_code = BUS_ADRALN; | |
299 | sig = SIGBUS; | |
82bd1d7d | 300 | strerror = KERN_NOTICE EXC_0x2A(KERN_NOTICE); |
a5ac0129 | 301 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 | 302 | break; |
f26fbc48 | 303 | /* 0x2B - Instruction CPLB protection violation, handled here */ |
1394f032 BW |
304 | case VEC_CPLB_I_VL: |
305 | info.si_code = ILL_CPLB_VI; | |
f26fbc48 | 306 | sig = SIGBUS; |
82bd1d7d | 307 | strerror = KERN_NOTICE EXC_0x2B(KERN_NOTICE); |
a5ac0129 | 308 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
309 | break; |
310 | /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ | |
311 | case VEC_CPLB_I_M: | |
312 | info.si_code = ILL_CPLB_MISS; | |
313 | sig = SIGBUS; | |
82bd1d7d | 314 | strerror = KERN_NOTICE EXC_0x2C(KERN_NOTICE); |
1394f032 BW |
315 | break; |
316 | /* 0x2D - Instruction CPLB Multiple Hits, handled here */ | |
317 | case VEC_CPLB_I_MHIT: | |
318 | info.si_code = ILL_CPLB_MULHIT; | |
1394f032 | 319 | sig = SIGSEGV; |
c6c6f75d | 320 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
8f65873e | 321 | if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START) |
82bd1d7d | 322 | strerror = KERN_NOTICE "Jump to NULL address\n"; |
c6c6f75d | 323 | else |
1394f032 | 324 | #endif |
82bd1d7d | 325 | strerror = KERN_NOTICE EXC_0x2D(KERN_NOTICE); |
a5ac0129 | 326 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
327 | break; |
328 | /* 0x2E - Illegal use of Supervisor Resource, handled here */ | |
329 | case VEC_ILL_RES: | |
330 | info.si_code = ILL_PRVOPC; | |
331 | sig = SIGILL; | |
82bd1d7d | 332 | strerror = KERN_NOTICE EXC_0x2E(KERN_NOTICE); |
a5ac0129 | 333 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
334 | break; |
335 | /* 0x2F - Reserved, Caught by default */ | |
336 | /* 0x30 - Reserved, Caught by default */ | |
337 | /* 0x31 - Reserved, Caught by default */ | |
338 | /* 0x32 - Reserved, Caught by default */ | |
339 | /* 0x33 - Reserved, Caught by default */ | |
340 | /* 0x34 - Reserved, Caught by default */ | |
341 | /* 0x35 - Reserved, Caught by default */ | |
342 | /* 0x36 - Reserved, Caught by default */ | |
343 | /* 0x37 - Reserved, Caught by default */ | |
344 | /* 0x38 - Reserved, Caught by default */ | |
345 | /* 0x39 - Reserved, Caught by default */ | |
346 | /* 0x3A - Reserved, Caught by default */ | |
347 | /* 0x3B - Reserved, Caught by default */ | |
348 | /* 0x3C - Reserved, Caught by default */ | |
349 | /* 0x3D - Reserved, Caught by default */ | |
350 | /* 0x3E - Reserved, Caught by default */ | |
351 | /* 0x3F - Reserved, Caught by default */ | |
13fe24f3 RG |
352 | case VEC_HWERR: |
353 | info.si_code = BUS_ADRALN; | |
354 | sig = SIGBUS; | |
355 | switch (fp->seqstat & SEQSTAT_HWERRCAUSE) { | |
356 | /* System MMR Error */ | |
357 | case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): | |
358 | info.si_code = BUS_ADRALN; | |
359 | sig = SIGBUS; | |
82bd1d7d | 360 | strerror = KERN_NOTICE HWC_x2(KERN_NOTICE); |
13fe24f3 RG |
361 | break; |
362 | /* External Memory Addressing Error */ | |
363 | case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): | |
a00b4fe5 BS |
364 | if (ANOMALY_05000310) { |
365 | static unsigned long anomaly_rets; | |
366 | ||
367 | if ((fp->pc >= (L1_CODE_START + L1_CODE_LENGTH - 512)) && | |
368 | (fp->pc < (L1_CODE_START + L1_CODE_LENGTH))) { | |
369 | /* | |
370 | * A false hardware error will happen while fetching at | |
371 | * the L1 instruction SRAM boundary. Ignore it. | |
372 | */ | |
373 | anomaly_rets = fp->rets; | |
374 | goto traps_done; | |
375 | } else if (fp->rets == anomaly_rets) { | |
376 | /* | |
377 | * While boundary code returns to a function, at the ret | |
378 | * point, a new false hardware error might occur too based | |
379 | * on tests. Ignore it too. | |
380 | */ | |
381 | goto traps_done; | |
382 | } else if ((fp->rets >= (L1_CODE_START + L1_CODE_LENGTH - 512)) && | |
383 | (fp->rets < (L1_CODE_START + L1_CODE_LENGTH))) { | |
384 | /* | |
385 | * If boundary code calls a function, at the entry point, | |
386 | * a new false hardware error maybe happen based on tests. | |
387 | * Ignore it too. | |
388 | */ | |
389 | goto traps_done; | |
390 | } else | |
391 | anomaly_rets = 0; | |
392 | } | |
393 | ||
13fe24f3 RG |
394 | info.si_code = BUS_ADRERR; |
395 | sig = SIGBUS; | |
82bd1d7d | 396 | strerror = KERN_NOTICE HWC_x3(KERN_NOTICE); |
13fe24f3 RG |
397 | break; |
398 | /* Performance Monitor Overflow */ | |
399 | case (SEQSTAT_HWERRCAUSE_PERF_FLOW): | |
82bd1d7d | 400 | strerror = KERN_NOTICE HWC_x12(KERN_NOTICE); |
13fe24f3 RG |
401 | break; |
402 | /* RAISE 5 instruction */ | |
403 | case (SEQSTAT_HWERRCAUSE_RAISE_5): | |
404 | printk(KERN_NOTICE HWC_x18(KERN_NOTICE)); | |
405 | break; | |
406 | default: /* Reserved */ | |
407 | printk(KERN_NOTICE HWC_default(KERN_NOTICE)); | |
408 | break; | |
409 | } | |
a5ac0129 | 410 | CHK_DEBUGGER_TRAP_MAYBE(); |
13fe24f3 | 411 | break; |
5c64e0d5 RG |
412 | /* |
413 | * We should be handling all known exception types above, | |
414 | * if we get here we hit a reserved one, so panic | |
415 | */ | |
1394f032 | 416 | default: |
5c64e0d5 RG |
417 | info.si_code = ILL_ILLPARAOP; |
418 | sig = SIGILL; | |
9f06c38f | 419 | verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", |
1394f032 | 420 | (fp->seqstat & SEQSTAT_EXCAUSE)); |
a5ac0129 | 421 | CHK_DEBUGGER_TRAP_MAYBE(); |
1394f032 BW |
422 | break; |
423 | } | |
424 | ||
226eb1ef RG |
425 | BUG_ON(sig == 0); |
426 | ||
82bd1d7d MF |
427 | /* If the fault was caused by a kernel thread, or interrupt handler |
428 | * we will kernel panic, so the system reboots. | |
429 | */ | |
430 | if (kernel_mode_regs(fp) || (current && !current->mm)) { | |
431 | console_verbose(); | |
432 | oops_in_progress = 1; | |
82bd1d7d MF |
433 | } |
434 | ||
226eb1ef | 435 | if (sig != SIGTRAP) { |
15627bd3 MF |
436 | if (strerror) |
437 | verbose_printk(strerror); | |
438 | ||
49dce912 | 439 | dump_bfin_process(fp); |
b03b08ba | 440 | dump_bfin_mem(fp); |
49dce912 | 441 | show_regs(fp); |
226eb1ef RG |
442 | |
443 | /* Print out the trace buffer if it makes sense */ | |
444 | #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE | |
445 | if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) | |
9f06c38f | 446 | verbose_printk(KERN_NOTICE "No trace since you do not have " |
ad361c98 | 447 | "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n\n"); |
226eb1ef RG |
448 | else |
449 | #endif | |
450 | dump_bfin_trace_buffer(); | |
f09630bf | 451 | |
226eb1ef | 452 | if (oops_in_progress) { |
f09630bf | 453 | /* Dump the current kernel stack */ |
ad361c98 | 454 | verbose_printk(KERN_NOTICE "Kernel Stack\n"); |
f09630bf | 455 | show_stack(current, NULL); |
aee3a292 | 456 | print_modules(); |
226eb1ef | 457 | #ifndef CONFIG_ACCESS_CHECK |
9f06c38f | 458 | verbose_printk(KERN_EMERG "Please turn on " |
90c7f468 | 459 | "CONFIG_ACCESS_CHECK\n"); |
226eb1ef | 460 | #endif |
1394f032 | 461 | panic("Kernel exception"); |
f09630bf | 462 | } else { |
4ee1c453 | 463 | #ifdef CONFIG_DEBUG_VERBOSE |
9f06c38f | 464 | unsigned long *stack; |
f09630bf RG |
465 | /* Dump the user space stack */ |
466 | stack = (unsigned long *)rdusp(); | |
9f06c38f | 467 | verbose_printk(KERN_NOTICE "Userspace Stack\n"); |
f09630bf | 468 | show_stack(NULL, stack); |
9f06c38f | 469 | #endif |
226eb1ef | 470 | } |
1394f032 | 471 | } |
fb322915 | 472 | |
6a01f230 YL |
473 | #ifdef CONFIG_IPIPE |
474 | if (!ipipe_trap_notify(fp->seqstat & 0x3f, fp)) | |
475 | #endif | |
476 | { | |
477 | info.si_signo = sig; | |
478 | info.si_errno = 0; | |
5e8d3210 BS |
479 | switch (trapnr) { |
480 | case VEC_CPLB_VL: | |
481 | case VEC_MISALI_D: | |
482 | case VEC_CPLB_M: | |
483 | case VEC_CPLB_MHIT: | |
484 | info.si_addr = (void __user *)cpu_pda[cpu].dcplb_fault_addr; | |
485 | break; | |
486 | default: | |
487 | info.si_addr = (void __user *)fp->pc; | |
488 | break; | |
489 | } | |
6a01f230 YL |
490 | force_sig_info(sig, &info, current); |
491 | } | |
1394f032 | 492 | |
0e4edcf0 | 493 | if ((ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) || |
f574a76a RG |
494 | (ANOMALY_05000281 && trapnr == VEC_HWERR) || |
495 | (ANOMALY_05000189 && (trapnr == VEC_CPLB_I_VL || trapnr == VEC_CPLB_VL))) | |
0acad8df RG |
496 | fp->pc = SAFE_USER_INSTRUCTION; |
497 | ||
6510a20e | 498 | traps_done: |
1394f032 | 499 | trace_buffer_restore(j); |
1394f032 BW |
500 | } |
501 | ||
2a12c463 | 502 | asmlinkage void double_fault_c(struct pt_regs *fp) |
1394f032 | 503 | { |
518039bc | 504 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON |
2a12c463 RG |
505 | int j; |
506 | trace_buffer_save(j); | |
518039bc | 507 | #endif |
1394f032 | 508 | |
2a12c463 RG |
509 | console_verbose(); |
510 | oops_in_progress = 1; | |
9f06c38f | 511 | #ifdef CONFIG_DEBUG_VERBOSE |
2a12c463 RG |
512 | printk(KERN_EMERG "Double Fault\n"); |
513 | #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT | |
514 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { | |
515 | unsigned int cpu = raw_smp_processor_id(); | |
516 | char buf[150]; | |
517 | decode_address(buf, cpu_pda[cpu].retx_doublefault); | |
518 | printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", | |
519 | (unsigned int)cpu_pda[cpu].seqstat_doublefault & SEQSTAT_EXCAUSE, buf); | |
520 | decode_address(buf, cpu_pda[cpu].dcplb_doublefault_addr); | |
521 | printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); | |
522 | decode_address(buf, cpu_pda[cpu].icplb_doublefault_addr); | |
523 | printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); | |
9a62ca40 | 524 | |
2a12c463 RG |
525 | decode_address(buf, fp->retx); |
526 | printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf); | |
49dce912 | 527 | } else |
9ba3c24f | 528 | #endif |
2a12c463 RG |
529 | { |
530 | dump_bfin_process(fp); | |
531 | dump_bfin_mem(fp); | |
532 | show_regs(fp); | |
533 | dump_bfin_trace_buffer(); | |
226eb1ef | 534 | } |
1394f032 | 535 | #endif |
2a12c463 | 536 | panic("Double Fault - unrecoverable event"); |
1394f032 | 537 | |
1394f032 BW |
538 | } |
539 | ||
1ffe6646 | 540 | |
1394f032 BW |
541 | void panic_cplb_error(int cplb_panic, struct pt_regs *fp) |
542 | { | |
543 | switch (cplb_panic) { | |
544 | case CPLB_NO_UNLOCKED: | |
545 | printk(KERN_EMERG "All CPLBs are locked\n"); | |
546 | break; | |
547 | case CPLB_PROT_VIOL: | |
548 | return; | |
549 | case CPLB_NO_ADDR_MATCH: | |
550 | return; | |
551 | case CPLB_UNKNOWN_ERR: | |
552 | printk(KERN_EMERG "Unknown CPLB Exception\n"); | |
553 | break; | |
554 | } | |
555 | ||
226eb1ef RG |
556 | oops_in_progress = 1; |
557 | ||
49dce912 | 558 | dump_bfin_process(fp); |
b03b08ba | 559 | dump_bfin_mem(fp); |
49dce912 | 560 | show_regs(fp); |
1394f032 | 561 | dump_stack(); |
d8804adf | 562 | panic("Unrecoverable event"); |
1394f032 | 563 | } |
2a12c463 RG |
564 | |
565 | #ifdef CONFIG_BUG | |
566 | int is_valid_bugaddr(unsigned long addr) | |
567 | { | |
9a95e2f1 | 568 | unsigned int opcode; |
2a12c463 RG |
569 | |
570 | if (!get_instruction(&opcode, (unsigned short *)addr)) | |
571 | return 0; | |
572 | ||
573 | return opcode == BFIN_BUG_OPCODE; | |
574 | } | |
575 | #endif | |
d28cff4b RG |
576 | |
577 | /* stub this out */ | |
578 | #ifndef CONFIG_DEBUG_VERBOSE | |
579 | void show_regs(struct pt_regs *fp) | |
580 | { | |
581 | ||
582 | } | |
583 | #endif |