diff options
Diffstat (limited to 'arch/arm/mm/fault.c')
-rw-r--r-- | arch/arm/mm/fault.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 379f78556055..ae0e25f5a70e 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -519,9 +519,58 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
519 | arm_notify_die("", regs, &info, fsr, 0); | 519 | arm_notify_die("", regs, &info, fsr, 0); |
520 | } | 520 | } |
521 | 521 | ||
522 | |||
523 | static struct fsr_info ifsr_info[] = { | ||
524 | { do_bad, SIGBUS, 0, "unknown 0" }, | ||
525 | { do_bad, SIGBUS, 0, "unknown 1" }, | ||
526 | { do_bad, SIGBUS, 0, "debug event" }, | ||
527 | { do_bad, SIGSEGV, SEGV_ACCERR, "section access flag fault" }, | ||
528 | { do_bad, SIGBUS, 0, "unknown 4" }, | ||
529 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, | ||
530 | { do_bad, SIGSEGV, SEGV_ACCERR, "page access flag fault" }, | ||
531 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, | ||
532 | { do_bad, SIGBUS, 0, "external abort on non-linefetch" }, | ||
533 | { do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" }, | ||
534 | { do_bad, SIGBUS, 0, "unknown 10" }, | ||
535 | { do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" }, | ||
536 | { do_bad, SIGBUS, 0, "external abort on translation" }, | ||
537 | { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" }, | ||
538 | { do_bad, SIGBUS, 0, "external abort on translation" }, | ||
539 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" }, | ||
540 | { do_bad, SIGBUS, 0, "unknown 16" }, | ||
541 | { do_bad, SIGBUS, 0, "unknown 17" }, | ||
542 | { do_bad, SIGBUS, 0, "unknown 18" }, | ||
543 | { do_bad, SIGBUS, 0, "unknown 19" }, | ||
544 | { do_bad, SIGBUS, 0, "unknown 20" }, | ||
545 | { do_bad, SIGBUS, 0, "unknown 21" }, | ||
546 | { do_bad, SIGBUS, 0, "unknown 22" }, | ||
547 | { do_bad, SIGBUS, 0, "unknown 23" }, | ||
548 | { do_bad, SIGBUS, 0, "unknown 24" }, | ||
549 | { do_bad, SIGBUS, 0, "unknown 25" }, | ||
550 | { do_bad, SIGBUS, 0, "unknown 26" }, | ||
551 | { do_bad, SIGBUS, 0, "unknown 27" }, | ||
552 | { do_bad, SIGBUS, 0, "unknown 28" }, | ||
553 | { do_bad, SIGBUS, 0, "unknown 29" }, | ||
554 | { do_bad, SIGBUS, 0, "unknown 30" }, | ||
555 | { do_bad, SIGBUS, 0, "unknown 31" }, | ||
556 | }; | ||
557 | |||
522 | asmlinkage void __exception | 558 | asmlinkage void __exception |
523 | do_PrefetchAbort(unsigned long addr, struct pt_regs *regs) | 559 | do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) |
524 | { | 560 | { |
525 | do_translation_fault(addr, FSR_LNX_PF, regs); | 561 | const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); |
562 | struct siginfo info; | ||
563 | |||
564 | if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) | ||
565 | return; | ||
566 | |||
567 | printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", | ||
568 | inf->name, ifsr, addr); | ||
569 | |||
570 | info.si_signo = inf->sig; | ||
571 | info.si_errno = 0; | ||
572 | info.si_code = inf->code; | ||
573 | info.si_addr = (void __user *)addr; | ||
574 | arm_notify_die("", regs, &info, ifsr, 0); | ||
526 | } | 575 | } |
527 | 576 | ||