diff options
author | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2010-06-29 21:13:44 +0000 |
---|---|---|
committer | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2010-06-29 21:13:44 +0000 |
commit | 84f63f75f1fd1314ab9e0bb3e08c92225d29e9d0 (patch) | |
tree | 4687e735aa29c6c7e66837aa7578ee49fd409aa5 | |
parent | 46f86966950c3d77c793ab239e8db8013ceb8034 (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.c | 65 | ||||
-rw-r--r-- | sys/arch/amd64/include/fpu.h | 5 | ||||
-rw-r--r-- | sys/arch/i386/include/npx.h | 4 | ||||
-rw-r--r-- | sys/arch/i386/isa/npx.c | 67 |
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. + */ +} |