From ddd061d954434ea8b04da914c0e1b724d6e8b8c1 Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 23 Jun 2010 11:21:19 +0000 Subject: 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 --- sys/i386/i386/machdep.c | 5 ++-- sys/i386/i386/vm_machdep.c | 9 +++---- sys/i386/isa/npx.c | 62 ++++++++++++++++++++-------------------------- 3 files changed, 33 insertions(+), 43 deletions(-) (limited to 'sys/i386') 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) -- cgit v1.1