svn commit: r216162 - in stable/8/sys: amd64/amd64 amd64/ia32 amd64/include i386/i386 i386/include i386/isa pc98/pc98

Konstantin Belousov kib at FreeBSD.org
Fri Dec 3 22:07:07 UTC 2010


Author: kib
Date: Fri Dec  3 22:07:07 2010
New Revision: 216162
URL: http://svn.freebsd.org/changeset/base/216162

Log:
  MFC r209463:
  Fix bugs on pc98, use npxgetuserregs() instead of npxgetregs() for
  get_fpcontext(), and npxsetuserregs() for set_fpcontext). Also,
  note that usercontext is not initialized anymore in fpstate_drop().
  
  Systematically replace references to npxgetregs() and npxsetregs()
  by npxgetuserregs() and npxsetuserregs() in comments.
  
  MFC r215865:
  Remove npxgetregs(), npxsetregs(), fpugetregs() and fpusetregs()
  functions, they are unused. Remove 'user' from npxgetuserregs()
  etc. names.
  
  For {npx,fpu}{get,set}regs(), always use pcb->pcb_user_save for FPU
  context storage.
  
  MFC r216012:
  Calling fill_fpregs() for curthread is legitimate, and ELF coredump
  does this.
  
  Approved by:	re (bz)

Modified:
  stable/8/sys/amd64/amd64/fpu.c
  stable/8/sys/amd64/amd64/machdep.c
  stable/8/sys/amd64/ia32/ia32_reg.c
  stable/8/sys/amd64/ia32/ia32_signal.c
  stable/8/sys/amd64/include/fpu.h
  stable/8/sys/i386/i386/machdep.c
  stable/8/sys/i386/include/npx.h
  stable/8/sys/i386/isa/npx.c
  stable/8/sys/pc98/pc98/machdep.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/amd64/amd64/fpu.c
==============================================================================
--- stable/8/sys/amd64/amd64/fpu.c	Fri Dec  3 21:54:10 2010	(r216161)
+++ stable/8/sys/amd64/amd64/fpu.c	Fri Dec  3 22:07:07 2010	(r216162)
@@ -426,9 +426,7 @@ fpudna(void)
 		fxrstor(&fpu_initialstate);
 		if (pcb->pcb_initial_fpucw != __INITIAL_FPUCW__)
 			fldcw(pcb->pcb_initial_fpucw);
-		pcb->pcb_flags |= PCB_FPUINITDONE;
-		if (PCB_USER_FPU(pcb))
-			pcb->pcb_flags |= PCB_USERFPUINITDONE;
+		fpuuserinited(curthread);
 	} else
 		fxrstor(pcb->pcb_save);
 	critical_exit();
@@ -448,60 +446,50 @@ fpudrop()
 }
 
 /*
- * Get the state of the FPU without dropping ownership (if possible).
- * It returns the FPU ownership status.
+ * Get the user state of the FPU into pcb->pcb_user_save without
+ * dropping ownership (if possible).  It returns the FPU ownership
+ * status.
  */
 int
-fpugetuserregs(struct thread *td, struct savefpu *addr)
+fpugetregs(struct thread *td)
 {
 	struct pcb *pcb;
 
 	pcb = td->td_pcb;
 	if ((pcb->pcb_flags & PCB_USERFPUINITDONE) == 0) {
-		bcopy(&fpu_initialstate, addr, sizeof(fpu_initialstate));
-		addr->sv_env.en_cw = pcb->pcb_initial_fpucw;
-		return (_MC_FPOWNED_NONE);
+		bcopy(&fpu_initialstate, &pcb->pcb_user_save,
+		    sizeof(fpu_initialstate));
+		pcb->pcb_user_save.sv_env.en_cw = pcb->pcb_initial_fpucw;
+		fpuuserinited(td);
+		return (_MC_FPOWNED_PCB);
 	}
 	critical_enter();
 	if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) {
-		fxsave(addr);
+		fxsave(&pcb->pcb_user_save);
 		critical_exit();
 		return (_MC_FPOWNED_FPU);
 	} else {
 		critical_exit();
-		bcopy(&pcb->pcb_user_save, addr, sizeof(*addr));
 		return (_MC_FPOWNED_PCB);
 	}
 }
 
