diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c index 7cc706d45d02..e1d9507985f2 100644 --- a/sys/arch/amd64/amd64/fpu.c +++ b/sys/arch/amd64/amd64/fpu.c @@ -1,4 +1,4 @@ -/* $NetBSD: fpu.c,v 1.28 2008/11/11 14:40:18 ad Exp $ */ +/* $NetBSD: fpu.c,v 1.29 2008/11/11 15:53:53 ad Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. All @@ -100,7 +100,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.28 2008/11/11 14:40:18 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.29 2008/11/11 15:53:53 ad Exp $"); #include "opt_multiprocessor.h" @@ -394,13 +394,13 @@ fpusave_lwp(struct lwp *l, bool save) oci = l->l_addr->u_pcb.pcb_fpcpu; if (oci == NULL) { splx(s); - return; + break; } if (oci == curcpu()) { KASSERT(oci->ci_fpcurlwp == l); fpusave_cpu(save); splx(s); - return; + break; } splx(s); x86_send_ipi(oci, X86_IPI_SYNCH_FPU); @@ -413,4 +413,9 @@ fpusave_lwp(struct lwp *l, bool save) panic("fpusave_lwp: did not"); } } + + if (!save) { + /* Ensure we restart with a clean slate. */ + l->l_md.md_flags &= ~MDP_USEDFPU; + } } diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 1d540141fcd1..9fdc16fd9d44 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.104 2008/11/11 14:40:18 ad Exp $ */ +/* $NetBSD: machdep.c,v 1.105 2008/11/11 15:53:53 ad Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008 @@ -112,7 +112,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.104 2008/11/11 14:40:18 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.105 2008/11/11 15:53:53 ad Exp $"); /* #define XENDEBUG_LOW */ @@ -537,6 +537,9 @@ buildcontext(struct lwp *l, void *catcher, void *f) tf->tf_rflags &= ~PSL_CLEARSIG; tf->tf_rsp = (uint64_t)f; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); + + /* Ensure FP state is reset, if FP is used. */ + l->l_md.md_flags &= ~MDP_USEDFPU; } void @@ -1947,9 +1950,10 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) l->l_md.md_flags |= MDP_IRET; } + if (l->l_addr->u_pcb.pcb_fpcpu != NULL) + fpusave_lwp(l, false); + if ((flags & _UC_FPU) != 0) { - if (l->l_addr->u_pcb.pcb_fpcpu != NULL) - fpusave_lwp(l, false); memcpy(&l->l_addr->u_pcb.pcb_savefpu.fp_fxsave, mcp->__fpregs, sizeof (mcp->__fpregs)); l->l_md.md_flags |= MDP_USEDFPU; diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 923c570e6ffa..49494fe26eb8 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.646 2008/11/11 14:40:18 ad Exp $ */ +/* $NetBSD: machdep.c,v 1.647 2008/11/11 15:53:53 ad Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008 The NetBSD Foundation, Inc. @@ -65,7 +65,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.646 2008/11/11 14:40:18 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.647 2008/11/11 15:53:53 ad Exp $"); #include "opt_beep.h" #include "opt_compat_ibcs2.h" @@ -770,6 +770,9 @@ buildcontext(struct lwp *l, int sel, void *catcher, void *fp) tf->tf_eflags &= ~PSL_CLEARSIG; tf->tf_esp = (int)fp; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); + + /* Ensure FP state is reset, if FP is used. */ + l->l_md.md_flags &= ~MDL_USEDFPU; } static void @@ -2211,8 +2214,6 @@ cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) /* * If this process is the current FP owner, dump its * context to the PCB first. - * XXX npxsave() also clears the FPU state; depending on the - * XXX application this might be a penalty. */ if (l->l_addr->u_pcb.pcb_fpcpu) { npxsave_lwp(l, true); @@ -2294,15 +2295,16 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) tf->tf_ss = gr[_REG_SS]; } +#if NNPX > 0 + /* + * If we were using the FPU, forget that we were. + */ + if (l->l_addr->u_pcb.pcb_fpcpu != NULL) + npxsave_lwp(l, false); +#endif + /* Restore floating point register context, if any. */ if ((flags & _UC_FPU) != 0) { -#if NNPX > 0 - /* - * If we were using the FPU, forget that we were. - */ - if (l->l_addr->u_pcb.pcb_fpcpu != NULL) - npxsave_lwp(l, false); -#endif if (flags & _UC_FXSAVE) { if (i386_use_fxsave) { memcpy( @@ -2326,12 +2328,7 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) sizeof (l->l_addr->u_pcb.pcb_savefpu.sv_87)); } } - /* If not set already. */ l->l_md.md_flags |= MDL_USEDFPU; -#if 0 - /* Apparently unused. */ - l->l_addr->u_pcb.pcb_saveemc = mcp->mc_fp.fp_emcsts; -#endif } mutex_enter(p->p_lock); if (flags & _UC_SETSTACK) diff --git a/sys/arch/i386/isa/npx.c b/sys/arch/i386/isa/npx.c index 027b384a3809..197f3503c53a 100644 --- a/sys/arch/i386/isa/npx.c +++ b/sys/arch/i386/isa/npx.c @@ -1,4 +1,4 @@ -/* $NetBSD: npx.c,v 1.131 2008/11/11 14:40:19 ad Exp $ */ +/* $NetBSD: npx.c,v 1.132 2008/11/11 15:53:53 ad Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -96,7 +96,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: npx.c,v 1.131 2008/11/11 14:40:19 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npx.c,v 1.132 2008/11/11 15:53:53 ad Exp $"); #if 0 #define IPRINTF(x) printf x @@ -700,13 +700,13 @@ npxsave_lwp(struct lwp *l, bool save) oci = l->l_addr->u_pcb.pcb_fpcpu; if (oci == NULL) { splx(s); - return; + break; } if (oci == curcpu()) { KASSERT(oci->ci_fpcurlwp == l); npxsave_cpu(save); splx(s); - return; + break; } splx(s); x86_send_ipi(oci, X86_IPI_SYNCH_FPU); @@ -719,4 +719,9 @@ npxsave_lwp(struct lwp *l, bool save) panic("npxsave_lwp: did not"); } } + + if (!save) { + /* Ensure we restart with a clean slate. */ + l->l_md.md_flags &= ~MDL_USEDFPU; + } }