Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/i386 Add support for saving/restoring SSE/SSE2 stat...



details:   https://anonhg.NetBSD.org/src/rev/642417e59ec2
branches:  trunk
changeset: 513516:642417e59ec2
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Thu Aug 02 21:04:43 2001 +0000

description:
Add support for saving/restoring SSE/SSE2 state using FXSAVE/FXRSTOR.

Reviewed by Frank.

diffstat:

 sys/arch/i386/i386/locore.s          |    4 +-
 sys/arch/i386/i386/machdep.c         |   27 +++++++-
 sys/arch/i386/i386/process_machdep.c |  122 +++++++++++++++++++++++++++++-----
 sys/arch/i386/include/cpu.h          |    4 +-
 sys/arch/i386/include/npx.h          |   63 +++++++++++++++--
 sys/arch/i386/include/pcb.h          |    5 +-
 sys/arch/i386/isa/npx.c              |  123 ++++++++++++++++++++++++++++++----
 7 files changed, 299 insertions(+), 49 deletions(-)

diffs (truncated from 616 to 300 lines):

diff -r 141f5888a70c -r 642417e59ec2 sys/arch/i386/i386/locore.s
--- a/sys/arch/i386/i386/locore.s       Thu Aug 02 20:24:03 2001 +0000
+++ b/sys/arch/i386/i386/locore.s       Thu Aug 02 21:04:43 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.s,v 1.245 2001/07/31 22:52:44 jdolecek Exp $    */
+/*     $NetBSD: locore.s,v 1.246 2001/08/02 21:04:43 thorpej Exp $     */
 
 /*-
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -2141,7 +2141,7 @@
        pushl   $T_DNA
        INTRENTRY
        pushl   _C_LABEL(curproc)
-       call    _C_LABEL(npxdna)
+       call    *_C_LABEL(npxdna_func)
        addl    $4,%esp
        testl   %eax,%eax
        jz      calltrap
diff -r 141f5888a70c -r 642417e59ec2 sys/arch/i386/i386/machdep.c
--- a/sys/arch/i386/i386/machdep.c      Thu Aug 02 20:24:03 2001 +0000
+++ b/sys/arch/i386/i386/machdep.c      Thu Aug 02 21:04:43 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.449 2001/08/01 19:50:48 thorpej Exp $    */
+/*     $NetBSD: machdep.c,v 1.450 2001/08/02 21:04:43 thorpej Exp $    */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc.
@@ -200,6 +200,8 @@
 int    i386_fpu_exception;
 int    i386_fpu_fdivbug;
 
+int    cpu_use_fxsave;
+
 #define        CPUID2MODEL(cpuid)      (((cpuid) >> 4) & 15)
 
 vaddr_t        msgbuf_vaddr;
@@ -1515,6 +1517,17 @@
                cpu_tsc_freq = (rdtsc() - last_tsc) * 10;
        }
 #endif