-int
-fpugetregs(struct thread *td, struct savefpu *addr)
+void
+fpuuserinited(struct thread *td)
 {
 	struct pcb *pcb;
 
 	pcb = td->td_pcb;
-	if ((pcb->pcb_flags & PCB_FPUINITDONE) == 0) {
-		bcopy(&fpu_initialstate, addr, sizeof(fpu_initialstate));
-		addr->sv_env.en_cw = pcb->pcb_initial_fpucw;
-		return (_MC_FPOWNED_NONE);
-	}
-	critical_enter();
-	if (td == PCPU_GET(fpcurthread)) {
-		fxsave(addr);
-		critical_exit();
-		return (_MC_FPOWNED_FPU);
-	} else {
-		critical_exit();
-		bcopy(pcb->pcb_save, addr, sizeof(*addr));
-		return (_MC_FPOWNED_PCB);
-	}
+	if (PCB_USER_FPU(pcb))
+		pcb->pcb_flags |= PCB_FPUINITDONE;
+	pcb->pcb_flags |= PCB_USERFPUINITDONE;
 }
 
 /*
  * Set the state of the FPU.
  */
 void
-fpusetuserregs(struct thread *td, struct savefpu *addr)
+fpusetregs(struct thread *td, struct savefpu *addr)
 {
 	struct pcb *pcb;
 
@@ -514,31 +502,10 @@ fpusetuserregs(struct thread *td, struct
 	} else {
 		critical_exit();
 		bcopy(addr, &td->td_pcb->pcb_user_save, sizeof(*addr));
-		if (PCB_USER_FPU(pcb))
-			pcb->pcb_flags |= PCB_FPUINITDONE;
-		pcb->pcb_flags |= PCB_USERFPUINITDONE;
+		fpuuserinited(td);
 	}
 }
 
