Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Load and save the fpu registers (for copies to/from...



details:   https://anonhg.NetBSD.org/src/rev/cd57ceaac12f
branches:  trunk
changeset: 326743:cd57ceaac12f
user:      dsl <dsl%NetBSD.org@localhost>
date:      Sat Feb 15 22:20:41 2014 +0000

description:
Load and save the fpu registers (for copies to/from userspace) using
  helper functions in arch/x86/x86/fpu.c
They (hopefully) ensure that we write to the entire buffer and don't load
  values that might cause faults in kernel.
Also zero out the 'pad' field of the i386 mcontext fp area that I think
  once contained the registers of any Weitek fpu.
  Dunno why it wasn't pasrt of the union.
Some of these copies could be removed if the code directly copied the save
  area to/from userspace addresses.

diffstat:

 sys/arch/amd64/amd64/machdep.c          |  20 ++----
 sys/arch/amd64/amd64/netbsd32_machdep.c |  25 +++-----
 sys/arch/amd64/amd64/process_machdep.c  |  24 ++------
 sys/arch/amd64/include/mcontext.h       |  12 +--
 sys/arch/i386/i386/machdep.c            |  66 ++++++-----------------
 sys/arch/i386/i386/process_machdep.c    |  54 +++++--------------
 sys/arch/i386/include/mcontext.h        |   4 +-
 sys/arch/x86/include/fpu.h              |  10 +++-
 sys/arch/x86/x86/convert_xmm_s87.c      |   9 +-
 sys/arch/x86/x86/fpu.c                  |  90 ++++++++++++++++++++++++++++++--
 10 files changed, 158 insertions(+), 156 deletions(-)

diffs (truncated from 644 to 300 lines):

diff -r d2e433f303ee -r cd57ceaac12f sys/arch/amd64/amd64/machdep.c
--- a/sys/arch/amd64/amd64/machdep.c    Sat Feb 15 19:45:43 2014 +0000
+++ b/sys/arch/amd64/amd64/machdep.c    Sat Feb 15 22:20:41 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.204 2014/02/15 10:11:14 dsl Exp $        */
+/*     $NetBSD: machdep.c,v 1.205 2014/02/15 22:20:41 dsl Exp $        */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -111,7 +111,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.204 2014/02/15 10:11:14 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.205 2014/02/15 22:20:41 dsl Exp $");
 
 /* #define XENDEBUG_LOW  */
 
@@ -1896,7 +1896,6 @@
 cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
 {
        const struct trapframe *tf = l->l_md.md_regs;
-       struct pcb *pcb;
        __greg_t ras_rip;
 
        /* Copy general registers member by member */
@@ -1913,10 +1912,7 @@
        mcp->_mc_tlsbase = (uintptr_t)l->l_private;;
        *flags |= _UC_TLSBASE;
 
-       pcb = lwp_getpcb(l);
-
-       fpusave_lwp(l, true);
-       memcpy(mcp->__fpregs, &pcb->pcb_savefpu.sv_xmm, sizeof (mcp->__fpregs));
+       process_read_fpregs_xmm(l, (struct fxsave *)&mcp->__fpregs);
        *flags |= _UC_FPU;
 }
 
@@ -1925,12 +1921,13 @@
 {
        struct trapframe *tf = l->l_md.md_regs;
        const __greg_t *gr = mcp->__gregs;
-       struct pcb *pcb = lwp_getpcb(l);
        struct proc *p = l->l_proc;
        int error;
        int err, trapno;
        int64_t rflags;
 
+       CTASSERT(sizeof (mcontext_t) == 26 * 8 + 8 + 512);
+
        if ((flags & _UC_CPU) != 0) {
                error = cpu_mcontext_validate(l, mcp);
                if (error != 0)
@@ -1966,11 +1963,8 @@
                l->l_md.md_flags |= MDL_IRET;
        }
 
-       if ((flags & _UC_FPU) != 0) {
-               fpusave_lwp(l, false);
-               memcpy(&pcb->pcb_savefpu.sv_xmm, mcp->__fpregs,
-                   sizeof (mcp->__fpregs));
-       }
+       if ((flags & _UC_FPU) != 0)
+               process_write_fpregs_xmm(l, (const struct fxsave *)&mcp->__fpregs);
 
        if ((flags & _UC_TLSBASE) != 0)
                lwp_setprivate(l, (void *)(uintptr_t)mcp->_mc_tlsbase);
diff -r d2e433f303ee -r cd57ceaac12f sys/arch/amd64/amd64/netbsd32_machdep.c
--- a/sys/arch/amd64/amd64/netbsd32_machdep.c   Sat Feb 15 19:45:43 2014 +0000
+++ b/sys/arch/amd64/amd64/netbsd32_machdep.c   Sat Feb 15 22:20:41 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: netbsd32_machdep.c,v 1.91 2014/02/15 10:11:14 dsl Exp $        */
+/*     $NetBSD: netbsd32_machdep.c,v 1.92 2014/02/15 22:20:41 dsl Exp $        */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.91 2014/02/15 10:11:14 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.92 2014/02/15 22:20:41 dsl Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -806,14 +806,9 @@
 
        /* Restore floating point register context, if any. */
        if ((flags & _UC_FPU) != 0) {
-               struct pcb *pcb = lwp_getpcb(l);
-
-               /*
-                * If we were using the FPU, forget that we were.
-                */
-               fpusave_lwp(l, false);
-               memcpy(&pcb->pcb_savefpu.sv_xmm, &mcp->__fpregs,
-                   sizeof (pcb->pcb_savefpu.sv_xmm));
+               /* Assume fxsave context */
+               process_write_fpregs_xmm(l, (const struct fxsave *)
+                   &mcp->__fpregs.__fp_reg_set.__fp_xmm_state);
        }
 
        mutex_enter(p->p_lock);
@@ -832,7 +827,6 @@
        const struct trapframe *tf = l->l_md.md_regs;
        __greg32_t *gr = mcp->__gregs;
        __greg32_t ras_eip;
-       struct pcb *pcb;
 
        /* Save register context. */
        gr[_REG32_GS]  = tf->tf_gs;
@@ -865,11 +859,10 @@
        *flags |= _UC_TLSBASE;
 
        /* Save floating point register context. */
-       fpusave_lwp(l, true);
-       pcb = lwp_getpcb(l);
-       memcpy(&mcp->__fpregs, &pcb->pcb_savefpu.sv_xmm,
-           sizeof (pcb->pcb_savefpu.sv_xmm));
-       *flags |= _UC_FPU;
+       process_read_fpregs_xmm(l, (struct fxsave *)
+           &mcp->__fpregs.__fp_reg_set.__fp_xmm_state);
+       memset(&mcp->__fpregs.__fp_pad, 0, sizeof mcp->__fpregs.__fp_pad);
+       *flags |= _UC_FXSAVE | _UC_FPU;
 }
 
 void
diff -r d2e433f303ee -r cd57ceaac12f sys/arch/amd64/amd64/process_machdep.c
--- a/sys/arch/amd64/amd64/process_machdep.c    Sat Feb 15 19:45:43 2014 +0000
+++ b/sys/arch/amd64/amd64/process_machdep.c    Sat Feb 15 22:20:41 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: process_machdep.c,v 1.28 2014/02/15 10:11:14 dsl Exp $ */
+/*     $NetBSD: process_machdep.c,v 1.29 2014/02/15 22:20:41 dsl Exp $ */
 
 /*-
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -53,7 +53,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.28 2014/02/15 10:11:14 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.29 2014/02/15 22:20:41 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -69,7 +69,6 @@
 #include <x86/fpu.h>
 
 static inline struct trapframe *process_frame(struct lwp *);
-static inline struct fxsave *process_fpframe(struct lwp *);
 #if 0
 static inline int verr_gdt(struct pmap *, int sel);
 static inline int verr_ldt(struct pmap *, int sel);
@@ -82,14 +81,6 @@
        return (l->l_md.md_regs);
 }
 
-static inline struct fxsave *
-process_fpframe(struct lwp *l)
-{
-       struct pcb *pcb = lwp_getpcb(l);
-
-       return &pcb->pcb_savefpu.sv_xmm;
-}
-
 int
 process_read_regs(struct lwp *l, struct reg *regs)
 {
@@ -106,10 +97,9 @@
 process_read_fpregs(struct lwp *l, struct fpreg *regs, size_t *sz)
 {
 
-       fpusave_lwp(l, true);
+       process_read_fpregs_xmm(l, &regs->fxstate);
 
-       regs->fxstate = *process_fpframe(l);
-       return (0);
+       return 0;
 }
 
 int
@@ -139,10 +129,8 @@
 process_write_fpregs(struct lwp *l, const struct fpreg *regs, size_t sz)
 {
 
-       fpusave_lwp(l, false);
-
-       memcpy(process_fpframe(l), &regs->fxstate, sizeof(*regs));
-       return (0);
+       process_write_fpregs_xmm(l, &regs->fxstate);
+       return 0;
 }
 
 int
diff -r d2e433f303ee -r cd57ceaac12f sys/arch/amd64/include/mcontext.h
--- a/sys/arch/amd64/include/mcontext.h Sat Feb 15 19:45:43 2014 +0000
+++ b/sys/arch/amd64/include/mcontext.h Sat Feb 15 22:20:41 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mcontext.h,v 1.16 2012/12/15 22:39:04 dsl Exp $        */
+/*     $NetBSD: mcontext.h,v 1.17 2014/02/15 22:20:41 dsl Exp $        */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -131,18 +131,12 @@
        union {
                struct {
                        int     __fp_state[27]; /* Environment and registers */
-                       int     __fp_status;    /* Software status word */
                } __fpchip_state;
                struct {
-                       char    __fp_emul[246];
-                       char    __fp_epad[2];
-               } __fp_emul_space;
-               struct {
                        char    __fp_xmm[512];
                } __fp_xmm_state;
-               int     __fp_fpregs[128];
        } __fp_reg_set;
-       int     __fp_wregs[33];                 /* Weitek? */
+       int     __fp_pad[33];                   /* Historic padding */
 } __fpregset32_t;
 
 typedef struct {
@@ -151,6 +145,8 @@
        uint32_t        _mc_tlsbase;
 } mcontext32_t;
 
