Skip to contentSkip to conversation

MIPS: Full ISA emulation for FPU emulation of delay slots

RFC PATCH New David Daney 1 participant 6 messages Dec 20, 2014 MIPS

lore
Share & tools
lore
#0 lore raw

v2 cover MIPS: Full ISA emulation for FPU emulation of delay slots

From: David Daney <[email protected]>

I have been improving my emulator little by little. It is still not quite complete, but I am on vacation for the next several weeks, so I thought I would send it as-is for your comments and general enjoyment.

David Daney (5):
MIPS: Add FPU emulator counter for emulated delay slots.
MIPS: Add FPU emulator counter for non-FPU instructions emulated.
MIPS: Add instruction coding for SYNCI and add trap formats.
MIPS: Add full ISA emulator.
MIPS: Use full instruction emulation for FPU emulator delay slot
emulation.

 arch/mips/include/asm/fpu_emulator.h |    2 +
 arch/mips/include/uapi/asm/inst.h    |   13 +-
 arch/mips/kernel/Makefile            |    2 +-
 arch/mips/kernel/insn-emul.c         | 1543 ++++++++++++++++++++++++++++++++++
 arch/mips/math-emu/cp1emu.c          |   13 +-
 arch/mips/math-emu/dsemul.c          |    2 +-
 arch/mips/math-emu/me-debugfs.c      |    2 +
 7 files changed, 1572 insertions(+), 5 deletions(-)
 create mode 100644 arch/mips/kernel/insn-emul.c
Signature · 1 line
1.7.11.7
#1 lore raw

RFC PATCH v2 1/5 MIPS: Add FPU emulator counter for emulated delay slots.

From: David Daney <[email protected]>

Delay slot emulation in the FPU emulator is the only kernel user of an executable stack, it is also very slow. Add a counter so we can see how many of these emulations are done.

---
 arch/mips/include/asm/fpu_emulator.h | 1 +
 arch/mips/math-emu/dsemul.c          | 2 +-
 arch/mips/math-emu/me-debugfs.c      | 1 +
 3 files changed, 3 insertions(+), 1 deletion(-)
arch/mips/include/asm/fpu_emulator.h +1 -0
index 3ee3477..6370c82 100644
@@ -44,6 +44,7 @@ struct mips_fpu_emulator_stats {
 	unsigned long ieee754_overflow;
 	unsigned long ieee754_zerodiv;
 	unsigned long ieee754_invalidop;
+	unsigned long ds_emul;
 };
 
 DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
arch/mips/math-emu/dsemul.c +1 -1
index 4f514f3..58f5818 100644
@@ -158,6 +158,6 @@ int do_dsemulret(struct pt_regs *xcp)
 
 	/* Set EPC to return to post-branch instruction */
 	xcp->cp0_epc = epc;
-
+	MIPS_FPU_EMU_INC_STATS(ds_emul);
 	return 1;
 }
arch/mips/math-emu/me-debugfs.c +1 -0
index becdd63..f308e0f 100644
@@ -61,6 +61,7 @@ do {									\
 	FPU_STAT_CREATE(ieee754_overflow);
 	FPU_STAT_CREATE(ieee754_zerodiv);
 	FPU_STAT_CREATE(ieee754_invalidop);
+	FPU_STAT_CREATE(ds_emul);
 
 	return 0;
 }
Signature · 1 line
1.7.11.7
#2 lore raw

RFC PATCH v2 2/5 MIPS: Add FPU emulator counter for non-FPU instructions emulated.

In reply to David Daney

From: David Daney <[email protected]>

Used in follow-on patch, the counter is called "insn_emul".

---
 arch/mips/include/asm/fpu_emulator.h | 1 +
 arch/mips/math-emu/me-debugfs.c      | 1 +
 2 files changed, 2 insertions(+)
arch/mips/include/asm/fpu_emulator.h +1 -0
index 6370c82..bd5b63f 100644
@@ -45,6 +45,7 @@ struct mips_fpu_emulator_stats {
 	unsigned long ieee754_zerodiv;
 	unsigned long ieee754_invalidop;
 	unsigned long ds_emul;
+	unsigned long insn_emul;
 };
 
 DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
arch/mips/math-emu/me-debugfs.c +1 -0
index f308e0f..93fc155 100644
@@ -62,6 +62,7 @@ do {									\
 	FPU_STAT_CREATE(ieee754_zerodiv);
 	FPU_STAT_CREATE(ieee754_invalidop);
 	FPU_STAT_CREATE(ds_emul);
+	FPU_STAT_CREATE(insn_emul);
 
 	return 0;
 }
Signature · 1 line
1.7.11.7
#3 lore raw