-void
-fpusetregs(struct thread *td, struct savefpu *addr)
-{
-	struct pcb *pcb;
-
-	pcb = td->td_pcb;
-	critical_enter();
-	if (td == PCPU_GET(fpcurthread)) {
-		fxrstor(addr);
-		critical_exit();
-	} else {
-		critical_exit();
-		bcopy(addr, td->td_pcb->pcb_save, sizeof(*addr));
-	}
-	if (PCB_USER_FPU(pcb))
-		pcb->pcb_flags |= PCB_USERFPUINITDONE;
-	pcb->pcb_flags |= PCB_FPUINITDONE;
-}
-
 /*
  * On AuthenticAMD processors, the fxrstor instruction does not restore
  * the x87's stored last instruction pointer, last data pointer, and last

Modified: stable/8/sys/amd64/amd64/machdep.c
==============================================================================
--- stable/8/sys/amd64/amd64/machdep.c	Fri Dec  3 21:54:10 2010	(r216161)
+++ stable/8/sys/amd64/amd64/machdep.c	Fri Dec  3 22:07:07 2010	(r216162)
@@ -1964,6 +1964,9 @@ int
 fill_fpregs(struct thread *td, struct fpreg *fpregs)
 {
 
+	KASSERT(td == curthread || TD_IS_SUSPENDED(td),
+	    ("not suspended thread %p", td));
+	fpugetregs(td);
 	fill_fpregs_xmm(&td->td_pcb->pcb_user_save, fpregs);
 	return (0);
 }
@@ -1974,6 +1977,7 @@ set_fpregs(struct thread *td, struct fpr
 {
 
 	set_fpregs_xmm(fpregs, &td->td_pcb->pcb_user_save);
+	fpuuserinited(td);
 	return (0);
 }
 
@@ -2088,8 +2092,9 @@ static void
 get_fpcontext(struct thread *td, mcontext_t *mcp)
 {
 
-	mcp->mc_ownedfp = fpugetuserregs(td,
-	    (struct savefpu *)&mcp->mc_fpstate);
+	mcp->mc_ownedfp = fpugetregs(td);
+	bcopy(&td->td_pcb->pcb_user_save, &mcp->mc_fpstate,
+	    sizeof(mcp->mc_fpstate));
 	mcp->mc_fpformat = fpuformat();
 }
 
@@ -2109,7 +2114,7 @@ set_fpcontext(struct thread *td, const m
 	    mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
 		fpstate = (struct savefpu *)&mcp->mc_fpstate;
 		fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask;
-		fpusetuserregs(td, fpstate);
+		fpusetregs(td, fpstate);
 	} else
 		return (EINVAL);
 	return (0);
@@ -2127,10 +2132,10 @@ fpstate_drop(struct thread *td)
 	 * XXX force a full drop of the fpu.  The above only drops it if we
 	 * owned it.
 	 *
-	 * XXX I don't much like fpugetregs()'s semantics of doing a full
+	 * XXX I don't much like fpugetuserregs()'s semantics of doing a full
 	 * drop.  Dropping only to the pcb matches fnsave's behaviour.
 	 * We only need to drop to !PCB_INITDONE in sendsig().  But
-	 * sendsig() is the only caller of fpugetregs()... perhaps we just
+	 * sendsig() is the only caller of fpugetuserregs()... perhaps we just
 	 * have too many layers.
 	 */
 	curthread->td_pcb->pcb_flags &= ~(PCB_FPUINITDONE |

Modified: stable/8/sys/amd64/ia32/ia32_reg.c
==============================================================================
--- stable/8/sys/amd64/ia32/ia32_reg.c	Fri Dec  3 21:54:10 2010	(r216161)
+++ stable/8/sys/amd64/ia32/ia32_reg.c	Fri Dec  3 22:07:07 2010	(r216162)
@@ -145,13 +145,18 @@ set_regs32(struct thread *td, struct reg
 int
 fill_fpregs32(struct thread *td, struct fpreg32 *regs)
 {
-	struct save87 *sv_87 = (struct save87 *)regs;
-	struct env87 *penv_87 = &sv_87->sv_env;
-	struct savefpu *sv_fpu = &td->td_pcb->pcb_user_save;
-	struct envxmm *penv_xmm = &sv_fpu->sv_env;
+	struct savefpu *sv_fpu;
+	struct save87 *sv_87;
+	struct env87 *penv_87;
+	struct envxmm *penv_xmm;
 	int i;
 
 	bzero(regs, sizeof(*regs));
+	sv_87 = (struct save87 *)regs;
+	penv_87 = &sv_87->sv_env;
+	fpugetregs(td);
+	sv_fpu = &td->td_pcb->pcb_user_save;
+	penv_xmm = &sv_fpu->sv_env;
 	
 	/* FPU control/status */
 	penv_87->en_cw = penv_xmm->en_cw;
@@ -200,6 +205,7 @@ set_fpregs32(struct thread *td, struct f
 		sv_fpu->sv_fp[i].fp_acc = sv_87->sv_ac[i];
 	for (i = 8; i < 16; ++i)
 		bzero(&sv_fpu->sv_fp[i].fp_acc, sizeof(sv_fpu->sv_fp[i].fp_acc));
+	fpuuserinited(td);
 
 	return (0);
 }

Modified: stable/8/sys/amd64/ia32/ia32_signal.c
==============================================================================
--- stable/8/sys/amd64/ia32/ia32_signal.c	Fri Dec  3 21:54:10 2010	(r216161)
+++ stable/8/sys/amd64/ia32/ia32_signal.c	Fri Dec  3 22:07:07 2010	(r216162)
@@ -98,8 +98,9 @@ ia32_get_fpcontext(struct thread *td, st
 	 * 64bit instruction and data pointers. Ignore the difference
 	 * for now, it should be irrelevant for most applications.
 	 */
-	mcp->mc_ownedfp = fpugetuserregs(td,
-	    (struct savefpu *)&mcp->mc_fpstate);
+	mcp->mc_ownedfp = fpugetregs(td);
+	bcopy(&td->td_pcb->pcb_user_save, &mcp->mc_fpstate,
+	    sizeof(mcp->mc_fpstate));
 	mcp->mc_fpformat = fpuformat();
 }
 
@@ -116,7 +117,7 @@ ia32_set_fpcontext(struct thread *td, co
 		fpstate_drop(td);
 	else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
 	    mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
-		fpusetuserregs(td, (struct savefpu *)&mcp->mc_fpstate);
+		fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate);
 	} else
 		return (EINVAL);
 	return (0);

Modified: stable/8/sys/amd64/include/fpu.h
==============================================================================
--- stable/8/sys/amd64/include/fpu.h	Fri Dec  3 21:54:10 2010	(r216161)
+++ stable/8/sys/amd64/include/fpu.h	Fri Dec  3 22:07:07 2010	(r216162)
@@ -112,12 +112,11 @@ void	fpudna(void);
 void	fpudrop(void);
 void	fpuexit(struct thread *td);
 int	fpuformat(void);
-int	fpugetregs(struct thread *td, struct savefpu *addr);
-int	fpugetuserregs(struct thread *td, struct savefpu *addr);
+int	fpugetregs(struct thread *td);
 void	fpuinit(void);
 void	fpusetregs(struct thread *td, struct savefpu *addr);
-void	fpusetuserregs(struct thread *td, struct savefpu *addr);
 int	fputrap(void);
+void	fpuuserinited(struct thread *td);
 int	fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx,
 	    u_int flags);
 int	fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx);

