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