diff options
author | Maciej W. Rozycki <macro@imgtec.com> | 2016-01-30 04:08:28 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2016-02-01 20:16:29 -0500 |
commit | 7aa7047100113ec9f5e4e685f94223825bd74a7b (patch) | |
tree | 6bea043bb48433dd7867fba6856ca0611ca24c7a | |
parent | 10f6d99f0fb186bbca1e9e2905d0d3693f941396 (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.c | 9 |
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 | ||
666 | static int simulate_rdhwr_mm(struct pt_regs *regs, unsigned short opcode) | 666 | static 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); |