+#define _UC_FXSAVE       0x20    /* FP state is in FXSAVE format in XMM space */
+
 #define        _UC_MACHINE32_PAD       4
 #define        __UCONTEXT32_SIZE       776
 
diff -r d2e433f303ee -r cd57ceaac12f sys/arch/i386/i386/machdep.c
--- a/sys/arch/i386/i386/machdep.c      Sat Feb 15 19:45:43 2014 +0000
+++ b/sys/arch/i386/i386/machdep.c      Sat Feb 15 22:20:41 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.747 2014/02/15 10:11:15 dsl Exp $        */
+/*     $NetBSD: machdep.c,v 1.748 2014/02/15 22:20:41 dsl Exp $        */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.747 2014/02/15 10:11:15 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.748 2014/02/15 22:20:41 dsl Exp $");
 
 #include "opt_beep.h"
 #include "opt_compat_ibcs2.h"
@@ -1621,33 +1621,21 @@
        mcp->_mc_tlsbase = (uintptr_t)l->l_private;
        *flags |= _UC_TLSBASE;
 
-       /* Save floating point register context. */
-       pcb = lwp_getpcb(l);
-
        /*
-        * If this process is the current FP owner, dump its
-        * context to the PCB first.
+        * Save floating point register context.
+        *
+        * If the cpu doesn't support fxsave we must still write to
+        * the entire 512 byte area - otherwise we leak kernel memory
+        * contents to userspace.
+        * It wouldn't matter if we were doing the copyout here.
+        * So we might as well convert to fxsave format.
         */