RFC PATCH v2 3/5 MIPS: Add instruction coding for SYNCI and add trap formats.

In reply to David Daney

From: David Daney <[email protected]>

---
 arch/mips/include/uapi/asm/inst.h | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
arch/mips/include/uapi/asm/inst.h +12 -1
index 89c2243..7cd4107 100644
@@ -100,7 +100,8 @@ enum rt_op {
 	bltzal_op, bgezal_op, bltzall_op, bgezall_op,
 	rt_op_0x14, rt_op_0x15, rt_op_0x16, rt_op_0x17,
 	rt_op_0x18, rt_op_0x19, rt_op_0x1a, rt_op_0x1b,
-	bposge32_op, rt_op_0x1d, rt_op_0x1e, rt_op_0x1f
+	bposge32_op, rt_op_0x1d, rt_op_0x1e, rt_op_0x1f,
+	op_synci = rt_op_0x1f
 };
 
 /*
@@ -547,6 +548,15 @@ struct r_format {			/* Register format */
 	;))))))
 };
 
+struct t_format {			/* Trap format */
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rs : 5,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(unsigned int code : 10,
+	__BITFIELD_FIELD(unsigned int func : 6,
+	;)))))
+};
+
 struct p_format {		/* Performance counter format (R10000) */
 	__BITFIELD_FIELD(unsigned int opcode : 6,
 	__BITFIELD_FIELD(unsigned int rs : 5,
@@ -881,6 +891,7 @@ union mips_instruction {
 	struct u_format u_format;
 	struct c_format c_format;
 	struct r_format r_format;
+	struct t_format t_format;
 	struct p_format p_format;
 	struct f_format f_format;
 	struct ma_format ma_format;
Signature · 1 line
1.7.11.7
#4 lore raw

RFC PATCH v2 4/5 MIPS: Add full ISA emulator.

In reply to David Daney

From: David Daney <[email protected]>

Used in follow-on patch to replace FPU delay-slot instruction execution on stack.

---
 arch/mips/kernel/Makefile    |    2 +-
 arch/mips/kernel/insn-emul.c | 1543 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1544 insertions(+), 1 deletion(-)
 create mode 100644 arch/mips/kernel/insn-emul.c
arch/mips/kernel/Makefile +1 -1
index 92987d1..44c0670 100644
@@ -7,7 +7,7 @@ extra-y		:= head.o vmlinux.lds
 obj-y		+= cpu-probe.o branch.o elf.o entry.o genex.o idle.o irq.o \
 		   process.o prom.o ptrace.o reset.o setup.o signal.o \
 		   syscall.o time.o topology.o traps.o unaligned.o watch.o \
-		   vdso.o
+		   vdso.o insn-emul.o
 
 ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
arch/mips/kernel/insn-emul.c new file +1543 -0

1,543 lines not on this page · raw message

Signature · 1 line
1.7.11.7
#5 lore raw

RFC PATCH v2 5/5 MIPS: Use full instruction emulation for FPU emulator delay slot emulation.

In reply to David Daney

From: David Daney <[email protected]>

Current delay slot handling does eXecute Out of Line (XOL) on the stack, which prevents a non-executable stack. Use the instruction emulator instead.

Tested by booting 32-bit Debian on OCTEON. More than 1700 instructions emulated to login to command line.

---
 arch/mips/math-emu/cp1emu.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
arch/mips/math-emu/cp1emu.c +11 -2
index 9dfcd7f..0611697 100644
@@ -699,11 +699,12 @@ do {									\
  * Emulate the single floating point instruction pointed at by EPC.
  * Two instructions if the instruction is in a branch delay slot.
  */
-
+int mips_insn_emul(struct pt_regs *regs, mips_instruction ir, void *__user *fault_addr);
 static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		struct mm_decoded_insn dec_insn, void *__user *fault_addr)
 {
 	unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc;
+	unsigned long origpc = xcp->cp0_epc;
 	unsigned int cond, cbit;
 	mips_instruction ir;
 	int likely, pc_inc;
@@ -1043,7 +1044,15 @@ emul:
 				 * Single step the non-cp1
 				 * instruction in the dslot
 				 */
-				return mips_dsemul(xcp, ir, contpc);
+				sig = mips_insn_emul(xcp, ir, fault_addr);
+				if (sig == 0) {
+					xcp->cp0_epc = contpc;
+					MIPS_FPU_EMU_INC_STATS(insn_emul);
+				} else {
+					xcp->cp0_epc = origpc;
+					pr_err("mips_insn_emul: %08x ->%d\n", (unsigned)ir, sig);
+				}
+				return sig;
 			} else if (likely) {	/* branch not taken */
 					/*
 					 * branch likely nullifies
Signature · 1 line
1.7.11.7