|
@@ -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 = ®s->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 = ®s->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 = ®s->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 = ®s->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 = ®s->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,34 +474,31 @@ 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);
|
|
|
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;
|
|
@@ -538,16 +536,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,
|
|
|
- ®ptr, &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;
|