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
96
arch/mips/include/asm/mips-r2-to-r6-emul.h
Normal file
96
arch/mips/include/asm/mips-r2-to-r6-emul.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (c) 2014 Imagination Technologies Ltd.
|
||||
* Author: Markos Chandras <markos.chandras@imgtec.com>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MIPS_R2_TO_R6_EMUL_H
|
||||
#define __ASM_MIPS_R2_TO_R6_EMUL_H
|
||||
|
||||
struct mips_r2_emulator_stats {
|
||||
u64 movs;
|
||||
u64 hilo;
|
||||
u64 muls;
|
||||
u64 divs;
|
||||
u64 dsps;
|
||||
u64 bops;
|
||||
u64 traps;
|
||||
u64 fpus;
|
||||
u64 loads;
|
||||
u64 stores;
|
||||
u64 llsc;
|
||||
u64 dsemul;
|
||||
};
|
||||
|
||||
struct mips_r2br_emulator_stats {
|
||||
u64 jrs;
|
||||
u64 bltzl;
|
||||
u64 bgezl;
|
||||
u64 bltzll;
|
||||
u64 bgezll;
|
||||
u64 bltzall;
|
||||
u64 bgezall;
|
||||
u64 bltzal;
|
||||
u64 bgezal;
|
||||
u64 beql;
|
||||
u64 bnel;
|
||||
u64 blezl;
|
||||
u64 bgtzl;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
#define MIPS_R2_STATS(M) \
|
||||
do { \
|
||||
u32 nir; \
|
||||
int err; \
|
||||
\
|
||||
preempt_disable(); \
|
||||
__this_cpu_inc(mipsr2emustats.M); \
|
||||
err = __get_user(nir, (u32 __user *)regs->cp0_epc); \
|
||||
if (!err) { \
|
||||
if (nir == BREAK_MATH) \
|
||||
__this_cpu_inc(mipsr2bdemustats.M); \
|
||||
} \
|
||||
preempt_enable(); \
|
||||
} while (0)
|
||||
|
||||
#define MIPS_R2BR_STATS(M) \
|
||||
do { \
|
||||
preempt_disable(); \
|
||||
__this_cpu_inc(mipsr2bremustats.M); \
|
||||
preempt_enable(); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define MIPS_R2_STATS(M) do { } while (0)
|
||||
#define MIPS_R2BR_STATS(M) do { } while (0)
|
||||
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
struct r2_decoder_table {
|
||||
u32 mask;
|
||||
u32 code;
|
||||
int (*func)(struct pt_regs *regs, u32 inst);
|
||||
};
|
||||
|
||||
|
||||
extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
|
||||
const char *str);
|
||||
|
||||
#ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
|
||||
static int mipsr2_emulation;
|
||||
static __maybe_unused int mipsr2_decoder(struct pt_regs *regs, u32 inst) { return 0; };
|
||||
#else
|
||||
/* MIPS R2 Emulator ON/OFF */
|
||||
extern int mipsr2_emulation;
|
||||
extern int mipsr2_decoder(struct pt_regs *regs, u32 inst);
|
||||
#endif /* CONFIG_MIPSR2_TO_R6_EMULATOR */
|
||||
|
||||
#define NO_R6EMU (cpu_has_mips_r6 && !mipsr2_emulation)
|
||||
|
||||
#endif /* __ASM_MIPS_R2_TO_R6_EMUL_H */
|
Reference in New Issue
Block a user