Module Name: src Committed By: dsl Date: Sat Feb 15 10:11:15 UTC 2014
Modified Files: src/sys/arch/amd64/amd64: genassym.cf machdep.c netbsd32_machdep.c process_machdep.c src/sys/arch/amd64/include: proc.h src/sys/arch/i386/i386: compat_16_machdep.c genassym.cf machdep.c process_machdep.c src/sys/arch/i386/include: proc.h src/sys/arch/x86/include: cpu.h cpu_extended_state.h fpu.h src/sys/arch/x86/x86: fpu.c vm_machdep.c src/sys/compat/linux/arch/amd64: linux_machdep.c src/sys/compat/linux/arch/i386: linux_machdep.c src/sys/compat/linux32/arch/amd64: linux32_machdep.c Log Message: Remove all references to MDL_USEDFPU and deferred fpu initialisation. The cost of zeroing the save area on exec is minimal. This stops the FP registers of a random process being used the first time an lwp uses the fpu. sendsig_siginfo() and get_mcontext() now unconditionally copy the FP registers. I'll remove the double-copy for signal handlers soon. get_mcontext() might have been leaking kernel memory to userspace - and may still do so if i386_use_fxsave is false (short copies). To generate a diff of this commit: cvs rdiff -u -r1.54 -r1.55 src/sys/arch/amd64/amd64/genassym.cf cvs rdiff -u -r1.203 -r1.204 src/sys/arch/amd64/amd64/machdep.c cvs rdiff -u -r1.90 -r1.91 src/sys/arch/amd64/amd64/netbsd32_machdep.c cvs rdiff -u -r1.27 -r1.28 src/sys/arch/amd64/amd64/process_machdep.c cvs rdiff -u -r1.17 -r1.18 src/sys/arch/amd64/include/proc.h cvs rdiff -u -r1.24 -r1.25 src/sys/arch/i386/i386/compat_16_machdep.c cvs rdiff -u -r1.96 -r1.97 src/sys/arch/i386/i386/genassym.cf cvs rdiff -u -r1.746 -r1.747 src/sys/arch/i386/i386/machdep.c cvs rdiff -u -r1.82 -r1.83 src/sys/arch/i386/i386/process_machdep.c cvs rdiff -u -r1.40 -r1.41 src/sys/arch/i386/include/proc.h cvs rdiff -u -r1.61 -r1.62 src/sys/arch/x86/include/cpu.h cvs rdiff -u -r1.6 -r1.7 src/sys/arch/x86/include/cpu_extended_state.h cvs rdiff -u -r1.2 -r1.3 src/sys/arch/x86/include/fpu.h cvs rdiff -u -r1.4 -r1.5 src/sys/arch/x86/x86/fpu.c cvs rdiff -u -r1.21 -r1.22 src/sys/arch/x86/x86/vm_machdep.c cvs rdiff -u -r1.46 -r1.47 src/sys/compat/linux/arch/amd64/linux_machdep.c cvs rdiff -u -r1.156 -r1.157 src/sys/compat/linux/arch/i386/linux_machdep.c cvs rdiff -u -r1.34 -r1.35 \ src/sys/compat/linux32/arch/amd64/linux32_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/amd64/amd64/genassym.cf diff -u src/sys/arch/amd64/amd64/genassym.cf:1.54 src/sys/arch/amd64/amd64/genassym.cf:1.55 --- src/sys/arch/amd64/amd64/genassym.cf:1.54 Sun Dec 1 01:05:16 2013 +++ src/sys/arch/amd64/amd64/genassym.cf Sat Feb 15 10:11:14 2014 @@ -1,4 +1,4 @@ -# $NetBSD: genassym.cf,v 1.54 2013/12/01 01:05:16 christos Exp $ +# $NetBSD: genassym.cf,v 1.55 2014/02/15 10:11:14 dsl Exp $ # # Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -185,7 +185,6 @@ define PCB_USERSP offsetof(struct pcb, define PCB_RSP0 offsetof(struct pcb, pcb_rsp0) define PCB_CR0 offsetof(struct pcb, pcb_cr0) define PCB_ONFAULT offsetof(struct pcb, pcb_onfault) -define PCB_FPCPU offsetof(struct pcb, pcb_fpcpu) define PCB_FLAGS offsetof(struct pcb, pcb_flags) define PCB_COMPAT32 PCB_COMPAT32 define PCB_FS offsetof(struct pcb, pcb_fs) Index: src/sys/arch/amd64/amd64/machdep.c diff -u src/sys/arch/amd64/amd64/machdep.c:1.203 src/sys/arch/amd64/amd64/machdep.c:1.204 --- src/sys/arch/amd64/amd64/machdep.c:1.203 Tue Feb 11 20:17:16 2014 +++ src/sys/arch/amd64/amd64/machdep.c Sat Feb 15 10:11:14 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.203 2014/02/11 20:17:16 dsl Exp $ */ +/* $NetBSD: machdep.c,v 1.204 2014/02/15 10:11:14 dsl Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011 @@ -111,7 +111,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.203 2014/02/11 20:17:16 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.204 2014/02/15 10:11:14 dsl Exp $"); /* #define XENDEBUG_LOW */ @@ -548,8 +548,8 @@ buildcontext(struct lwp *l, void *catche 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 &= ~MDL_USEDFPU; + /* Ensure FP state is sane */ + fpu_save_area_reset(l); } void @@ -566,7 +566,7 @@ sendsig_siginfo(const ksiginfo_t *ksi, c struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sigacts *ps = p->p_sigacts; - int onstack, tocopy, error; + int onstack, error; int sig = ksi->ksi_signo; struct sigframe_siginfo *fp, frame; sig_t catcher = SIGACTION(p, sig).sa_handler; @@ -587,21 +587,9 @@ sendsig_siginfo(const ksiginfo_t *ksi, c sp = (char *)tf->tf_rsp - 128; sp -= sizeof(struct sigframe_siginfo); - /* - * Round down the stackpointer to a multiple of 16 for - * fxsave and the ABI. - */ + /* Round down the stackpointer to a multiple of 16 for the ABI. */ fp = (struct sigframe_siginfo *)(((unsigned long)sp & ~15) - 8); - /* - * Don't bother copying out FP state if there is none. - */ - if (l->l_md.md_flags & MDL_USEDFPU) - tocopy = sizeof (struct sigframe_siginfo); - else - tocopy = sizeof (struct sigframe_siginfo) - - sizeof (frame.sf_uc.uc_mcontext.__fpregs); - frame.sf_ra = (uint64_t)ps->sa_sigdesc[sig].sd_tramp; frame.sf_si._info = ksi->ksi_info; frame.sf_uc.uc_flags = _UC_SIGMASK; @@ -614,7 +602,8 @@ sendsig_siginfo(const ksiginfo_t *ksi, c mutex_exit(p->p_lock); cpu_getmcontext(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); - error = copyout(&frame, fp, tocopy); + /* Copyout all the fp regs, the signal handler might expect them. */ + error = copyout(&frame, fp, sizeof frame); mutex_enter(p->p_lock); if (error != 0) { @@ -1329,23 +1318,13 @@ setregs(struct lwp *l, struct exec_packa struct pcb *pcb = lwp_getpcb(l); struct trapframe *tf; - /* If we were using the FPU, forget about it. */ - if (pcb->pcb_fpcpu != NULL) { - fpusave_lwp(l, false); - } - #ifdef USER_LDT pmap_ldt_cleanup(l); #endif - l->l_md.md_flags &= ~MDL_USEDFPU; + fpu_save_area_clear(l, pack->ep_osversion >= 699002600 + ? __NetBSD_NPXCW__ : __NetBSD_COMPAT_NPXCW__); pcb->pcb_flags = 0; - if (pack->ep_osversion >= 699002600) - pcb->pcb_savefpu.sv_xmm.fx_cw = __NetBSD_NPXCW__; - else - pcb->pcb_savefpu.sv_xmm.fx_cw = __NetBSD_COMPAT_NPXCW__; - pcb->pcb_savefpu.sv_xmm.fx_mxcsr = __INITIAL_MXCSR__; - pcb->pcb_savefpu.sv_xmm.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; l->l_proc->p_flag &= ~PK_32; @@ -1917,6 +1896,7 @@ void cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) { const struct trapframe *tf = l->l_md.md_regs; + struct pcb *pcb; __greg_t ras_rip; /* Copy general registers member by member */ @@ -1933,16 +1913,11 @@ cpu_getmcontext(struct lwp *l, mcontext_ mcp->_mc_tlsbase = (uintptr_t)l->l_private;; *flags |= _UC_TLSBASE; - if ((l->l_md.md_flags & MDL_USEDFPU) != 0) { - struct pcb *pcb = lwp_getpcb(l); + pcb = lwp_getpcb(l); - if (pcb->pcb_fpcpu) { - fpusave_lwp(l, true); - } - memcpy(mcp->__fpregs, &pcb->pcb_savefpu.sv_xmm, - sizeof (mcp->__fpregs)); - *flags |= _UC_FPU; - } + fpusave_lwp(l, true); + memcpy(mcp->__fpregs, &pcb->pcb_savefpu.sv_xmm, sizeof (mcp->__fpregs)); + *flags |= _UC_FPU; } int @@ -1991,13 +1966,10 @@ cpu_setmcontext(struct lwp *l, const mco l->l_md.md_flags |= MDL_IRET; } - if (pcb->pcb_fpcpu != NULL) - fpusave_lwp(l, false); - if ((flags & _UC_FPU) != 0) { + fpusave_lwp(l, false); memcpy(&pcb->pcb_savefpu.sv_xmm, mcp->__fpregs, sizeof (mcp->__fpregs)); - l->l_md.md_flags |= MDL_USEDFPU; } if ((flags & _UC_TLSBASE) != 0) Index: src/sys/arch/amd64/amd64/netbsd32_machdep.c diff -u src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.90 src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.91 --- src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.90 Tue Feb 11 20:17:16 2014 +++ src/sys/arch/amd64/amd64/netbsd32_machdep.c Sat Feb 15 10:11:14 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_machdep.c,v 1.90 2014/02/11 20:17:16 dsl Exp $ */ +/* $NetBSD: netbsd32_machdep.c,v 1.91 2014/02/15 10:11:14 dsl Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.90 2014/02/11 20:17:16 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.91 2014/02/15 10:11:14 dsl Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" @@ -128,26 +128,17 @@ netbsd32_setregs(struct lwp *l, struct e pcb = lwp_getpcb(l); - /* If we were using the FPU, forget about it. */ - if (pcb->pcb_fpcpu != NULL) { - fpusave_lwp(l, false); - } - #if defined(USER_LDT) && 0 pmap_ldt_cleanup(p); #endif netbsd32_adjust_limits(p); - l->l_md.md_flags &= ~MDL_USEDFPU; l->l_md.md_flags |= MDL_COMPAT32; /* Force iret not sysret */ pcb->pcb_flags = PCB_COMPAT32; - if (pack->ep_osversion >= 699002600) - pcb->pcb_savefpu.sv_xmm.fx_cw = __NetBSD_NPXCW__; - else - pcb->pcb_savefpu.sv_xmm.fx_cw = __NetBSD_COMPAT_NPXCW__; - pcb->pcb_savefpu.sv_xmm.fx_mxcsr = __INITIAL_MXCSR__; - pcb->pcb_savefpu.sv_xmm.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; + + fpu_save_area_clear(l, pack->ep_osversion >= 699002600 + ? __NetBSD_NPXCW__ : __NetBSD_COMPAT_NPXCW__); p->p_flag |= PK_32; @@ -263,8 +254,8 @@ netbsd32_sendsig_sigcontext(const ksigin tf->tf_fs = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_gs = GSEL(GUDATA32_SEL, SEL_UPL); - /* Ensure FP state is reset, if FP is used. */ - l->l_md.md_flags &= ~MDL_USEDFPU; + /* Ensure FP state is sane. */ + fpu_save_area_reset(l); tf->tf_rip = (uint64_t)catcher; tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL); @@ -366,8 +357,8 @@ netbsd32_sendsig_siginfo(const ksiginfo_ tf->tf_rsp = (uint64_t)fp; tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL); - /* Ensure FP state is reset, if FP is used. */ - l->l_md.md_flags &= ~MDL_USEDFPU; + /* Ensure FP state is sane. */ + fpu_save_area_reset(l); /* Remember that we're now on the signal stack. */ if (onstack) @@ -820,13 +811,9 @@ cpu_setmcontext32(struct lwp *l, const m /* * If we were using the FPU, forget that we were. */ - if (pcb->pcb_fpcpu != NULL) { - fpusave_lwp(l, false); - } + fpusave_lwp(l, false); memcpy(&pcb->pcb_savefpu.sv_xmm, &mcp->__fpregs, sizeof (pcb->pcb_savefpu.sv_xmm)); - /* If not set already. */ - l->l_md.md_flags |= MDL_USEDFPU; } mutex_enter(p->p_lock); @@ -845,6 +832,7 @@ cpu_getmcontext32(struct lwp *l, mcontex const struct trapframe *tf = l->l_md.md_regs; __greg32_t *gr = mcp->__gregs; __greg32_t ras_eip; + struct pcb *pcb; /* Save register context. */ gr[_REG32_GS] = tf->tf_gs; @@ -876,17 +864,12 @@ cpu_getmcontext32(struct lwp *l, mcontex mcp->_mc_tlsbase = (uint32_t)(uintptr_t)l->l_private; *flags |= _UC_TLSBASE; - /* Save floating point register context, if any. */ - if ((l->l_md.md_flags & MDL_USEDFPU) != 0) { - struct pcb *pcb = lwp_getpcb(l); - - if (pcb->pcb_fpcpu) { - fpusave_lwp(l, true); - } - memcpy(&mcp->__fpregs, &pcb->pcb_savefpu.sv_xmm, - sizeof (pcb->pcb_savefpu.sv_xmm)); - *flags |= _UC_FPU; - } + /* Save floating point register context. */ + fpusave_lwp(l, true); + pcb = lwp_getpcb(l); + memcpy(&mcp->__fpregs, &pcb->pcb_savefpu.sv_xmm, + sizeof (pcb->pcb_savefpu.sv_xmm)); + *flags |= _UC_FPU; } void Index: src/sys/arch/amd64/amd64/process_machdep.c diff -u src/sys/arch/amd64/amd64/process_machdep.c:1.27 src/sys/arch/amd64/amd64/process_machdep.c:1.28 --- src/sys/arch/amd64/amd64/process_machdep.c:1.27 Tue Feb 11 20:17:16 2014 +++ src/sys/arch/amd64/amd64/process_machdep.c Sat Feb 15 10:11:14 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: process_machdep.c,v 1.27 2014/02/11 20:17:16 dsl Exp $ */ +/* $NetBSD: process_machdep.c,v 1.28 2014/02/15 10:11:14 dsl Exp $ */ /*- * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. @@ -53,7 +53,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.27 2014/02/11 20:17:16 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.28 2014/02/15 10:11:14 dsl Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -103,34 +103,12 @@ process_read_regs(struct lwp *l, struct } int -process_read_fpregs(struct lwp *l, struct fpreg *regs,size_t *sz) +process_read_fpregs(struct lwp *l, struct fpreg *regs, size_t *sz) { - struct fxsave *frame = process_fpframe(l); - if (l->l_md.md_flags & MDL_USEDFPU) { - fpusave_lwp(l, true); - } else { - uint16_t cw; - uint32_t mxcsr, mxcsr_mask; - - /* - * Fake a FNINIT. - * The initial control word was already set by setregs(), so - * save it temporarily. - */ - cw = frame->fx_cw; - mxcsr = frame->fx_mxcsr; - mxcsr_mask = frame->fx_mxcsr_mask; - memset(frame, 0, sizeof(*regs)); - frame->fx_cw = cw; - frame->fx_sw = 0x0000; - frame->fx_tw = 0x00; /* abridged tag; all empty */ - frame->fx_mxcsr = mxcsr; - frame->fx_mxcsr_mask = mxcsr_mask; - l->l_md.md_flags |= MDL_USEDFPU; - } + fpusave_lwp(l, true); - regs->fxstate = *frame; + regs->fxstate = *process_fpframe(l); return (0); } @@ -160,15 +138,10 @@ process_write_regs(struct lwp *l, const int process_write_fpregs(struct lwp *l, const struct fpreg *regs, size_t sz) { - struct fxsave *frame = process_fpframe(l); - if (l->l_md.md_flags & MDL_USEDFPU) { - fpusave_lwp(l, false); - } else { - l->l_md.md_flags |= MDL_USEDFPU; - } + fpusave_lwp(l, false); - memcpy(frame, ®s->fxstate, sizeof(*regs)); + memcpy(process_fpframe(l), ®s->fxstate, sizeof(*regs)); return (0); } Index: src/sys/arch/amd64/include/proc.h diff -u src/sys/arch/amd64/include/proc.h:1.17 src/sys/arch/amd64/include/proc.h:1.18 --- src/sys/arch/amd64/include/proc.h:1.17 Sun Dec 1 01:05:16 2013 +++ src/sys/arch/amd64/include/proc.h Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: proc.h,v 1.17 2013/12/01 01:05:16 christos Exp $ */ +/* $NetBSD: proc.h,v 1.18 2014/02/15 10:11:15 dsl Exp $ */ /* * Copyright (c) 1991 Regents of the University of California. @@ -53,7 +53,6 @@ struct mdlwp { volatile int md_astpending; }; -#define MDL_USEDFPU 0x0001 /* has used the FPU */ #define MDL_COMPAT32 0x0008 /* i386, always return via iret */ #define MDL_IRET 0x0010 /* force return via iret, not sysret */ Index: src/sys/arch/i386/i386/compat_16_machdep.c diff -u src/sys/arch/i386/i386/compat_16_machdep.c:1.24 src/sys/arch/i386/i386/compat_16_machdep.c:1.25 --- src/sys/arch/i386/i386/compat_16_machdep.c:1.24 Sun Dec 1 01:05:16 2013 +++ src/sys/arch/i386/i386/compat_16_machdep.c Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: compat_16_machdep.c,v 1.24 2013/12/01 01:05:16 christos Exp $ */ +/* $NetBSD: compat_16_machdep.c,v 1.25 2014/02/15 10:11:15 dsl Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.24 2013/12/01 01:05:16 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.25 2014/02/15 10:11:15 dsl Exp $"); #ifdef _KERNEL_OPT #include "opt_vm86.h" @@ -260,9 +260,8 @@ sendsig_sigcontext(const ksiginfo_t *ksi /* NOTREACHED */ } - int svufpu = l->l_md.md_flags & MDL_USEDFPU; + fpu_save_area_reset(l); buildcontext(l, sel, catcher, fp); - l->l_md.md_flags |= svufpu; /* Remember that we're now on the signal stack. */ if (onstack) Index: src/sys/arch/i386/i386/genassym.cf diff -u src/sys/arch/i386/i386/genassym.cf:1.96 src/sys/arch/i386/i386/genassym.cf:1.97 --- src/sys/arch/i386/i386/genassym.cf:1.96 Sun Dec 1 01:05:16 2013 +++ src/sys/arch/i386/i386/genassym.cf Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -# $NetBSD: genassym.cf,v 1.96 2013/12/01 01:05:16 christos Exp $ +# $NetBSD: genassym.cf,v 1.97 2014/02/15 10:11:15 dsl Exp $ # # Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -204,7 +204,6 @@ define PCB_ESP offsetof(struct pcb, pc define PCB_ESP0 offsetof(struct pcb, pcb_esp0) define PCB_CR0 offsetof(struct pcb, pcb_cr0) define PCB_ONFAULT offsetof(struct pcb, pcb_onfault) -define PCB_FPCPU offsetof(struct pcb, pcb_fpcpu) define PCB_FSD offsetof(struct pcb, pcb_fsd) define PCB_GSD offsetof(struct pcb, pcb_gsd) define PCB_IOMAP offsetof(struct pcb, pcb_iomap) Index: src/sys/arch/i386/i386/machdep.c diff -u src/sys/arch/i386/i386/machdep.c:1.746 src/sys/arch/i386/i386/machdep.c:1.747 --- src/sys/arch/i386/i386/machdep.c:1.746 Tue Feb 4 22:48:26 2014 +++ src/sys/arch/i386/i386/machdep.c Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.746 2014/02/04 22:48:26 dsl Exp $ */ +/* $NetBSD: machdep.c,v 1.747 2014/02/15 10:11:15 dsl Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009 @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.746 2014/02/04 22:48:26 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.747 2014/02/15 10:11:15 dsl Exp $"); #include "opt_beep.h" #include "opt_compat_ibcs2.h" @@ -667,8 +667,8 @@ buildcontext(struct lwp *l, int sel, voi 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; + /* Ensure FP state is reset. */ + fpu_save_area_reset(l); } void @@ -865,27 +865,14 @@ setregs(struct lwp *l, struct exec_packa struct pmap *pmap = vm_map_pmap(&l->l_proc->p_vmspace->vm_map); struct pcb *pcb = lwp_getpcb(l); struct trapframe *tf; - uint16_t control; - - /* If we were using the FPU, forget about it. */ - if (pcb->pcb_fpcpu != NULL) - fpusave_lwp(l, false); #ifdef USER_LDT pmap_ldt_cleanup(l); #endif - if (pack->ep_osversion >= 699002600) - control = __INITIAL_NPXCW__; - else - control = __NetBSD_COMPAT_NPXCW__; + fpu_save_area_clear(l, pack->ep_osversion >= 699002600 + ? __INITIAL_NPXCW__ : __NetBSD_COMPAT_NPXCW__); - l->l_md.md_flags &= ~MDL_USEDFPU; - if (i386_use_fxsave) { - pcb->pcb_savefpu.sv_xmm.fx_cw = control; - pcb->pcb_savefpu.sv_xmm.fx_mxcsr = __INITIAL_MXCSR__; - } else - pcb->pcb_savefpu.sv_87.s87_cw = control; memcpy(&pcb->pcb_fsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_fsd)); memcpy(&pcb->pcb_gsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_gsd)); @@ -1590,6 +1577,7 @@ cpu_getmcontext(struct lwp *l, mcontext_ { const struct trapframe *tf = l->l_md.md_regs; __greg_t *gr = mcp->__gregs; + struct pcb *pcb; __greg_t ras_eip; /* Save register context. */ @@ -1633,36 +1621,33 @@ cpu_getmcontext(struct lwp *l, mcontext_ mcp->_mc_tlsbase = (uintptr_t)l->l_private; *flags |= _UC_TLSBASE; - /* Save floating point register context, if any. */ - if ((l->l_md.md_flags & MDL_USEDFPU) != 0) { - struct pcb *pcb = lwp_getpcb(l); + /* Save floating point register context. */ + pcb = lwp_getpcb(l); - /* - * If this process is the current FP owner, dump its - * context to the PCB first. - */ - if (pcb->pcb_fpcpu) - fpusave_lwp(l, true); - if (i386_use_fxsave) { - __CTASSERT(sizeof pcb->pcb_savefpu.sv_xmm == - sizeof mcp->__fpregs.__fp_reg_set.__fp_xmm_state); - memcpy(&mcp->__fpregs.__fp_reg_set.__fp_xmm_state, - &pcb->pcb_savefpu.sv_xmm, - sizeof (mcp->__fpregs.__fp_reg_set.__fp_xmm_state)); - *flags |= _UC_FXSAVE; - } else { - __CTASSERT(sizeof pcb->pcb_savefpu.sv_87 == - sizeof mcp->__fpregs.__fp_reg_set.__fpchip_state); - memcpy(&mcp->__fpregs.__fp_reg_set.__fpchip_state, - &pcb->pcb_savefpu.sv_87, - sizeof (mcp->__fpregs.__fp_reg_set.__fpchip_state)); - } + /* + * If this process is the current FP owner, dump its + * context to the PCB first. + */ + fpusave_lwp(l, true); + if (i386_use_fxsave) { + __CTASSERT(sizeof pcb->pcb_savefpu.sv_xmm == + sizeof mcp->__fpregs.__fp_reg_set.__fp_xmm_state); + memcpy(&mcp->__fpregs.__fp_reg_set.__fp_xmm_state, + &pcb->pcb_savefpu.sv_xmm, + sizeof (mcp->__fpregs.__fp_reg_set.__fp_xmm_state)); + *flags |= _UC_FXSAVE; + } else { + __CTASSERT(sizeof pcb->pcb_savefpu.sv_87 == + sizeof mcp->__fpregs.__fp_reg_set.__fpchip_state); + memcpy(&mcp->__fpregs.__fp_reg_set.__fpchip_state, + &pcb->pcb_savefpu.sv_87, + sizeof (mcp->__fpregs.__fp_reg_set.__fpchip_state)); + } #if 0 - /* Apparently nothing ever touches this. */ - ucp->mcp.mc_fp.fp_emcsts = pcb->pcb_saveemc; + /* Apparently nothing ever touches this. */ + ucp->mcp.mc_fp.fp_emcsts = pcb->pcb_saveemc; #endif - *flags |= _UC_FPU; - } + *flags |= _UC_FPU; } int @@ -1738,19 +1723,14 @@ cpu_setmcontext(struct lwp *l, const mco if ((flags & _UC_TLSBASE) != 0) lwp_setprivate(l, (void *)(uintptr_t)mcp->_mc_tlsbase); - /* - * If we were using the FPU, forget that we were. - */ - if (pcb->pcb_fpcpu != NULL) - fpusave_lwp(l, false); - - /* Restore floating point register context, if any. */ + /* Restore floating point register context, if given. */ if ((flags & _UC_FPU) != 0) { __CTASSERT(sizeof pcb->pcb_savefpu.sv_xmm == sizeof mcp->__fpregs.__fp_reg_set.__fp_xmm_state); __CTASSERT(sizeof pcb->pcb_savefpu.sv_87 == sizeof mcp->__fpregs.__fp_reg_set.__fpchip_state); + fpusave_lwp(l, false); if (flags & _UC_FXSAVE) { if (i386_use_fxsave) { memcpy(&pcb->pcb_savefpu.sv_xmm, @@ -1773,8 +1753,8 @@ cpu_setmcontext(struct lwp *l, const mco sizeof (pcb->pcb_savefpu.sv_87)); } } - l->l_md.md_flags |= MDL_USEDFPU; } + mutex_enter(p->p_lock); if (flags & _UC_SETSTACK) l->l_sigstk.ss_flags |= SS_ONSTACK; Index: src/sys/arch/i386/i386/process_machdep.c diff -u src/sys/arch/i386/i386/process_machdep.c:1.82 src/sys/arch/i386/i386/process_machdep.c:1.83 --- src/sys/arch/i386/i386/process_machdep.c:1.82 Fri Feb 7 22:40:22 2014 +++ src/sys/arch/i386/i386/process_machdep.c Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: process_machdep.c,v 1.82 2014/02/07 22:40:22 dsl Exp $ */ +/* $NetBSD: process_machdep.c,v 1.83 2014/02/15 10:11:15 dsl Exp $ */ /*- * Copyright (c) 1998, 2000, 2001, 2008 The NetBSD Foundation, Inc. @@ -52,7 +52,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.82 2014/02/07 22:40:22 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.83 2014/02/15 10:11:15 dsl Exp $"); #include "opt_vm86.h" #include "opt_ptrace.h" @@ -131,34 +131,7 @@ process_read_fpregs(struct lwp *l, struc { union savefpu *frame = process_fpframe(l); - if (l->l_md.md_flags & MDL_USEDFPU) { - fpusave_lwp(l, true); - } else { - /* - * Fake a FNINIT. - * The initial control word was already set by setregs(), so - * save it temporarily. - */ - if (i386_use_fxsave) { - uint32_t mxcsr = frame->sv_xmm.fx_mxcsr; - uint16_t cw = frame->sv_xmm.fx_cw; - - /* XXX Don't zero XMM regs? */ - memset(&frame->sv_xmm, 0, sizeof(frame->sv_xmm)); - frame->sv_xmm.fx_cw = cw; - frame->sv_xmm.fx_mxcsr = mxcsr; - frame->sv_xmm.fx_sw = 0x0000; - frame->sv_xmm.fx_tw = 0x00; - } else { - uint16_t cw = frame->sv_87.s87_cw; - - memset(&frame->sv_87, 0, sizeof(frame->sv_87)); - frame->sv_87.s87_cw = cw; - frame->sv_87.s87_sw = 0x0000; - frame->sv_87.s87_tw = 0xffff; - } - l->l_md.md_flags |= MDL_USEDFPU; - } + fpusave_lwp(l, true); __CTASSERT(sizeof *regs == sizeof (struct save87)); if (i386_use_fxsave) { @@ -229,11 +202,7 @@ process_write_fpregs(struct lwp *l, cons { union savefpu *frame = process_fpframe(l); - if (l->l_md.md_flags & MDL_USEDFPU) { - fpusave_lwp(l, false); - } else { - l->l_md.md_flags |= MDL_USEDFPU; - } + fpusave_lwp(l, false); if (i386_use_fxsave) { process_s87_to_xmm((const struct save87 *)regs, &frame->sv_xmm); @@ -269,60 +238,26 @@ process_set_pc(struct lwp *l, void *addr static int process_machdep_read_xmmregs(struct lwp *l, struct xmmregs *regs) { - union savefpu *frame = process_fpframe(l); if (i386_use_fxsave == 0) return (EINVAL); - if (l->l_md.md_flags & MDL_USEDFPU) { - struct pcb *pcb = lwp_getpcb(l); + fpusave_lwp(l, true); - if (pcb->pcb_fpcpu != NULL) { - fpusave_lwp(l, true); - } - } else { - /* - * Fake a FNINIT. - * The initial control word was already set by setregs(), - * so save it temporarily. - */ - uint32_t mxcsr = frame->sv_xmm.fx_mxcsr; - uint16_t cw = frame->sv_xmm.fx_cw; - - /* XXX Don't zero XMM regs? */ - memset(&frame->sv_xmm, 0, sizeof(frame->sv_xmm)); - frame->sv_xmm.fx_cw = cw; - frame->sv_xmm.fx_mxcsr = mxcsr; - frame->sv_xmm.fx_sw = 0x0000; - frame->sv_xmm.fx_tw = 0x00; - - l->l_md.md_flags |= MDL_USEDFPU; - } - - memcpy(regs, &frame->sv_xmm, sizeof(*regs)); + memcpy(regs, &process_fpframe(l)->sv_xmm, sizeof(*regs)); return (0); } static int process_machdep_write_xmmregs(struct lwp *l, struct xmmregs *regs) { - union savefpu *frame = process_fpframe(l); if (i386_use_fxsave == 0) return (EINVAL); - if (l->l_md.md_flags & MDL_USEDFPU) { - struct pcb *pcb = lwp_getpcb(l); - - /* If we were using the FPU, drop it. */ - if (pcb->pcb_fpcpu != NULL) { - fpusave_lwp(l, false); - } - } else { - l->l_md.md_flags |= MDL_USEDFPU; - } + fpusave_lwp(l, false); - memcpy(&frame->sv_xmm, regs, sizeof(*regs)); + memcpy(&process_fpframe(l)->sv_xmm, regs, sizeof(*regs)); return (0); } Index: src/sys/arch/i386/include/proc.h diff -u src/sys/arch/i386/include/proc.h:1.40 src/sys/arch/i386/include/proc.h:1.41 --- src/sys/arch/i386/include/proc.h:1.40 Sun Dec 1 01:05:16 2013 +++ src/sys/arch/i386/include/proc.h Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: proc.h,v 1.40 2013/12/01 01:05:16 christos Exp $ */ +/* $NetBSD: proc.h,v 1.41 2014/02/15 10:11:15 dsl Exp $ */ /* * Copyright (c) 1991 Regents of the University of California. @@ -52,7 +52,6 @@ struct mdlwp { }; /* md_flags */ -#define MDL_USEDFPU 0x0001 /* has used the FPU */ #define MDL_IOPL 0x0002 /* XEN: i/o privilege */ struct mdproc { Index: src/sys/arch/x86/include/cpu.h diff -u src/sys/arch/x86/include/cpu.h:1.61 src/sys/arch/x86/include/cpu.h:1.62 --- src/sys/arch/x86/include/cpu.h:1.61 Wed Feb 12 23:24:09 2014 +++ src/sys/arch/x86/include/cpu.h Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.61 2014/02/12 23:24:09 dsl Exp $ */ +/* $NetBSD: cpu.h,v 1.62 2014/02/15 10:11:15 dsl Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -435,10 +435,6 @@ void i8254_initclocks(void); void cpu_probe_features(struct cpu_info *); -/* npx.c */ -void fpusave_lwp(struct lwp *, bool); -void fpusave_cpu(bool); - /* vm_machdep.c */ paddr_t kvtop(void *); Index: src/sys/arch/x86/include/cpu_extended_state.h diff -u src/sys/arch/x86/include/cpu_extended_state.h:1.6 src/sys/arch/x86/include/cpu_extended_state.h:1.7 --- src/sys/arch/x86/include/cpu_extended_state.h:1.6 Thu Feb 13 19:37:08 2014 +++ src/sys/arch/x86/include/cpu_extended_state.h Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu_extended_state.h,v 1.6 2014/02/13 19:37:08 dsl Exp $ */ +/* $NetBSD: cpu_extended_state.h,v 1.7 2014/02/15 10:11:15 dsl Exp $ */ #ifndef _X86_CPU_EXTENDED_STATE_H_ #define _X86_CPU_EXTENDED_STATE_H_ @@ -122,8 +122,9 @@ __CTASSERT_NOLINT(sizeof (struct fxsave) /* The end of the fsave buffer can be used by the operating system */ struct fxsave_os { - uint8_t fxo_fxsave[512 - 48]; - /* 48 bytes available */ + uint8_t fxo_fxsave[512 - 48]; + /* 48 bytes available, NB copied to/from userspace */ + uint16_t fxo_dflt_cw; /* Control word for signal handlers */ }; union savefpu { Index: src/sys/arch/x86/include/fpu.h diff -u src/sys/arch/x86/include/fpu.h:1.2 src/sys/arch/x86/include/fpu.h:1.3 --- src/sys/arch/x86/include/fpu.h:1.2 Wed Feb 12 23:24:09 2014 +++ src/sys/arch/x86/include/fpu.h Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu.h,v 1.2 2014/02/12 23:24:09 dsl Exp $ */ +/* $NetBSD: fpu.h,v 1.3 2014/02/15 10:11:15 dsl Exp $ */ #ifndef _X86_FPU_H_ #define _X86_FPU_H_ @@ -7,8 +7,9 @@ #ifdef _KERNEL -struct trapframe; struct cpu_info; +struct lwp; +struct trapframe; void fpuinit(struct cpu_info *); void fpusave_lwp(struct lwp *, bool); @@ -20,6 +21,11 @@ void fpudna(struct trapframe *); void process_xmm_to_s87(const struct fxsave *, struct save87 *); void process_s87_to_xmm(const struct save87 *, struct fxsave *); +/* Set all to defaults (eg during exec) */ +void fpu_save_area_clear(struct lwp *, unsigned int); +/* Reset control words only - for signal handlers */ +void fpu_save_area_reset(struct lwp *); + #endif #endif /* _X86_FPU_H_ */ Index: src/sys/arch/x86/x86/fpu.c diff -u src/sys/arch/x86/x86/fpu.c:1.4 src/sys/arch/x86/x86/fpu.c:1.5 --- src/sys/arch/x86/x86/fpu.c:1.4 Thu Feb 13 19:37:08 2014 +++ src/sys/arch/x86/x86/fpu.c Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu.c,v 1.4 2014/02/13 19:37:08 dsl Exp $ */ +/* $NetBSD: fpu.c,v 1.5 2014/02/15 10:11:15 dsl Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. All @@ -100,7 +100,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.4 2014/02/13 19:37:08 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.5 2014/02/15 10:11:15 dsl Exp $"); #include "opt_multiprocessor.h" @@ -430,34 +430,20 @@ fpudna(struct trapframe *frame) clts(); ci->ci_fpcurlwp = l; pcb->pcb_fpcpu = ci; - if ((l->l_md.md_flags & MDL_USEDFPU) == 0) { - fninit(); - if (i386_use_fxsave) { - fldcw(&pcb->pcb_savefpu.sv_xmm.fx_cw); - x86_ldmxcsr(&pcb->pcb_savefpu.sv_xmm.fx_mxcsr); - } else { - fldcw(&pcb->pcb_savefpu.sv_87.s87_cw); - } - l->l_md.md_flags |= MDL_USEDFPU; - } else if (i386_use_fxsave) { - /* - * AMD FPU's do not restore FIP, FDP, and FOP on fxrstor, - * leaking other process's execution history. Clear them - * manually. - */ + if (i386_use_fxsave) { /* + * AMD FPU's do not restore FIP, FDP, and FOP on fxrstor, + * leaking other process's execution history. + * Clear them manually by loading a zero onto the fpu stack. + * * Clear the ES bit in the x87 status word if it is currently * set, in order to avoid causing a fault in the upcoming load. */ if (fngetsw() & 0x80) fnclex(); - - /* - * Load a zero into the x87 stack. This mangles the x87 stack, - * but we don't care since we're about to call fxrstor() anyway. - */ fldummy(); + fxrstor(&pcb->pcb_savefpu.sv_xmm); } else { frstor(&pcb->pcb_savefpu.sv_87); @@ -509,15 +495,14 @@ fpusave_cpu(bool save) void fpusave_lwp(struct lwp *l, bool save) { + struct pcb *pcb = lwp_getpcb(l); struct cpu_info *oci; - struct pcb *pcb; int s, spins, ticks; spins = 0; ticks = hardclock_ticks; for (;;) { s = splhigh(); - pcb = lwp_getpcb(l); oci = pcb->pcb_fpcpu; if (oci == NULL) { splx(s); @@ -546,9 +531,52 @@ 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 &= ~MDL_USEDFPU; +/* + * exec needs to clear the fpu save area to avoid leaking info from the + * old process to userspace. + * We must also load these values into the fpu - otherwise the process + * will see another processes fpu registers. + */ +void +fpu_save_area_clear(struct lwp *lwp, unsigned int x87_cw) +{ + struct pcb *pcb; + union savefpu *fpu_save; + + fpusave_lwp(lwp, false); + + pcb = lwp_getpcb(lwp); + fpu_save = &pcb->pcb_savefpu; + + if (i386_use_fxsave) { + memset(&fpu_save->sv_xmm, 0, sizeof fpu_save->sv_xmm); + fpu_save->sv_xmm.fx_mxcsr = __INITIAL_MXCSR__; + fpu_save->sv_xmm.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; + fpu_save->sv_xmm.fx_cw = x87_cw; + } else { + memset(&fpu_save->sv_87, 0, sizeof fpu_save->sv_87); + fpu_save->sv_87.s87_tw = 0xffff; + fpu_save->sv_87.s87_cw = x87_cw; + } + fpu_save->sv_os.fxo_dflt_cw = x87_cw; +} + +/* For signal handlers the register values don't matter */ +void +fpu_save_area_reset(struct lwp *lwp) +{ + struct pcb *pcb = lwp_getpcb(lwp); + union savefpu *fpu_save = &pcb->pcb_savefpu; + + if (i386_use_fxsave) { + fpu_save->sv_xmm.fx_mxcsr = __INITIAL_MXCSR__; + fpu_save->sv_xmm.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; + fpu_save->sv_xmm.fx_tw = 0; + fpu_save->sv_xmm.fx_cw = fpu_save->sv_os.fxo_dflt_cw; + } else { + fpu_save->sv_87.s87_tw = 0xffff; + fpu_save->sv_87.s87_cw = fpu_save->sv_os.fxo_dflt_cw; } } Index: src/sys/arch/x86/x86/vm_machdep.c diff -u src/sys/arch/x86/x86/vm_machdep.c:1.21 src/sys/arch/x86/x86/vm_machdep.c:1.22 --- src/sys/arch/x86/x86/vm_machdep.c:1.21 Tue Feb 11 20:17:16 2014 +++ src/sys/arch/x86/x86/vm_machdep.c Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: vm_machdep.c,v 1.21 2014/02/11 20:17:16 dsl Exp $ */ +/* $NetBSD: vm_machdep.c,v 1.22 2014/02/15 10:11:15 dsl Exp $ */ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. @@ -80,7 +80,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.21 2014/02/11 20:17:16 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.22 2014/02/15 10:11:15 dsl Exp $"); #include "opt_mtrr.h" @@ -137,9 +137,7 @@ cpu_lwp_fork(struct lwp *l1, struct lwp * If parent LWP was using FPU, then we have to save the FPU h/w * state to PCB so that we can copy it. */ - if (pcb1->pcb_fpcpu != NULL) { - fpusave_lwp(l1, true); - } + fpusave_lwp(l1, true); /* * Sync the PCB before we copy it. @@ -238,12 +236,9 @@ cpu_lwp_fork(struct lwp *l1, struct lwp void cpu_lwp_free(struct lwp *l, int proc) { - struct pcb *pcb = lwp_getpcb(l); /* If we were using the FPU, forget about it. */ - if (pcb->pcb_fpcpu != NULL) { - fpusave_lwp(l, false); - } + fpusave_lwp(l, false); #ifdef MTRR if (proc && l->l_proc->p_md.md_flags & MDP_USEDMTRR) Index: src/sys/compat/linux/arch/amd64/linux_machdep.c diff -u src/sys/compat/linux/arch/amd64/linux_machdep.c:1.46 src/sys/compat/linux/arch/amd64/linux_machdep.c:1.47 --- src/sys/compat/linux/arch/amd64/linux_machdep.c:1.46 Tue Feb 11 20:17:16 2014 +++ src/sys/compat/linux/arch/amd64/linux_machdep.c Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.46 2014/02/11 20:17:16 dsl Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.47 2014/02/15 10:11:15 dsl Exp $ */ /*- * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. @@ -33,7 +33,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.46 2014/02/11 20:17:16 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.47 2014/02/15 10:11:15 dsl Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -83,15 +83,8 @@ linux_setregs(struct lwp *l, struct exec struct pcb *pcb = lwp_getpcb(l); struct trapframe *tf; - /* If we were using the FPU, forget about it. */ - if (pcb->pcb_fpcpu != NULL) - fpusave_lwp(l, 0); - - l->l_md.md_flags &= ~MDL_USEDFPU; + fpu_save_area_clear(l, __NetBSD_NPXCW__); pcb->pcb_flags = 0; - pcb->pcb_savefpu.sv_xmm.fx_cw = __NetBSD_NPXCW__; - pcb->pcb_savefpu.sv_xmm.fx_mxcsr = __INITIAL_MXCSR__; - pcb->pcb_savefpu.sv_xmm.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; l->l_proc->p_flag &= ~PK_32; @@ -152,15 +145,9 @@ linux_sendsig(const ksiginfo_t *ksi, con else sp = (char *)tf->tf_rsp - 128; - /* - * Save FPU state, if any - */ - if (l->l_md.md_flags & MDL_USEDFPU) { - sp = (char *) - (((long)sp - sizeof (*fpsp)) & ~0xfUL); - fpsp = (struct linux__fpstate *)sp; - } else - fpsp = NULL; + /* Save FPU state */ + sp = (char *) (((long)sp - sizeof (*fpsp)) & ~0xfUL); + fpsp = (struct linux__fpstate *)sp; /* * Populate the rt_sigframe Index: src/sys/compat/linux/arch/i386/linux_machdep.c diff -u src/sys/compat/linux/arch/i386/linux_machdep.c:1.156 src/sys/compat/linux/arch/i386/linux_machdep.c:1.157 --- src/sys/compat/linux/arch/i386/linux_machdep.c:1.156 Sun Jan 26 19:16:17 2014 +++ src/sys/compat/linux/arch/i386/linux_machdep.c Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.156 2014/01/26 19:16:17 dsl Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.157 2014/02/15 10:11:15 dsl Exp $ */ /*- * Copyright (c) 1995, 2000, 2008, 2009 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.156 2014/01/26 19:16:17 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.157 2014/02/15 10:11:15 dsl Exp $"); #if defined(_KERNEL_OPT) #include "opt_vm86.h" @@ -126,25 +126,13 @@ extern char linux_sigcode[], linux_rt_si void linux_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) { - struct pcb *pcb = lwp_getpcb(l); struct trapframe *tf; - /* If we were using the FPU, forget about it. */ - if (pcb->pcb_fpcpu != NULL) - fpusave_lwp(l, false); - - #ifdef USER_LDT pmap_ldt_cleanup(l); #endif - l->l_md.md_flags &= ~MDL_USEDFPU; - - if (i386_use_fxsave) { - pcb->pcb_savefpu.sv_xmm.fx_cw = __Linux_NPXCW__; - pcb->pcb_savefpu.sv_xmm.fx_mxcsr = __INITIAL_MXCSR__; - } else - pcb->pcb_savefpu.sv_87.s87_cw = __Linux_NPXCW__; + fpu_save_area_clear(l, __Linux_NPXCW__); tf = l->l_md.md_regs; tf->tf_gs = 0; Index: src/sys/compat/linux32/arch/amd64/linux32_machdep.c diff -u src/sys/compat/linux32/arch/amd64/linux32_machdep.c:1.34 src/sys/compat/linux32/arch/amd64/linux32_machdep.c:1.35 --- src/sys/compat/linux32/arch/amd64/linux32_machdep.c:1.34 Fri Feb 7 22:40:22 2014 +++ src/sys/compat/linux32/arch/amd64/linux32_machdep.c Sat Feb 15 10:11:15 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_machdep.c,v 1.34 2014/02/07 22:40:22 dsl Exp $ */ +/* $NetBSD: linux32_machdep.c,v 1.35 2014/02/15 10:11:15 dsl Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_machdep.c,v 1.34 2014/02/07 22:40:22 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_machdep.c,v 1.35 2014/02/15 10:11:15 dsl Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -273,22 +273,16 @@ linux32_setregs(struct lwp *l, struct ex struct trapframe *tf; struct proc *p = l->l_proc; - /* If we were using the FPU, forget about it. */ - if (pcb->pcb_fpcpu != NULL) - fpusave_lwp(l, 0); - #if defined(USER_LDT) && 0 pmap_ldt_cleanup(p); #endif netbsd32_adjust_limits(p); - l->l_md.md_flags &= ~MDL_USEDFPU; + fpu_save_area_clear(l, __Linux_NPXCW__); + l->l_md.md_flags |= MDL_COMPAT32; /* Forces iret not sysret */ pcb->pcb_flags = PCB_COMPAT32; - pcb->pcb_savefpu.sv_xmm.fx_cw = __Linux_NPXCW__; - pcb->pcb_savefpu.sv_xmm.fx_mxcsr = __INITIAL_MXCSR__; - pcb->pcb_savefpu.sv_xmm.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; p->p_flag |= PK_32;