[PATCH] MIPS: micromips: Add 16-bit instruction floating point breakpoints.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds explicit support for 16-bit instruction breakpoints
for floating point exceptions.

Signed-off-by: Steven J. Hill <Steven.Hill@xxxxxxxxxx>
---
 arch/mips/include/asm/break.h        |    1 +
 arch/mips/include/asm/fpu_emulator.h |    3 +-
 arch/mips/kernel/traps.c             |   47 ++++++++++++++++-----------------
 arch/mips/math-emu/dsemul.c          |    6 ++--
 4 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/arch/mips/include/asm/break.h b/arch/mips/include/asm/break.h
index 0ef1142..79fbb5d 100644
--- a/arch/mips/include/asm/break.h
+++ b/arch/mips/include/asm/break.h
@@ -19,6 +19,7 @@
  */
 #define BRK_KDB		513	/* Used in KDB_ENTER() */
 #define BRK_MEMU	514	/* Used by FPU emulator */
+#define BRK_MEMU_16	14	/* Used by FPU emulator (16-bit instructions) */
 #define BRK_KPROBE_BP	515	/* Kprobe break */
 #define BRK_KPROBE_SSTEPBP 516	/* Kprobe single step software implementation */
 #define BRK_MULOVF	1023	/* Multiply overflow */
diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
index 2abb587..5a4cfbf 100644
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -69,6 +69,7 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 /*
  * Break instruction with special math emu break code set
  */
-#define BREAK_MATH (0x0000000d | (BRK_MEMU << 16))
+#define BREAK_MATH	(0x0000000d | (BRK_MEMU << 16))
+#define BREAK_MATH_16	(0x00000007 | (BRK_MEMU_16 << 16))
 
 #endif /* _ASM_FPU_EMULATOR_H */
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index a75ae40..887ebc6 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -811,6 +811,7 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
 		force_sig(SIGTRAP, current);
 		break;
 	case BRK_MEMU:
+	case BRK_MEMU_16:
 		/*
 		 * Address errors may be deliberately induced by the FPU
 		 * emulator to retake control of the CPU after executing the
@@ -835,39 +836,37 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
 asmlinkage void do_bp(struct pt_regs *regs)
 {
 	unsigned int opcode, bcode;
-	unsigned long epc;
-	u16 instr[2];
+	unsigned long epc = exception_epc(regs);
 
 	if (get_isa16_mode(regs->cp0_epc)) {
-		/* Calculate EPC. */
-		epc = exception_epc(regs);
+		u16 instr[2];
+
+		if (__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)))
+			goto out_sigsegv;
+
 		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)))))
+			/* microMIPS mode */
+			if (__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2)))
 				goto out_sigsegv;
-		    opcode = (instr[0] << 16) | instr[1];
+			bcode = (instr[1] >> 6) & 0x3f;
 		} else {
-		    /* MIPS16e mode */
-		    if (__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)))
-				goto out_sigsegv;
-		    bcode = (instr[0] >> 6) & 0x3f;
-		    do_trap_or_bp(regs, bcode, "Break");
-		    return;
+			/* MIPS16e mode */
+			bcode = (instr[0] >> 6) & 0x3f;
 		}
 	} else {
-		if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+		if (__get_user(opcode, (unsigned int __user *) epc))
 			goto out_sigsegv;
-	}
 
-	/*
-	 * There is the ancient bug in the MIPS assemblers that the break
-	 * code starts left to bit 16 instead to bit 6 in the opcode.
-	 * 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;
+		/*
+		 * There is the ancient bug in the MIPS assemblers that the
+		 * break code starts left to bit 16 instead to bit 6 in the
+		 * opcode. 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;
+	}
 
 	/*
 	 * notify the kprobe handlers, if instruction is likely to
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index 7ea622a..2521274 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -96,8 +96,8 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
 	if (get_isa16_mode(regs->cp0_epc)) {
 		err = __put_user(ir >> 16, (u16 __user *)(&fr->emul));
 		err |= __put_user(ir & 0xffff, (u16 __user *)((long)(&fr->emul) + 2));
-		err |= __put_user(BREAK_MATH >> 16, (u16 __user *)(&fr->badinst));
-		err |= __put_user(BREAK_MATH & 0xffff, (u16 __user *)((long)(&fr->badinst) + 2));
+		err |= __put_user(BREAK_MATH_16 >> 16, (u16 __user *)(&fr->badinst));
+		err |= __put_user(BREAK_MATH_16 & 0xffff, (u16 __user *)((long)(&fr->badinst) + 2));
 	} else {
 		err = __put_user(ir, &fr->emul);
 		err |= __put_user((mips_instruction)BREAK_MATH, &fr->badinst);
@@ -152,7 +152,7 @@ int do_dsemulret(struct pt_regs *xcp)
 	}
 	err |= __get_user(cookie, &fr->cookie);
 
-	if (unlikely(err || (insn != BREAK_MATH) || (cookie != BD_COOKIE))) {
+	if (unlikely(err || (insn != BREAK_MATH) || (insn != BREAK_MATH_16) || (cookie != BD_COOKIE))) {
 		MIPS_FPU_EMU_INC_STATS(errors);
 		return 0;
 	}
-- 
1.7.2.5



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux