From: Carsten Langgaard <carstenl@mips.com>
To: linux-mips@oss.sgi.com
Subject: FP emulator patch
Date: Wed, 15 Aug 2001 14:53:12 +0200 [thread overview]
Message-ID: <3B7A70B8.ED92FE4@mips.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 641 bytes --]
There has been some reports regarding FP emulator failures, which the
attached patch should solve.
The patch include a fix for emulation of instructions in a COP1
delay-slot, a fix for FP context switching and some additional stuff ,
which was needed to pass our torture test.
Ralf could you please apply this patch.
/Carsten
--
_ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com
|\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527
| \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555
TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556
Denmark http://www.mips.com
[-- Attachment #2: fp_emulator.patch --]
[-- Type: text/plain, Size: 12232 bytes --]
Index: linux/arch/mips/kernel/signal.c
===================================================================
RCS file: /cvs/linux/arch/mips/kernel/signal.c,v
retrieving revision 1.36
diff -u -r1.36 signal.c
--- linux/arch/mips/kernel/signal.c 2001/06/18 22:43:35 1.36
+++ linux/arch/mips/kernel/signal.c 2001/08/15 12:33:38
@@ -220,6 +220,8 @@
err |= __get_user(owned_fp, &sc->sc_ownedfp);
if (owned_fp) {
+ if (last_task_used_math && (last_task_used_math != current))
+ last_task_used_math->thread.cp0_status &= ~ST0_CU1;
err |= restore_fp_context(sc);
last_task_used_math = current;
}
@@ -353,12 +355,11 @@
owned_fp = (current == last_task_used_math);
err |= __put_user(owned_fp, &sc->sc_ownedfp);
- if (current->used_math) { /* fp is active. */
+ if (owned_fp) { /* fp is active. */
set_cp0_status(ST0_CU1);
err |= save_fp_context(sc);
last_task_used_math = NULL;
regs->cp0_status &= ~ST0_CU1;
- current->used_math = 0;
}
return err;
@@ -375,6 +376,13 @@
/* Default to using normal stack */
sp = regs->regs[29];
+ /*
+ * FPU emulator may have it's own trampoline active just
+ * above the user stack, 16-bytes before the next lowest
+ * 16 byte boundary. Try to avoid trashing it.
+ */
+ sp -= 32;
+
/* This is the X/Open sanctioned signal stack switching. */
if ((ka->sa.sa_flags & SA_ONSTACK) && ! on_sig_stack(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
@@ -435,7 +443,7 @@
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n",
- current->comm, current->pid, frame, regs->cp0_epc, frame->code);
+ current->comm, current->pid, frame, regs->cp0_epc, frame->sf_code);
#endif
return;
Index: linux/arch/mips/kernel/unaligned.c
===================================================================
RCS file: /cvs/linux/arch/mips/kernel/unaligned.c,v
retrieving revision 1.12
diff -u -r1.12 unaligned.c
--- linux/arch/mips/kernel/unaligned.c 2001/07/11 22:05:11 1.12
+++ linux/arch/mips/kernel/unaligned.c 2001/08/15 12:33:38
@@ -365,15 +365,12 @@
return;
}
- die_if_kernel ("Unhandled kernel unaligned access", regs);
send_sig(SIGSEGV, current, 1);
return;
sigbus:
- die_if_kernel ("Unhandled kernel unaligned access", regs);
send_sig(SIGBUS, current, 1);
return;
sigill:
- die_if_kernel ("Unhandled kernel unaligned access or invalid instruction", regs);
send_sig(SIGILL, current, 1);
return;
}
@@ -391,11 +388,10 @@
* 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;
- if ((unsigned long)regs->cp0_epc == current->thread.dsemul_aerpc) {
- do_dsemulret(regs);
- return;
- }
+ /* Otherwise handle as normal */
/*
* Did we catch a fault trying to load an instruction?
@@ -417,7 +413,6 @@
return;
sigbus:
- die_if_kernel ("Kernel unaligned instruction access", regs);
force_sig(SIGBUS, current);
return;
Index: linux/arch/mips/math-emu/cp1emu.c
===================================================================
RCS file: /cvs/linux/arch/mips/math-emu/cp1emu.c,v
retrieving revision 1.7
diff -u -r1.7 cp1emu.c
--- linux/arch/mips/math-emu/cp1emu.c 2001/08/02 21:55:26 1.7
+++ linux/arch/mips/math-emu/cp1emu.c 2001/08/15 12:33:38
@@ -6,7 +6,7 @@
* http://www.algor.co.uk
*
* Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.
+ * Copyright (C) 2000-2001 MIPS Technologies, Inc.
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
@@ -273,7 +273,10 @@
fpuemuprivate.stats.errors++;
return SIGBUS;
}
+ /* __computer_return_epc() will have updated cp0_epc */
contpc = REG_TO_VA xcp->cp0_epc;
+ /* In order not to confuse ptrace() et al, tweak context */
+ xcp->cp0_epc = VA_TO_REG emulpc - 4;
} else {
emulpc = REG_TO_VA xcp->cp0_epc;
contpc = REG_TO_VA xcp->cp0_epc + 4;
@@ -753,29 +756,73 @@
* execution of delay-slot instruction execution.
*/
+* Instruction inserted following delay slot instruction to force trap */
+
+#define AdELOAD 0x8c000001 /* lw $0,1($0) */
+
+/* Instruction inserted following the AdELOAD to further tag the sequence */
+
+#define BD_COOKIE 0x0000bd36 /* tne $0,$0 with baggage */
+
int do_dsemulret(struct pt_regs *xcp)
{
+ unsigned long *pinst;
+ unsigned long stackitem;
+ int err = 0;
+
+ /* See if this trap was deliberate. First check the instruction */
+
+ pinst = (unsigned long *) REG_TO_VA(xcp->cp0_epc);
+
+ /*
+ * If we can't even access the area, something is very
+ * wrong, but we'll leave that to the default handling
+ */
+ if (verify_area(VERIFY_READ, pinst, sizeof(unsigned long) * 3))
+ return 0;
+
+ /* Is the instruction pointed to by the EPC an AdELOAD? */
+ stackitem = mips_get_word(xcp, pinst, &err);
+ if (err || (stackitem != AdELOAD)) return 0;
+ /* Is the following memory word the BD_COOKIE? */
+ stackitem = mips_get_word(xcp, pinst+1, &err);
+ if (err || (stackitem != BD_COOKIE)) return 0;
+
+ /*
+ * At this point, we are satisfied that it's a BD emulation
+ * trap. Yes, a user might have deliberately put two
+ * malformed and useless instructions in a row in his program,
+ * in which case he's in for a nasty surprise - the
+ * next instruction will be treated as a continuation
+ * address! Alas, this seems to be the only way that
+ * we can handle signals, recursion, and longjmps()
+ * in the context of emulating the branch delay instruction.
+ */
+
#ifdef DSEMUL_TRACE
printk("desemulret\n");
#endif
+
+ /* Fetch the Saved EPC to Resume */
+
+ stackitem = mips_get_word(xcp, pinst+2, &err);
+ if (err) {
+ /* This is not a good situation to be in */
+ fpuemuprivate.stats.errors++;
+ force_sig(SIGBUS, current);
+ return(1);
+ }
+
/* Set EPC to return to post-branch instruction */
- xcp->cp0_epc = current->thread.dsemul_epc;
- /*
- * Clear the state that got us here.
- */
- current->thread.dsemul_aerpc = (unsigned long) 0;
+ xcp->cp0_epc = stackitem;
- return 0;
+ return 1;
}
-
-#define AdELOAD 0x8c000001 /* lw $0,1($0) */
-
static int
mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc)
{
mips_instruction *dsemul_insns;
- mips_instruction forcetrap;
extern asmlinkage void handle_dsemulret(void);
if (ir == 0) { /* a nop is easy */
@@ -791,13 +838,22 @@
* and put a trap after it which we can catch and jump to
* the required address any alternative apart from full
* instruction emulation!!.
+ *
+ * Algorithmics used a system call instruction, and
+ * borrowed that vector. MIPS/Linux version is a bit
+ * more heavyweight in the interests of portability and
+ * multiprocessor support. We flag the thread for special
+ * handling in the unaligned access handler and force an
+ * address error excpetion.
*/
- dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3);
- dsemul_insns -= 3; /* Two instructions, plus one for luck ;-) */
+
+ /* Ensure that the two instructions are in the same cache line */
+ dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~0xf);
+ dsemul_insns -= 4; /* Retain 16-byte alignment */
/* Verify that the stack pointer is not competely insane */
if (verify_area(VERIFY_WRITE, dsemul_insns,
- sizeof(mips_instruction) * 2))
+ sizeof(mips_instruction) * 4))
return SIGBUS;
if (mips_put_word(xcp, &dsemul_insns[0], ir)) {
@@ -805,29 +861,22 @@
return SIGBUS;
}
- /*
- * Algorithmics used a system call instruction, and
- * borrowed that vector. MIPS/Linux version is a bit
- * more heavyweight in the interests of portability and
- * multiprocessor support. We flag the thread for special
- * handling in the unaligned access handler and force an
- * address error excpetion.
- */
+ if (mips_put_word(xcp, &dsemul_insns[1], (mips_instruction)AdELOAD)) {
+ fpuemuprivate.stats.errors++;
+ return (SIGBUS);
+ }
- /* If one is *really* paranoid, one tests for a bad stack pointer */
- if ((xcp->regs[29] & 0x3) == 0x3)
- forcetrap = AdELOAD - 1;
- else
- forcetrap = AdELOAD;
+ if (mips_put_word(xcp, &dsemul_insns[2],
+ (mips_instruction)BD_COOKIE)) {
+ fpuemuprivate.stats.errors++;
+ return (SIGBUS);
+ }
- if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) {
+ if (mips_put_word(xcp, &dsemul_insns[3], (mips_instruction)cpc)) {
fpuemuprivate.stats.errors++;
return (SIGBUS);
}
- /* Set thread state to catch and handle the exception */
- current->thread.dsemul_epc = (unsigned long) cpc;
- current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1];
xcp->cp0_epc = VA_TO_REG & dsemul_insns[0];
flush_cache_sigtramp((unsigned long) dsemul_insns);
Index: linux/arch/mips/math-emu/kernel_linkage.c
===================================================================
RCS file: /cvs/linux/arch/mips/math-emu/kernel_linkage.c,v
retrieving revision 1.3
diff -u -r1.3 kernel_linkage.c
--- linux/arch/mips/math-emu/kernel_linkage.c 2001/01/13 18:17:58 1.3
+++ linux/arch/mips/math-emu/kernel_linkage.c 2001/08/15 12:33:38
@@ -3,7 +3,7 @@
* arch/mips/math_emu/kernel_linkage.c
*
* Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2000-2001 MIPS Technologies, Inc. All rights reserved.
*
* ########################################################################
*
@@ -45,7 +45,7 @@
if (first) {
first = 0;
- printk("Algorithmics/MIPS FPU Emulator v1.4\n");
+ printk("Algorithmics/MIPS FPU Emulator v1.5\n");
}
current->thread.fpu.soft.sr = 0;
Index: linux/arch/mips/tools/offset.c
===================================================================
RCS file: /cvs/linux/arch/mips/tools/offset.c,v
retrieving revision 1.16
diff -u -r1.16 offset.c
--- linux/arch/mips/tools/offset.c 2000/12/10 07:56:02 1.16
+++ linux/arch/mips/tools/offset.c 2001/08/15 12:33:39
@@ -121,10 +121,6 @@
thread.irix_trampoline);
offset("#define THREAD_OLDCTX ", struct task_struct, \
thread.irix_oldctx);
- offset("#define THREAD_DSEEPC ", struct task_struct, \
- thread.dsemul_epc);
- offset("#define THREAD_DSEAERPC ", struct task_struct, \
- thread.dsemul_aerpc);
linefeed;
}
Index: linux/include/asm-mips/processor.h
===================================================================
RCS file: /cvs/linux/include/asm-mips/processor.h,v
retrieving revision 1.37
diff -u -r1.37 processor.h
--- linux/include/asm-mips/processor.h 2001/07/23 00:17:39 1.37
+++ linux/include/asm-mips/processor.h 2001/08/15 12:33:42
@@ -151,21 +151,6 @@
mm_segment_t current_ds;
unsigned long irix_trampoline; /* Wheee... */
unsigned long irix_oldctx;
-
- /*
- * These are really only needed if the full FPU emulator is configured.
- * Would be made conditional on MIPS_FPU_EMULATOR if it weren't for the
- * fact that having offset.h rebuilt differently for different config
- * options would be asking for trouble.
- *
- * Saved EPC during delay-slot emulation (see math-emu/cp1emu.c)
- */
- unsigned long dsemul_epc;
-
- /*
- * Pointer to instruction used to induce address error
- */
- unsigned long dsemul_aerpc;
};
#endif /* !defined (_LANGUAGE_ASSEMBLY) */
@@ -195,11 +180,6 @@
* For now the default is to fix address errors \
*/ \
MF_FIXADE, { 0 }, 0, 0, \
- /* \
- * dsemul_epc and dsemul_aerpc should never be used uninitialized, \
- * but... \
- */ \
- 0 ,0 \
}
#ifdef __KERNEL__
@@ -235,8 +215,8 @@
* Do necessary setup to start up a newly executed thread.
*/
#define start_thread(regs, new_pc, new_sp) do { \
- /* New thread looses kernel privileges. */ \
- regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KU_USER;\
+ /* New thread loses kernel and FPU privileges. */ \
+ regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU|ST0_CU1)) | KU_USER;\
regs->cp0_epc = new_pc; \
regs->regs[29] = new_sp; \
current->thread.current_ds = USER_DS; \
next reply other threads:[~2001-08-15 12:54 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-08-15 12:53 Carsten Langgaard [this message]
2001-08-15 18:06 ` FP emulator patch Daniel Jacobowitz
2001-08-16 0:05 ` Kevin D. Kissell
2001-08-16 0:05 ` Kevin D. Kissell
2001-08-16 4:20 ` Atsushi Nemoto
2001-08-16 12:35 ` Kevin D. Kissell
2001-08-16 12:35 ` Kevin D. Kissell
2001-08-16 7:07 ` Carsten Langgaard
2001-08-16 4:35 ` Atsushi Nemoto
-- strict thread matches above, loose matches on Subject: below --
2001-08-16 18:23 Kevin D. Kissell
2001-08-16 18:23 ` Kevin D. Kissell
2001-08-16 18:49 ` Pete Popov
2001-08-16 18:53 ` Daniel Jacobowitz
2001-08-16 19:15 ` Jun Sun
2001-08-16 20:40 ` Kevin D. Kissell
2001-08-16 20:40 ` Kevin D. Kissell
2001-08-16 21:34 ` Jun Sun
2001-08-16 22:33 ` Kevin D. Kissell
2001-08-16 22:33 ` Kevin D. Kissell
2001-08-16 22:38 ` Pete Popov
2001-08-16 22:37 ` Daniel Jacobowitz
2001-08-16 23:12 ` Jun Sun
2001-08-16 23:38 ` Kevin D. Kissell
2001-08-16 23:38 ` Kevin D. Kissell
2001-08-16 19:20 ` Kevin D. Kissell
2001-08-16 19:20 ` Kevin D. Kissell
2001-08-16 20:20 ` Jun Sun
2001-08-16 22:58 Kevin D. Kissell
2001-08-16 22:58 ` Kevin D. Kissell
2001-08-16 23:14 ` Jun Sun
2001-08-16 23:46 ` Kevin D. Kissell
2001-08-16 23:46 ` Kevin D. Kissell
2002-09-10 11:55 Carsten Langgaard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3B7A70B8.ED92FE4@mips.com \
--to=carstenl@mips.com \
--cc=linux-mips@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox