summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThordur I. Bjornsson <thib@cvs.openbsd.org>2010-06-29 21:13:44 +0000
committerThordur I. Bjornsson <thib@cvs.openbsd.org>2010-06-29 21:13:44 +0000
commit84f63f75f1fd1314ab9e0bb3e08c92225d29e9d0 (patch)
tree4687e735aa29c6c7e66837aa7578ee49fd409aa5
parent46f86966950c3d77c793ab239e8db8013ceb8034 (diff)
fpu_kernel_{enter,exit}; Functions to allow the use of
the FPU in the kernel. From Mike Belopuhov; Little bits by myself. Comments/OK kettenis@
-rw-r--r--sys/arch/amd64/amd64/fpu.c65
-rw-r--r--sys/arch/amd64/include/fpu.h5
-rw-r--r--sys/arch/i386/include/npx.h4
-rw-r--r--sys/arch/i386/isa/npx.c67
4 files changed, 136 insertions, 5 deletions
diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c
index e8deedcbba2..51515478f97 100644
--- a/sys/arch/amd64/amd64/fpu.c
+++ b/sys/arch/amd64/amd64/fpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fpu.c,v 1.15 2010/06/07 08:23:58 thib Exp $ */
+/* $OpenBSD: fpu.c,v 1.16 2010/06/29 21:13:43 thib Exp $ */
/* $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*-
@@ -322,3 +322,66 @@ fpusave_proc(struct proc *p, int save)
fpusave_cpu(ci, save);
#endif
}
+
+void
+fpu_kernel_enter(void)
+{
+ struct cpu_info *oci, *ci = curcpu();
+ struct proc *p = curproc;
+ uint32_t cw;
+ int s;
+
+ KASSERT(p != NULL && (p->p_flag & P_SYSTEM));
+
+ /*
+ * Fast path. If we were the last proc on the FPU,
+ * there is no work to do besides clearing TS.
+ */
+ if (ci->ci_fpcurproc == p) {
+ p->p_addr->u_pcb.pcb_cr0 &= ~CR0_TS;
+ clts();
+ return;
+ }
+
+ s = splipi();
+
+ if (ci->ci_fpcurproc != NULL) {
+ fpusave_cpu(ci, 1);
+ uvmexp.fpswtch++;
+ }
+
+ /*
+ * If we were switched away to the other cpu, cleanup
+ * an fpcurproc pointer.
+ */
+ oci = p->p_addr->u_pcb.pcb_fpcpu;
+ if (oci != NULL && oci != ci && oci->ci_fpcurproc == p)
+ oci->ci_fpcurproc = NULL;
+
+ /* Claim the FPU */
+ ci->ci_fpcurproc = p;
+ p->p_addr->u_pcb.pcb_fpcpu = ci;
+ p->p_addr->u_pcb.pcb_cr0 &= ~CR0_TS;
+
+ splx(s);
+
+ /* Disables DNA exceptions */
+ clts();
+
+ /* Initialize the FPU */
+ fninit();
+ cw = __INITIAL_NPXCW__;
+ fldcw(&cw);
+ cw = __INITIAL_MXCSR__;
+ ldmxcsr(&cw);
+}
+
+void
+fpu_kernel_exit(void)
+{
+ /*
+ * Nothing to do.
+ * TS is restored on a context switch automatically
+ * as long as we use hardware assisted task switching.
+ */
+}
diff --git a/sys/arch/amd64/include/fpu.h b/sys/arch/amd64/include/fpu.h
index f7da949e8e0..69f77ee812f 100644
--- a/sys/arch/amd64/include/fpu.h
+++ b/sys/arch/amd64/include/fpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fpu.h,v 1.3 2006/10/01 10:52:10 kettenis Exp $ */
+/* $OpenBSD: fpu.h,v 1.4 2010/06/29 21:13:43 thib Exp $ */
/* $NetBSD: fpu.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */
#ifndef _AMD64_FPU_H_
@@ -51,11 +51,12 @@ struct cpu_info;
void fpuinit(struct cpu_info *);
void fpudrop(void);
-void fpusave(struct proc *);
void fpudiscard(struct proc *);
void fputrap(struct trapframe *);
void fpusave_proc(struct proc *, int);
void fpusave_cpu(struct cpu_info *, int);
+void fpu_kernel_enter(void);
+void fpu_kernel_exit(void);
#endif
diff --git a/sys/arch/i386/include/npx.h b/sys/arch/i386/include/npx.h
index a3b787214b6..f2e63403439 100644
--- a/sys/arch/i386/include/npx.h
+++ b/sys/arch/i386/include/npx.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: npx.h,v 1.11 2009/10/03 21:51:01 kettenis Exp $ */
+/* $OpenBSD: npx.h,v 1.12 2010/06/29 21:13:43 thib Exp $ */
/* $NetBSD: npx.h,v 1.11 1994/10/27 04:16:11 cgd Exp $ */
/*-
@@ -167,5 +167,7 @@ struct trapframe;
void npxinit(struct cpu_info *);
void npxtrap(struct trapframe *);
+void fpu_kernel_enter(void);
+void fpu_kernel_exit(void);
#endif /* !_I386_NPX_H_ */
diff --git a/sys/arch/i386/isa/npx.c b/sys/arch/i386/isa/npx.c
index 49d376ecd31..232886c0788 100644
--- a/sys/arch/i386/isa/npx.c
+++ b/sys/arch/i386/isa/npx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: npx.c,v 1.47 2009/10/28 21:12:18 deraadt Exp $ */
+/* $OpenBSD: npx.c,v 1.48 2010/06/29 21:13:43 thib Exp $ */
/* $NetBSD: npx.c,v 1.57 1996/05/12 23:12:24 mycroft Exp $ */
#if 0
@@ -859,3 +859,68 @@ npxsave_proc(struct proc *p, int save)
npxsave_cpu(ci, save);
#endif
}
+
+void
+fpu_kernel_enter(void)
+{
+ struct cpu_info *oci, *ci = curcpu();
+ struct proc *p = curproc;
+ uint32_t cw;
+ int s;
+
+ KASSERT(p != NULL && (p->p_flag & P_SYSTEM));
+
+ /*
+ * Fast path. If we were the last proc on the FPU,
+ * there is no work to do besides clearing TS.
+ */
+ if (ci->ci_fpcurproc == p) {
+ p->p_addr->u_pcb.pcb_cr0 &= ~CR0_TS;
+ clts();
+ return;
+ }
+
+ s = splipi();
+
+ if (ci->ci_fpcurproc != NULL) {
+ npxsave_cpu(ci, 1);
+ uvmexp.fpswtch++;
+ }
+
+ /*
+ * If we were switched away to the other cpu, cleanup
+ * an fpcurproc pointer.
+ */
+ oci = p->p_addr->u_pcb.pcb_fpcpu;
+ if (oci != NULL && oci != ci && oci->ci_fpcurproc == p)
+ oci->ci_fpcurproc = NULL;
+
+ /* Claim the FPU */
+ ci->ci_fpcurproc = p;
+ p->p_addr->u_pcb.pcb_fpcpu = ci;
+ p->p_addr->u_pcb.pcb_cr0 &= ~CR0_TS;
+
+ splx(s);
+
+ /* Disables DNA exceptions */
+ clts();
+
+ /* Initialize the FPU */
+ fninit();
+ cw = __INITIAL_NPXCW__;
+ fldcw(&cw);
+ if (i386_has_sse || i386_has_sse2) {
+ cw = __INITIAL_MXCSR__;
+ ldmxcsr(&cw);
+ }
+}
+
+void
+fpu_kernel_exit(void)
+{
+ /*
+ * Nothing to do.
+ * TS is restored on a context switch automatically
+ * as long as we use hardware assisted task switching.
+ */
+}