Make sure that the FPU IPIs shoot down the right FPU context and not the FPU
authorkettenis <kettenis@openbsd.org>
Wed, 21 Jul 2010 14:08:09 +0000 (14:08 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 21 Jul 2010 14:08:09 +0000 (14:08 +0000)
context of some random process that happened to be switched onto the FPU
after the decision was made to send the IPI.

sys/arch/amd64/amd64/fpu.c
sys/arch/amd64/amd64/ipifuncs.c
sys/arch/amd64/include/cpu.h
sys/arch/i386/i386/ipifuncs.c
sys/arch/i386/include/cpu.h
sys/arch/i386/isa/npx.c

index 5151547..fdc0753 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fpu.c,v 1.16 2010/06/29 21:13:43 thib Exp $   */
+/*     $OpenBSD: fpu.c,v 1.17 2010/07/21 14:08:09 kettenis Exp $       */
 /*     $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $     */
 
 /*-
@@ -312,8 +312,9 @@ fpusave_proc(struct proc *p, int save)
                fpusave_cpu(ci, save);
                splx(s);
        } else {
+               oci->ci_fpsaveproc = p;
                x86_send_ipi(oci,
-               save ? X86_IPI_SYNCH_FPU : X86_IPI_FLUSH_FPU);
+                   save ? X86_IPI_SYNCH_FPU : X86_IPI_FLUSH_FPU);
                while (p->p_addr->u_pcb.pcb_fpcpu != NULL)
                        SPINLOCK_SPIN_HOOK;
        }
index 73fed19..5738f9d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ipifuncs.c,v 1.12 2010/06/26 15:56:40 mlarkin Exp $   */
+/*     $OpenBSD: ipifuncs.c,v 1.13 2010/07/21 14:08:09 kettenis Exp $  */
 /*     $NetBSD: ipifuncs.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
 
 /*-
@@ -110,13 +110,15 @@ x86_64_ipi_halt(struct cpu_info *ci)
 void
 x86_64_ipi_flush_fpu(struct cpu_info *ci)
 {
-       fpusave_cpu(ci, 0);
+       if (ci->ci_fpsaveproc == ci->ci_fpcurproc)
+               fpusave_cpu(ci, 0);
 }
 
 void
 x86_64_ipi_synch_fpu(struct cpu_info *ci)
 {
-       fpusave_cpu(ci, 1);
+       if (ci->ci_fpsaveproc == ci->ci_fpcurproc)
+               fpusave_cpu(ci, 1);
 }
 
 #if NMTRR > 0
index 71286c5..c973070 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.h,v 1.51 2009/12/09 14:27:34 oga Exp $    */
+/*     $OpenBSD: cpu.h,v 1.52 2010/07/21 14:08:09 kettenis Exp $       */
 /*     $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $     */
 
 /*-
@@ -74,6 +74,7 @@ struct cpu_info {
        u_int64_t ci_scratch;
 
        struct proc *ci_fpcurproc;
+       struct proc *ci_fpsaveproc;
        int ci_fpsaving;
 
        struct pcb *ci_curpcb;
index 3d2dcf6..064b3ff 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ipifuncs.c,v 1.17 2010/06/26 15:56:40 mlarkin Exp $   */
+/*     $OpenBSD: ipifuncs.c,v 1.18 2010/07/21 14:08:09 kettenis Exp $  */
 /* $NetBSD: ipifuncs.c,v 1.1.2.3 2000/06/26 02:04:06 sommerfeld Exp $ */
 
 /*-
@@ -114,13 +114,15 @@ i386_ipi_halt(struct cpu_info *ci)
 void
 i386_ipi_flush_fpu(struct cpu_info *ci)
 {
-       npxsave_cpu(ci, 0);
+       if (ci->ci_fpsaveproc == ci->ci_fpcurproc)
+               npxsave_cpu(ci, 0);
 }
 
 void
 i386_ipi_synch_fpu(struct cpu_info *ci)
 {
-       npxsave_cpu(ci, 1);
+       if (ci->ci_fpsaveproc == ci->ci_fpcurproc)
+               npxsave_cpu(ci, 1);
 }
 #endif
 
index e3944a9..d6c0e6e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.h,v 1.110 2010/05/23 22:41:49 deraadt Exp $       */
+/*     $OpenBSD: cpu.h,v 1.111 2010/07/21 14:08:09 kettenis Exp $      */
 /*     $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $        */
 
 /*-
@@ -92,6 +92,7 @@ struct cpu_info {
         * Private members.
         */
        struct proc *ci_fpcurproc;      /* current owner of the FPU */
+       struct proc *ci_fpsaveproc;
        int ci_fpsaving;                /* save in progress */
 
        struct pcb *ci_curpcb;          /* VA of current HW PCB */
index 232886c..5f8c73d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: npx.c,v 1.48 2010/06/29 21:13:43 thib Exp $   */
+/*     $OpenBSD: npx.c,v 1.49 2010/07/21 14:08:09 kettenis Exp $       */
 /*     $NetBSD: npx.c,v 1.57 1996/05/12 23:12:24 mycroft Exp $ */
 
 #if 0
@@ -848,9 +848,9 @@ npxsave_proc(struct proc *p, int save)
                IPRINTF(("%s: fp ipi to %s %s %lx\n", ci->ci_dev.dv_xname,
                    oci->ci_dev.dv_xname, save ? "save" : "flush", (u_long)p));
 
+               oci->ci_fpsaveproc = p;
                i386_send_ipi(oci,
                    save ? I386_IPI_SYNCH_FPU : I386_IPI_FLUSH_FPU);
-
                while (p->p_addr->u_pcb.pcb_fpcpu != NULL)
                        SPINLOCK_SPIN_HOOK;
        }