aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/kernel/module.c4
-rw-r--r--arch/arm/mm/alignment.c56
-rw-r--r--arch/arm/mm/init.c2
-rw-r--r--arch/arm/mm/proc-arm946.S3
-rw-r--r--drivers/dma/amba-pl08x.c1
6 files changed, 50 insertions, 19 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2c71a8f3535a..5ebc5d922ea1 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -195,8 +195,7 @@ config VECTORS_BASE
195 The base address of exception vectors. 195 The base address of exception vectors.
196 196
197config ARM_PATCH_PHYS_VIRT 197config ARM_PATCH_PHYS_VIRT
198 bool "Patch physical to virtual translations at runtime (EXPERIMENTAL)" 198 bool "Patch physical to virtual translations at runtime"
199 depends on EXPERIMENTAL
200 depends on !XIP_KERNEL && MMU 199 depends on !XIP_KERNEL && MMU
201 depends on !ARCH_REALVIEW || !SPARSEMEM 200 depends on !ARCH_REALVIEW || !SPARSEMEM
202 help 201 help
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 05b377616fd5..cc2020c2c709 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -323,7 +323,11 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
323#endif 323#endif
324 s = find_mod_section(hdr, sechdrs, ".alt.smp.init"); 324 s = find_mod_section(hdr, sechdrs, ".alt.smp.init");
325 if (s && !is_smp()) 325 if (s && !is_smp())
326#ifdef CONFIG_SMP_ON_UP
326 fixup_smp((void *)s->sh_addr, s->sh_size); 327 fixup_smp((void *)s->sh_addr, s->sh_size);
328#else
329 return -EINVAL;
330#endif
327 return 0; 331 return 0;
328} 332}
329 333
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index be7c638b648b..cfbcf8b95599 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -22,6 +22,7 @@
22#include <linux/sched.h> 22#include <linux/sched.h>
23#include <linux/uaccess.h> 23#include <linux/uaccess.h>
24 24
25#include <asm/system.h>
25#include <asm/unaligned.h> 26#include <asm/unaligned.h>
26 27
27#include "fault.h" 28#include "fault.h"
@@ -95,6 +96,33 @@ static const char *usermode_action[] = {
95 "signal+warn" 96 "signal+warn"
96}; 97};
97 98
99/* Return true if and only if the ARMv6 unaligned access model is in use. */
100static bool cpu_is_v6_unaligned(void)
101{
102 return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U);
103}
104
105static int safe_usermode(int new_usermode, bool warn)
106{
107 /*
108 * ARMv6 and later CPUs can perform unaligned accesses for
109 * most single load and store instructions up to word size.
110 * LDM, STM, LDRD and STRD still need to be handled.
111 *
112 * Ignoring the alignment fault is not an option on these
113 * CPUs since we spin re-faulting the instruction without
114 * making any progress.
115 */
116 if (cpu_is_v6_unaligned() && !(new_usermode & (UM_FIXUP | UM_SIGNAL))) {
117 new_usermode |= UM_FIXUP;
118
119 if (warn)
120 printk(KERN_WARNING "alignment: ignoring faults is unsafe on this CPU. Defaulting to fixup mode.\n");
121 }
122
123 return new_usermode;
124}
125
98static int alignment_proc_show(struct seq_file *m, void *v) 126static int alignment_proc_show(struct seq_file *m, void *v)
99{ 127{
100 seq_printf(m, "User:\t\t%lu\n", ai_user); 128 seq_printf(m, "User:\t\t%lu\n", ai_user);
@@ -125,7 +153,7 @@ static ssize_t alignment_proc_write(struct file *file, const char __user *buffer
125 if (get_user(mode, buffer)) 153 if (get_user(mode, buffer))
126 return -EFAULT; 154 return -EFAULT;
127 if (mode >= '0' && mode <= '5') 155 if (mode >= '0' && mode <= '5')
128 ai_usermode = mode - '0'; 156 ai_usermode = safe_usermode(mode - '0', true);
129 } 157 }
130 return count; 158 return count;
131} 159}
@@ -886,9 +914,16 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
886 if (ai_usermode & UM_FIXUP) 914 if (ai_usermode & UM_FIXUP)
887 goto fixup; 915 goto fixup;
888 916
889 if (ai_usermode & UM_SIGNAL) 917 if (ai_usermode & UM_SIGNAL) {
890 force_sig(SIGBUS, current); 918 siginfo_t si;
891 else { 919
920 si.si_signo = SIGBUS;
921 si.si_errno = 0;
922 si.si_code = BUS_ADRALN;
923 si.si_addr = (void __user *)addr;
924
925 force_sig_info(si.si_signo, &si, current);
926 } else {
892 /* 927 /*
893 * We're about to disable the alignment trap and return to 928 * We're about to disable the alignment trap and return to
894 * user space. But if an interrupt occurs before actually 929 * user space. But if an interrupt occurs before actually
@@ -926,20 +961,11 @@ static int __init alignment_init(void)
926 return -ENOMEM; 961 return -ENOMEM;
927#endif 962#endif
928 963
929 /* 964 if (cpu_is_v6_unaligned()) {
930 * ARMv6 and later CPUs can perform unaligned accesses for
931 * most single load and store instructions up to word size.
932 * LDM, STM, LDRD and STRD still need to be handled.
933 *
934 * Ignoring the alignment fault is not an option on these
935 * CPUs since we spin re-faulting the instruction without
936 * making any progress.
937 */
938 if (cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U)) {
939 cr_alignment &= ~CR_A; 965 cr_alignment &= ~CR_A;
940 cr_no_alignment &= ~CR_A; 966 cr_no_alignment &= ~CR_A;
941 set_cr(cr_alignment); 967 set_cr(cr_alignment);
942 ai_usermode = UM_FIXUP; 968 ai_usermode = safe_usermode(ai_usermode, false);
943 } 969 }
944 970
945 hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN, 971 hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 2fee782077c1..91bca355cd31 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -441,7 +441,7 @@ static inline int free_area(unsigned long pfn, unsigned long end, char *s)
441static inline void poison_init_mem(void *s, size_t count) 441static inline void poison_init_mem(void *s, size_t count)
442{ 442{
443 u32 *p = (u32 *)s; 443 u32 *p = (u32 *)s;
444 while ((count = count - 4)) 444 for (; count != 0; count -= 4)
445 *p++ = 0xe7fddef0; 445 *p++ = 0xe7fddef0;
446} 446}
447 447
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index f8f7ea34bfc5..683af3a182b7 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -410,6 +410,7 @@ __arm946_proc_info:
410 .long 0x41009460 410 .long 0x41009460
411 .long 0xff00fff0 411 .long 0xff00fff0
412 .long 0 412 .long 0
413 .long 0
413 b __arm946_setup 414 b __arm946_setup
414 .long cpu_arch_name 415 .long cpu_arch_name
415 .long cpu_elf_name 416 .long cpu_elf_name
@@ -418,6 +419,6 @@ __arm946_proc_info:
418 .long arm946_processor_functions 419 .long arm946_processor_functions
419 .long 0 420 .long 0
420 .long 0 421 .long 0
421 .long arm940_cache_fns 422 .long arm946_cache_fns
422 .size __arm946_proc_info, . - __arm946_proc_info 423 .size __arm946_proc_info, . - __arm946_proc_info
423 424
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 196a7378d332..be21e3f138a8 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -80,6 +80,7 @@
80#include <linux/interrupt.h> 80#include <linux/interrupt.h>
81#include <linux/slab.h> 81#include <linux/slab.h>
82#include <linux/delay.h> 82#include <linux/delay.h>
83#include <linux/dma-mapping.h>
83#include <linux/dmapool.h> 84#include <linux/dmapool.h>
84#include <linux/dmaengine.h> 85#include <linux/dmaengine.h>
85#include <linux/amba/bus.h> 86#include <linux/amba/bus.h>