summaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@imgtec.com>2016-01-30 09:08:43 +0000
committerRalf Baechle <ralf@linux-mips.org>2016-04-04 15:25:34 +0200
commit3d50a7fb42992545e45e10b068406546ea699489 (patch)
tree377a54dd0c80f3f287e4463d3ea9577866384cfa /arch/mips
parent6870e707c6d934329872eadc77a7d2d07586e36c (diff)
MIPS: traps.c: Verify the ISA for microMIPS RDHWR emulation
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>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/kernel/traps.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 80339ce64521..ae0c89d23ad7 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -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)