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-stable-8
mailing list