summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/unaligned.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-31 20:41:53 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-31 20:41:53 -0700
commitd6dd9e93c7531fa31370e27d053a3940d8d662fb (patch)
treeafab573031b3f0b9bbe5e417a890f7cae09a7224 /arch/mips/kernel/unaligned.c
parentdd9cd6d4351076c78bb8c0f9146d1904b481fdbb (diff)
parentb4b2917cc8babe8eaf4bc133bca31b11ed7dac13 (diff)
downloadkernel-crypto-d6dd9e93c7531fa31370e27d053a3940d8d662fb.tar.gz
kernel-crypto-d6dd9e93c7531fa31370e27d053a3940d8d662fb.tar.xz
kernel-crypto-d6dd9e93c7531fa31370e27d053a3940d8d662fb.zip
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (50 commits) [MIPS] Add smp_call_function_single() [MIPS] thread_info.h: kmalloc + memset conversion to kzalloc [MIPS] Kexec: Fix several 64-bit bugs. [MIPS] Kexec: Fix several warnings. [MIPS] DDB5477: Remove support [MIPS] Fulong: Remove unneeded header file [MIPS] Cobalt: Enable UART on RaQ1 [MIPS] Remove unused GROUP_TOSHIBA_NAMES [MIPS] remove some duplicate includes [MIPS] Oprofile: Fix rm9000 performance counter handler [MIPS] Use -Werror on subdirectories which build cleanly. [MIPS] Yosemite: Fix warning. [MIPS] PMON: Fix cpustart declaration. [MIPS] Yosemite: Only build ll_ht_smp_irq_handler() if HYPERTRANSPORT. [MIPS] Yosemite: Fix build error due to undeclared titan_mailbox_irq(). [MIPS] Yosemite: Don't declare titan_mailbox_irq() as asmlinkage. [MIPS] Yosemite: Fix warnings in i2c-yoesmite by deleting the unused code. [MIPS] Delete unused arch/mips/gt64120/common/ [MIPS] Fix build warning in unaligned load/store emulator. [MIPS] IP32: Don't ignore request_irq's return value. ...
Diffstat (limited to 'arch/mips/kernel/unaligned.c')
-rw-r--r--arch/mips/kernel/unaligned.c53
1 files changed, 21 insertions, 32 deletions
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 8b9c34ffae1..d34b1fb3665 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -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,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;
@@ -524,7 +522,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 +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,
- &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;