MIPS: Full ISA emulation for FPU emulation of delay slots
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
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
@@ -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
@@ -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
@@ -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
RFC PATCH v2 2/5 MIPS: Add FPU emulator counter for non-FPU instructions emulated.
In reply to David DaneyFrom: 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
@@ -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
@@ -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
RFC PATCH v2 3/5 MIPS: Add instruction coding for SYNCI and add trap formats.
In reply to David DaneyFrom: 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
@@ -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
RFC PATCH v2 4/5 MIPS: Add full ISA emulator.
In reply to David DaneyFrom: 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
@@ -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
RFC PATCH v2 5/5 MIPS: Use full instruction emulation for FPU emulator delay slot emulation.
In reply to David DaneyFrom: 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
@@ -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