Re: fpu_emulator can lose fpu on get_user/put_user

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>>>>> On Wed, 06 Oct 2004 10:19:20 +0900 (JST), Atsushi Nemoto <anemo@xxxxxxxxxxxxx> 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


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux