* backport MIPS FPU emulator: allow Cause bits of FCSR to be writeable
by ctc1. (closes: #580602). svn path=/dists/sid/linux-2.6/; revision=15659
This commit is contained in:
parent
49ede2ac48
commit
ff12f60bcc
|
@ -27,6 +27,8 @@ linux-2.6 (2.6.32-13) UNRELEASED; urgency=low
|
|||
* mips/swarm: fix boot from IDE based media (Sebastian Andrzej Siewior)
|
||||
(closes: #466977).
|
||||
* backport mips/swarm: fix M3 TLB exception handler.
|
||||
* backport MIPS FPU emulator: allow Cause bits of FCSR to be writeable
|
||||
by ctc1. (closes: #580602).
|
||||
|
||||
-- Frederik Schüler <fs@debian.org> Wed, 05 May 2010 17:54:01 +0200
|
||||
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
From: Shane McDonald <mcdonald.shane@gmail.com>
|
||||
Date: Fri, 7 May 2010 05:26:57 +0000 (-0600)
|
||||
Subject: MIPS FPU emulator: allow Cause bits of FCSR to be writeable by ctc1
|
||||
X-Git-Url: http://www.linux-mips.org/git?p=linux.git;a=commitdiff_plain;h=2c8fb481214e608f6b9a71aa85651d9ddf7fd6e4
|
||||
|
||||
MIPS FPU emulator: allow Cause bits of FCSR to be writeable by ctc1
|
||||
|
||||
In the FPU emulator code of the MIPS, the Cause bits of the FCSR register
|
||||
are not currently writeable by the ctc1 instruction. In odd corner cases,
|
||||
this can cause problems. For example, a case existed where a divide-by-zero
|
||||
exception was generated by the FPU, and the signal handler attempted to
|
||||
restore the FPU registers to their state before the exception occurred. In
|
||||
this particular setup, writing the old value to the FCSR register would
|
||||
cause another divide-by-zero exception to occur immediately. The solution
|
||||
is to change the ctc1 instruction emulator code to allow the Cause bits of
|
||||
the FCSR register to be writeable. This is the behaviour of the hardware
|
||||
that the code is emulating.
|
||||
|
||||
This problem was found by Shane McDonald, but the credit for the fix goes
|
||||
to Kevin Kissell. In Kevin's words:
|
||||
|
||||
I submit that the bug is indeed in that ctc_op: case of the emulator. The
|
||||
Cause bits (17:12) are supposed to be writable by that instruction, but the
|
||||
CTC1 emulation won't let them be updated by the instruction. I think that
|
||||
actually if you just completely removed lines 387-388 [...] things would
|
||||
work a good deal better. At least, it would be a more accurate emulation of
|
||||
the architecturally defined FPU. If I wanted to be really, really pedantic
|
||||
(which I sometimes do), I'd also protect the reserved bits that aren't
|
||||
necessarily writable.
|
||||
|
||||
Signed-off-by: Shane McDonald <mcdonald.shane@gmail.com>
|
||||
To: anemo@mba.ocn.ne.jp
|
||||
To: kevink@paralogos.com
|
||||
To: sshtylyov@mvista.com
|
||||
Patchwork: http://patchwork.linux-mips.org/patch/1205/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
(cherry picked from commit 635be78c7c80d4c61f0f16b6132a730d7668cb43)
|
||||
---
|
||||
|
||||
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
|
||||
index a581d60..608dc97 100644
|
||||
--- a/arch/mips/include/asm/mipsregs.h
|
||||
+++ b/arch/mips/include/asm/mipsregs.h
|
||||
@@ -135,6 +135,12 @@
|
||||
#define FPU_CSR_COND7 0x80000000 /* $fcc7 */
|
||||
|
||||
/*
|
||||
+ * Bits 18 - 20 of the FPU Status Register will be read as 0,
|
||||
+ * and should be written as zero.
|
||||
+ */
|
||||
+#define FPU_CSR_RSVD 0x001c0000
|
||||
+
|
||||
+/*
|
||||
* X the exception cause indicator
|
||||
* E the exception enable
|
||||
* S the sticky/flag bit
|
||||
@@ -161,7 +167,8 @@
|
||||
#define FPU_CSR_UDF_S 0x00000008
|
||||
#define FPU_CSR_INE_S 0x00000004
|
||||
|
||||
-/* rounding mode */
|
||||
+/* Bits 0 and 1 of FPU Status Register specify the rounding mode */
|
||||
+#define FPU_CSR_RM 0x00000003
|
||||
#define FPU_CSR_RN 0x0 /* nearest */
|
||||
#define FPU_CSR_RZ 0x1 /* towards zero */
|
||||
#define FPU_CSR_RU 0x2 /* towards +Infinity */
|
||||
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
|
||||
index 454b539..c15d94b 100644
|
||||
--- a/arch/mips/math-emu/cp1emu.c
|
||||
+++ b/arch/mips/math-emu/cp1emu.c
|
||||
@@ -75,6 +75,9 @@ struct mips_fpu_emulator_stats fpuemustats;
|
||||
#define FPCREG_RID 0 /* $0 = revision id */
|
||||
#define FPCREG_CSR 31 /* $31 = csr */
|
||||
|
||||
+/* Determine rounding mode from the RM bits of the FCSR */
|
||||
+#define modeindex(v) ((v) & FPU_CSR_RM)
|
||||
+
|
||||
/* Convert Mips rounding mode (0..3) to IEEE library modes. */
|
||||
static const unsigned char ieee_rm[4] = {
|
||||
[FPU_CSR_RN] = IEEE754_RN,
|
||||
@@ -381,10 +384,14 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
|
||||
(void *) (xcp->cp0_epc),
|
||||
MIPSInst_RT(ir), value);
|
||||
#endif
|
||||
- value &= (FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
|
||||
- ctx->fcr31 &= ~(FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
|
||||
- /* convert to ieee library modes */
|
||||
- ctx->fcr31 |= (value & ~0x3) | ieee_rm[value & 0x3];
|
||||
+
|
||||
+ /*
|
||||
+ * Don't write reserved bits,
|
||||
+ * and convert to ieee library modes
|
||||
+ */
|
||||
+ ctx->fcr31 = (value &
|
||||
+ ~(FPU_CSR_RSVD | FPU_CSR_RM)) |
|
||||
+ ieee_rm[modeindex(value)];
|
||||
}
|
||||
if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
|
||||
return SIGFPE;
|
|
@ -10,3 +10,4 @@
|
|||
+ features/all/rtl8192su-Add-Sitecom-WL-349.patch
|
||||
+ bugfix/mips/mips-ide-flush-dcache.patch
|
||||
+ bugfix/mips/sibyte-m3-tlb-exception.patch
|
||||
+ bugfix/mips/fpu-emulator.patch
|
||||
|
|
Loading…
Reference in New Issue