From: kettenis Date: Fri, 23 Jul 2010 15:10:16 +0000 (+0000) Subject: Change the strategy for using the FPU in the kernel. The kernel FPU state X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=6714fb1253e3b9da9a46008ab8925bccc2ba5490;p=openbsd Change the strategy for using the FPU in the kernel. The kernel FPU state is now shared with all processes/threads. As a result, you can now use the FPU in true process context (instead of just in kernel threads), but you need to make sure you restore the default FPU state before calling fpu_kernel_exit() if you change rounding mode, precision or exception masks. Lots of discussion with thib@ and Mike Belopuhov. ok thib@, deraadt@ --- diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c index 9da2313356e..832aa859789 100644 --- a/sys/arch/amd64/amd64/fpu.c +++ b/sys/arch/amd64/amd64/fpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fpu.c,v 1.18 2010/07/23 14:56:31 kettenis Exp $ */ +/* $OpenBSD: fpu.c,v 1.19 2010/07/23 15:10:16 kettenis Exp $ */ /* $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */ /*- @@ -210,7 +210,7 @@ fpudna(struct cpu_info *ci) * was using the FPU, save their state. */ if (ci->ci_fpcurproc != NULL && ci->ci_fpcurproc != p) { - fpusave_cpu(ci, 1); + fpusave_cpu(ci, ci->ci_fpcurproc != &proc0); uvmexp.fpswtch++; } splx(s); @@ -332,19 +332,15 @@ fpusave_proc(struct proc *p, int save) void fpu_kernel_enter(void) { - struct cpu_info *oci, *ci = curcpu(); - struct proc *p = curproc; + struct cpu_info *ci = curcpu(); 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. + * Fast path. If the kernel was using the FPU before, there + * is no work to do besides clearing TS. */ - if (ci->ci_fpcurproc == p) { - p->p_addr->u_pcb.pcb_cr0 &= ~CR0_TS; + if (ci->ci_fpcurproc == &proc0) { clts(); return; } @@ -356,22 +352,12 @@ fpu_kernel_enter(void) 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; + ci->ci_fpcurproc = &proc0; splx(s); - /* Disables DNA exceptions */ + /* Disable DNA exceptions */ clts(); /* Initialize the FPU */ @@ -385,9 +371,6 @@ fpu_kernel_enter(void) 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. - */ + /* Enable DNA exceptions */ + stts(); } diff --git a/sys/arch/i386/isa/npx.c b/sys/arch/i386/isa/npx.c index 7bc894beaf6..71c772443c1 100644 --- a/sys/arch/i386/isa/npx.c +++ b/sys/arch/i386/isa/npx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npx.c,v 1.50 2010/07/23 14:56:31 kettenis Exp $ */ +/* $OpenBSD: npx.c,v 1.51 2010/07/23 15:10:16 kettenis Exp $ */ /* $NetBSD: npx.c,v 1.57 1996/05/12 23:12:24 mycroft Exp $ */ #if 0 @@ -631,7 +631,7 @@ npxdna_xmm(struct cpu_info *ci) if (ci->ci_fpcurproc != NULL) { IPRINTF(("%s: fp save %lx\n", ci->ci_dev.dv_xname, (u_long)ci->ci_fpcurproc)); - npxsave_cpu(ci, 1); + npxsave_cpu(ci, ci->ci_fpcurproc != &proc0); } else { clts(); IPRINTF(("%s: fp init\n", ci->ci_dev.dv_xname)); @@ -712,7 +712,7 @@ npxdna_s87(struct cpu_info *ci) if (ci->ci_fpcurproc != NULL) { IPRINTF(("%s: fp save %lx\n", ci->ci_dev.dv_xname, (u_long)ci->ci_fpcurproc)); - npxsave_cpu(ci, 1); + npxsave_cpu(ci, ci->ci_fpcurproc != &proc0); } else { clts(); IPRINTF(("%s: fp init\n", ci->ci_dev.dv_xname)); @@ -870,19 +870,15 @@ npxsave_proc(struct proc *p, int save) void fpu_kernel_enter(void) { - struct cpu_info *oci, *ci = curcpu(); - struct proc *p = curproc; + struct cpu_info *ci = curcpu(); 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. + * Fast path. If the kernel was using the FPU before, there + * is no work to do besides clearing TS. */ - if (ci->ci_fpcurproc == p) { - p->p_addr->u_pcb.pcb_cr0 &= ~CR0_TS; + if (ci->ci_fpcurproc == &proc0) { clts(); return; } @@ -894,22 +890,12 @@ fpu_kernel_enter(void) 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; + ci->ci_fpcurproc = &proc0; splx(s); - /* Disables DNA exceptions */ + /* Disable DNA exceptions */ clts(); /* Initialize the FPU */ @@ -925,9 +911,6 @@ fpu_kernel_enter(void) 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. - */ + /* Enable DNA exceptions */ + stts(); }