summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2010-06-23 11:21:19 +0000
committerkib <kib@FreeBSD.org>2010-06-23 11:21:19 +0000
commitddd061d954434ea8b04da914c0e1b724d6e8b8c1 (patch)
treea03ea21bf2e3d1be097e97c08e1e9d6b6d6f1202 /sys/i386
parent6375d4e4dbfd5685b41e1a8c5bab47946781e84d (diff)
downloadFreeBSD-src-ddd061d954434ea8b04da914c0e1b724d6e8b8c1.zip
FreeBSD-src-ddd061d954434ea8b04da914c0e1b724d6e8b8c1.tar.gz
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
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/machdep.c5
-rw-r--r--sys/i386/i386/vm_machdep.c9
-rw-r--r--sys/i386/isa/npx.c62
3 files changed, 33 insertions, 43 deletions
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 989b325..67d9c47 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -3391,10 +3391,9 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp)
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
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index 70c3153..6f86895 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -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. */
diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c
index 6059ee8..00fc6af 100644
--- a/sys/i386/isa/npx.c
+++ b/sys/i386/isa/npx.c
@@ -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 savefpu *addr)
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 savefpu *addr)
* 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 savefpu *addr)
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 savefpu *addr)
* 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)
OpenPOWER on IntegriCloud