Skip to content

Commit

Permalink
MIPS: BREAK instruction interpretation corrections
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Maciej W. Rozycki authored and Ralf Baechle committed Apr 7, 2015
1 parent 68893e0 commit f6a31da
Showing 1 changed file with 18 additions and 18 deletions.
36 changes: 18 additions & 18 deletions arch/mips/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);
}

/*
Expand All @@ -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;

Expand Down

0 comments on commit f6a31da

Please sign in to comment.