linux-mips
[Top] [All Lists]

Re: fpu_emulator can lose fpu on get_user/put_user

To: linux-mips@linux-mips.org
Subject: Re: fpu_emulator can lose fpu on get_user/put_user
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Wed, 06 Oct 2004 18:40:14 +0900 (JST)
Cc: ralf@linux-mips.org
In-reply-to: <20041006.101920.126571873.nemoto@toshiba-tops.co.jp>
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <20041006.101920.126571873.nemoto@toshiba-tops.co.jp>
Sender: linux-mips-bounce@linux-mips.org
>>>>> On Wed, 06 Oct 2004 10:19:20 +0900 (JST), Atsushi Nemoto 
>>>>> <anemo@mba.ocn.ne.jp> said:
anemo> Also, there is another problem in the math-emu.  While math-emu
anemo> is not reentrant, it will not work properly if a process lose
anemo> ownership in the math-emu and another process uses the
anemo> math-emu.  One possible fix is to save/restore ieee754_csr on
anemo> get_user/put_user.  I will post a patch later.

Here it is.  Can be applied bath 2.4 and 2.6.

--- linux-mips/arch/mips/math-emu/cp1emu.c      Wed Sep  1 10:47:21 2004
+++ linux/arch/mips/math-emu/cp1emu.c   Wed Oct  6 12:34:43 2004
@@ -51,6 +51,24 @@
 #include "ieee754.h"
 #include "dsemul.h"
 
+#define math_put_user(x, ptr) \
+({ \
+       long math_pu_err; \
+       struct ieee754_csr pu_csr_save; \
+       pu_csr_save = ieee754_csr; \
+       math_pu_err = put_user(x, ptr); \
+       ieee754_csr = pu_csr_save; \
+       math_pu_err; \
+})
+#define math_get_user(x, ptr) \
+({ \
+       long math_gu_err; \
+       struct ieee754_csr gu_csr_save; \
+       gu_csr_save = ieee754_csr; \
+       math_gu_err = get_user(x, ptr); \
+       ieee754_csr = gu_csr_save; \
+       math_gu_err; \
+})
 /* Strap kernel emulator for full MIPS IV emulation */
 
 #ifdef __mips
@@ -199,7 +217,7 @@
        vaddr_t emulpc, contpc;
        unsigned int cond;
 
-       if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) {
+       if (math_get_user(ir, (mips_instruction *) xcp->cp0_epc)) {
                fpuemuprivate.stats.errors++;
                return SIGBUS;
        }
@@ -230,7 +248,7 @@
 #endif
                        return SIGILL;
                }
-               if (get_user(ir, (mips_instruction *) emulpc)) {
+               if (math_get_user(ir, (mips_instruction *) emulpc)) {
                        fpuemuprivate.stats.errors++;
                        return SIGBUS;
                }
@@ -254,7 +272,7 @@
                u64 val;
 
                fpuemuprivate.stats.loads++;
-               if (get_user(val, va)) {
+               if (math_get_user(val, va)) {
                        fpuemuprivate.stats.errors++;
                        return SIGBUS;
                }
@@ -269,7 +287,7 @@
 
                fpuemuprivate.stats.stores++;
                DIFROMREG(val, MIPSInst_RT(ir));
-               if (put_user(val, va)) {
+               if (math_put_user(val, va)) {
                        fpuemuprivate.stats.errors++;
                        return SIGBUS;
                }
@@ -283,7 +301,7 @@
                u32 val;
 
                fpuemuprivate.stats.loads++;
-               if (get_user(val, va)) {
+               if (math_get_user(val, va)) {
                        fpuemuprivate.stats.errors++;
                        return SIGBUS;
                }
@@ -310,7 +328,7 @@
                }
 #endif
                SIFROMREG(val, MIPSInst_RT(ir));
-               if (put_user(val, va)) {
+               if (math_put_user(val, va)) {
                        fpuemuprivate.stats.errors++;
                        return SIGBUS;
                }
@@ -449,7 +467,7 @@
                                        (xcp->cp0_epc +
                                        (MIPSInst_SIMM(ir) << 2));
 
-                               if (get_user(ir, (mips_instruction *)
+                               if (math_get_user(ir, (mips_instruction *)
                                                REG_TO_VA xcp->cp0_epc)) {
                                        fpuemuprivate.stats.errors++;
                                        return SIGBUS;
@@ -632,7 +650,7 @@
                                xcp->regs[MIPSInst_FT(ir)]);
 
                        fpuemuprivate.stats.loads++;
-                       if (get_user(val, va)) {
+                       if (math_get_user(val, va)) {
                                fpuemuprivate.stats.errors++;
                                return SIGBUS;
                        }
@@ -662,7 +680,7 @@
 #endif
 
                        SIFROMREG(val, MIPSInst_FS(ir));
-                       if (put_user(val, va)) {
+                       if (math_put_user(val, va)) {
                                fpuemuprivate.stats.errors++;
                                return SIGBUS;
                        }
@@ -728,7 +746,7 @@
                                xcp->regs[MIPSInst_FT(ir)]);
 
                        fpuemuprivate.stats.loads++;
-                       if (get_user(val, va)) {
+                       if (math_get_user(val, va)) {
                                fpuemuprivate.stats.errors++;
                                return SIGBUS;
                        }
@@ -741,7 +759,7 @@
 
                        fpuemuprivate.stats.stores++;
                        DIFROMREG(val, MIPSInst_FS(ir));
-                       if (put_user(val, va)) {
+                       if (math_put_user(val, va)) {
                                fpuemuprivate.stats.errors++;
                                return SIGBUS;
                        }
@@ -1290,7 +1308,7 @@
        do {
                prevepc = xcp->cp0_epc;
 
-               if (get_user(insn, (mips_instruction *) xcp->cp0_epc)) {
+               if (math_get_user(insn, (mips_instruction *) xcp->cp0_epc)) {
                        fpuemuprivate.stats.errors++;
                        return SIGBUS;
                }

---
Atsushi Nemoto

<Prev in Thread] Current Thread [Next in Thread>