diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-10-02 16:20:43 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-10-02 16:20:43 -0700 |
commit | a037a79dceaf717409fbf42f4ad209b9c15f435c (patch) | |
tree | c30b5b033c74ab9470e875554bded16464bbdf9b /arch/arm/mm/fault.c | |
parent | 90d5ffc729e92bffc0f84e2447e2e6dc280240a5 (diff) | |
parent | d25ef8b86e6a58f5476bf6e4a8da730b335f68fa (diff) | |
download | linux-a037a79dceaf717409fbf42f4ad209b9c15f435c.tar.bz2 |
Merge master.kernel.org:/home/rmk/linux-2.6-arm
* master.kernel.org:/home/rmk/linux-2.6-arm: (25 commits)
ARM: 5728/1: Proper prefetch abort handling on ARMv6 and ARMv7
ARM: 5727/1: Pass IFSR register to do_PrefetchAbort()
ARM: 5740/1: fix valid_phys_addr_range() range check
ARM: 5739/1: ARM: allow empty ATAG_CORE
ARM: 5735/1: sa1111: CodingStyle cleanups
ARM: 5738/1: Correct TCM documentation
ARM: 5734/1: arm: fix compilation of entry-common.S for older CPUs
ARM: 5733/1: fix bcmring compile error
ARM: 5732/1: remove redundant include file
ARM: 5731/2: Fix U300 generic GPIO, remove ifdefs from MMCI v3
ARM: Ensure do_cache_op takes mmap_sem
ARM: Fix __cpuexit section mismatch warnings
ARM: Don't allow highmem on SMP platforms without h/w TLB ops broadcast
ARM: includecheck fix: mach-davinci, board-dm365-evm.c
ARM: Remove unused CONFIG SA1100_H3XXX
ARM: Fix warning: unused variable 'highmem'
ARM: Fix warning: #warning syscall migrate_pages not implemented
ARM: Fix SA11x0 clocksource warning
ARM: Fix SA1100 Neponset serial section mismatch
ARM: Fix SA1100 Assabet/Neponset PCMCIA section mismatch warnings
...
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) arm_notify_die("", regs, &info, fsr, 0); } + +static struct fsr_info ifsr_info[] = { + { do_bad, SIGBUS, 0, "unknown 0" }, + { do_bad, SIGBUS, 0, "unknown 1" }, + { do_bad, SIGBUS, 0, "debug event" }, + { do_bad, SIGSEGV, SEGV_ACCERR, "section access flag fault" }, + { do_bad, SIGBUS, 0, "unknown 4" }, + { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, + { do_bad, SIGSEGV, SEGV_ACCERR, "page access flag fault" }, + { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, + { do_bad, SIGBUS, 0, "external abort on non-linefetch" }, + { do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" }, + { do_bad, SIGBUS, 0, "unknown 10" }, + { do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" }, + { do_bad, SIGBUS, 0, "external abort on translation" }, + { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" }, + { do_bad, SIGBUS, 0, "external abort on translation" }, + { do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" }, + { do_bad, SIGBUS, 0, "unknown 16" }, + { do_bad, SIGBUS, 0, "unknown 17" }, + { do_bad, SIGBUS, 0, "unknown 18" }, + { do_bad, SIGBUS, 0, "unknown 19" }, + { do_bad, SIGBUS, 0, "unknown 20" }, + { do_bad, SIGBUS, 0, "unknown 21" }, + { do_bad, SIGBUS, 0, "unknown 22" }, + { do_bad, SIGBUS, 0, "unknown 23" }, + { do_bad, SIGBUS, 0, "unknown 24" }, + { do_bad, SIGBUS, 0, "unknown 25" }, + { do_bad, SIGBUS, 0, "unknown 26" }, + { do_bad, SIGBUS, 0, "unknown 27" }, + { do_bad, SIGBUS, 0, "unknown 28" }, + { do_bad, SIGBUS, 0, "unknown 29" }, + { do_bad, SIGBUS, 0, "unknown 30" }, + { do_bad, SIGBUS, 0, "unknown 31" }, +}; + asmlinkage void __exception -do_PrefetchAbort(unsigned long addr, struct pt_regs *regs) +do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) { - do_translation_fault(addr, FSR_LNX_PF, regs); + const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); + struct siginfo info; + + if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) + return; + + printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", + inf->name, ifsr, addr); + + info.si_signo = inf->sig; + info.si_errno = 0; + info.si_code = inf->code; + info.si_addr = (void __user *)addr; + arm_notify_die("", regs, &info, ifsr, 0); } |