Author: kib
Date: Wed Jun 23 11:21:19 2010
New Revision: 209462
URL: http://svn.freebsd.org/changeset/base/209462

Log:
  After the FPU use requires #MF working due to INT13 FPU exception handling
  removal, MFi386 r209198:
      Use critical sections instead of disabling local interrupts to ensure
      the consistency between PCPU fpcurthread and the state of FPU.
  
  Reviewed by:  bde
  Tested by:    pho

Modified:
  head/sys/i386/i386/machdep.c
  head/sys/i386/i386/vm_machdep.c
  head/sys/i386/isa/npx.c
  head/sys/pc98/pc98/machdep.c

Modified: head/sys/i386/i386/machdep.c
==============================================================================
--- head/sys/i386/i386/machdep.c        Wed Jun 23 11:12:58 2010        
(r209461)
+++ head/sys/i386/i386/machdep.c        Wed Jun 23 11:21:19 2010        
(r209462)
@@ -3391,10 +3391,9 @@ set_fpcontext(struct thread *td, const m
 static void
 fpstate_drop(struct thread *td)
 {
-       register_t s;
 
        KASSERT(PCB_USER_FPU(td->td_pcb), ("fpstate_drop: kernel-owned fpu"));
-       s = intr_disable();
+       critical_enter();
 #ifdef DEV_NPX
        if (PCPU_GET(fpcurthread) == td)
                npxdrop();
@@ -3411,7 +3410,7 @@ fpstate_drop(struct thread *td)
         */
        curthread->td_pcb->pcb_flags &= ~(PCB_NPXINITDONE |
            PCB_NPXUSERINITDONE);
-       intr_restore(s);
+       critical_exit();
 }
 
 int

Modified: head/sys/i386/i386/vm_machdep.c
==============================================================================
--- head/sys/i386/i386/vm_machdep.c     Wed Jun 23 11:12:58 2010        
(r209461)
+++ head/sys/i386/i386/vm_machdep.c     Wed Jun 23 11:21:19 2010        
(r209462)
@@ -150,9 +150,6 @@ cpu_fork(td1, p2, td2, flags)
        register struct proc *p1;
        struct pcb *pcb2;
        struct mdproc *mdp2;
-#ifdef DEV_NPX
-       register_t savecrit;
-#endif
 
        p1 = td1->td_proc;
        if ((flags & RFPROC) == 0) {
@@ -180,10 +177,10 @@ cpu_fork(td1, p2, td2, flags)
        if (td1 == curthread)
                td1->td_pcb->pcb_gs = rgs();
 #ifdef DEV_NPX
-       savecrit = intr_disable();
+       critical_enter();
        if (PCPU_GET(fpcurthread) == td1)
                npxsave(td1->td_pcb->pcb_save);
-       intr_restore(savecrit);
+       critical_exit();
 #endif
 
        /* Point the pcb to the top of the stack */
@@ -328,8 +325,10 @@ cpu_thread_exit(struct thread *td)
 {
 
 #ifdef DEV_NPX
+       critical_enter();
        if (td == PCPU_GET(fpcurthread))
                npxdrop();
+       critical_exit();
 #endif
 
        /* Disable any hardware breakpoints. */

Modified: head/sys/i386/isa/npx.c
==============================================================================
--- head/sys/i386/isa/npx.c     Wed Jun 23 11:12:58 2010        (r209461)
+++ head/sys/i386/isa/npx.c     Wed Jun 23 11:21:19 2010        (r209462)
@@ -308,10 +308,9 @@ cleanup:
 static int
 npx_attach(device_t dev)
 {
-       register_t s;
 
        npxinit();
-       s = intr_disable();
+       critical_enter();
        stop_emulating();
        fpusave(&npx_initialstate);
        start_emulating();
@@ -331,7 +330,7 @@ npx_attach(device_t dev)
 #endif
                bzero(npx_initialstate.sv_87.sv_ac,
                    sizeof(npx_initialstate.sv_87.sv_ac));
-       intr_restore(s);
+       critical_exit();
 
        return (0);
 }
@@ -352,6 +351,8 @@ npxinit(void)
         * fninit has the same h/w bugs as fnsave.  Use the detoxified
         * fnsave to throw away any junk in the fpu.  npxsave() initializes
         * the fpu and sets fpcurthread = NULL as important side effects.
+        *
+        * It is too early for critical_enter() to work on AP.
         */
        savecrit = intr_disable();
        npxsave(&dummy);
@@ -374,12 +375,11 @@ void
 npxexit(td)
        struct thread *td;
 {
-       register_t savecrit;
 
-       savecrit = intr_disable();
+       critical_enter();
        if (curthread == PCPU_GET(fpcurthread))
                npxsave(PCPU_GET(curpcb)->pcb_save);
-       intr_restore(savecrit);
+       critical_exit();
 #ifdef NPX_DEBUG
        if (hw_float) {
                u_int   masked_exceptions;
@@ -602,7 +602,6 @@ static char fpetable[128] = {
 int
 npxtrap()
 {
-       register_t savecrit;
        u_short control, status;
 
        if (!hw_float) {
@@ -610,7 +609,7 @@ npxtrap()
                       PCPU_GET(fpcurthread), curthread, hw_float);
                panic("npxtrap from nowhere");
        }
-       savecrit = intr_disable();
+       critical_enter();
 
        /*
         * Interrupt handling (for another interrupt) may have pushed the
@@ -627,7 +626,7 @@ npxtrap()
 
        if (PCPU_GET(fpcurthread) == curthread)
                fnclex();
-       intr_restore(savecrit);
+       critical_exit();
        return (fpetable[status & ((~control & 0x3f) | 0x40)]);
 }
 
@@ -645,14 +644,15 @@ int
 npxdna(void)
 {
        struct pcb *pcb;
-       register_t s;
 
        if (!hw_float)
                return (0);
+       critical_enter();
        if (PCPU_GET(fpcurthread) == curthread) {
                printf("npxdna: fpcurthread == curthread %d times\n",
                    ++err_count);
                stop_emulating();
+               critical_exit();
                return (1);
        }
        if (PCPU_GET(fpcurthread) != NULL) {
@@ -662,7 +662,6 @@ npxdna(void)
                       curthread, curthread->td_proc->p_pid);
                panic("npxdna");
        }
-       s = intr_disable();
        stop_emulating();
        /*
         * Record new context early in case frstor causes an IRQ13.
@@ -704,7 +703,7 @@ npxdna(void)
                 */
                fpurstor(pcb->pcb_save);
        }
-       intr_restore(s);
+       critical_exit();
 
        return (1);
 }
@@ -744,10 +743,6 @@ npxsave(addr)
        PCPU_SET(fpcurthread, NULL);
 }
 
-/*
- * This should be called with interrupts disabled and only when the owning
- * FPU thread is non-null.
- */
 void
 npxdrop()
 {
@@ -763,6 +758,8 @@ npxdrop()
                fnclex();
 
        td = PCPU_GET(fpcurthread);
+       KASSERT(td == curthread, ("fpudrop: fpcurthread != curthread"));
+       CRITICAL_ASSERT(td);
        PCPU_SET(fpcurthread, NULL);
        td->td_pcb->pcb_flags &= ~PCB_NPXINITDONE;
        start_emulating();
@@ -776,7 +773,6 @@ int
 npxgetregs(struct thread *td, union savefpu *addr)
 {
        struct pcb *pcb;
-       register_t s;
 
        if (!hw_float)
                return (_MC_FPOWNED_NONE);
@@ -787,7 +783,7 @@ npxgetregs(struct thread *td, union save
                SET_FPU_CW(addr, pcb->pcb_initial_npxcw);
                return (_MC_FPOWNED_NONE);
        }
-       s = intr_disable();
+       critical_enter();
        if (td == PCPU_GET(fpcurthread)) {
                fpusave(addr);
 #ifdef CPU_ENABLE_SSE
@@ -799,10 +795,10 @@ npxgetregs(struct thread *td, union save
                         * starts with a clean state next time.
                         */
                        npxdrop();
-               intr_restore(s);
+               critical_exit();
                return (_MC_FPOWNED_FPU);
        } else {
-               intr_restore(s);
+               critical_exit();
                bcopy(pcb->pcb_save, addr, sizeof(*addr));
                return (_MC_FPOWNED_PCB);
        }
@@ -812,7 +808,6 @@ int
 npxgetuserregs(struct thread *td, union savefpu *addr)
 {
        struct pcb *pcb;
-       register_t s;
 
        if (!hw_float)
                return (_MC_FPOWNED_NONE);
@@ -823,7 +818,7 @@ npxgetuserregs(struct thread *td, union 
                SET_FPU_CW(addr, pcb->pcb_initial_npxcw);
                return (_MC_FPOWNED_NONE);
        }
-       s = intr_disable();
+       critical_enter();
        if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) {
                fpusave(addr);
 #ifdef CPU_ENABLE_SSE
@@ -835,10 +830,10 @@ npxgetuserregs(struct thread *td, union 
                         * starts with a clean state next time.
                         */
                        npxdrop();
-               intr_restore(s);
+               critical_exit();
                return (_MC_FPOWNED_FPU);
        } else {
-               intr_restore(s);
+               critical_exit();
                bcopy(&pcb->pcb_user_save, addr, sizeof(*addr));
                return (_MC_FPOWNED_PCB);
        }
@@ -851,22 +846,21 @@ void
 npxsetregs(struct thread *td, union savefpu *addr)
 {
        struct pcb *pcb;
-       register_t s;
 
        if (!hw_float)
                return;
 
        pcb = td->td_pcb;
-       s = intr_disable();
+       critical_enter();
        if (td == PCPU_GET(fpcurthread)) {
 #ifdef CPU_ENABLE_SSE
                if (!cpu_fxsr)
 #endif
                        fnclex();       /* As in npxdrop(). */
                fpurstor(addr);
-               intr_restore(s);
+               critical_exit();
        } else {
-               intr_restore(s);
+               critical_exit();
                bcopy(addr, pcb->pcb_save, sizeof(*addr));
        }
        if (PCB_USER_FPU(pcb))
@@ -878,23 +872,22 @@ void
 npxsetuserregs(struct thread *td, union savefpu *addr)
 {
        struct pcb *pcb;
-       register_t s;
 
        if (!hw_float)
                return;
 
        pcb = td->td_pcb;
-       s = intr_disable();
+       critical_enter();
        if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) {
 #ifdef CPU_ENABLE_SSE
                if (!cpu_fxsr)
 #endif
                        fnclex();       /* As in npxdrop(). */
                fpurstor(addr);
-               intr_restore(s);
+               critical_exit();
                pcb->pcb_flags |= PCB_NPXUSERINITDONE | PCB_NPXINITDONE;
        } else {
-               intr_restore(s);
+               critical_exit();
                bcopy(addr, &pcb->pcb_user_save, sizeof(*addr));
                if (PCB_USER_FPU(pcb))
                        pcb->pcb_flags |= PCB_NPXINITDONE;
@@ -1062,13 +1055,12 @@ int
 fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx)
 {
        struct pcb *pcb;
-       register_t savecrit;
 
        pcb = td->td_pcb;
-       savecrit = intr_disable();
+       critical_enter();
        if (curthread == PCPU_GET(fpcurthread))
                npxdrop();
-       intr_restore(savecrit);
+       critical_exit();
        pcb->pcb_save = ctx->prev;
        if (pcb->pcb_save == &pcb->pcb_user_save) {
                if ((pcb->pcb_flags & PCB_NPXUSERINITDONE) != 0)

Modified: head/sys/pc98/pc98/machdep.c
==============================================================================
--- head/sys/pc98/pc98/machdep.c        Wed Jun 23 11:12:58 2010        
(r209461)
+++ head/sys/pc98/pc98/machdep.c        Wed Jun 23 11:21:19 2010        
(r209462)
@@ -2719,9 +2719,8 @@ set_fpcontext(struct thread *td, const m
 static void
 fpstate_drop(struct thread *td)
 {
-       register_t s;
 
-       s = intr_disable();
+       critical_enter();
 #ifdef DEV_NPX
        if (PCPU_GET(fpcurthread) == td)
                npxdrop();
@@ -2737,7 +2736,7 @@ fpstate_drop(struct thread *td)
         * have too many layers.
         */
        curthread->td_pcb->pcb_flags &= ~PCB_NPXINITDONE;
-       intr_restore(s);
+       critical_exit();
 }
 
 int
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to