MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6
MIPS R6 removed quite a few R2 instructions. However, there is plenty of <R6 userland code so we add an in-kernel emulator so we can still be able to execute all R2 userland out there. The emulator comes with a handy debugfs under /mips/ directory (r2-emul-stats) to provide some basic statistics of the instructions that are being emulated. Below are some statistics from booting a minimal buildroot image: Instruction Total BDslot ------------------------------ movs 236969 0 hilo 56686 0 muls 55279 0 divs 10941 0 dsps 0 0 bops 1 0 traps 0 0 fpus 0 0 loads 214981 17 stores 103364 0 llsc 56898 0 dsemul 150418 0 jr 370158 bltzl 43 bgezl 1594 bltzll 0 bgezll 0 bltzal 39 bgezal 39 beql 14503 bnel 138741 blezl 0 bgtzl 3988 Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
This commit is contained in:

committed by
Markos Chandras

parent
b55b9e2715
commit
b0a668fb20
@@ -46,6 +46,7 @@
|
||||
#include <asm/fpu.h>
|
||||
#include <asm/fpu_emulator.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/mips-r2-to-r6-emul.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/mipsmtregs.h>
|
||||
#include <asm/module.h>
|
||||
@@ -837,7 +838,7 @@ out:
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
||||
static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
|
||||
void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
|
||||
const char *str)
|
||||
{
|
||||
siginfo_t info;
|
||||
@@ -1027,7 +1028,32 @@ asmlinkage void do_ri(struct pt_regs *regs)
|
||||
unsigned int opcode = 0;
|
||||
int status = -1;
|
||||
|
||||
/*
|
||||
* Avoid any kernel code. Just emulate the R2 instruction
|
||||
* as quickly as possible.
|
||||
*/
|
||||
if (mipsr2_emulation && cpu_has_mips_r6 &&
|
||||
likely(user_mode(regs))) {
|
||||
if (likely(get_user(opcode, epc) >= 0)) {
|
||||
status = mipsr2_decoder(regs, opcode);
|
||||
switch (status) {
|
||||
case 0:
|
||||
case SIGEMT:
|
||||
return;
|
||||
case SIGILL:
|
||||
goto no_r2_instr;
|
||||
default:
|
||||
process_fpemu_return(status,
|
||||
¤t->thread.cp0_baduaddr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
no_r2_instr:
|
||||
|
||||
prev_state = exception_enter();
|
||||
|
||||
if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs),
|
||||
SIGILL) == NOTIFY_STOP)
|
||||
goto out;
|
||||
|
Reference in New Issue
Block a user