linux_dsm_epyc7002/arch/mips/include/asm/mips-r2-to-r6-emul.h
Maciej W. Rozycki 733b8bc183 MIPS: math-emu: Make microMIPS branch delay slot emulation work
Complement commit 102cedc32a ("MIPS: microMIPS: Floating point
support.") which introduced microMIPS FPU emulation, but did not adjust
the encoding of the BREAK instruction used to terminate the branch delay
slot emulation frame.  Consequently the execution of any such frame is
indeterminate and, depending on CPU configuration, will result in random
code execution or an offending program being terminated with SIGILL.

This is because the regular MIPS BREAK instruction is encoded with the 0
major and the 0xd minor opcode, however in the microMIPS instruction set
this major/minor opcode pair denotes an encoding reserved for the DSP
ASE.  Instead the microMIPS BREAK instruction is encoded with the 0
major and the 0x7 minor opcode.

Use the correct BREAK encoding for microMIPS FPU emulation then.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/12174/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-01-24 01:35:46 +01:00

102 lines
2.0 KiB
C

/*
* 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(0)) \
__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 inline int mipsr2_decoder(struct pt_regs *regs, u32 inst,
unsigned long *fcr31)
{
return 0;
};
#else
/* MIPS R2 Emulator ON/OFF */
extern int mipsr2_emulation;
extern int mipsr2_decoder(struct pt_regs *regs, u32 inst,
unsigned long *fcr31);
#endif /* CONFIG_MIPSR2_TO_R6_EMULATOR */
#define NO_R6EMU (cpu_has_mips_r6 && !mipsr2_emulation)
#endif /* __ASM_MIPS_R2_TO_R6_EMUL_H */