RE: Floating point corruption: followup

David Mosberger <[email protected]> Thu, 8 May 2003 15:35:28 -0700
Newsgroups gmane.linux.redhat.ia64.general
Message-ID <[email protected]>
>>>>> On Thu, 8 May 2003 17:01:02 -0500, [email protected] said:

  Mike> If you are interested in demonstrating this, I can provide
  Mike> some example instructions.

Yes, the problem is understood now (it sounds like several people were
pursuing this, don't know if it was discovered independently or not).
See the discussion here:

 https://lists.linuxia64.org/archives//linux-ia64/2003-May/005418.html

I'm currently using the attached patch to fix the problem, but it
clearly needs more testing.

	--david

===== include/asm-ia64/system.h 1.34 vs edited =====
--- 1.34/include/asm-ia64/system.h	Tue Apr  1 01:19:53 2003
+++ edited/include/asm-ia64/system.h	Thu May  8 14:52:49 2003
@@ -213,6 +213,7 @@
 #endif
 
 #define __switch_to(prev,next,last) do {						\
+	ia64_psr(ia64_task_regs(next))->dfh = (ia64_get_fpu_owner() != (next));		\
 	if (((prev)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID))	\
 	    || IS_IA32_PROCESS(ia64_task_regs(prev)) || PERFMON_IS_SYSWIDE())		\
 		ia64_save_extra(prev);							\
@@ -223,13 +224,11 @@
 } while (0)
 
 #ifdef CONFIG_SMP
-
 /*
- * In the SMP case, we save the fph state when context-switching
- * away from a thread that modified fph.  This way, when the thread
- * gets scheduled on another CPU, the CPU can pick up the state from
- * task->thread.fph, avoiding the complication of having to fetch
- * the latest fph state from another CPU.
+ * In the SMP case, we save the fph state when context-switching away from a thread that
+ * modified fph.  This way, when the thread gets scheduled on another CPU, the CPU can
+ * pick up the state from task->thread.fph, avoiding the complication of having to fetch
+ * the latest fph state from another CPU.  In other words: eager save, lazy restore.
  */
 # define switch_to(prev,next,last) do {					\
 	if (ia64_psr(ia64_task_regs(prev))->mfh) {			\
@@ -238,22 +237,10 @@
 		__ia64_save_fpu((prev)->thread.fph);			\
 		(prev)->thread.last_fph_cpu = smp_processor_id();	\
 	}								\
-	if ((next)->thread.flags & IA64_THREAD_FPH_VALID) {		\
-		if (((next)->thread.last_fph_cpu == smp_processor_id())	\
-		    && (ia64_get_fpu_owner() == next))			\
-		{							\
-			ia64_psr(ia64_task_regs(next))->dfh = 0;	\
-			ia64_psr(ia64_task_regs(next))->mfh = 0;	\
-		} else							\
-			ia64_psr(ia64_task_regs(next))->dfh = 1;	\
-	}								\
-	__switch_to(prev,next,last);					\
+	__switch_to(prev, next, last);					\
   } while (0)
 #else
-# define switch_to(prev,next,last) do {						\
-	ia64_psr(ia64_task_regs(next))->dfh = (ia64_get_fpu_owner() != (next));	\
-	__switch_to(prev,next,last);						\
-} while (0)
+# define switch_to(prev,next,last) 	__switch_to(prev, next, last)
 #endif
 
 /*