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();
 }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to