Modified: stable/8/sys/i386/i386/machdep.c
==============================================================================
--- stable/8/sys/i386/i386/machdep.c	Fri Dec  3 21:54:10 2010	(r216161)
+++ stable/8/sys/i386/i386/machdep.c	Fri Dec  3 22:07:07 2010	(r216162)
@@ -632,13 +632,6 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, 
 	sf.sf_uc.uc_mcontext.mc_gs = rgs();
 	bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
 	sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
-
-	/*
-	 * The get_fpcontext() call must be placed before assignments
-	 * to mc_fsbase and mc_gsbase due to the alignment-override
-	 * code in get_fpcontext() that possibly clobbers 12 bytes of
-	 * mcontext after mc_fpstate.
-	 */
 	get_fpcontext(td, &sf.sf_uc.uc_mcontext);
 	fpstate_drop(td);
 	/*
@@ -3186,28 +3179,34 @@ set_fpregs_xmm(sv_87, sv_xmm)
 int
 fill_fpregs(struct thread *td, struct fpreg *fpregs)
 {
+
+	KASSERT(td == curthread || TD_IS_SUSPENDED(td),
+	    ("not suspended thread %p", td));
+	npxgetregs(td);
 #ifdef CPU_ENABLE_SSE
-	if (cpu_fxsr) {
+	if (cpu_fxsr)
 		fill_fpregs_xmm(&td->td_pcb->pcb_user_save.sv_xmm,
-						(struct save87 *)fpregs);
-		return (0);
-	}
+		    (struct save87 *)fpregs);
+	else
 #endif /* CPU_ENABLE_SSE */
-	bcopy(&td->td_pcb->pcb_user_save.sv_87, fpregs, sizeof *fpregs);
+		bcopy(&td->td_pcb->pcb_user_save.sv_87, fpregs,
+		    sizeof(*fpregs));
 	return (0);
 }
 
 int
 set_fpregs(struct thread *td, struct fpreg *fpregs)
 {
+
 #ifdef CPU_ENABLE_SSE
-	if (cpu_fxsr) {
+	if (cpu_fxsr)
 		set_fpregs_xmm((struct save87 *)fpregs,
 		    &td->td_pcb->pcb_user_save.sv_xmm);
-		return (0);
-	}
+	else
 #endif /* CPU_ENABLE_SSE */
-	bcopy(fpregs, &td->td_pcb->pcb_user_save.sv_87, sizeof *fpregs);
+		bcopy(fpregs, &td->td_pcb->pcb_user_save.sv_87,
+		    sizeof(*fpregs));
+	npxuserinited(td);
 	return (0);
 }
 
@@ -3249,13 +3248,6 @@ get_mcontext(struct thread *td, mcontext
 	mcp->mc_esp = tp->tf_esp;
 	mcp->mc_ss = tp->tf_ss;
 	mcp->mc_len = sizeof(*mcp);
-
-	/*
-	 * The get_fpcontext() call must be placed before assignments
-	 * to mc_fsbase and mc_gsbase due to the alignment-override
-	 * code in get_fpcontext() that possibly clobbers 12 bytes of
-	 * mcontext after mc_fpstate.
-	 */
 	get_fpcontext(td, mcp);
 	sdp = &td->td_pcb->pcb_fsd;
 	mcp->mc_fsbase = sdp->sd_hibase << 24 | sdp->sd_lobase;
@@ -3306,39 +3298,14 @@ set_mcontext(struct thread *td, const mc
 static void
 get_fpcontext(struct thread *td, mcontext_t *mcp)
 {
+
 #ifndef DEV_NPX
 	mcp->mc_fpformat = _MC_FPFMT_NODEV;
 	mcp->mc_ownedfp = _MC_FPOWNED_NONE;
 #else
-	union savefpu *addr;
-
-	/*
-	 * XXX mc_fpstate might be misaligned, since its declaration is not
-	 * unportabilized using __attribute__((aligned(16))) like the
-	 * declaration of struct savemm, and anyway, alignment doesn't work
-	 * for auto variables since we don't use gcc's pessimal stack
-	 * alignment.  Work around this by abusing the spare fields after
-	 * mcp->mc_fpstate.
-	 *
-	 * XXX unpessimize most cases by only aligning when fxsave might be
-	 * called, although this requires knowing too much about
-	 * npxgetregs()'s internals.
-	 */
-	addr = (union savefpu *)&mcp->mc_fpstate;
-	if (td == PCPU_GET(fpcurthread) &&
-#ifdef CPU_ENABLE_SSE
-	    cpu_fxsr &&
-#endif
-	    ((uintptr_t)(void *)addr & 0xF)) {
-		do
-			addr = (void *)((char *)addr + 4);
-		while ((uintptr_t)(void *)addr & 0xF);
-	}
-	mcp->mc_ownedfp = npxgetuserregs(td, addr);
-	if (addr != (union savefpu *)&mcp->mc_fpstate) {
-		bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate));
-		bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2));
-	}
+	mcp->mc_ownedfp = npxgetregs(td);
+	bcopy(&td->td_pcb->pcb_user_save, &mcp->mc_fpstate,
+	    sizeof(mcp->mc_fpstate));
 	mcp->mc_fpformat = npxformat();
 #endif
 }
