linux-mips
[Top] [All Lists]

Re: preempt safe fpu-emulator

To: linux-mips@linux-mips.org
Subject: Re: preempt safe fpu-emulator
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Wed, 27 Apr 2005 14:46:33 +0900 (JST)
Cc: ralf@linux-mips.org
In-reply-to: <20050427.143622.77402407.nemoto@toshiba-tops.co.jp>
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <20050427.143622.77402407.nemoto@toshiba-tops.co.jp>
Sender: linux-mips-bounce@linux-mips.org
>>>>> On Wed, 27 Apr 2005 14:36:22 +0900 (JST), Atsushi Nemoto 
>>>>> <anemo@mba.ocn.ne.jp> said:
anemo> With this patch, whole fpu-emulator can be run without
anemo> disabling preempt.  I will post a patch to fix preemption issue
anemo> soon.

Here it is.

It also fixes these issues:

* The process might lose fpu BEFORE calling preempt_disable() in
  do_fpe().
* The saved fp context might be overwritten if another process took
  fpu.


--- linux-mips/arch/mips/kernel/traps.c 2005-04-18 11:42:47.000000000 +0900
+++ linux/arch/mips/kernel/traps.c      2005-04-27 14:04:53.407006244 +0900
@@ -551,6 +551,14 @@
 
                preempt_disable();
 
+#ifdef CONFIG_PREEMPT
+               if (!is_fpu_owner()) {
+                       /* We might lose fpu before disabling preempt... */
+                       own_fpu();
+                       BUG_ON(!used_math());
+                       restore_fp(current);
+               }
+#endif
                /*
                 * Unimplemented operation exception.  If we've got the full
                 * software emulator on-board, let's use it...
@@ -562,11 +570,18 @@
                 * a bit extreme for what should be an infrequent event.
                 */
                save_fp(current);
+               /* Ensure 'resume' not overwrite saved fp context again. */
+               lose_fpu();
+
+               preempt_enable();
 
                /* Run the emulator */
                sig = fpu_emulator_cop1Handler (0, regs,
                        &current->thread.fpu.soft);
 
+               preempt_disable();
+
+               own_fpu();      /* Using the FPU again.  */
                /*
                 * We can't allow the emulated instruction to leave any of
                 * the cause bit set in $fcr31.
@@ -712,6 +727,8 @@
                        set_used_math();
                }
 
+               preempt_enable();
+
                if (!cpu_has_fpu) {
                        int sig = fpu_emulator_cop1Handler(0, regs,
                                                &current->thread.fpu.soft);
@@ -719,8 +736,6 @@
                                force_sig(sig, current);
                }
 
-               preempt_enable();
-
                return;
 
        case 2:

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