+
+#if defined(I686_CPU)
+       /*
+        * If we have FXSAVE/FXRESTOR, use them.
+        */
+       if (cpu_feature & CPUID_FXSR) {
+               cpu_use_fxsave = 1;
+               lcr4(rcr4() | CR4_OSFXSR);
+       } else
+               cpu_use_fxsave = 0;
+#endif /* I686_CPU */
 }
 
 /*  
@@ -2132,7 +2145,10 @@
 
        p->p_md.md_flags &= ~MDP_USEDFPU;
        pcb->pcb_flags = 0;
-       pcb->pcb_savefpu.sv_env.en_cw = __NetBSD_NPXCW__;
+       if (cpu_use_fxsave)
+               pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __NetBSD_NPXCW__;
+       else
+               pcb->pcb_savefpu.sv_87.sv_env.en_cw = __NetBSD_NPXCW__;
 
        tf = p->p_md.md_regs;
        tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);
@@ -2333,6 +2349,13 @@
                panic("init386: PAGE_SIZE != NBPG");
 
        /*
+        * Saving SSE registers won't work if the save area isn't
+        * 16-byte aligned.
+        */
+       if (offsetof(struct user, u_pcb.pcb_savefpu) & 0xf)
+               panic("init386: pcb_savefpu not 16-byte aligned");
+
+       /*
         * Start with 2 color bins -- this is just a guess to get us
         * started.  We'll recolor when we determine the largest cache
         * sizes on the system.
diff -r 141f5888a70c -r 642417e59ec2 sys/arch/i386/i386/process_machdep.c
--- a/sys/arch/i386/i386/process_machdep.c      Thu Aug 02 20:24:03 2001 +0000
+++ b/sys/arch/i386/i386/process_machdep.c      Thu Aug 02 21:04:43 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: process_machdep.c,v 1.34 2001/06/18 03:33:59 sommerfeld Exp $  */
+/*     $NetBSD: process_machdep.c,v 1.35 2001/08/02 21:04:44 thorpej Exp $     */
 
 /*-
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -80,25 +80,88 @@
 #include <machine/vm86.h>
 #endif
 
-static __inline struct trapframe *process_frame __P((struct proc *));
-static __inline struct save87 *process_fpframe __P((struct proc *));
-
 static __inline struct trapframe *
-process_frame(p)
-       struct proc *p;
+process_frame(struct proc *p)
 {
 
        return (p->p_md.md_regs);
 }
 
-static __inline struct save87 *
-process_fpframe(p)
-       struct proc *p;
+static __inline union savefpu *
+process_fpframe(struct proc *p)
 {
 
        return (&p->p_addr->u_pcb.pcb_savefpu);
 }
 
+void
+process_xmm_to_s87(const struct savexmm *sxmm, struct save87 *s87)
+{
+       int i;
+
+       /* FPU control/status */
+       s87->sv_env.en_cw = sxmm->sv_env.en_cw;
+       s87->sv_env.en_sw = sxmm->sv_env.en_sw;
+       /* tag word handled below */
+       s87->sv_env.en_fip = sxmm->sv_env.en_fip;
+       s87->sv_env.en_fcs = sxmm->sv_env.en_fcs;
+       s87->sv_env.en_opcode = sxmm->sv_env.en_opcode;
+       s87->sv_env.en_foo = sxmm->sv_env.en_foo;
+       s87->sv_env.en_fos = sxmm->sv_env.en_fos;
+
+       /* Tag word and registers. */
+       for (i = 0; i < 8; i++) {
+               if (sxmm->sv_env.en_tw & (1U << i))
+                       s87->sv_env.en_tw &= ~(3U << (i * 2));
+               else
+                       s87->sv_env.en_tw |= (3U << (i * 2));
+
+               if (sxmm->sv_ex_tw & (1U << i))
+                       s87->sv_ex_tw &= ~(3U << (i * 2));
+               else
+                       s87->sv_ex_tw |= (3U << (i * 2));
+
+               memcpy(&s87->sv_ac[i].fp_bytes, &sxmm->sv_ac[i].fp_bytes,
+                   sizeof(s87->sv_ac[i].fp_bytes));
+       }
+
+       s87->sv_ex_sw = sxmm->sv_ex_sw;
+}
+
+void
+process_s87_to_xmm(const struct save87 *s87, struct savexmm *sxmm)
+{
+       int i;
+
+       /* FPU control/status */
+       sxmm->sv_env.en_cw = s87->sv_env.en_cw;
+       sxmm->sv_env.en_sw = s87->sv_env.en_sw;
+       /* tag word handled below */
+       sxmm->sv_env.en_fip = s87->sv_env.en_fip;
+       sxmm->sv_env.en_fcs = s87->sv_env.en_fcs;
+       sxmm->sv_env.en_opcode = s87->sv_env.en_opcode;
+       sxmm->sv_env.en_foo = s87->sv_env.en_foo;
+       sxmm->sv_env.en_fos = s87->sv_env.en_fos;
+
+       /* Tag word and registers. */
+       for (i = 0; i < 8; i++) {
+               if (((s87->sv_env.en_tw >> (i * 2)) & 3) == 3)
+                       sxmm->sv_env.en_tw &= ~(1U << i);
+               else
+                       sxmm->sv_env.en_tw |= (1U << i);
+
+               if (((s87->sv_ex_tw >> (i * 2)) & 3) == 3)
+                       sxmm->sv_ex_tw &= ~(1U << i);
+               else
+                       sxmm->sv_ex_tw |= (1U << i);
+
+               memcpy(&sxmm->sv_ac[i].fp_bytes, &s87->sv_ac[i].fp_bytes,
+                   sizeof(sxmm->sv_ac[i].fp_bytes));
+       }
+
+       sxmm->sv_ex_sw = s87->sv_ex_sw;
+}
+
 int
 process_read_regs(p, regs)
        struct proc *p;
