Skip to content

Commit

Permalink
MIPS: Switch FPU emulator trap to BREAK instruction.
Browse files Browse the repository at this point in the history
Arguably using the address error handler has always been ugly.  But with
processors that handle unaligned loads and stores in hardware the
current mechanism ceases to work so switch it to a BREAK instruction and
allocate break code 514 to the FPU emulator.

Yoichi Yuasa provided a build fix for CONFIG_BUG=n.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
  • Loading branch information
Ralf Baechle committed Oct 30, 2008
1 parent 076c6e4 commit ba3049e
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 37 deletions.
1 change: 1 addition & 0 deletions arch/mips/include/asm/break.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#define _BRK_THREADBP 11 /* For threads, user bp (used by debuggers) */
#define BRK_BUG 512 /* Used by BUG() */
#define BRK_KDB 513 /* Used in KDB_ENTER() */
#define BRK_MEMU 514 /* Used by FPU emulator */
#define BRK_MULOVF 1023 /* Multiply overflow */

#endif /* __ASM_BREAK_H */
17 changes: 17 additions & 0 deletions arch/mips/include/asm/fpu_emulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#ifndef _ASM_FPU_EMULATOR_H
#define _ASM_FPU_EMULATOR_H

#include <asm/break.h>
#include <asm/inst.h>

struct mips_fpu_emulator_stats {
unsigned int emulated;
unsigned int loads;
Expand All @@ -34,4 +37,18 @@ struct mips_fpu_emulator_stats {

extern struct mips_fpu_emulator_stats fpuemustats;

extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
unsigned long cpc);
extern int do_dsemulret(struct pt_regs *xcp);

/*
* Instruction inserted following the badinst to further tag the sequence
*/
#define BD_COOKIE 0x0000bd36 /* tne $0, $0 with baggage */

/*
* Break instruction with special math emu break code set
*/
#define BREAK_MATH (0x0000000d | (BRK_MEMU << 16))

#endif /* _ASM_FPU_EMULATOR_H */
16 changes: 16 additions & 0 deletions arch/mips/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <asm/cpu.h>
#include <asm/dsp.h>
#include <asm/fpu.h>
#include <asm/fpu_emulator.h>
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/module.h>
Expand Down Expand Up @@ -722,6 +723,21 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
die_if_kernel("Kernel bug detected", regs);
force_sig(SIGTRAP, current);
break;
case BRK_MEMU:
/*
* Address errors may be deliberately induced by the FPU
* emulator to retake control of the CPU after executing the
* instruction in the delay slot of an emulated branch.
*
* Terminate if exception was recognized as a delay slot return
* otherwise handle as normal.
*/
if (do_dsemulret(regs))
return;

die_if_kernel("Math emu break/trap", regs);
force_sig(SIGTRAP, current);
break;
default:
scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
die_if_kernel(b, regs);
Expand Down
12 changes: 0 additions & 12 deletions arch/mips/kernel/unaligned.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,21 +499,9 @@ static void emulate_load_store_insn(struct pt_regs *regs,

asmlinkage void do_ade(struct pt_regs *regs)
{
extern int do_dsemulret(struct pt_regs *);
unsigned int __user *pc;
mm_segment_t seg;

/*
* Address errors may be deliberately induced by the FPU emulator to
* retake control of the CPU after executing the instruction in the
* delay slot of an emulated branch.
*/
/* Terminate if exception was recognized as a delay slot return */
if (do_dsemulret(regs))
return;

/* Otherwise handle as normal */

/*
* Did we catch a fault trying to load an instruction?
* Or are we running in MIPS16 mode?
Expand Down
4 changes: 0 additions & 4 deletions arch/mips/math-emu/cp1emu.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
#include <asm/branch.h>

#include "ieee754.h"
#include "dsemul.h"

/* Strap kernel emulator for full MIPS IV emulation */

Expand Down Expand Up @@ -346,9 +345,6 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
/* cop control register rd -> gpr[rt] */
u32 value;

if (ir == CP1UNDEF) {
return do_dsemulret(xcp);
}
if (MIPSInst_RD(ir) == FPCREG_CSR) {
value = ctx->fcr31;
value = (value & ~0x3) | mips_rm[value & 0x3];
Expand Down
7 changes: 3 additions & 4 deletions arch/mips/math-emu/dsemul.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <asm/fpu_emulator.h>

#include "ieee754.h"
#include "dsemul.h"

/* Strap kernel emulator for full MIPS IV emulation */

Expand Down Expand Up @@ -94,7 +93,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
return SIGBUS;

err = __put_user(ir, &fr->emul);
err |= __put_user((mips_instruction)BADINST, &fr->badinst);
err |= __put_user((mips_instruction)BREAK_MATH, &fr->badinst);
err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie);
err |= __put_user(cpc, &fr->epc);

Expand Down Expand Up @@ -130,13 +129,13 @@ int do_dsemulret(struct pt_regs *xcp)
/*
* Do some sanity checking on the stackframe:
*
* - Is the instruction pointed to by the EPC an BADINST?
* - Is the instruction pointed to by the EPC an BREAK_MATH?
* - Is the following memory word the BD_COOKIE?
*/
err = __get_user(insn, &fr->badinst);
err |= __get_user(cookie, &fr->cookie);

if (unlikely(err || (insn != BADINST) || (cookie != BD_COOKIE))) {
if (unlikely(err || (insn != BREAK_MATH) || (cookie != BD_COOKIE))) {
fpuemustats.errors++;
return 0;
}
Expand Down
17 changes: 0 additions & 17 deletions arch/mips/math-emu/dsemul.h

This file was deleted.

0 comments on commit ba3049e

Please sign in to comment.