@@ -3346,7 +3313,6 @@ get_fpcontext(struct thread *td, mcontex
 static int
 set_fpcontext(struct thread *td, const mcontext_t *mcp)
 {
-	union savefpu *addr;
 
 	if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
 		return (0);
@@ -3358,34 +3324,14 @@ set_fpcontext(struct thread *td, const m
 		fpstate_drop(td);
 	else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
 	    mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
-		/* XXX align as above. */
-		addr = (union savefpu *)&mcp->mc_fpstate;
-		if (td == PCPU_GET(fpcurthread) &&
-#ifdef CPU_ENABLE_SSE
-		    cpu_fxsr &&
-#endif
-		    ((uintptr_t)(void *)addr & 0xF)) {
-			do
-				addr = (void *)((char *)addr + 4);
-			while ((uintptr_t)(void *)addr & 0xF);
-			bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate));
-		}
 #ifdef DEV_NPX
 #ifdef CPU_ENABLE_SSE
 		if (cpu_fxsr)
-			addr->sv_xmm.sv_env.en_mxcsr &= cpu_mxcsr_mask;
+			((union savefpu *)&mcp->mc_fpstate)->sv_xmm.sv_env.
+			    en_mxcsr &= cpu_mxcsr_mask;
 #endif
-		/*
-		 * XXX we violate the dubious requirement that npxsetregs()
-		 * be called with interrupts disabled.
-		 */
-		npxsetuserregs(td, addr);
+		npxsetregs(td, (union savefpu *)&mcp->mc_fpstate);
 #endif
-		/*
-		 * Don't bother putting things back where they were in the
-		 * misaligned case, since we know that the caller won't use
-		 * them again.
-		 */
 	} else
 		return (EINVAL);
 	return (0);

Modified: stable/8/sys/i386/include/npx.h
==============================================================================
--- stable/8/sys/i386/include/npx.h	Fri Dec  3 21:54:10 2010	(r216161)
+++ stable/8/sys/i386/include/npx.h	Fri Dec  3 22:07:07 2010	(r216162)
@@ -151,13 +151,12 @@ int	npxdna(void);
 void	npxdrop(void);
 void	npxexit(struct thread *td);
 int	npxformat(void);
-int	npxgetregs(struct thread *td, union savefpu *addr);
-int	npxgetuserregs(struct thread *td, union savefpu *addr);
+int	npxgetregs(struct thread *td);
 void	npxinit(void);
 void	npxsave(union savefpu *addr);
 void	npxsetregs(struct thread *td, union savefpu *addr);
-void	npxsetuserregs(struct thread *td, union savefpu *addr);
 int	npxtrap(void);
+void	npxuserinited(struct thread *);
 int	fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx,
 	    u_int flags);
 int	fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx);

Modified: stable/8/sys/i386/isa/npx.c
==============================================================================
--- stable/8/sys/i386/isa/npx.c	Fri Dec  3 21:54:10 2010	(r216161)
+++ stable/8/sys/i386/isa/npx.c	Fri Dec  3 22:07:07 2010	(r216162)
@@ -684,9 +684,7 @@ npxdna(void)
 		fpurstor(&npx_initialstate);
 		if (pcb->pcb_initial_npxcw != __INITIAL_NPXCW__)
 			fldcw(pcb->pcb_initial_npxcw);