@@ -142,7 +205,7 @@
        struct proc *p;
        struct fpreg *regs;
 {
-       struct save87 *frame = process_fpframe(p);
+       union savefpu *frame = process_fpframe(p);
 
        if (p->p_md.md_flags & MDP_USEDFPU) {
 #if NNPX > 0
@@ -159,15 +222,31 @@
                 * The initial control word was already set by setregs(), so
                 * save it temporarily.
                 */
-               cw = frame->sv_env.en_cw;
-               memset(frame, 0, sizeof(*regs));
-               frame->sv_env.en_cw = cw;
-               frame->sv_env.en_sw = 0x0000;
-               frame->sv_env.en_tw = 0xffff;
+               if (cpu_use_fxsave) {
+                       cw = frame->sv_xmm.sv_env.en_cw;
+                       /* XXX Don't zero XMM regs? */
+                       memset(&frame->sv_xmm, 0, sizeof(frame->sv_xmm));
+                       frame->sv_xmm.sv_env.en_cw = cw;
+                       frame->sv_xmm.sv_env.en_sw = 0x0000;
+                       frame->sv_xmm.sv_env.en_tw = 0x00;
+               } else {
+                       cw = frame->sv_87.sv_env.en_cw;
+                       memset(&frame->sv_87, 0, sizeof(frame->sv_87));
+                       frame->sv_87.sv_env.en_cw = cw;
+                       frame->sv_87.sv_env.en_sw = 0x0000;
+                       frame->sv_87.sv_env.en_tw = 0xffff;
+               }
                p->p_md.md_flags |= MDP_USEDFPU;
        }
 
-       memcpy(regs, frame, sizeof(*regs));
+       if (cpu_use_fxsave) {
+               struct save87 s87;
+
+               /* XXX Yuck */
+               process_xmm_to_s87(&frame->sv_xmm, &s87);
+               memcpy(regs, &s87, sizeof(*regs));
+       } else
+               memcpy(regs, &frame->sv_87, sizeof(*regs));
        return (0);
 }
 
@@ -228,7 +307,7 @@
        struct proc *p;
        struct fpreg *regs;
 {
-       struct save87 *frame = process_fpframe(p);
+       union savefpu *frame = process_fpframe(p);
 
        if (p->p_md.md_flags & MDP_USEDFPU) {
 #if NNPX > 0
@@ -241,7 +320,14 @@
                p->p_md.md_flags |= MDP_USEDFPU;
        }
 
-       memcpy(frame, regs, sizeof(*regs));
+       if (cpu_use_fxsave) {
+               struct save87 s87;
+
+               /* XXX Yuck. */
+               memcpy(&s87, regs, sizeof(*regs));
+               process_s87_to_xmm(&s87, &frame->sv_xmm);
+       } else
+               memcpy(&frame->sv_87, regs, sizeof(*regs));
        return (0);
 }
 
diff -r 141f5888a70c -r 642417e59ec2 sys/arch/i386/include/cpu.h
--- a/sys/arch/i386/include/cpu.h       Thu Aug 02 20:24:03 2001 +0000
+++ b/sys/arch/i386/include/cpu.h       Thu Aug 02 21:04:43 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cpu.h,v 1.73 2001/08/01 19:50:49 thorpej Exp $ */
+/*     $NetBSD: cpu.h,v 1.74 2001/08/02 21:04:44 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -181,6 +181,8 @@
 extern const struct cpu_nocpuid_nameclass i386_nocpuid_cpus[];
 extern const struct cpu_cpuid_nameclass i386_cpuid_cpus[];
 
+extern int cpu_use_fxsave;
+
 /* machdep.c */
 void   delay __P((int));
 void   dumpconf __P((void));
diff -r 141f5888a70c -r 642417e59ec2 sys/arch/i386/include/npx.h
--- a/sys/arch/i386/include/npx.h       Thu Aug 02 20:24:03 2001 +0000
+++ b/sys/arch/i386/include/npx.h       Thu Aug 02 21:04:43 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npx.h,v 1.14 1999/01/26 14:25:02 christos Exp $        */
+/*     $NetBSD: npx.h,v 1.15 2001/08/02 21:04:45 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -47,7 +47,7 @@
 #define        _I386_NPX_H_
 
 /* Environment information of floating point unit */
-struct env87 {
+struct env87 {
        long    en_cw;          /* control word (16bits) */
        long    en_sw;          /* status word (16bits) */
        long    en_tw;          /* tag word (16bits) */
@@ -59,7 +59,7 @@
 };
 
 /* Contents of each floating point accumulator */
-struct fpacc87 {
+struct fpacc87 {



Home | Main Index | Thread Index | Old Index