Commit f6a31da5 authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Ralf Baechle

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: default avatarMaciej W. Rozycki <macro@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/9696/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 68893e00
...@@ -901,10 +901,9 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, ...@@ -901,10 +901,9 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
asmlinkage void do_bp(struct pt_regs *regs) asmlinkage void do_bp(struct pt_regs *regs)
{ {
unsigned long epc = msk_isa16_mode(exception_epc(regs));
unsigned int opcode, bcode; unsigned int opcode, bcode;
enum ctx_state prev_state; enum ctx_state prev_state;
unsigned long epc;
u16 instr[2];
mm_segment_t seg; mm_segment_t seg;
seg = get_fs(); seg = get_fs();
...@@ -913,26 +912,28 @@ asmlinkage void do_bp(struct pt_regs *regs) ...@@ -913,26 +912,28 @@ asmlinkage void do_bp(struct pt_regs *regs)
prev_state = exception_enter(); prev_state = exception_enter();
if (get_isa16_mode(regs->cp0_epc)) { if (get_isa16_mode(regs->cp0_epc)) {
/* Calculate EPC. */ u16 instr[2];
epc = exception_epc(regs);
if (cpu_has_mmips) { if (__get_user(instr[0], (u16 __user *)epc))
if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)) || goto out_sigsegv;
(__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2)))))
goto out_sigsegv; if (!cpu_has_mmips) {
opcode = (instr[0] << 16) | instr[1];
} else {
/* MIPS16e mode */ /* MIPS16e mode */
if (__get_user(instr[0],
(u16 __user *)msk_isa16_mode(epc)))
goto out_sigsegv;
bcode = (instr[0] >> 5) & 0x3f; bcode = (instr[0] >> 5) & 0x3f;
do_trap_or_bp(regs, bcode, "Break"); } else if (mm_insn_16bit(instr[0])) {
goto out; /* 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 { } else {
if (__get_user(opcode, if (__get_user(opcode, (unsigned int __user *)epc))
(unsigned int __user *) exception_epc(regs)))
goto out_sigsegv; goto out_sigsegv;
bcode = (opcode >> 6) & ((1 << 20) - 1);
} }
/* /*
...@@ -941,7 +942,6 @@ asmlinkage void do_bp(struct pt_regs *regs) ...@@ -941,7 +942,6 @@ asmlinkage void do_bp(struct pt_regs *regs)
* Gas is bug-compatible, but not always, grrr... * Gas is bug-compatible, but not always, grrr...
* We handle both cases with a simple heuristics. --macro * We handle both cases with a simple heuristics. --macro
*/ */
bcode = ((opcode >> 6) & ((1 << 20) - 1));
if (bcode >= (1 << 10)) if (bcode >= (1 << 10))
bcode >>= 10; bcode >>= 10;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment