Update ARM alignment patch to upstream

This commit is contained in:
Peter Robinson 2012-10-29 18:04:05 +00:00
parent a0a8db50e5
commit 39c7bf392f
4 changed files with 132 additions and 88 deletions

127
arm-alignment-faults.patch Normal file
View File

@ -0,0 +1,127 @@
arch/arm/kernel/traps.c | 34 +++++++---------------------------
arch/arm/mm/alignment.c | 11 ++++-------
2 files changed, 11 insertions(+), 34 deletions(-)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index b0179b8..62f429e 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -89,17 +89,8 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
unsigned long top)
{
unsigned long first;
- mm_segment_t fs;
int i;
- /*
- * We need to switch to kernel mode so that we can use __get_user
- * to safely read from kernel space. Note that we now dump the
- * code first, just in case the backtrace kills us.
- */
- fs = get_fs();
- set_fs(KERNEL_DS);
-
printk("%s%s(0x%08lx to 0x%08lx)\n", lvl, str, bottom, top);
for (first = bottom & ~31; first < top; first += 32) {
@@ -112,7 +103,7 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
if (p >= bottom && p < top) {
unsigned long val;
- if (__get_user(val, (unsigned long *)p) == 0)
+ if (probe_kernel_address(p, val) == 0)
sprintf(str + i * 9, " %08lx", val);
else
sprintf(str + i * 9, " ????????");
@@ -120,8 +111,6 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
}
printk("%s%04lx:%s\n", lvl, first & 0xffff, str);
}
-
- set_fs(fs);
}
static void dump_instr(const char *lvl, struct pt_regs *regs)
@@ -129,25 +118,18 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
unsigned long addr = instruction_pointer(regs);
const int thumb = thumb_mode(regs);
const int width = thumb ? 4 : 8;
- mm_segment_t fs;
char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
int i;
- /*
- * We need to switch to kernel mode so that we can use __get_user
- * to safely read from kernel space. Note that we now dump the
- * code first, just in case the backtrace kills us.
- */
- fs = get_fs();
- set_fs(KERNEL_DS);
-
for (i = -4; i < 1 + !!thumb; i++) {
unsigned int val, bad;
- if (thumb)
- bad = __get_user(val, &((u16 *)addr)[i]);
- else
- bad = __get_user(val, &((u32 *)addr)[i]);
+ if (thumb) {
+ u16 instr;
+ bad = probe_kernel_address(addr, instr);
+ val = instr;
+ } else
+ bad = probe_kernel_address(addr, val);
if (!bad)
p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ",
@@ -158,8 +140,6 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
}
}
printk("%sCode: %s\n", lvl, str);
-
- set_fs(fs);
}
#ifdef CONFIG_ARM_UNWIND
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index b9f60eb..f8f14fc 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -749,7 +749,6 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
unsigned long instr = 0, instrptr;
int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
unsigned int type;
- mm_segment_t fs;
unsigned int fault;
u16 tinstr = 0;
int isize = 4;
@@ -760,16 +759,15 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
instrptr = instruction_pointer(regs);
- fs = get_fs();
- set_fs(KERNEL_DS);
if (thumb_mode(regs)) {
- fault = __get_user(tinstr, (u16 *)(instrptr & ~1));
+ unsigned long ptr = instrptr;
+ fault = probe_kernel_address(ptr, tinstr);
if (!fault) {
if (cpu_architecture() >= CPU_ARCH_ARMv7 &&
IS_T32(tinstr)) {
/* Thumb-2 32-bit */
u16 tinst2 = 0;
- fault = __get_user(tinst2, (u16 *)(instrptr+2));
+ fault = probe_kernel_address(ptr + 2, tinst2);
instr = (tinstr << 16) | tinst2;
thumb2_32b = 1;
} else {
@@ -778,8 +776,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
}
}
} else
- fault = __get_user(instr, (u32 *)instrptr);
- set_fs(fs);
+ fault = probe_kernel_address(instrptr, instr);
if (fault) {
type = TYPE_FAULT;

View File

@ -1,83 +0,0 @@
commit dd945918f747f61eff384f5cb8889e524f60615a
Author: Jon Masters <jcm@jonmasters.org>
Date: Fri Oct 5 22:32:29 2012 -0400
Revert "ARM: 7528/1: uaccess: annotate [__]{get,put}_user functions with might_fault()"
This reverts commit ad72907acd2943304c292ae36960bb66e6dc23c9.
Technically, the original commit is totally correct, however it exposes
a deep-rooted problem with missaligned accesses in e.g. the networking
stack and we need to revert this (sweep under rug) until we can get
a good solution in place upstream. The problem is that the compiler
believes the structs concerned are aligned (they are in the code),
however at runtime the IP structs are actually not aligned within
received network packets, and the fault handler is not guaranteed
to be entirely atomic and free of calls to the scheduler.
Signed-off-by: Jon Masters <jcm@jonmasters.org>
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 77bd79f..6f83ad6 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -118,7 +118,7 @@ extern int __get_user_4(void *);
: "0" (__p), "r" (__l) \
: __GUP_CLOBBER_##__s)
-#define __get_user_check(x,p) \
+#define get_user(x,p) \
({ \
unsigned long __limit = current_thread_info()->addr_limit - 1; \
register const typeof(*(p)) __user *__p asm("r0") = (p);\
@@ -141,12 +141,6 @@ extern int __get_user_4(void *);
__e; \
})
-#define get_user(x,p) \
- ({ \
- might_fault(); \
- __get_user_check(x,p); \
- })
-
extern int __put_user_1(void *, unsigned int);
extern int __put_user_2(void *, unsigned int);
extern int __put_user_4(void *, unsigned int);
@@ -161,7 +155,7 @@ extern int __put_user_8(void *, unsigned long long);
: "0" (__p), "r" (__r2), "r" (__l) \
: "ip", "lr", "cc")
-#define __put_user_check(x,p) \
+#define put_user(x,p) \
({ \
unsigned long __limit = current_thread_info()->addr_limit - 1; \
register const typeof(*(p)) __r2 asm("r2") = (x); \
@@ -186,12 +180,6 @@ extern int __put_user_8(void *, unsigned long long);
__e; \
})
-#define put_user(x,p) \
- ({ \
- might_fault(); \
- __put_user_check(x,p); \
- })
-
#else /* CONFIG_MMU */
/*
@@ -245,7 +233,6 @@ do { \
unsigned long __gu_addr = (unsigned long)(ptr); \
unsigned long __gu_val; \
__chk_user_ptr(ptr); \
- might_fault(); \
switch (sizeof(*(ptr))) { \
case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \
case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \
@@ -327,7 +314,6 @@ do { \
unsigned long __pu_addr = (unsigned long)(ptr); \
__typeof__(*(ptr)) __pu_val = (x); \
__chk_user_ptr(ptr); \
- might_fault(); \
switch (sizeof(*(ptr))) { \
case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \
case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \

View File

@ -88,9 +88,6 @@ CONFIG_STRICT_DEVMEM=y
CONFIG_SPARSE_IRQ=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
CONFIG_LSM_MMAP_MIN_ADDR=32768
# Generic HW for all ARM platforms
CONFIG_LEDS=y
CONFIG_LEDS_CPU=y

View File

@ -733,7 +733,7 @@ Patch19001: i82975x-edac-fix.patch
Patch21000: arm-read_current_timer.patch
Patch21001: arm-fix-omapdrm.patch
Patch21002: arm-fix_radio_shark.patch
Patch21003: arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch
Patch21003: arm-alignment-faults.patch
# OMAP
# ARM tegra
@ -1368,7 +1368,7 @@ ApplyPatch arm-tegra-nvec-kconfig.patch
ApplyPatch arm-tegra-usb-no-reset-linux33.patch
ApplyPatch arm-tegra-sdhci-module-fix.patch
ApplyPatch arm-highbank-sata-fix.patch
ApplyPatch arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch
ApplyPatch arm-alignment-faults.patch
ApplyPatch arm-smdk310-regulator-fix.patch
ApplyPatch arm-origen-regulator-fix.patch
@ -2376,6 +2376,9 @@ fi
# ||----w |
# || ||
%changelog
* Mon Oct 29 2012 Peter Robinson <pbrobinson@fedoraproject.org>
- Update ARM alignment patch to upstream
* Mon Oct 29 2012 Justin M. Forbes <jforbes@redhat.com> 3.6.4-1
- Linux 3.6.4