diff options
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/traps.c | 318 |
1 files changed, 179 insertions, 139 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index ce86659f9b65..cfa05436c972 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -37,10 +37,24 @@ | |||
37 | #include <asm/blackfin.h> | 37 | #include <asm/blackfin.h> |
38 | #include <asm/irq_handler.h> | 38 | #include <asm/irq_handler.h> |
39 | #include <asm/trace.h> | 39 | #include <asm/trace.h> |
40 | #include <asm/fixed_code.h> | ||
40 | 41 | ||
41 | #ifdef CONFIG_KGDB | 42 | #ifdef CONFIG_KGDB |
42 | # include <linux/debugger.h> | 43 | # include <linux/debugger.h> |
43 | # include <linux/kgdb.h> | 44 | # include <linux/kgdb.h> |
45 | |||
46 | # define CHK_DEBUGGER_TRAP() \ | ||
47 | do { \ | ||
48 | CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \ | ||
49 | } while (0) | ||
50 | # define CHK_DEBUGGER_TRAP_MAYBE() \ | ||
51 | do { \ | ||
52 | if (kgdb_connected) \ | ||
53 | CHK_DEBUGGER_TRAP(); \ | ||
54 | } while (0) | ||
55 | #else | ||
56 | # define CHK_DEBUGGER_TRAP() do { } while (0) | ||
57 | # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) | ||
44 | #endif | 58 | #endif |
45 | 59 | ||
46 | /* Initiate the event table handler */ | 60 | /* Initiate the event table handler */ |
@@ -53,8 +67,7 @@ void __init trap_init(void) | |||
53 | 67 | ||
54 | int kstack_depth_to_print = 48; | 68 | int kstack_depth_to_print = 48; |
55 | 69 | ||
56 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON | 70 | static void decode_address(char *buf, unsigned long address) |
57 | static void printk_address(unsigned long address) | ||
58 | { | 71 | { |
59 | struct vm_list_struct *vml; | 72 | struct vm_list_struct *vml; |
60 | struct task_struct *p; | 73 | struct task_struct *p; |
@@ -76,7 +89,7 @@ static void printk_address(unsigned long address) | |||
76 | /* yeah! kernel space! */ | 89 | /* yeah! kernel space! */ |
77 | if (!modname) | 90 | if (!modname) |
78 | modname = delim = ""; | 91 | modname = delim = ""; |
79 | printk("<0x%p> { %s%s%s%s + 0x%lx }", | 92 | sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }", |
80 | (void *)address, delim, modname, delim, symname, | 93 | (void *)address, delim, modname, delim, symname, |
81 | (unsigned long)offset); | 94 | (unsigned long)offset); |
82 | return; | 95 | return; |
@@ -84,6 +97,18 @@ static void printk_address(unsigned long address) | |||
84 | } | 97 | } |
85 | #endif | 98 | #endif |
86 | 99 | ||
100 | /* Problem in fixed code section? */ | ||
101 | if (address >= FIXED_CODE_START && address < FIXED_CODE_END) { | ||
102 | sprintf(buf, "<0x%p> /* Maybe fixed code section */", (void *)address); | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | /* Problem somewhere before the kernel start address */ | ||
107 | if (address < CONFIG_BOOT_LOAD) { | ||
108 | sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address); | ||
109 | return; | ||
110 | } | ||
111 | |||
87 | /* looks like we're off in user-land, so let's walk all the | 112 | /* looks like we're off in user-land, so let's walk all the |
88 | * mappings of all our processes and see if we can't be a whee | 113 | * mappings of all our processes and see if we can't be a whee |
89 | * bit more specific | 114 | * bit more specific |
@@ -119,7 +144,7 @@ static void printk_address(unsigned long address) | |||
119 | else | 144 | else |
120 | offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); | 145 | offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); |
121 | 146 | ||
122 | printk("<0x%p> [ %s + 0x%lx ]", | 147 | sprintf(buf, "<0x%p> [ %s + 0x%lx ]", |
123 | (void *)address, name, offset); | 148 | (void *)address, name, offset); |
124 | if (!in_exception) | 149 | if (!in_exception) |
125 | mmput(mm); | 150 | mmput(mm); |
@@ -133,15 +158,16 @@ static void printk_address(unsigned long address) | |||
133 | } | 158 | } |
134 | 159 | ||
135 | /* we were unable to find this address anywhere */ | 160 | /* we were unable to find this address anywhere */ |
136 | printk("[<0x%p>]", (void *)address); | 161 | sprintf(buf, "[<0x%p>]", (void *)address); |
137 | 162 | ||
138 | done: | 163 | done: |
139 | write_unlock_irqrestore(&tasklist_lock, flags); | 164 | write_unlock_irqrestore(&tasklist_lock, flags); |
140 | } | 165 | } |
141 | #endif | ||
142 | 166 | ||
143 | asmlinkage void double_fault_c(struct pt_regs *fp) | 167 | asmlinkage void double_fault_c(struct pt_regs *fp) |
144 | { | 168 | { |
169 | console_verbose(); | ||
170 | oops_in_progress = 1; | ||
145 | printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); | 171 | printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); |
146 | dump_bfin_regs(fp, (void *)fp->retx); | 172 | dump_bfin_regs(fp, (void *)fp->retx); |
147 | panic("Double Fault - unrecoverable event\n"); | 173 | panic("Double Fault - unrecoverable event\n"); |
@@ -157,22 +183,29 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
157 | siginfo_t info; | 183 | siginfo_t info; |
158 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; | 184 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; |
159 | 185 | ||
186 | trace_buffer_save(j); | ||
187 | |||
188 | /* Important - be very careful dereferncing pointers - will lead to | ||
189 | * double faults if the stack has become corrupt | ||
190 | */ | ||
191 | |||
192 | /* If the fault was caused by a kernel thread, or interrupt handler | ||
193 | * we will kernel panic, so the system reboots. | ||
194 | * If KGDB is enabled, don't set this for kernel breakpoints | ||
195 | */ | ||
196 | if ((bfin_read_IPEND() & 0xFFC0) | ||
160 | #ifdef CONFIG_KGDB | 197 | #ifdef CONFIG_KGDB |
161 | # define CHK_DEBUGGER_TRAP() \ | 198 | && trapnr != VEC_EXCPT02 |
162 | do { \ | ||
163 | CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \ | ||
164 | } while (0) | ||
165 | # define CHK_DEBUGGER_TRAP_MAYBE() \ | ||
166 | do { \ | ||
167 | if (kgdb_connected) \ | ||
168 | CHK_DEBUGGER_TRAP(); \ | ||
169 | } while (0) | ||
170 | #else | ||
171 | # define CHK_DEBUGGER_TRAP() do { } while (0) | ||
172 | # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) | ||
173 | #endif | 199 | #endif |
174 | 200 | ){ | |
175 | trace_buffer_save(j); | 201 | console_verbose(); |
202 | oops_in_progress = 1; | ||
203 | } else if (current) { | ||
204 | if (current->mm == NULL) { | ||
205 | console_verbose(); | ||
206 | oops_in_progress = 1; | ||
207 | } | ||
208 | } | ||
176 | 209 | ||
177 | /* trap_c() will be called for exceptions. During exceptions | 210 | /* trap_c() will be called for exceptions. During exceptions |
178 | * processing, the pc value should be set with retx value. | 211 | * processing, the pc value should be set with retx value. |
@@ -217,7 +250,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
217 | case VEC_EXCPT03: | 250 | case VEC_EXCPT03: |
218 | info.si_code = SEGV_STACKFLOW; | 251 | info.si_code = SEGV_STACKFLOW; |
219 | sig = SIGSEGV; | 252 | sig = SIGSEGV; |
220 | printk(KERN_EMERG EXC_0x03); | 253 | printk(KERN_NOTICE EXC_0x03); |
221 | CHK_DEBUGGER_TRAP(); | 254 | CHK_DEBUGGER_TRAP(); |
222 | break; | 255 | break; |
223 | /* 0x04 - User Defined, Caught by default */ | 256 | /* 0x04 - User Defined, Caught by default */ |
@@ -246,7 +279,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
246 | case VEC_OVFLOW: | 279 | case VEC_OVFLOW: |
247 | info.si_code = TRAP_TRACEFLOW; | 280 | info.si_code = TRAP_TRACEFLOW; |
248 | sig = SIGTRAP; | 281 | sig = SIGTRAP; |
249 | printk(KERN_EMERG EXC_0x11); | 282 | printk(KERN_NOTICE EXC_0x11); |
250 | CHK_DEBUGGER_TRAP(); | 283 | CHK_DEBUGGER_TRAP(); |
251 | break; | 284 | break; |
252 | /* 0x12 - Reserved, Caught by default */ | 285 | /* 0x12 - Reserved, Caught by default */ |
@@ -268,14 +301,14 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
268 | case VEC_UNDEF_I: | 301 | case VEC_UNDEF_I: |
269 | info.si_code = ILL_ILLOPC; | 302 | info.si_code = ILL_ILLOPC; |
270 | sig = SIGILL; | 303 | sig = SIGILL; |
271 | printk(KERN_EMERG EXC_0x21); | 304 | printk(KERN_NOTICE EXC_0x21); |
272 | CHK_DEBUGGER_TRAP(); | 305 | CHK_DEBUGGER_TRAP(); |
273 | break; | 306 | break; |
274 | /* 0x22 - Illegal Instruction Combination, handled here */ | 307 | /* 0x22 - Illegal Instruction Combination, handled here */ |
275 | case VEC_ILGAL_I: | 308 | case VEC_ILGAL_I: |
276 | info.si_code = ILL_ILLPARAOP; | 309 | info.si_code = ILL_ILLPARAOP; |
277 | sig = SIGILL; | 310 | sig = SIGILL; |
278 | printk(KERN_EMERG EXC_0x22); | 311 | printk(KERN_NOTICE EXC_0x22); |
279 | CHK_DEBUGGER_TRAP(); | 312 | CHK_DEBUGGER_TRAP(); |
280 | break; | 313 | break; |
281 | /* 0x23 - Data CPLB Protection Violation, | 314 | /* 0x23 - Data CPLB Protection Violation, |
@@ -283,21 +316,21 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
283 | case VEC_CPLB_VL: | 316 | case VEC_CPLB_VL: |
284 | info.si_code = ILL_CPLB_VI; | 317 | info.si_code = ILL_CPLB_VI; |
285 | sig = SIGILL; | 318 | sig = SIGILL; |
286 | printk(KERN_EMERG EXC_0x23); | 319 | printk(KERN_NOTICE EXC_0x23); |
287 | CHK_DEBUGGER_TRAP(); | 320 | CHK_DEBUGGER_TRAP(); |
288 | break; | 321 | break; |
289 | /* 0x24 - Data access misaligned, handled here */ | 322 | /* 0x24 - Data access misaligned, handled here */ |
290 | case VEC_MISALI_D: | 323 | case VEC_MISALI_D: |
291 | info.si_code = BUS_ADRALN; | 324 | info.si_code = BUS_ADRALN; |
292 | sig = SIGBUS; | 325 | sig = SIGBUS; |
293 | printk(KERN_EMERG EXC_0x24); | 326 | printk(KERN_NOTICE EXC_0x24); |
294 | CHK_DEBUGGER_TRAP(); | 327 | CHK_DEBUGGER_TRAP(); |
295 | break; | 328 | break; |
296 | /* 0x25 - Unrecoverable Event, handled here */ | 329 | /* 0x25 - Unrecoverable Event, handled here */ |
297 | case VEC_UNCOV: | 330 | case VEC_UNCOV: |
298 | info.si_code = ILL_ILLEXCPT; | 331 | info.si_code = ILL_ILLEXCPT; |
299 | sig = SIGILL; | 332 | sig = SIGILL; |
300 | printk(KERN_EMERG EXC_0x25); | 333 | printk(KERN_NOTICE EXC_0x25); |
301 | CHK_DEBUGGER_TRAP(); | 334 | CHK_DEBUGGER_TRAP(); |
302 | break; | 335 | break; |
303 | /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, | 336 | /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, |
@@ -305,7 +338,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
305 | case VEC_CPLB_M: | 338 | case VEC_CPLB_M: |
306 | info.si_code = BUS_ADRALN; | 339 | info.si_code = BUS_ADRALN; |
307 | sig = SIGBUS; | 340 | sig = SIGBUS; |
308 | printk(KERN_EMERG EXC_0x26); | 341 | printk(KERN_NOTICE EXC_0x26); |
309 | CHK_DEBUGGER_TRAP(); | 342 | CHK_DEBUGGER_TRAP(); |
310 | break; | 343 | break; |
311 | /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ | 344 | /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ |
@@ -313,11 +346,10 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
313 | info.si_code = ILL_CPLB_MULHIT; | 346 | info.si_code = ILL_CPLB_MULHIT; |
314 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | 347 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
315 | sig = SIGSEGV; | 348 | sig = SIGSEGV; |
316 | printk(KERN_EMERG "\n" | 349 | printk(KERN_NOTICE "NULL pointer access (probably)\n"); |
317 | KERN_EMERG "NULL pointer access (probably)\n"); | ||
318 | #else | 350 | #else |
319 | sig = SIGILL; | 351 | sig = SIGILL; |
320 | printk(KERN_EMERG EXC_0x27); | 352 | printk(KERN_NOTICE EXC_0x27); |
321 | #endif | 353 | #endif |
322 | CHK_DEBUGGER_TRAP(); | 354 | CHK_DEBUGGER_TRAP(); |
323 | break; | 355 | break; |
@@ -337,7 +369,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
337 | case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ | 369 | case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ |
338 | info.si_code = BUS_OPFETCH; | 370 | info.si_code = BUS_OPFETCH; |
339 | sig = SIGBUS; | 371 | sig = SIGBUS; |
340 | printk(KERN_EMERG "BF535: VEC_ISTRU_VL\n"); | 372 | printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); |
341 | CHK_DEBUGGER_TRAP(); | 373 | CHK_DEBUGGER_TRAP(); |
342 | break; | 374 | break; |
343 | #else | 375 | #else |
@@ -347,7 +379,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
347 | case VEC_MISALI_I: | 379 | case VEC_MISALI_I: |
348 | info.si_code = BUS_ADRALN; | 380 | info.si_code = BUS_ADRALN; |
349 | sig = SIGBUS; | 381 | sig = SIGBUS; |
350 | printk(KERN_EMERG EXC_0x2A); | 382 | printk(KERN_NOTICE EXC_0x2A); |
351 | CHK_DEBUGGER_TRAP(); | 383 | CHK_DEBUGGER_TRAP(); |
352 | break; | 384 | break; |
353 | /* 0x2B - Instruction CPLB protection Violation, | 385 | /* 0x2B - Instruction CPLB protection Violation, |
@@ -355,14 +387,14 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
355 | case VEC_CPLB_I_VL: | 387 | case VEC_CPLB_I_VL: |
356 | info.si_code = ILL_CPLB_VI; | 388 | info.si_code = ILL_CPLB_VI; |
357 | sig = SIGILL; | 389 | sig = SIGILL; |
358 | printk(KERN_EMERG EXC_0x2B); | 390 | printk(KERN_NOTICE EXC_0x2B); |
359 | CHK_DEBUGGER_TRAP(); | 391 | CHK_DEBUGGER_TRAP(); |
360 | break; | 392 | break; |
361 | /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ | 393 | /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ |
362 | case VEC_CPLB_I_M: | 394 | case VEC_CPLB_I_M: |
363 | info.si_code = ILL_CPLB_MISS; | 395 | info.si_code = ILL_CPLB_MISS; |
364 | sig = SIGBUS; | 396 | sig = SIGBUS; |
365 | printk(KERN_EMERG EXC_0x2C); | 397 | printk(KERN_NOTICE EXC_0x2C); |
366 | CHK_DEBUGGER_TRAP(); | 398 | CHK_DEBUGGER_TRAP(); |
367 | break; | 399 | break; |
368 | /* 0x2D - Instruction CPLB Multiple Hits, handled here */ | 400 | /* 0x2D - Instruction CPLB Multiple Hits, handled here */ |
@@ -370,10 +402,10 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
370 | info.si_code = ILL_CPLB_MULHIT; | 402 | info.si_code = ILL_CPLB_MULHIT; |
371 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | 403 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
372 | sig = SIGSEGV; | 404 | sig = SIGSEGV; |
373 | printk(KERN_EMERG "\n\nJump to address 0 - 0x0fff\n"); | 405 | printk(KERN_NOTICE "Jump to address 0 - 0x0fff\n"); |
374 | #else | 406 | #else |
375 | sig = SIGILL; | 407 | sig = SIGILL; |
376 | printk(KERN_EMERG EXC_0x2D); | 408 | printk(KERN_NOTICE EXC_0x2D); |
377 | #endif | 409 | #endif |
378 | CHK_DEBUGGER_TRAP(); | 410 | CHK_DEBUGGER_TRAP(); |
379 | break; | 411 | break; |
@@ -381,7 +413,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
381 | case VEC_ILL_RES: | 413 | case VEC_ILL_RES: |
382 | info.si_code = ILL_PRVOPC; | 414 | info.si_code = ILL_PRVOPC; |
383 | sig = SIGILL; | 415 | sig = SIGILL; |
384 | printk(KERN_EMERG EXC_0x2E); | 416 | printk(KERN_NOTICE EXC_0x2E); |
385 | CHK_DEBUGGER_TRAP(); | 417 | CHK_DEBUGGER_TRAP(); |
386 | break; | 418 | break; |
387 | /* 0x2F - Reserved, Caught by default */ | 419 | /* 0x2F - Reserved, Caught by default */ |
@@ -410,38 +442,40 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
410 | break; | 442 | break; |
411 | } | 443 | } |
412 | 444 | ||
413 | if (sig != 0 && sig != SIGTRAP) { | 445 | BUG_ON(sig == 0); |
446 | |||
447 | if (sig != SIGTRAP) { | ||
414 | unsigned long stack; | 448 | unsigned long stack; |
415 | dump_bfin_regs(fp, (void *)fp->retx); | 449 | dump_bfin_regs(fp, (void *)fp->retx); |
416 | dump_bfin_trace_buffer(); | 450 | |
451 | /* Print out the trace buffer if it makes sense */ | ||
452 | #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE | ||
453 | if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) | ||
454 | printk(KERN_NOTICE "No trace since you do not have " | ||
455 | "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n" | ||
456 | KERN_NOTICE "\n"); | ||
457 | else | ||
458 | #endif | ||
459 | dump_bfin_trace_buffer(); | ||
417 | show_stack(current, &stack); | 460 | show_stack(current, &stack); |
418 | if (current->mm == NULL) | 461 | if (oops_in_progress) { |
462 | #ifndef CONFIG_ACCESS_CHECK | ||
463 | printk(KERN_EMERG "Hey - dork - please turn on " | ||
464 | "CONFIG_ACCESS_CHECK\n"); | ||
465 | #endif | ||
419 | panic("Kernel exception"); | 466 | panic("Kernel exception"); |
467 | } | ||
468 | |||
469 | /* Ensure that bad return addresses don't end up in an infinite | ||
470 | * loop, due to speculative loads/reads | ||
471 | */ | ||
472 | fp->pc = SAFE_USER_INSTRUCTION; | ||
420 | } | 473 | } |
421 | info.si_signo = sig; | 474 | info.si_signo = sig; |
422 | info.si_errno = 0; | 475 | info.si_errno = 0; |
423 | info.si_addr = (void *)fp->pc; | 476 | info.si_addr = (void *)fp->pc; |
424 | force_sig_info(sig, &info, current); | 477 | force_sig_info(sig, &info, current); |
425 | 478 | ||
426 | /* if the address that we are about to return to is not valid, set it | ||
427 | * to a valid address, if we have a current application or panic | ||
428 | */ | ||
429 | if (!(fp->pc <= physical_mem_end | ||
430 | #if L1_CODE_LENGTH != 0 | ||
431 | || (fp->pc >= L1_CODE_START && | ||
432 | fp->pc <= (L1_CODE_START + L1_CODE_LENGTH)) | ||
433 | #endif | ||
434 | )) { | ||
435 | if (current->mm) { | ||
436 | fp->pc = current->mm->start_code; | ||
437 | } else { | ||
438 | printk(KERN_EMERG | ||
439 | "I can't return to memory that doesn't exist" | ||
440 | " - bad things happen\n"); | ||
441 | panic("Help - I've fallen and can't get up\n"); | ||
442 | } | ||
443 | } | ||
444 | |||
445 | trace_buffer_restore(j); | 479 | trace_buffer_restore(j); |
446 | return; | 480 | return; |
447 | } | 481 | } |
@@ -454,21 +488,21 @@ void dump_bfin_trace_buffer(void) | |||
454 | { | 488 | { |
455 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON | 489 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON |
456 | int tflags, i = 0; | 490 | int tflags, i = 0; |
491 | char buf[150]; | ||
457 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND | 492 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND |
458 | int j, index; | 493 | int j, index; |
459 | #endif | 494 | #endif |
460 | 495 | ||
461 | trace_buffer_save(tflags); | 496 | trace_buffer_save(tflags); |
462 | 497 | ||
463 | printk(KERN_EMERG "Hardware Trace:\n"); | 498 | printk(KERN_NOTICE "Hardware Trace:\n"); |
464 | 499 | ||
465 | if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) { | 500 | if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) { |
466 | for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) { | 501 | for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) { |
467 | printk(KERN_EMERG "%4i Target : ", i); | 502 | decode_address(buf, (unsigned long)bfin_read_TBUF()); |
468 | printk_address((unsigned long)bfin_read_TBUF()); | 503 | printk(KERN_NOTICE "%4i Target : %s\n", i, buf); |
469 | printk("\n" KERN_EMERG " Source : "); | 504 | decode_address(buf, (unsigned long)bfin_read_TBUF()); |
470 | printk_address((unsigned long)bfin_read_TBUF()); | 505 | printk(KERN_NOTICE " Source : %s\n", buf); |
471 | printk("\n"); | ||
472 | } | 506 | } |
473 | } | 507 | } |
474 | 508 | ||
@@ -480,17 +514,16 @@ void dump_bfin_trace_buffer(void) | |||
480 | 514 | ||
481 | j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128; | 515 | j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128; |
482 | while (j) { | 516 | while (j) { |
483 | printk(KERN_EMERG "%4i Target : ", i); | 517 | decode_address(buf, software_trace_buff[index]); |
484 | printk_address(software_trace_buff[index]); | 518 | printk(KERN_NOTICE "%4i Target : %s\n", i, buf); |
485 | index -= 1; | 519 | index -= 1; |
486 | if (index < 0 ) | 520 | if (index < 0 ) |
487 | index = EXPAND_LEN; | 521 | index = EXPAND_LEN; |
488 | printk("\n" KERN_EMERG " Source : "); | 522 | decode_address(buf, software_trace_buff[index]); |
489 | printk_address(software_trace_buff[index]); | 523 | printk(KERN_NOTICE " Source : %s\n", buf); |
490 | index -= 1; | 524 | index -= 1; |
491 | if (index < 0) | 525 | if (index < 0) |
492 | index = EXPAND_LEN; | 526 | index = EXPAND_LEN; |
493 | printk("\n"); | ||
494 | j--; | 527 | j--; |
495 | i++; | 528 | i++; |
496 | } | 529 | } |
@@ -505,10 +538,7 @@ static void show_trace(struct task_struct *tsk, unsigned long *sp) | |||
505 | { | 538 | { |
506 | unsigned long addr; | 539 | unsigned long addr; |
507 | 540 | ||
508 | printk("\nCall Trace:"); | 541 | printk(KERN_NOTICE "\n" KERN_NOTICE "Call Trace:\n"); |
509 | #ifdef CONFIG_KALLSYMS | ||
510 | printk("\n"); | ||
511 | #endif | ||
512 | 542 | ||
513 | while (!kstack_end(sp)) { | 543 | while (!kstack_end(sp)) { |
514 | addr = *sp++; | 544 | addr = *sp++; |
@@ -524,7 +554,7 @@ static void show_trace(struct task_struct *tsk, unsigned long *sp) | |||
524 | print_ip_sym(addr); | 554 | print_ip_sym(addr); |
525 | } | 555 | } |
526 | 556 | ||
527 | printk("\n"); | 557 | printk(KERN_NOTICE "\n"); |
528 | } | 558 | } |
529 | 559 | ||
530 | void show_stack(struct task_struct *task, unsigned long *stack) | 560 | void show_stack(struct task_struct *task, unsigned long *stack) |
@@ -546,14 +576,15 @@ void show_stack(struct task_struct *task, unsigned long *stack) | |||
546 | addr = (unsigned long)stack; | 576 | addr = (unsigned long)stack; |
547 | endstack = (unsigned long *)PAGE_ALIGN(addr); | 577 | endstack = (unsigned long *)PAGE_ALIGN(addr); |
548 | 578 | ||
549 | printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack); | 579 | printk(KERN_NOTICE "Stack from %08lx:", (unsigned long)stack); |
550 | for (i = 0; i < kstack_depth_to_print; i++) { | 580 | for (i = 0; i < kstack_depth_to_print; i++) { |
551 | if (stack + 1 > endstack) | 581 | if (stack + 1 > endstack) |
552 | break; | 582 | break; |
553 | if (i % 8 == 0) | 583 | if (i % 8 == 0) |
554 | printk("\n" KERN_EMERG " "); | 584 | printk("\n" KERN_NOTICE " "); |
555 | printk(" %08lx", *stack++); | 585 | printk(" %08lx", *stack++); |
556 | } | 586 | } |
587 | printk("\n"); | ||
557 | 588 | ||
558 | show_trace(task, stack); | 589 | show_trace(task, stack); |
559 | } | 590 | } |
@@ -574,33 +605,34 @@ EXPORT_SYMBOL(dump_stack); | |||
574 | 605 | ||
575 | void dump_bfin_regs(struct pt_regs *fp, void *retaddr) | 606 | void dump_bfin_regs(struct pt_regs *fp, void *retaddr) |
576 | { | 607 | { |
577 | if (current->pid) { | 608 | char buf [150]; |
578 | printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n" | 609 | |
579 | KERN_EMERG "\n"); | 610 | if (!oops_in_progress) { |
580 | printk(KERN_EMERG "COMM=%s PID=%d\n", | 611 | if (current->pid && current->mm) { |
581 | current->comm, current->pid); | 612 | printk(KERN_NOTICE "\n" KERN_NOTICE "CURRENT PROCESS:\n"); |
613 | printk(KERN_NOTICE "COMM=%s PID=%d\n", | ||
614 | current->comm, current->pid); | ||
615 | |||
616 | printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" | ||
617 | KERN_NOTICE "BSS = 0x%p-0x%p USER-STACK = 0x%p\n" | ||
618 | KERN_NOTICE "\n", | ||
619 | (void *)current->mm->start_code, | ||
620 | (void *)current->mm->end_code, | ||
621 | (void *)current->mm->start_data, | ||
622 | (void *)current->mm->end_data, | ||
623 | (void *)current->mm->end_data, | ||
624 | (void *)current->mm->brk, | ||
625 | (void *)current->mm->start_stack); | ||
626 | } else { | ||
627 | printk (KERN_NOTICE "\n" KERN_NOTICE | ||
628 | "No Valid pid - Either things are really messed up," | ||
629 | " or you are in the kernel\n"); | ||
630 | } | ||
582 | } else { | 631 | } else { |
583 | printk | 632 | printk(KERN_NOTICE "Kernel or interrupt exception\n"); |
584 | (KERN_EMERG "\n" KERN_EMERG | ||
585 | "No Valid pid - Either things are really messed up," | ||
586 | " or you are in the kernel\n"); | ||
587 | } | ||
588 | |||
589 | if (current->mm) { | ||
590 | printk(KERN_EMERG "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" | ||
591 | KERN_EMERG "BSS = 0x%p-0x%p USER-STACK = 0x%p\n" | ||
592 | KERN_EMERG "\n", | ||
593 | (void *)current->mm->start_code, | ||
594 | (void *)current->mm->end_code, | ||
595 | (void *)current->mm->start_data, | ||
596 | (void *)current->mm->end_data, | ||
597 | (void *)current->mm->end_data, | ||
598 | (void *)current->mm->brk, | ||
599 | (void *)current->mm->start_stack); | ||
600 | } | 633 | } |
601 | 634 | ||
602 | printk(KERN_EMERG "return address: [0x%p]; contents of:", retaddr); | 635 | if (retaddr >= (void *)FIXED_CODE_START && retaddr < (void *)physical_mem_end |
603 | if (retaddr != 0 && retaddr <= (void *)physical_mem_end | ||
604 | #if L1_CODE_LENGTH != 0 | 636 | #if L1_CODE_LENGTH != 0 |
605 | /* FIXME: Copy the code out of L1 Instruction SRAM through dma | 637 | /* FIXME: Copy the code out of L1 Instruction SRAM through dma |
606 | memcpy. */ | 638 | memcpy. */ |
@@ -610,18 +642,20 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr) | |||
610 | ) { | 642 | ) { |
611 | int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32; | 643 | int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32; |
612 | unsigned short x = 0; | 644 | unsigned short x = 0; |
645 | printk(KERN_NOTICE "return address: [0x%p]; contents of:", retaddr); | ||
613 | for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) { | 646 | for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) { |
614 | if (!(i & 0xF)) | 647 | if (!(i & 0xF)) |
615 | printk("\n" KERN_EMERG "0x%08x: ", i); | 648 | printk("\n" KERN_NOTICE "0x%08x: ", i); |
616 | 649 | ||
617 | if (get_user(x, (unsigned short *)i)) | 650 | if (get_user(x, (unsigned short *)i)) |
618 | break; | 651 | break; |
619 | #ifndef CONFIG_DEBUG_HWERR | 652 | #ifndef CONFIG_DEBUG_HWERR |
620 | /* If one of the last few instructions was a STI | 653 | /* If one of the last few instructions was a STI |
621 | * it is likely that the error occured awhile ago | 654 | * it is likely that the error occured awhile ago |
622 | * and we just noticed | 655 | * and we just noticed. This only happens in kernel |
656 | * context, which should mean an oops is happening | ||
623 | */ | 657 | */ |
624 | if (x >= 0x0040 && x <= 0x0047 && i <= 0) | 658 | if (oops_in_progress && x >= 0x0040 && x <= 0x0047 && i <= 0) |
625 | panic("\n\nWARNING : You should reconfigure" | 659 | panic("\n\nWARNING : You should reconfigure" |
626 | " the kernel to turn on\n" | 660 | " the kernel to turn on\n" |
627 | " 'Hardware error interrupt" | 661 | " 'Hardware error interrupt" |
@@ -634,56 +668,60 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr) | |||
634 | else | 668 | else |
635 | printk(" %04x ", x); | 669 | printk(" %04x ", x); |
636 | } | 670 | } |
637 | printk("\n" KERN_EMERG "\n"); | 671 | printk("\n"); |
638 | } else | 672 | } else |
639 | printk(KERN_EMERG | 673 | printk("\n" KERN_NOTICE |
640 | "Cannot look at the [PC] for it is" | 674 | "Cannot look at the [PC] for it is" |
641 | "in unreadable L1 SRAM - sorry\n"); | 675 | " in unreadable memory - sorry\n"); |
676 | |||
677 | printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n"); | ||
678 | printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", | ||
679 | (long)fp->seqstat, fp->ipend, fp->syscfg); | ||
642 | 680 | ||
681 | decode_address(buf, fp->rete); | ||
682 | printk(KERN_NOTICE " RETE: %s\n", buf); | ||
683 | decode_address(buf, fp->retn); | ||
684 | printk(KERN_NOTICE " RETN: %s\n", buf); | ||
685 | decode_address(buf, fp->retx); | ||
686 | printk(KERN_NOTICE " RETX: %s\n", buf); | ||
687 | decode_address(buf, fp->rets); | ||
688 | printk(KERN_NOTICE " RETS: %s\n", buf); | ||
643 | 689 | ||
644 | printk(KERN_EMERG | 690 | if ((long)fp->seqstat & SEQSTAT_EXCAUSE) { |
645 | "RETE: %08lx RETN: %08lx RETX: %08lx RETS: %08lx\n", | 691 | decode_address(buf, bfin_read_DCPLB_FAULT_ADDR()); |
646 | fp->rete, fp->retn, fp->retx, fp->rets); | 692 | printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); |
647 | printk(KERN_EMERG "IPEND: %04lx SYSCFG: %04lx\n", | 693 | decode_address(buf, bfin_read_ICPLB_FAULT_ADDR()); |
648 | fp->ipend, fp->syscfg); | 694 | printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); |
649 | printk(KERN_EMERG "SEQSTAT: %08lx SP: %08lx\n", | 695 | } |
650 | (long)fp->seqstat, (long)fp); | 696 | |
651 | printk(KERN_EMERG "R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n", | 697 | printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); |
698 | printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", | ||
652 | fp->r0, fp->r1, fp->r2, fp->r3); | 699 | fp->r0, fp->r1, fp->r2, fp->r3); |
653 | printk(KERN_EMERG "R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n", | 700 | printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", |
654 | fp->r4, fp->r5, fp->r6, fp->r7); | 701 | fp->r4, fp->r5, fp->r6, fp->r7); |
655 | printk(KERN_EMERG "P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n", | 702 | printk(KERN_NOTICE " P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n", |
656 | fp->p0, fp->p1, fp->p2, fp->p3); | 703 | fp->p0, fp->p1, fp->p2, fp->p3); |
657 | printk(KERN_EMERG | 704 | printk(KERN_NOTICE " P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n", |
658 | "P4: %08lx P5: %08lx FP: %08lx\n", | 705 | fp->p4, fp->p5, fp->fp, (long)fp); |
659 | fp->p4, fp->p5, fp->fp); | 706 | printk(KERN_NOTICE " LB0: %08lx LT0: %08lx LC0: %08lx\n", |
660 | printk(KERN_EMERG | ||
661 | "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", | ||
662 | fp->a0w, fp->a0x, fp->a1w, fp->a1x); | ||
663 | |||
664 | printk(KERN_EMERG "LB0: %08lx LT0: %08lx LC0: %08lx\n", | ||
665 | fp->lb0, fp->lt0, fp->lc0); | 707 | fp->lb0, fp->lt0, fp->lc0); |
666 | printk(KERN_EMERG "LB1: %08lx LT1: %08lx LC1: %08lx\n", | 708 | printk(KERN_NOTICE " LB1: %08lx LT1: %08lx LC1: %08lx\n", |
667 | fp->lb1, fp->lt1, fp->lc1); | 709 | fp->lb1, fp->lt1, fp->lc1); |
668 | printk(KERN_EMERG "B0: %08lx L0: %08lx M0: %08lx I0: %08lx\n", | 710 | printk(KERN_NOTICE " B0 : %08lx L0 : %08lx M0 : %08lx I0 : %08lx\n", |
669 | fp->b0, fp->l0, fp->m0, fp->i0); | 711 | fp->b0, fp->l0, fp->m0, fp->i0); |
670 | printk(KERN_EMERG "B1: %08lx L1: %08lx M1: %08lx I1: %08lx\n", | 712 | printk(KERN_NOTICE " B1 : %08lx L1 : %08lx M1 : %08lx I1 : %08lx\n", |
671 | fp->b1, fp->l1, fp->m1, fp->i1); | 713 | fp->b1, fp->l1, fp->m1, fp->i1); |
672 | printk(KERN_EMERG "B2: %08lx L2: %08lx M2: %08lx I2: %08lx\n", | 714 | printk(KERN_NOTICE " B2 : %08lx L2 : %08lx M2 : %08lx I2 : %08lx\n", |
673 | fp->b2, fp->l2, fp->m2, fp->i2); | 715 | fp->b2, fp->l2, fp->m2, fp->i2); |
674 | printk(KERN_EMERG "B3: %08lx L3: %08lx M3: %08lx I3: %08lx\n", | 716 | printk(KERN_NOTICE " B3 : %08lx L3 : %08lx M3 : %08lx I3 : %08lx\n", |
675 | fp->b3, fp->l3, fp->m3, fp->i3); | 717 | fp->b3, fp->l3, fp->m3, fp->i3); |
718 | printk(KERN_NOTICE "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", | ||
719 | fp->a0w, fp->a0x, fp->a1w, fp->a1x); | ||
676 | 720 | ||
677 | printk(KERN_EMERG "\n" KERN_EMERG "USP: %08lx ASTAT: %08lx\n", | 721 | printk(KERN_NOTICE "USP : %08lx ASTAT: %08lx\n", |
678 | rdusp(), fp->astat); | 722 | rdusp(), fp->astat); |
679 | if ((long)fp->seqstat & SEQSTAT_EXCAUSE) { | ||
680 | printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", | ||
681 | (void *)bfin_read_DCPLB_FAULT_ADDR()); | ||
682 | printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", | ||
683 | (void *)bfin_read_ICPLB_FAULT_ADDR()); | ||
684 | } | ||
685 | 723 | ||
686 | printk("\n\n"); | 724 | printk(KERN_NOTICE "\n"); |
687 | } | 725 | } |
688 | 726 | ||
689 | #ifdef CONFIG_SYS_BFIN_SPINLOCK_L1 | 727 | #ifdef CONFIG_SYS_BFIN_SPINLOCK_L1 |
@@ -758,6 +796,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp) | |||
758 | break; | 796 | break; |
759 | } | 797 | } |
760 | 798 | ||
799 | oops_in_progress = 1; | ||
800 | |||
761 | printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR()); | 801 | printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR()); |
762 | printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR()); | 802 | printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR()); |
763 | dump_bfin_regs(fp, (void *)fp->retx); | 803 | dump_bfin_regs(fp, (void *)fp->retx); |