aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/traps.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-06-07 17:08:28 -0400
committerMike Frysinger <vapier@gentoo.org>2009-06-13 07:20:09 -0400
commit82bd1d7d45a69c54fb6beedb78ccb1c7d308dd93 (patch)
treef9a60086a663ab07304db13eacb53b7ce325b42f /arch/blackfin/kernel/traps.c
parent6510a20e1b1a3a5703429a09d03adf44882ae373 (diff)
Blackfin: push down exception oops checking
Rather than maintain a duplicate list of valid exceptions we can take in the kernel both in the first if() check and the switch() check, delay the oops check to after the switch(). All valid exceptions will have returned by this point leaving only the invalid ones. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r--arch/blackfin/kernel/traps.c88
1 files changed, 43 insertions, 45 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index ed7127b1b9f9..d279552fe9b0 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -239,6 +239,11 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
239 239
240} 240}
241 241
242static int kernel_mode_regs(struct pt_regs *regs)
243{
244 return regs->ipend & 0xffc0;
245}
246
242asmlinkage void trap_c(struct pt_regs *fp) 247asmlinkage void trap_c(struct pt_regs *fp)
243{ 248{
244#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON 249#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
@@ -247,6 +252,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
247#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO 252#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
248 unsigned int cpu = smp_processor_id(); 253 unsigned int cpu = smp_processor_id();
249#endif 254#endif
255 const char *strerror = NULL;
250 int sig = 0; 256 int sig = 0;
251 siginfo_t info; 257 siginfo_t info;
252 unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; 258 unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
@@ -260,27 +266,10 @@ asmlinkage void trap_c(struct pt_regs *fp)
260 * double faults if the stack has become corrupt 266 * double faults if the stack has become corrupt
261 */ 267 */
262 268
263 /* If the fault was caused by a kernel thread, or interrupt handler 269#ifndef CONFIG_KGDB
264 * we will kernel panic, so the system reboots. 270 /* IPEND is skipped if KGDB isn't enabled (see entry code) */
265 * If KGDB is enabled, don't set this for kernel breakpoints 271 fp->ipend = bfin_read_IPEND();
266 */
267
268 /* TODO: check to see if we are in some sort of deferred HWERR
269 * that we should be able to recover from, not kernel panic
270 */
271 if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP)
272#ifdef CONFIG_KGDB
273 && (trapnr != VEC_EXCPT02)
274#endif 272#endif
275 ){
276 console_verbose();
277 oops_in_progress = 1;
278 } else if (current) {
279 if (current->mm == NULL) {
280 console_verbose();
281 oops_in_progress = 1;
282 }
283 }
284 273
285 /* trap_c() will be called for exceptions. During exceptions 274 /* trap_c() will be called for exceptions. During exceptions
286 * processing, the pc value should be set with retx value. 275 * processing, the pc value should be set with retx value.
@@ -308,7 +297,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
308 sig = SIGTRAP; 297 sig = SIGTRAP;
309 CHK_DEBUGGER_TRAP_MAYBE(); 298 CHK_DEBUGGER_TRAP_MAYBE();
310 /* Check if this is a breakpoint in kernel space */ 299 /* Check if this is a breakpoint in kernel space */
311 if (fp->ipend & 0xffc0) 300 if (kernel_mode_regs(fp))
312 goto traps_done; 301 goto traps_done;
313 else 302 else
314 break; 303 break;
@@ -316,7 +305,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
316 case VEC_EXCPT03: 305 case VEC_EXCPT03:
317 info.si_code = SEGV_STACKFLOW; 306 info.si_code = SEGV_STACKFLOW;
318 sig = SIGSEGV; 307 sig = SIGSEGV;
319 verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); 308 strerror = KERN_NOTICE EXC_0x03(KERN_NOTICE);
320 CHK_DEBUGGER_TRAP_MAYBE(); 309 CHK_DEBUGGER_TRAP_MAYBE();
321 break; 310 break;
322 /* 0x02 - KGDB initial connection and break signal trap */ 311 /* 0x02 - KGDB initial connection and break signal trap */
@@ -345,7 +334,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
345 case VEC_EXCPT04 ... VEC_EXCPT15: 334 case VEC_EXCPT04 ... VEC_EXCPT15:
346 info.si_code = ILL_ILLPARAOP; 335 info.si_code = ILL_ILLPARAOP;
347 sig = SIGILL; 336 sig = SIGILL;
348 verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE)); 337 strerror = KERN_NOTICE EXC_0x04(KERN_NOTICE);
349 CHK_DEBUGGER_TRAP_MAYBE(); 338 CHK_DEBUGGER_TRAP_MAYBE();
350 break; 339 break;
351 /* 0x10 HW Single step, handled here */ 340 /* 0x10 HW Single step, handled here */
@@ -354,7 +343,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
354 sig = SIGTRAP; 343 sig = SIGTRAP;
355 CHK_DEBUGGER_TRAP_MAYBE(); 344 CHK_DEBUGGER_TRAP_MAYBE();
356 /* Check if this is a single step in kernel space */ 345 /* Check if this is a single step in kernel space */
357 if (fp->ipend & 0xffc0) 346 if (kernel_mode_regs(fp))
358 goto traps_done; 347 goto traps_done;
359 else 348 else
360 break; 349 break;
@@ -362,7 +351,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
362 case VEC_OVFLOW: 351 case VEC_OVFLOW:
363 info.si_code = TRAP_TRACEFLOW; 352 info.si_code = TRAP_TRACEFLOW;
364 sig = SIGTRAP; 353 sig = SIGTRAP;
365 verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); 354 strerror = KERN_NOTICE EXC_0x11(KERN_NOTICE);
366 CHK_DEBUGGER_TRAP_MAYBE(); 355 CHK_DEBUGGER_TRAP_MAYBE();
367 break; 356 break;
368 /* 0x12 - Reserved, Caught by default */ 357 /* 0x12 - Reserved, Caught by default */
@@ -401,35 +390,35 @@ asmlinkage void trap_c(struct pt_regs *fp)
401#endif 390#endif
402 info.si_code = ILL_ILLOPC; 391 info.si_code = ILL_ILLOPC;
403 sig = SIGILL; 392 sig = SIGILL;
404 verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); 393 strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE);
405 CHK_DEBUGGER_TRAP_MAYBE(); 394 CHK_DEBUGGER_TRAP_MAYBE();
406 break; 395 break;
407 /* 0x22 - Illegal Instruction Combination, handled here */ 396 /* 0x22 - Illegal Instruction Combination, handled here */
408 case VEC_ILGAL_I: 397 case VEC_ILGAL_I:
409 info.si_code = ILL_ILLPARAOP; 398 info.si_code = ILL_ILLPARAOP;
410 sig = SIGILL; 399 sig = SIGILL;
411 verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); 400 strerror = KERN_NOTICE EXC_0x22(KERN_NOTICE);
412 CHK_DEBUGGER_TRAP_MAYBE(); 401 CHK_DEBUGGER_TRAP_MAYBE();
413 break; 402 break;
414 /* 0x23 - Data CPLB protection violation, handled here */ 403 /* 0x23 - Data CPLB protection violation, handled here */
415 case VEC_CPLB_VL: 404 case VEC_CPLB_VL:
416 info.si_code = ILL_CPLB_VI; 405 info.si_code = ILL_CPLB_VI;
417 sig = SIGBUS; 406 sig = SIGBUS;
418 verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); 407 strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
419 CHK_DEBUGGER_TRAP_MAYBE(); 408 CHK_DEBUGGER_TRAP_MAYBE();
420 break; 409 break;
421 /* 0x24 - Data access misaligned, handled here */ 410 /* 0x24 - Data access misaligned, handled here */
422 case VEC_MISALI_D: 411 case VEC_MISALI_D:
423 info.si_code = BUS_ADRALN; 412 info.si_code = BUS_ADRALN;
424 sig = SIGBUS; 413 sig = SIGBUS;
425 verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); 414 strerror = KERN_NOTICE EXC_0x24(KERN_NOTICE);
426 CHK_DEBUGGER_TRAP_MAYBE(); 415 CHK_DEBUGGER_TRAP_MAYBE();
427 break; 416 break;
428 /* 0x25 - Unrecoverable Event, handled here */ 417 /* 0x25 - Unrecoverable Event, handled here */
429 case VEC_UNCOV: 418 case VEC_UNCOV:
430 info.si_code = ILL_ILLEXCPT; 419 info.si_code = ILL_ILLEXCPT;
431 sig = SIGILL; 420 sig = SIGILL;
432 verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); 421 strerror = KERN_NOTICE EXC_0x25(KERN_NOTICE);
433 CHK_DEBUGGER_TRAP_MAYBE(); 422 CHK_DEBUGGER_TRAP_MAYBE();
434 break; 423 break;
435 /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, 424 /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
@@ -437,7 +426,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
437 case VEC_CPLB_M: 426 case VEC_CPLB_M:
438 info.si_code = BUS_ADRALN; 427 info.si_code = BUS_ADRALN;
439 sig = SIGBUS; 428 sig = SIGBUS;
440 verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); 429 strerror = KERN_NOTICE EXC_0x26(KERN_NOTICE);
441 break; 430 break;
442 /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ 431 /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
443 case VEC_CPLB_MHIT: 432 case VEC_CPLB_MHIT:
@@ -445,10 +434,10 @@ asmlinkage void trap_c(struct pt_regs *fp)
445 sig = SIGSEGV; 434 sig = SIGSEGV;
446#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO 435#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
447 if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START) 436 if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
448 verbose_printk(KERN_NOTICE "NULL pointer access\n"); 437 strerror = KERN_NOTICE "NULL pointer access\n";
449 else 438 else
450#endif 439#endif
451 verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); 440 strerror = KERN_NOTICE EXC_0x27(KERN_NOTICE);
452 CHK_DEBUGGER_TRAP_MAYBE(); 441 CHK_DEBUGGER_TRAP_MAYBE();
453 break; 442 break;
454 /* 0x28 - Emulation Watchpoint, handled here */ 443 /* 0x28 - Emulation Watchpoint, handled here */
@@ -458,7 +447,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
458 pr_debug(EXC_0x28(KERN_DEBUG)); 447 pr_debug(EXC_0x28(KERN_DEBUG));
459 CHK_DEBUGGER_TRAP_MAYBE(); 448 CHK_DEBUGGER_TRAP_MAYBE();
460 /* Check if this is a watchpoint in kernel space */ 449 /* Check if this is a watchpoint in kernel space */
461 if (fp->ipend & 0xffc0) 450 if (kernel_mode_regs(fp))
462 goto traps_done; 451 goto traps_done;
463 else 452 else
464 break; 453 break;
@@ -467,7 +456,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
467 case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ 456 case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */
468 info.si_code = BUS_OPFETCH; 457 info.si_code = BUS_OPFETCH;
469 sig = SIGBUS; 458 sig = SIGBUS;
470 verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); 459 strerror = KERN_NOTICE "BF535: VEC_ISTRU_VL\n";
471 CHK_DEBUGGER_TRAP_MAYBE(); 460 CHK_DEBUGGER_TRAP_MAYBE();
472 break; 461 break;
473#else 462#else
@@ -477,21 +466,21 @@ asmlinkage void trap_c(struct pt_regs *fp)
477 case VEC_MISALI_I: 466 case VEC_MISALI_I:
478 info.si_code = BUS_ADRALN; 467 info.si_code = BUS_ADRALN;
479 sig = SIGBUS; 468 sig = SIGBUS;
480 verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); 469 strerror = KERN_NOTICE EXC_0x2A(KERN_NOTICE);
481 CHK_DEBUGGER_TRAP_MAYBE(); 470 CHK_DEBUGGER_TRAP_MAYBE();
482 break; 471 break;
483 /* 0x2B - Instruction CPLB protection violation, handled here */ 472 /* 0x2B - Instruction CPLB protection violation, handled here */
484 case VEC_CPLB_I_VL: 473 case VEC_CPLB_I_VL:
485 info.si_code = ILL_CPLB_VI; 474 info.si_code = ILL_CPLB_VI;
486 sig = SIGBUS; 475 sig = SIGBUS;
487 verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); 476 strerror = KERN_NOTICE EXC_0x2B(KERN_NOTICE);
488 CHK_DEBUGGER_TRAP_MAYBE(); 477 CHK_DEBUGGER_TRAP_MAYBE();
489 break; 478 break;
490 /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ 479 /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
491 case VEC_CPLB_I_M: 480 case VEC_CPLB_I_M:
492 info.si_code = ILL_CPLB_MISS; 481 info.si_code = ILL_CPLB_MISS;
493 sig = SIGBUS; 482 sig = SIGBUS;
494 verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); 483 strerror = KERN_NOTICE EXC_0x2C(KERN_NOTICE);
495 break; 484 break;
496 /* 0x2D - Instruction CPLB Multiple Hits, handled here */ 485 /* 0x2D - Instruction CPLB Multiple Hits, handled here */
497 case VEC_CPLB_I_MHIT: 486 case VEC_CPLB_I_MHIT:
@@ -499,17 +488,17 @@ asmlinkage void trap_c(struct pt_regs *fp)
499 sig = SIGSEGV; 488 sig = SIGSEGV;
500#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO 489#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
501 if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START) 490 if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
502 verbose_printk(KERN_NOTICE "Jump to NULL address\n"); 491 strerror = KERN_NOTICE "Jump to NULL address\n";
503 else 492 else
504#endif 493#endif
505 verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); 494 strerror = KERN_NOTICE EXC_0x2D(KERN_NOTICE);
506 CHK_DEBUGGER_TRAP_MAYBE(); 495 CHK_DEBUGGER_TRAP_MAYBE();
507 break; 496 break;
508 /* 0x2E - Illegal use of Supervisor Resource, handled here */ 497 /* 0x2E - Illegal use of Supervisor Resource, handled here */
509 case VEC_ILL_RES: 498 case VEC_ILL_RES:
510 info.si_code = ILL_PRVOPC; 499 info.si_code = ILL_PRVOPC;
511 sig = SIGILL; 500 sig = SIGILL;
512 verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); 501 strerror = KERN_NOTICE EXC_0x2E(KERN_NOTICE);
513 CHK_DEBUGGER_TRAP_MAYBE(); 502 CHK_DEBUGGER_TRAP_MAYBE();
514 break; 503 break;
515 /* 0x2F - Reserved, Caught by default */ 504 /* 0x2F - Reserved, Caught by default */
@@ -537,17 +526,17 @@ asmlinkage void trap_c(struct pt_regs *fp)
537 case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): 526 case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
538 info.si_code = BUS_ADRALN; 527 info.si_code = BUS_ADRALN;
539 sig = SIGBUS; 528 sig = SIGBUS;
540 verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE)); 529 strerror = KERN_NOTICE HWC_x2(KERN_NOTICE);
541 break; 530 break;
542 /* External Memory Addressing Error */ 531 /* External Memory Addressing Error */
543 case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): 532 case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
544 info.si_code = BUS_ADRERR; 533 info.si_code = BUS_ADRERR;
545 sig = SIGBUS; 534 sig = SIGBUS;
546 verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE)); 535 strerror = KERN_NOTICE HWC_x3(KERN_NOTICE);
547 break; 536 break;
548 /* Performance Monitor Overflow */ 537 /* Performance Monitor Overflow */
549 case (SEQSTAT_HWERRCAUSE_PERF_FLOW): 538 case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
550 verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE)); 539 strerror = KERN_NOTICE HWC_x12(KERN_NOTICE);
551 break; 540 break;
552 /* RAISE 5 instruction */ 541 /* RAISE 5 instruction */
553 case (SEQSTAT_HWERRCAUSE_RAISE_5): 542 case (SEQSTAT_HWERRCAUSE_RAISE_5):
@@ -564,7 +553,6 @@ asmlinkage void trap_c(struct pt_regs *fp)
564 * if we get here we hit a reserved one, so panic 553 * if we get here we hit a reserved one, so panic
565 */ 554 */
566 default: 555 default:
567 oops_in_progress = 1;
568 info.si_code = ILL_ILLPARAOP; 556 info.si_code = ILL_ILLPARAOP;
569 sig = SIGILL; 557 sig = SIGILL;
570 verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", 558 verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
@@ -575,6 +563,16 @@ asmlinkage void trap_c(struct pt_regs *fp)
575 563
576 BUG_ON(sig == 0); 564 BUG_ON(sig == 0);
577 565
566 /* If the fault was caused by a kernel thread, or interrupt handler
567 * we will kernel panic, so the system reboots.
568 */
569 if (kernel_mode_regs(fp) || (current && !current->mm)) {
570 console_verbose();
571 oops_in_progress = 1;
572 if (strerror)
573 verbose_printk(strerror);
574 }
575
578 if (sig != SIGTRAP) { 576 if (sig != SIGTRAP) {
579 dump_bfin_process(fp); 577 dump_bfin_process(fp);
580 dump_bfin_mem(fp); 578 dump_bfin_mem(fp);