-		pcb->pcb_flags |= PCB_NPXINITDONE;
-		if (PCB_USER_FPU(pcb))
-			pcb->pcb_flags |= PCB_NPXUSERINITDONE;
+		npxuserinited(curthread);
 	} else {
 		/*
 		 * The following fpurstor() may cause an IRQ13 when the
@@ -767,11 +765,12 @@ npxdrop()
 }
 
 /*
- * Get the state of the FPU without dropping ownership (if possible).
- * It returns the FPU ownership status.
+ * Get the user state of the FPU into pcb->pcb_user_save without
+ * dropping ownership (if possible).  It returns the FPU ownership
+ * status.
  */
 int
-npxgetregs(struct thread *td, union savefpu *addr)
+npxgetregs(struct thread *td)
 {
 	struct pcb *pcb;
 
@@ -780,48 +779,15 @@ npxgetregs(struct thread *td, union save
 
 	pcb = td->td_pcb;
 	if ((pcb->pcb_flags & PCB_NPXINITDONE) == 0) {
-		bcopy(&npx_initialstate, addr, sizeof(npx_initialstate));
-		SET_FPU_CW(addr, pcb->pcb_initial_npxcw);
-		return (_MC_FPOWNED_NONE);
-	}
-	critical_enter();
-	if (td == PCPU_GET(fpcurthread)) {
-		fpusave(addr);
-#ifdef CPU_ENABLE_SSE
-		if (!cpu_fxsr)
-#endif
-			/*
-			 * fnsave initializes the FPU and destroys whatever
-			 * context it contains.  Make sure the FPU owner
-			 * starts with a clean state next time.
-			 */
-			npxdrop();
-		critical_exit();
-		return (_MC_FPOWNED_FPU);
-	} else {
-		critical_exit();
-		bcopy(pcb->pcb_save, addr, sizeof(*addr));
+		bcopy(&npx_initialstate, &pcb->pcb_user_save,
+		    sizeof(npx_initialstate));
+		SET_FPU_CW(&pcb->pcb_user_save, pcb->pcb_initial_npxcw);
+		npxuserinited(td);
 		return (_MC_FPOWNED_PCB);
 	}
-}
-
-int
-npxgetuserregs(struct thread *td, union savefpu *addr)
-{
-	struct pcb *pcb;
-
-	if (!hw_float)
-		return (_MC_FPOWNED_NONE);
-
-	pcb = td->td_pcb;
-	if ((pcb->pcb_flags & PCB_NPXUSERINITDONE) == 0) {
-		bcopy(&npx_initialstate, addr, sizeof(npx_initialstate));
-		SET_FPU_CW(addr, pcb->pcb_initial_npxcw);
-		return (_MC_FPOWNED_NONE);
-	}
 	critical_enter();
-	if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) {
-		fpusave(addr);
+	if (td == PCPU_GET(fpcurthread)) {
+		fpusave(&pcb->pcb_user_save);
 #ifdef CPU_ENABLE_SSE
 		if (!cpu_fxsr)
 #endif
@@ -835,42 +801,24 @@ npxgetuserregs(struct thread *td, union 
 		return (_MC_FPOWNED_FPU);
 	} else {
 		critical_exit();
-		bcopy(&pcb->pcb_user_save, addr, sizeof(*addr));
 		return (_MC_FPOWNED_PCB);
 	}
 }
 
-/*
- * Set the state of the FPU.
- */
 void
-npxsetregs(struct thread *td, union savefpu *addr)
+npxuserinited(struct thread *td)
 {
 	struct pcb *pcb;
 
-	if (!hw_float)
-		return;
-
 	pcb = td->td_pcb;
-	critical_enter();
-	if (td == PCPU_GET(fpcurthread)) {
-#ifdef CPU_ENABLE_SSE
-		if (!cpu_fxsr)
-#endif
-			fnclex();	/* As in npxdrop(). */
-		fpurstor(addr);
-		critical_exit();
-	} else {
-		critical_exit();
-		bcopy(addr, pcb->pcb_save, sizeof(*addr));
-	}
 	if (PCB_USER_FPU(pcb))
-		pcb->pcb_flags |= PCB_NPXUSERINITDONE;
-	pcb->pcb_flags |= PCB_NPXINITDONE;
+		pcb->pcb_flags |= PCB_NPXINITDONE;
+	pcb->pcb_flags |= PCB_NPXUSERINITDONE;
 }
 
+
 void
-npxsetuserregs(struct thread *td, union savefpu *addr)
+npxsetregs(struct thread *td, union savefpu *addr)
 {
 	struct pcb *pcb;
 
@@ -884,15 +832,17 @@ npxsetuserregs(struct thread *td, union 
 		if (!cpu_fxsr)
 #endif
 			fnclex();	/* As in npxdrop(). */
-		fpurstor(addr);
+		if (((uintptr_t)addr & 0xf) != 0) {
+			bcopy(addr, &pcb->pcb_user_save, sizeof(*addr));
+			fpurstor(&pcb->pcb_user_save);
+		} else
+			fpurstor(addr);
 		critical_exit();
 		pcb->pcb_flags |= PCB_NPXUSERINITDONE | PCB_NPXINITDONE;
 	} else {
 		critical_exit();
 		bcopy(addr, &pcb->pcb_user_save, sizeof(*addr));
-		if (PCB_USER_FPU(pcb))
-			pcb->pcb_flags |= PCB_NPXINITDONE;
-		pcb->pcb_flags |= PCB_NPXUSERINITDONE;
+		npxuserinited(td);
 	}
 }
 

Modified: stable/8/sys/pc98/pc98/machdep.c
==============================================================================
--- stable/8/sys/pc98/pc98/machdep.c	Fri Dec  3 21:54:10 2010	(r216161)
+++ stable/8/sys/pc98/pc98/machdep.c	Fri Dec  3 22:07:07 2010	(r216162)
@@ -567,13 +567,6 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, 
 	sf.sf_uc.uc_mcontext.mc_gs = rgs();
 	bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
 	sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
-
-	/*
-	 * The get_fpcontext() call must be placed before assignments
-	 * to mc_fsbase and mc_gsbase due to the alignment-override
-	 * code in get_fpcontext() that possibly clobbers 12 bytes of
-	 * mcontext after mc_fpstate.
-	 */
 	get_fpcontext(td, &sf.sf_uc.uc_mcontext);
 	fpstate_drop(td);
 	/*
@@ -2526,28 +2519,33 @@ set_fpregs_xmm(sv_87, sv_xmm)
 int
 fill_fpregs(struct thread *td, struct fpreg *fpregs)
 {
+
+	KASSERT(TD_IS_SUSPENDED(td), ("not suspended thread %p", td));
+	npxgetregs(td);
 #ifdef CPU_ENABLE_SSE
-	if (cpu_fxsr) {
-		fill_fpregs_xmm(&td->td_pcb->pcb_save->sv_xmm,
-						(struct save87 *)fpregs);
-		return (0);
-	}
+	if (cpu_fxsr)
+		fill_fpregs_xmm(&td->td_pcb->pcb_user_save.sv_xmm,
+		    (struct save87 *)fpregs);
+	else
 #endif /* CPU_ENABLE_SSE */
-	bcopy(&td->td_pcb->pcb_save->sv_87, fpregs, sizeof *fpregs);
+		bcopy(&td->td_pcb->pcb_user_save.sv_87, fpregs,
+		    sizeof(*fpregs));
 	return (0);
 }
 
 int
 set_fpregs(struct thread *td, struct fpreg *fpregs)
 {
+
 #ifdef CPU_ENABLE_SSE
-	if (cpu_fxsr) {
+	if (cpu_fxsr)
 		set_fpregs_xmm((struct save87 *)fpregs,
-					   &td->td_pcb->pcb_save->sv_xmm);
-		return (0);
-	}
+		    &td->td_pcb->pcb_user_save.sv_xmm);
+	else
 #endif /* CPU_ENABLE_SSE */
-	bcopy(fpregs, &td->td_pcb->pcb_save->sv_87, sizeof *fpregs);
+		bcopy(fpregs, &td->td_pcb->pcb_user_save.sv_87,
+		    sizeof(*fpregs));
+	npxuserinited(td);
 	return (0);
 }
 
@@ -2589,13 +2587,6 @@ get_mcontext(struct thread *td, mcontext
 	mcp->mc_esp = tp->tf_esp;
 	mcp->mc_ss = tp->tf_ss;
 	mcp->mc_len = sizeof(*mcp);
-
-	/*
-	 * The get_fpcontext() call must be placed before assignments
-	 * to mc_fsbase and mc_gsbase due to the alignment-override
-	 * code in get_fpcontext() that possibly clobbers 12 bytes of
-	 * mcontext after mc_fpstate.
-	 */
 	get_fpcontext(td, mcp);
 	sdp = &td->td_pcb->pcb_fsd;
 	mcp->mc_fsbase = sdp->sd_hibase << 24 | sdp->sd_lobase;
@@ -2646,39 +2637,14 @@ set_mcontext(struct thread *td, const mc
 static void
 get_fpcontext(struct thread *td, mcontext_t *mcp)
 {
+
 #ifndef DEV_NPX
 	mcp->mc_fpformat = _MC_FPFMT_NODEV;
 	mcp->mc_ownedfp = _MC_FPOWNED_NONE;
 #else
-	union savefpu *addr;
-
-	/*
-	 * XXX mc_fpstate might be misaligned, since its declaration is not
-	 * unportabilized using __attribute__((aligned(16))) like the
-	 * declaration of struct savemm, and anyway, alignment doesn't work
-	 * for auto variables since we don't use gcc's pessimal stack
-	 * alignment.  Work around this by abusing the spare fields after
-	 * mcp->mc_fpstate.
-	 *
-	 * XXX unpessimize most cases by only aligning when fxsave might be
-	 * called, although this requires knowing too much about
-	 * npxgetregs()'s internals.
-	 */
-	addr = (union savefpu *)&mcp->mc_fpstate;
-	if (td == PCPU_GET(fpcurthread) &&
-#ifdef CPU_ENABLE_SSE
-	    cpu_fxsr &&
-#endif
-	    ((uintptr_t)(void *)addr & 0xF)) {
-		do
-			addr = (void *)((char *)addr + 4);
-		while ((uintptr_t)(void *)addr & 0xF);
-	}
-	mcp->mc_ownedfp = npxgetregs(td, addr);
-	if (addr != (union savefpu *)&mcp->mc_fpstate) {
-		bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate));
-		bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2));
-	}
+	mcp->mc_ownedfp = npxgetregs(td);
+	bcopy(&td->td_pcb->pcb_user_save, &mcp->mc_fpstate,
+	    sizeof(mcp->mc_fpstate));
 	mcp->mc_fpformat = npxformat();
 #endif
 }
