aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index e3be67012d78..a75ae40184aa 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -897,22 +897,24 @@ out_sigsegv:
897 897
898asmlinkage void do_tr(struct pt_regs *regs) 898asmlinkage void do_tr(struct pt_regs *regs)
899{ 899{
900 unsigned int opcode, tcode = 0; 900 u32 opcode, tcode = 0;
901 u16 instr[2]; 901 u16 instr[2];
902 unsigned long epc = exception_epc(regs); 902 unsigned long epc = msk_isa16_mode(exception_epc(regs));
903 903
904 if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc))) || 904 if (get_isa16_mode(regs->cp0_epc)) {
905 (__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2)))) 905 if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
906 __get_user(instr[1], (u16 __user *)(epc + 2)))
906 goto out_sigsegv; 907 goto out_sigsegv;
907 opcode = (instr[0] << 16) | instr[1]; 908 opcode = (instr[0] << 16) | instr[1];
908 909 /* Immediate versions don't provide a code. */
909 /* Immediate versions don't provide a code. */ 910 if (!(opcode & OPCODE))
910 if (!(opcode & OPCODE)) { 911 tcode = (opcode >> 12) & ((1 << 4) - 1);
911 if (get_isa16_mode(regs->cp0_epc)) 912 } else {
912 /* microMIPS */ 913 if (__get_user(opcode, (u32 __user *)epc))
913 tcode = (opcode >> 12) & 0x1f; 914 goto out_sigsegv;
914 else 915 /* Immediate versions don't provide a code. */
915 tcode = ((opcode >> 6) & ((1 << 10) - 1)); 916 if (!(opcode & OPCODE))
917 tcode = (opcode >> 6) & ((1 << 10) - 1);
916 } 918 }
917 919
918 do_trap_or_bp(regs, tcode, "Trap"); 920 do_trap_or_bp(regs, tcode, "Trap");