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