diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2011-11-22 12:30:28 -0500 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2011-12-08 05:30:37 -0500 |
commit | 136848d4ca9cf6f08edf6e50cb9bbe19de55c32a (patch) | |
tree | 9b4b311b64f40afb2028db988710f3500e3995cf /arch/arm/mm | |
parent | e0c0313bd720977a7ed01dc48f0762a3ddec607f (diff) |
ARM: LPAE: Move the FSR definitions to separate files
The FSR structure is different with LPAE and this patch moves the
classic MMU specific definition to a separate fsr-2level.c file that is
included in fault.c. It also moves the fsr_fs and FSR bits to the
fault.h file.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/fault.c | 96 | ||||
-rw-r--r-- | arch/arm/mm/fault.h | 19 | ||||
-rw-r--r-- | arch/arm/mm/fsr-2level.c | 78 |
3 files changed, 100 insertions, 93 deletions
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index aa33949fef60..2a0271677725 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 | |||
38 | static 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 |
@@ -489,55 +476,16 @@ do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
489 | return 1; | 476 | return 1; |
490 | } | 477 | } |
491 | 478 | ||
492 | static struct fsr_info { | 479 | struct fsr_info { |
493 | int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs); | 480 | int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs); |
494 | int sig; | 481 | int sig; |
495 | int code; | 482 | int code; |
496 | const char *name; | 483 | const char *name; |
497 | } fsr_info[] = { | ||
498 | /* | ||
499 | * The following are the standard ARMv3 and ARMv4 aborts. ARMv5 | ||
500 | * defines these to be "precise" aborts. | ||
501 | */ | ||
502 | { do_bad, SIGSEGV, 0, "vector exception" }, | ||
503 | { do_bad, SIGBUS, BUS_ADRALN, "alignment exception" }, | ||
504 | { do_bad, SIGKILL, 0, "terminal exception" }, | ||
505 | { do_bad, SIGBUS, BUS_ADRALN, "alignment exception" }, | ||
506 | { do_bad, SIGBUS, 0, "external abort on linefetch" }, | ||
507 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, | ||
508 | { do_bad, SIGBUS, 0, "external abort on linefetch" }, | ||
509 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, | ||
510 | { do_bad, SIGBUS, 0, "external abort on non-linefetch" }, | ||
511 | { do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" }, | ||
512 | { do_bad, SIGBUS, 0, "external abort on non-linefetch" }, | ||
513 | { do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" }, | ||
514 | { do_bad, SIGBUS, 0, "external abort on translation" }, | ||
515 | { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" }, | ||
516 | { do_bad, SIGBUS, 0, "external abort on translation" }, | ||
517 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" }, | ||
518 | /* | ||
519 | * The following are "imprecise" aborts, which are signalled by bit | ||
520 | * 10 of the FSR, and may not be recoverable. These are only | ||
521 | * supported if the CPU abort handler supports bit 10. | ||
522 | */ | ||
523 | { do_bad, SIGBUS, 0, "unknown 16" }, | ||
524 | { do_bad, SIGBUS, 0, "unknown 17" }, | ||
525 | { do_bad, SIGBUS, 0, "unknown 18" }, | ||
526 | { do_bad, SIGBUS, 0, "unknown 19" }, | ||
527 | { do_bad, SIGBUS, 0, "lock abort" }, /* xscale */ | ||
528 | { do_bad, SIGBUS, 0, "unknown 21" }, | ||
529 | { do_bad, SIGBUS, BUS_OBJERR, "imprecise external abort" }, /* xscale */ | ||
530 | { do_bad, SIGBUS, 0, "unknown 23" }, | ||
531 | { do_bad, SIGBUS, 0, "dcache parity error" }, /* xscale */ | ||
532 | { do_bad, SIGBUS, 0, "unknown 25" }, | ||
533 | { do_bad, SIGBUS, 0, "unknown 26" }, | ||
534 | { do_bad, SIGBUS, 0, "unknown 27" }, | ||
535 | { do_bad, SIGBUS, 0, "unknown 28" }, | ||
536 | { do_bad, SIGBUS, 0, "unknown 29" }, | ||
537 | { do_bad, SIGBUS, 0, "unknown 30" }, | ||
538 | { do_bad, SIGBUS, 0, "unknown 31" } | ||
539 | }; | 484 | }; |
540 | 485 | ||
486 | /* FSR definition */ | ||
487 | #include "fsr-2level.c" | ||
488 | |||
541 | void __init | 489 | void __init |
542 | hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), | 490 | hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), |
543 | int sig, int code, const char *name) | 491 | int sig, int code, const char *name) |
@@ -573,42 +521,6 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
573 | arm_notify_die("", regs, &info, fsr, 0); | 521 | arm_notify_die("", regs, &info, fsr, 0); |
574 | } | 522 | } |
575 | 523 | ||
576 | |||
577 | static struct fsr_info ifsr_info[] = { | ||
578 | { do_bad, SIGBUS, 0, "unknown 0" }, | ||
579 | { do_bad, SIGBUS, 0, "unknown 1" }, | ||
580 | { do_bad, SIGBUS, 0, "debug event" }, | ||
581 | { do_bad, SIGSEGV, SEGV_ACCERR, "section access flag fault" }, | ||
582 | { do_bad, SIGBUS, 0, "unknown 4" }, | ||
583 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, | ||
584 | { do_bad, SIGSEGV, SEGV_ACCERR, "page access flag fault" }, | ||
585 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, | ||
586 | { do_bad, SIGBUS, 0, "external abort on non-linefetch" }, | ||
587 | { do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" }, | ||
588 | { do_bad, SIGBUS, 0, "unknown 10" }, | ||
589 | { do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" }, | ||
590 | { do_bad, SIGBUS, 0, "external abort on translation" }, | ||
591 | { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" }, | ||
592 | { do_bad, SIGBUS, 0, "external abort on translation" }, | ||
593 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" }, | ||
594 | { do_bad, SIGBUS, 0, "unknown 16" }, | ||
595 | { do_bad, SIGBUS, 0, "unknown 17" }, | ||
596 | { do_bad, SIGBUS, 0, "unknown 18" }, | ||
597 | { do_bad, SIGBUS, 0, "unknown 19" }, | ||
598 | { do_bad, SIGBUS, 0, "unknown 20" }, | ||
599 | { do_bad, SIGBUS, 0, "unknown 21" }, | ||
600 | { do_bad, SIGBUS, 0, "unknown 22" }, | ||
601 | { do_bad, SIGBUS, 0, "unknown 23" }, | ||
602 | { do_bad, SIGBUS, 0, "unknown 24" }, | ||
603 | { do_bad, SIGBUS, 0, "unknown 25" }, | ||
604 | { do_bad, SIGBUS, 0, "unknown 26" }, | ||
605 | { do_bad, SIGBUS, 0, "unknown 27" }, | ||
606 | { do_bad, SIGBUS, 0, "unknown 28" }, | ||
607 | { do_bad, SIGBUS, 0, "unknown 29" }, | ||
608 | { do_bad, SIGBUS, 0, "unknown 30" }, | ||
609 | { do_bad, SIGBUS, 0, "unknown 31" }, | ||
610 | }; | ||
611 | |||
612 | void __init | 524 | void __init |
613 | hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), | 525 | hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), |
614 | int sig, int code, const char *name) | 526 | int sig, int code, const char *name) |
diff --git a/arch/arm/mm/fault.h b/arch/arm/mm/fault.h index 49e9e3804de4..25b45c105be2 100644 --- a/arch/arm/mm/fault.h +++ b/arch/arm/mm/fault.h | |||
@@ -1,3 +1,20 @@ | |||
1 | void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs); | 1 | #ifndef __ARCH_ARM_FAULT_H |
2 | #define __ARCH_ARM_FAULT_H | ||
3 | |||
4 | /* | ||
5 | * Fault status register encodings. We steal bit 31 for our own purposes. | ||
6 | */ | ||
7 | #define FSR_LNX_PF (1 << 31) | ||
8 | #define FSR_WRITE (1 << 11) | ||
9 | #define FSR_FS4 (1 << 10) | ||
10 | #define FSR_FS3_0 (15) | ||
11 | |||
12 | static inline int fsr_fs(unsigned int fsr) | ||
13 | { | ||
14 | return (fsr & FSR_FS3_0) | (fsr & FSR_FS4) >> 6; | ||
15 | } | ||
2 | 16 | ||
17 | void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs); | ||
3 | unsigned long search_exception_table(unsigned long addr); | 18 | unsigned long search_exception_table(unsigned long addr); |
19 | |||
20 | #endif /* __ARCH_ARM_FAULT_H */ | ||
diff --git a/arch/arm/mm/fsr-2level.c b/arch/arm/mm/fsr-2level.c new file mode 100644 index 000000000000..18ca74c0f341 --- /dev/null +++ b/arch/arm/mm/fsr-2level.c | |||
@@ -0,0 +1,78 @@ | |||
1 | static struct fsr_info fsr_info[] = { | ||
2 | /* | ||
3 | * The following are the standard ARMv3 and ARMv4 aborts. ARMv5 | ||
4 | * defines these to be "precise" aborts. | ||
5 | */ | ||
6 | { do_bad, SIGSEGV, 0, "vector exception" }, | ||
7 | { do_bad, SIGBUS, BUS_ADRALN, "alignment exception" }, | ||
8 | { do_bad, SIGKILL, 0, "terminal exception" }, | ||
9 | { do_bad, SIGBUS, BUS_ADRALN, "alignment exception" }, | ||
10 | { do_bad, SIGBUS, 0, "external abort on linefetch" }, | ||
11 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, | ||
12 | { do_bad, SIGBUS, 0, "external abort on linefetch" }, | ||
13 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, | ||
14 | { do_bad, SIGBUS, 0, "external abort on non-linefetch" }, | ||
15 | { do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" }, | ||
16 | { do_bad, SIGBUS, 0, "external abort on non-linefetch" }, | ||
17 | { do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" }, | ||
18 | { do_bad, SIGBUS, 0, "external abort on translation" }, | ||
19 | { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" }, | ||
20 | { do_bad, SIGBUS, 0, "external abort on translation" }, | ||
21 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" }, | ||
22 | /* | ||
23 | * The following are "imprecise" aborts, which are signalled by bit | ||
24 | * 10 of the FSR, and may not be recoverable. These are only | ||
25 | * supported if the CPU abort handler supports bit 10. | ||
26 | */ | ||
27 | { do_bad, SIGBUS, 0, "unknown 16" }, | ||
28 | { do_bad, SIGBUS, 0, "unknown 17" }, | ||
29 | { do_bad, SIGBUS, 0, "unknown 18" }, | ||
30 | { do_bad, SIGBUS, 0, "unknown 19" }, | ||
31 | { do_bad, SIGBUS, 0, "lock abort" }, /* xscale */ | ||
32 | { do_bad, SIGBUS, 0, "unknown 21" }, | ||
33 | { do_bad, SIGBUS, BUS_OBJERR, "imprecise external abort" }, /* xscale */ | ||
34 | { do_bad, SIGBUS, 0, "unknown 23" }, | ||
35 | { do_bad, SIGBUS, 0, "dcache parity error" }, /* xscale */ | ||
36 | { do_bad, SIGBUS, 0, "unknown 25" }, | ||
37 | { do_bad, SIGBUS, 0, "unknown 26" }, | ||
38 | { do_bad, SIGBUS, 0, "unknown 27" }, | ||
39 | { do_bad, SIGBUS, 0, "unknown 28" }, | ||
40 | { do_bad, SIGBUS, 0, "unknown 29" }, | ||
41 | { do_bad, SIGBUS, 0, "unknown 30" }, | ||
42 | { do_bad, SIGBUS, 0, "unknown 31" }, | ||
43 | }; | ||
44 | |||
45 | static struct fsr_info ifsr_info[] = { | ||
46 | { do_bad, SIGBUS, 0, "unknown 0" }, | ||
47 | { do_bad, SIGBUS, 0, "unknown 1" }, | ||
48 | { do_bad, SIGBUS, 0, "debug event" }, | ||
49 | { do_bad, SIGSEGV, SEGV_ACCERR, "section access flag fault" }, | ||
50 | { do_bad, SIGBUS, 0, "unknown 4" }, | ||
51 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, | ||
52 | { do_bad, SIGSEGV, SEGV_ACCERR, "page access flag fault" }, | ||
53 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, | ||
54 | { do_bad, SIGBUS, 0, "external abort on non-linefetch" }, | ||
55 | { do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" }, | ||
56 | { do_bad, SIGBUS, 0, "unknown 10" }, | ||
57 | { do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" }, | ||
58 | { do_bad, SIGBUS, 0, "external abort on translation" }, | ||
59 | { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" }, | ||
60 | { do_bad, SIGBUS, 0, "external abort on translation" }, | ||
61 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" }, | ||
62 | { do_bad, SIGBUS, 0, "unknown 16" }, | ||
63 | { do_bad, SIGBUS, 0, "unknown 17" }, | ||
64 | { do_bad, SIGBUS, 0, "unknown 18" }, | ||
65 | { do_bad, SIGBUS, 0, "unknown 19" }, | ||
66 | { do_bad, SIGBUS, 0, "unknown 20" }, | ||
67 | { do_bad, SIGBUS, 0, "unknown 21" }, | ||
68 | { do_bad, SIGBUS, 0, "unknown 22" }, | ||
69 | { do_bad, SIGBUS, 0, "unknown 23" }, | ||
70 | { do_bad, SIGBUS, 0, "unknown 24" }, | ||
71 | { do_bad, SIGBUS, 0, "unknown 25" }, | ||
72 | { do_bad, SIGBUS, 0, "unknown 26" }, | ||
73 | { do_bad, SIGBUS, 0, "unknown 27" }, | ||
74 | { do_bad, SIGBUS, 0, "unknown 28" }, | ||
75 | { do_bad, SIGBUS, 0, "unknown 29" }, | ||
76 | { do_bad, SIGBUS, 0, "unknown 30" }, | ||
77 | { do_bad, SIGBUS, 0, "unknown 31" }, | ||
78 | }; | ||