diff options
Diffstat (limited to 'arch/arm/mm/alignment.c')
-rw-r--r-- | arch/arm/mm/alignment.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 924036473b16..b8cb1a2688a0 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/opcodes.h> | 28 | #include <asm/opcodes.h> |
29 | 29 | ||
30 | #include "fault.h" | 30 | #include "fault.h" |
31 | #include "mm.h" | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998 | 34 | * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998 |
@@ -81,6 +82,7 @@ static unsigned long ai_word; | |||
81 | static unsigned long ai_dword; | 82 | static unsigned long ai_dword; |
82 | static unsigned long ai_multi; | 83 | static unsigned long ai_multi; |
83 | static int ai_usermode; | 84 | static int ai_usermode; |
85 | static unsigned long cr_no_alignment; | ||
84 | 86 | ||
85 | core_param(alignment, ai_usermode, int, 0600); | 87 | core_param(alignment, ai_usermode, int, 0600); |
86 | 88 | ||
@@ -91,7 +93,7 @@ core_param(alignment, ai_usermode, int, 0600); | |||
91 | /* Return true if and only if the ARMv6 unaligned access model is in use. */ | 93 | /* Return true if and only if the ARMv6 unaligned access model is in use. */ |
92 | static bool cpu_is_v6_unaligned(void) | 94 | static bool cpu_is_v6_unaligned(void) |
93 | { | 95 | { |
94 | return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U); | 96 | return cpu_architecture() >= CPU_ARCH_ARMv6 && get_cr() & CR_U; |
95 | } | 97 | } |
96 | 98 | ||
97 | static int safe_usermode(int new_usermode, bool warn) | 99 | static int safe_usermode(int new_usermode, bool warn) |
@@ -949,6 +951,13 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
949 | return 0; | 951 | return 0; |
950 | } | 952 | } |
951 | 953 | ||
954 | static int __init noalign_setup(char *__unused) | ||
955 | { | ||
956 | set_cr(__clear_cr(CR_A)); | ||
957 | return 1; | ||
958 | } | ||
959 | __setup("noalign", noalign_setup); | ||
960 | |||
952 | /* | 961 | /* |
953 | * This needs to be done after sysctl_init, otherwise sys/ will be | 962 | * This needs to be done after sysctl_init, otherwise sys/ will be |
954 | * overwritten. Actually, this shouldn't be in sys/ at all since | 963 | * overwritten. Actually, this shouldn't be in sys/ at all since |
@@ -966,14 +975,12 @@ static int __init alignment_init(void) | |||
966 | return -ENOMEM; | 975 | return -ENOMEM; |
967 | #endif | 976 | #endif |
968 | 977 | ||
969 | #ifdef CONFIG_CPU_CP15 | ||
970 | if (cpu_is_v6_unaligned()) { | 978 | if (cpu_is_v6_unaligned()) { |
971 | cr_alignment &= ~CR_A; | 979 | set_cr(__clear_cr(CR_A)); |
972 | cr_no_alignment &= ~CR_A; | ||
973 | set_cr(cr_alignment); | ||
974 | ai_usermode = safe_usermode(ai_usermode, false); | 980 | ai_usermode = safe_usermode(ai_usermode, false); |
975 | } | 981 | } |
976 | #endif | 982 | |
983 | cr_no_alignment = get_cr() & ~CR_A; | ||
977 | 984 | ||
978 | hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN, | 985 | hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN, |
979 | "alignment exception"); | 986 | "alignment exception"); |