aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@imgtec.com>2016-01-30 04:08:28 -0500
committerRalf Baechle <ralf@linux-mips.org>2016-02-01 20:16:29 -0500
commit7aa7047100113ec9f5e4e685f94223825bd74a7b (patch)
tree6bea043bb48433dd7867fba6856ca0611ca24c7a
parent10f6d99f0fb186bbca1e9e2905d0d3693f941396 (diff)
MIPS: traps.c: Correct microMIPS RDHWR emulation
Fix the code to fetch and decode the whole 32-bit instruction. This only really matters with the `noulri' kernel parameter as all microMIPS processors are supposed to have all the hardware registers we support. Signed-off-by: Maciej W. Rozycki <macro@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12281/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/traps.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 485b0d517177..ae790c575d4f 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -663,7 +663,7 @@ static int simulate_rdhwr_normal(struct pt_regs *regs, unsigned int opcode)
663 return -1; 663 return -1;
664} 664}
665 665
666static int simulate_rdhwr_mm(struct pt_regs *regs, unsigned short opcode) 666static int simulate_rdhwr_mm(struct pt_regs *regs, unsigned int opcode)
667{ 667{
668 if ((opcode & MM_POOL32A_FUNC) == MM_RDHWR) { 668 if ((opcode & MM_POOL32A_FUNC) == MM_RDHWR) {
669 int rd = (opcode & MM_RS) >> 16; 669 int rd = (opcode & MM_RS) >> 16;
@@ -1119,11 +1119,12 @@ no_r2_instr:
1119 if (get_isa16_mode(regs->cp0_epc)) { 1119 if (get_isa16_mode(regs->cp0_epc)) {
1120 unsigned short mmop[2] = { 0 }; 1120 unsigned short mmop[2] = { 0 };
1121 1121
1122 if (unlikely(get_user(mmop[0], epc) < 0)) 1122 if (unlikely(get_user(mmop[0], (u16 __user *)epc + 0) < 0))
1123 status = SIGSEGV; 1123 status = SIGSEGV;
1124 if (unlikely(get_user(mmop[1], epc) < 0)) 1124 if (unlikely(get_user(mmop[1], (u16 __user *)epc + 1) < 0))
1125 status = SIGSEGV; 1125 status = SIGSEGV;
1126 opcode = (mmop[0] << 16) | mmop[1]; 1126 opcode = mmop[0];
1127 opcode = (opcode << 16) | mmop[1];
1127 1128
1128 if (status < 0) 1129 if (status < 0)
1129 status = simulate_rdhwr_mm(regs, opcode); 1130 status = simulate_rdhwr_mm(regs, opcode);