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, &regs->fxstate, sizeof(*regs));
+	memcpy(process_fpframe(l), &regs->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;
 

Reply via email to