@@ -2686,7 +2652,6 @@ get_fpcontext(struct thread *td, mcontex
 static int
 set_fpcontext(struct thread *td, const mcontext_t *mcp)
 {
-	union savefpu *addr;
 
 	if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
 		return (0);
@@ -2698,34 +2663,14 @@ set_fpcontext(struct thread *td, const m
 		fpstate_drop(td);
 	else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
 	    mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
-		/* XXX align as above. */
-		addr = (union savefpu *)&mcp->mc_fpstate;
-		if (td == PCPU_GET(fpcurthread) &&
-#ifdef CPU_ENABLE_SSE
-		    cpu_fxsr &&
-#endif
-		    ((uintptr_t)(void *)addr & 0xF)) {
-			do
-				addr = (void *)((char *)addr + 4);
-			while ((uintptr_t)(void *)addr & 0xF);
-			bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate));
-		}
 #ifdef DEV_NPX
 #ifdef CPU_ENABLE_SSE
 		if (cpu_fxsr)
-			addr->sv_xmm.sv_env.en_mxcsr &= cpu_mxcsr_mask;
+			((union savefpu *)&mcp->mc_fpstate)->sv_xmm.sv_env.
+			    en_mxcsr &= cpu_mxcsr_mask;
 #endif
-		/*
-		 * XXX we violate the dubious requirement that npxsetregs()
-		 * be called with interrupts disabled.
-		 */
-		npxsetregs(td, addr);
+		npxsetregs(td, (union savefpu *)&mcp->mc_fpstate);
 #endif
-		/*
-		 * Don't bother putting things back where they were in the
-		 * misaligned case, since we know that the caller won't use
-		 * them again.
-		 */
 	} else
 		return (EINVAL);
 	return (0);
@@ -2750,7 +2695,8 @@ fpstate_drop(struct thread *td)
 	 * sendsig() is the only caller of npxgetregs()... perhaps we just
 	 * have too many layers.
 	 */
-	curthread->td_pcb->pcb_flags &= ~PCB_NPXINITDONE;
+	curthread->td_pcb->pcb_flags &= ~(PCB_NPXINITDONE |
+	    PCB_NPXUSERINITDONE);
 	critical_exit();
 }
 


More information about the svn-src-all mailing list