diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2015-04-03 23:26:27 +0100 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-04-08 01:09:55 +0200 |
commit | f6a31da50158c1003bd487968d89a6b27ff25bb6 (patch) | |
tree | f883c9f7596805819d84efd7b5ba5af913ae67ed /arch/mips/kernel | |
parent | 68893e0051419ccdc14fd6eafcdecc96533c6cc3 (diff) | |
download | op-kernel-dev-f6a31da50158c1003bd487968d89a6b27ff25bb6.zip op-kernel-dev-f6a31da50158c1003bd487968d89a6b27ff25bb6.tar.gz |
MIPS: BREAK instruction interpretation corrections
Add the missing microMIPS BREAK16 instruction code interpretation and
reshape code removing instruction fetching duplication and the separate
call to `do_trap_or_bp' in the MIPS16 path.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/9696/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/traps.c | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index b6f2334..a671d33 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -901,10 +901,9 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, asmlinkage void do_bp(struct pt_regs *regs) { + unsigned long epc = msk_isa16_mode(exception_epc(regs)); unsigned int opcode, bcode; enum ctx_state prev_state; - unsigned long epc; - u16 instr[2]; mm_segment_t seg; seg = get_fs(); @@ -913,26 +912,28 @@ asmlinkage void do_bp(struct pt_regs *regs) prev_state = exception_enter(); if (get_isa16_mode(regs->cp0_epc)) { - /* Calculate EPC. */ - epc = exception_epc(regs); - if (cpu_has_mmips) { - if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)) || - (__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2))))) - goto out_sigsegv; - opcode = (instr[0] << 16) | instr[1]; - } else { + u16 instr[2]; + + if (__get_user(instr[0], (u16 __user *)epc)) + goto out_sigsegv; + + if (!cpu_has_mmips) { /* MIPS16e mode */ - if (__get_user(instr[0], - (u16 __user *)msk_isa16_mode(epc))) - goto out_sigsegv; bcode = (instr[0] >> 5) & 0x3f; - do_trap_or_bp(regs, bcode, "Break"); - goto out; + } else if (mm_insn_16bit(instr[0])) { + /* 16-bit microMIPS BREAK */ + bcode = instr[0] & 0xf; + } else { + /* 32-bit microMIPS BREAK */ + if (__get_user(instr[1], (u16 __user *)(epc + 2))) + goto out_sigsegv; + opcode = (instr[0] << 16) | instr[1]; + bcode = (opcode >> 6) & ((1 << 20) - 1); } } else { - if (__get_user(opcode, - (unsigned int __user *) exception_epc(regs))) + if (__get_user(opcode, (unsigned int __user *)epc)) goto out_sigsegv; + bcode = (opcode >> 6) & ((1 << 20) - 1); } /* @@ -941,7 +942,6 @@ asmlinkage void do_bp(struct pt_regs *regs) * Gas is bug-compatible, but not always, grrr... * We handle both cases with a simple heuristics. --macro */ - bcode = ((opcode >> 6) & ((1 << 20) - 1)); if (bcode >= (1 << 10)) bcode >>= 10; |