svn commit: r209462 - in head/sys: i386/i386 i386/isa pc98/pc98

Konstantin Belousov kib at FreeBSD.org
Wed Jun 23 11:21:20 UTC 2010


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


More information about the svn-src-head mailing list