MIPS: traps.c: Verify the ISA for microMIPS RDHWR emulation
authorMaciej W. Rozycki <macro@imgtec.com>
Sat, 30 Jan 2016 09:08:43 +0000 (09:08 +0000)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 4 Apr 2016 13:25:34 +0000 (15:25 +0200)
Make sure it's the microMIPS rather than MIPS16 ISA before emulating
microMIPS RDHWR.  Mostly needed as an optimisation for configurations
where `cpu_has_mmips' is hardcoded to 0 and also a good measure in case
we add further microMIPS instructions to emulate in the future, as the
corresponding MIPS16 encoding is ADDIUSP, not supposed to trap.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/12282/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/kernel/traps.c

index 80339ce645215edfc2e77864137664e16aebd866..ae0c89d23ad7d3e41a068f4178b69fec492e2252 100644 (file)
@@ -1122,19 +1122,7 @@ no_r2_instr:
        if (unlikely(compute_return_epc(regs) < 0))
                goto out;
 
-       if (get_isa16_mode(regs->cp0_epc)) {
-               unsigned short mmop[2] = { 0 };
-
-               if (unlikely(get_user(mmop[0], (u16 __user *)epc + 0) < 0))
-                       status = SIGSEGV;
-               if (unlikely(get_user(mmop[1], (u16 __user *)epc + 1) < 0))
-                       status = SIGSEGV;
-               opcode = mmop[0];
-               opcode = (opcode << 16) | mmop[1];
-
-               if (status < 0)
-                       status = simulate_rdhwr_mm(regs, opcode);
-       } else {
+       if (!get_isa16_mode(regs->cp0_epc)) {
                if (unlikely(get_user(opcode, epc) < 0))
                        status = SIGSEGV;
 
@@ -1149,6 +1137,18 @@ no_r2_instr:
 
                if (status < 0)
                        status = simulate_fp(regs, opcode, old_epc, old31);
+       } else if (cpu_has_mmips) {
+               unsigned short mmop[2] = { 0 };
+
+               if (unlikely(get_user(mmop[0], (u16 __user *)epc + 0) < 0))
+                       status = SIGSEGV;
+               if (unlikely(get_user(mmop[1], (u16 __user *)epc + 1) < 0))
+                       status = SIGSEGV;
+               opcode = mmop[0];
+               opcode = (opcode << 16) | mmop[1];
+
+               if (status < 0)
+                       status = simulate_rdhwr_mm(regs, opcode);
        }
 
        if (status < 0)