aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/fault.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm/fault.c')
-rw-r--r--arch/arm/mm/fault.c111
1 files changed, 19 insertions, 92 deletions
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 4aabeaec25df..bb7eac381a8e 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -27,19 +27,6 @@
27 27
28#include "fault.h" 28#include "fault.h"
29 29
30/*
31 * Fault status register encodings. We steal bit 31 for our own purposes.
32 */
33#define FSR_LNX_PF (1 << 31)
34#define FSR_WRITE (1 << 11)
35#define FSR_FS4 (1 << 10)
36#define FSR_FS3_0 (15)
37
38static inline int fsr_fs(unsigned int fsr)
39{
40 return (fsr & FSR_FS3_0) | (fsr & FSR_FS4) >> 6;
41}
42
43#ifdef CONFIG_MMU 30#ifdef CONFIG_MMU
44 31
45#ifdef CONFIG_KPROBES 32#ifdef CONFIG_KPROBES
@@ -123,8 +110,10 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
123 110
124 pte = pte_offset_map(pmd, addr); 111 pte = pte_offset_map(pmd, addr);
125 printk(", *pte=%08llx", (long long)pte_val(*pte)); 112 printk(", *pte=%08llx", (long long)pte_val(*pte));
113#ifndef CONFIG_ARM_LPAE
126 printk(", *ppte=%08llx", 114 printk(", *ppte=%08llx",
127 (long long)pte_val(pte[PTE_HWTABLE_PTRS])); 115 (long long)pte_val(pte[PTE_HWTABLE_PTRS]));
116#endif
128 pte_unmap(pte); 117 pte_unmap(pte);
129 } while(0); 118 } while(0);
130 119
@@ -461,6 +450,12 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
461 pmd = pmd_offset(pud, addr); 450 pmd = pmd_offset(pud, addr);
462 pmd_k = pmd_offset(pud_k, addr); 451 pmd_k = pmd_offset(pud_k, addr);
463 452
453#ifdef CONFIG_ARM_LPAE
454 /*
455 * Only one hardware entry per PMD with LPAE.
456 */
457 index = 0;
458#else
464 /* 459 /*
465 * On ARM one Linux PGD entry contains two hardware entries (see page 460 * On ARM one Linux PGD entry contains two hardware entries (see page
466 * tables layout in pgtable.h). We normally guarantee that we always 461 * tables layout in pgtable.h). We normally guarantee that we always
@@ -470,6 +465,7 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
470 * for the first of pair. 465 * for the first of pair.
471 */ 466 */
472 index = (addr >> SECTION_SHIFT) & 1; 467 index = (addr >> SECTION_SHIFT) & 1;
468#endif
473 if (pmd_none(pmd_k[index])) 469 if (pmd_none(pmd_k[index]))
474 goto bad_area; 470 goto bad_area;
475 471
@@ -509,55 +505,20 @@ do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
509 return 1; 505 return 1;
510} 506}
511 507
512static struct fsr_info { 508struct fsr_info {
513 int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs); 509 int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
514 int sig; 510 int sig;
515 int code; 511 int code;
516 const char *name; 512 const char *name;
517} fsr_info[] = {
518 /*
519 * The following are the standard ARMv3 and ARMv4 aborts. ARMv5
520 * defines these to be "precise" aborts.
521 */
522 { do_bad, SIGSEGV, 0, "vector exception" },
523 { do_bad, SIGBUS, BUS_ADRALN, "alignment exception" },
524 { do_bad, SIGKILL, 0, "terminal exception" },
525 { do_bad, SIGBUS, BUS_ADRALN, "alignment exception" },
526 { do_bad, SIGBUS, 0, "external abort on linefetch" },
527 { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" },
528 { do_bad, SIGBUS, 0, "external abort on linefetch" },
529 { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" },
530 { do_bad, SIGBUS, 0, "external abort on non-linefetch" },
531 { do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" },
532 { do_bad, SIGBUS, 0, "external abort on non-linefetch" },
533 { do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },
534 { do_bad, SIGBUS, 0, "external abort on translation" },
535 { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
536 { do_bad, SIGBUS, 0, "external abort on translation" },
537 { do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
538 /*
539 * The following are "imprecise" aborts, which are signalled by bit
540 * 10 of the FSR, and may not be recoverable. These are only
541 * supported if the CPU abort handler supports bit 10.
542 */
543 { do_bad, SIGBUS, 0, "unknown 16" },
544 { do_bad, SIGBUS, 0, "unknown 17" },
545 { do_bad, SIGBUS, 0, "unknown 18" },
546 { do_bad, SIGBUS, 0, "unknown 19" },
547 { do_bad, SIGBUS, 0, "lock abort" }, /* xscale */
548 { do_bad, SIGBUS, 0, "unknown 21" },
549 { do_bad, SIGBUS, BUS_OBJERR, "imprecise external abort" }, /* xscale */
550 { do_bad, SIGBUS, 0, "unknown 23" },
551 { do_bad, SIGBUS, 0, "dcache parity error" }, /* xscale */
552 { do_bad, SIGBUS, 0, "unknown 25" },
553 { do_bad, SIGBUS, 0, "unknown 26" },
554 { do_bad, SIGBUS, 0, "unknown 27" },
555 { do_bad, SIGBUS, 0, "unknown 28" },
556 { do_bad, SIGBUS, 0, "unknown 29" },
557 { do_bad, SIGBUS, 0, "unknown 30" },
558 { do_bad, SIGBUS, 0, "unknown 31" }
559}; 513};
560 514
515/* FSR definition */
516#ifdef CONFIG_ARM_LPAE
517#include "fsr-3level.c"
518#else
519#include "fsr-2level.c"
520#endif
521
561void __init 522void __init
562hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), 523hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
563 int sig, int code, const char *name) 524 int sig, int code, const char *name)
@@ -593,42 +554,6 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
593 arm_notify_die("", regs, &info, fsr, 0); 554 arm_notify_die("", regs, &info, fsr, 0);
594} 555}
595 556
596
597static struct fsr_info ifsr_info[] = {
598 { do_bad, SIGBUS, 0, "unknown 0" },
599 { do_bad, SIGBUS, 0, "unknown 1" },
600 { do_bad, SIGBUS, 0, "debug event" },
601 { do_bad, SIGSEGV, SEGV_ACCERR, "section access flag fault" },
602 { do_bad, SIGBUS, 0, "unknown 4" },
603 { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" },
604 { do_bad, SIGSEGV, SEGV_ACCERR, "page access flag fault" },
605 { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" },
606 { do_bad, SIGBUS, 0, "external abort on non-linefetch" },
607 { do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" },
608 { do_bad, SIGBUS, 0, "unknown 10" },
609 { do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },
610 { do_bad, SIGBUS, 0, "external abort on translation" },
611 { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
612 { do_bad, SIGBUS, 0, "external abort on translation" },
613 { do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
614 { do_bad, SIGBUS, 0, "unknown 16" },
615 { do_bad, SIGBUS, 0, "unknown 17" },
616 { do_bad, SIGBUS, 0, "unknown 18" },
617 { do_bad, SIGBUS, 0, "unknown 19" },
618 { do_bad, SIGBUS, 0, "unknown 20" },
619 { do_bad, SIGBUS, 0, "unknown 21" },
620 { do_bad, SIGBUS, 0, "unknown 22" },
621 { do_bad, SIGBUS, 0, "unknown 23" },
622 { do_bad, SIGBUS, 0, "unknown 24" },
623 { do_bad, SIGBUS, 0, "unknown 25" },
624 { do_bad, SIGBUS, 0, "unknown 26" },
625 { do_bad, SIGBUS, 0, "unknown 27" },
626 { do_bad, SIGBUS, 0, "unknown 28" },
627 { do_bad, SIGBUS, 0, "unknown 29" },
628 { do_bad, SIGBUS, 0, "unknown 30" },
629 { do_bad, SIGBUS, 0, "unknown 31" },
630};
631
632void __init 557void __init
633hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), 558hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
634 int sig, int code, const char *name) 559 int sig, int code, const char *name)
@@ -661,6 +586,7 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
661 arm_notify_die("", regs, &info, ifsr, 0); 586 arm_notify_die("", regs, &info, ifsr, 0);
662} 587}
663 588
589#ifndef CONFIG_ARM_LPAE
664static int __init exceptions_init(void) 590static int __init exceptions_init(void)
665{ 591{
666 if (cpu_architecture() >= CPU_ARCH_ARMv6) { 592 if (cpu_architecture() >= CPU_ARCH_ARMv6) {
@@ -683,3 +609,4 @@ static int __init exceptions_init(void)
683} 609}
684 610
685arch_initcall(exceptions_init); 611arch_initcall(exceptions_init);
612#endif