]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/mips/kernel/unaligned.c
Merge branch 'for-2.6.28' of git://linux-nfs.org/~bfields/linux
[linux-2.6-omap-h63xx.git] / arch / mips / kernel / unaligned.c
index 8b9c34ffae184fecf7fe720eaa0b596305194fe9..bf4c4a979abb787775477d1b42e2b7e54a43b9c3 100644 (file)
@@ -101,16 +101,14 @@ static u32 unaligned_action;
 #endif
 extern void show_registers(struct pt_regs *regs);
 
-static inline int emulate_load_store_insn(struct pt_regs *regs,
-       void __user *addr, unsigned int __user *pc,
-       unsigned long **regptr, unsigned long *newvalue)
+static void emulate_load_store_insn(struct pt_regs *regs,
+       void __user *addr, unsigned int __user *pc)
 {
        union mips_instruction insn;
        unsigned long value;
        unsigned int res;
 
        regs->regs[0] = 0;
-       *regptr=NULL;
 
        /*
         * This load never faults.
@@ -179,8 +177,8 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
                        : "r" (addr), "i" (-EFAULT));
                if (res)
                        goto fault;
-               *newvalue = value;
-               *regptr = &regs->regs[insn.i_format.rt];
+               compute_return_epc(regs);
+               regs->regs[insn.i_format.rt] = value;
                break;
 
        case lw_op:
@@ -209,8 +207,8 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
                        : "r" (addr), "i" (-EFAULT));
                if (res)
                        goto fault;
-               *newvalue = value;
-               *regptr = &regs->regs[insn.i_format.rt];
+               compute_return_epc(regs);
+               regs->regs[insn.i_format.rt] = value;
                break;
 
        case lhu_op:
@@ -243,8 +241,8 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
                        : "r" (addr), "i" (-EFAULT));
                if (res)
                        goto fault;
-               *newvalue = value;
-               *regptr = &regs->regs[insn.i_format.rt];
+               compute_return_epc(regs);
+               regs->regs[insn.i_format.rt] = value;
                break;
 
        case lwu_op:
@@ -283,8 +281,8 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
                        : "r" (addr), "i" (-EFAULT));
                if (res)
                        goto fault;
-               *newvalue = value;
-               *regptr = &regs->regs[insn.i_format.rt];
+               compute_return_epc(regs);
+               regs->regs[insn.i_format.rt] = value;
                break;
 #endif /* CONFIG_64BIT */
 
@@ -325,8 +323,8 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
                        : "r" (addr), "i" (-EFAULT));
                if (res)
                        goto fault;
-               *newvalue = value;
-               *regptr = &regs->regs[insn.i_format.rt];
+               compute_return_epc(regs);
+               regs->regs[insn.i_format.rt] = value;
                break;
 #endif /* CONFIG_64BIT */
 
@@ -367,6 +365,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
                        : "r" (value), "r" (addr), "i" (-EFAULT));
                if (res)
                        goto fault;
+               compute_return_epc(regs);
                break;
 
        case sw_op:
@@ -397,6 +396,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
                : "r" (value), "r" (addr), "i" (-EFAULT));
                if (res)
                        goto fault;
+               compute_return_epc(regs);
                break;
 
        case sd_op:
@@ -435,6 +435,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
                : "r" (value), "r" (addr), "i" (-EFAULT));
                if (res)
                        goto fault;
+               compute_return_epc(regs);
                break;
 #endif /* CONFIG_64BIT */
 
@@ -473,49 +474,34 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
        unaligned_instructions++;
 #endif
 
-       return 0;
+       return;
 
 fault:
        /* Did we have an exception handler installed? */
        if (fixup_exception(regs))
-               return 1;
+               return;
 
-       die_if_kernel ("Unhandled kernel unaligned access", regs);
+       die_if_kernel("Unhandled kernel unaligned access", regs);
        send_sig(SIGSEGV, current, 1);
 
-       return 0;
+       return;
 
 sigbus:
        die_if_kernel("Unhandled kernel unaligned access", regs);
        send_sig(SIGBUS, current, 1);
 
-       return 0;
+       return;
 
 sigill:
        die_if_kernel("Unhandled kernel unaligned access or invalid instruction", regs);
        send_sig(SIGILL, current, 1);
-
-       return 0;
 }
 
 asmlinkage void do_ade(struct pt_regs *regs)
 {
-       unsigned long *regptr, newval;
-       extern int do_dsemulret(struct pt_regs *);
        unsigned int __user *pc;
        mm_segment_t seg;
 
-       /*
-        * Address errors may be deliberately induced by the FPU emulator to
-        * retake control of the CPU after executing the instruction in the
-        * delay slot of an emulated branch.
-        */
-       /* Terminate if exception was recognized as a delay slot return */
-       if (do_dsemulret(regs))
-               return;
-
-       /* Otherwise handle as normal */
-
        /*
         * Did we catch a fault trying to load an instruction?
         * Or are we running in MIPS16 mode?
@@ -524,7 +510,7 @@ asmlinkage void do_ade(struct pt_regs *regs)
                goto sigbus;
 
        pc = (unsigned int __user *) exception_epc(regs);
-       if (user_mode(regs) && (current->thread.mflags & MF_FIXADE) == 0)
+       if (user_mode(regs) && !test_thread_flag(TIF_FIXADE))
                goto sigbus;
        if (unaligned_action == UNALIGNED_ACTION_SIGNAL)
                goto sigbus;
@@ -538,16 +524,7 @@ asmlinkage void do_ade(struct pt_regs *regs)
        seg = get_fs();
        if (!user_mode(regs))
                set_fs(KERNEL_DS);
-       if (!emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc,
-                                    &regptr, &newval)) {
-               compute_return_epc(regs);
-               /*
-                * Now that branch is evaluated, update the dest
-                * register if necessary
-                */
-               if (regptr)
-                       *regptr = newval;
-       }
+       emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc);
        set_fs(seg);
 
        return;
@@ -571,12 +548,12 @@ static int __init debugfs_unaligned(void)
                return -ENODEV;
        d = debugfs_create_u32("unaligned_instructions", S_IRUGO,
                               mips_debugfs_dir, &unaligned_instructions);
-       if (IS_ERR(d))
-               return PTR_ERR(d);
+       if (!d)
+               return -ENOMEM;
        d = debugfs_create_u32("unaligned_action", S_IRUGO | S_IWUSR,
                               mips_debugfs_dir, &unaligned_action);
-       if (IS_ERR(d))
-               return PTR_ERR(d);
+       if (!d)
+               return -ENOMEM;
        return 0;
 }
 __initcall(debugfs_unaligned);