From owner-svn-src-stable@FreeBSD.ORG Fri Dec 3 22:07:07 2010 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9C64E1065672; Fri, 3 Dec 2010 22:07:07 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 87E0B8FC27; Fri, 3 Dec 2010 22:07:07 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oB3M77fW038225; Fri, 3 Dec 2010 22:07:07 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oB3M77JC038214; Fri, 3 Dec 2010 22:07:07 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201012032207.oB3M77JC038214@svn.freebsd.org> From: Konstantin Belousov Date: Fri, 3 Dec 2010 22:07:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r216162 - in stable/8/sys: amd64/amd64 amd64/ia32 amd64/include i386/i386 i386/include i386/isa pc98/pc98 X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 03 Dec 2010 22:07:07 -0000 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(); }