aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);