* 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:
Aurelien Jarno 2010-05-11 13:00:41 +00:00
parent 49ede2ac48
commit ff12f60bcc
3 changed files with 102 additions and 0 deletions

2
debian/changelog vendored
View File

@ -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

View File

@ -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;

View File

@ -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