From ce17edb08d1c071f51d8618c73d93ff9f5ecb68b Mon Sep 17 00:00:00 2001
From: Nadav Har'El <nyh@cloudius-systems.com>
Date: Tue, 21 May 2013 09:15:12 +0300
Subject: [PATCH] Unfortunately, while in theory it should not be necessary to
 save the FPU on a context switch caused by a function call (as opposed to a
 preemption during interrupt), in practice this makes the "sunflow" benchmark
 from SpecJVM fail, producing wrong results.

This patch saves the FPU on any context switch and makes "sunflow"
work correctly, at the price of slower context switches and an
unsolved puzzle on why the heck this is needed in the first place :(
---
 core/sched.cc | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/core/sched.cc b/core/sched.cc
index 1b21f0dd1..5b2646e6a 100644
--- a/core/sched.cc
+++ b/core/sched.cc
@@ -81,13 +81,23 @@ void cpu::reschedule_from_interrupt(bool preempt)
     n->_status.store(thread::status::running);
     if (n != thread::current()) {
         if (preempt) {
-            asm volatile("clts");
+            p->_fpu.save();
+        } else {
+            // FIXME: In this case, in theory, we do not need to save the FPU
+            // state (perhaps just mxcsr and cw) because we got here through a
+            // function call and the calling conventions guarantee the caller
+            // clears the FPU state. Unfortunately, in practice, the SPECjvm
+            // "sunflow" benchmark breaks (gets wrong results) if we don't
+            // save the SSE registers here. We don't know why.
             p->_fpu.save();
         }
         trace_switch(n);
         n->switch_to();
         if (preempt) {
             p->_fpu.restore();
+        } else {
+            // FIXME: This shouldn't be here! See comment above.
+            p->_fpu.restore();
         }
     }
 }
-- 
GitLab