Merge tag 'samsung-drivers-exynos-mfc-4.8-2' of git://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / arch / parisc / kernel / unaligned.c
index d7c0acb..2b65c01 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/ratelimit.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
+#include <asm/traps.h>
 
 /* #define DEBUG_UNALIGNED 1 */
 
 
 int unaligned_enabled __read_mostly = 1;
 
-void die_if_kernel (char *str, struct pt_regs *regs, long err);
-
 static int emulate_ldh(struct pt_regs *regs, int toreg)
 {
        unsigned long saddr = regs->ior;
@@ -666,7 +665,7 @@ void handle_unaligned(struct pt_regs *regs)
                break;
        }
 
-       if (modify && R1(regs->iir))
+       if (ret == 0 && modify && R1(regs->iir))
                regs->gr[R1(regs->iir)] = newbase;
 
 
@@ -677,6 +676,14 @@ void handle_unaligned(struct pt_regs *regs)
 
        if (ret)
        {
+               /*
+                * The unaligned handler failed.
+                * If we were called by __get_user() or __put_user() jump
+                * to it's exception fixup handler instead of crashing.
+                */
+               if (!user_mode(regs) && fixup_exception(regs))
+                       return;
+
                printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
                die_if_kernel("Unaligned data reference", regs, 28);