-       fpusave_lwp(l, true);
-       if (i386_use_fxsave) {
-               __CTASSERT(sizeof pcb->pcb_savefpu.sv_xmm ==
-                   sizeof mcp->__fpregs.__fp_reg_set.__fp_xmm_state);
-               memcpy(&mcp->__fpregs.__fp_reg_set.__fp_xmm_state,
-                   &pcb->pcb_savefpu.sv_xmm,
-                   sizeof (mcp->__fpregs.__fp_reg_set.__fp_xmm_state));
-               *flags |= _UC_FXSAVE;
-       } else {
-               __CTASSERT(sizeof pcb->pcb_savefpu.sv_87 ==
-                   sizeof mcp->__fpregs.__fp_reg_set.__fpchip_state);
-               memcpy(&mcp->__fpregs.__fp_reg_set.__fpchip_state,
-                   &pcb->pcb_savefpu.sv_87,
-                   sizeof (mcp->__fpregs.__fp_reg_set.__fpchip_state));
-       }
-#if 0
-       /* Apparently nothing ever touches this. */
-       ucp->mcp.mc_fp.fp_emcsts = pcb->pcb_saveemc;
-#endif
-       *flags |= _UC_FPU;
+       __CTASSERT(sizeof pcb->pcb_savefpu.sv_xmm ==
+           sizeof mcp->__fpregs.__fp_reg_set.__fp_xmm_state);
+       process_read_fpregs_xmm(l, (struct fxsave *)
+           &mcp->__fpregs.__fp_reg_set.__fp_xmm_state);
+       memset(&mcp->__fpregs.__fp_pad, 0, sizeof mcp->__fpregs.__fp_pad);
+       *flags |= _UC_FXSAVE | _UC_FPU;
 }
 
 int
@@ -1730,28 +1718,12 @@
                __CTASSERT(sizeof pcb->pcb_savefpu.sv_87 ==
                    sizeof mcp->__fpregs.__fp_reg_set.__fpchip_state);



Home | Main Index | Thread Index | Old Index