Source-Changes-HG archive

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

[src/trunk]: src/sys Use the MI "pcu" framework for bookkeeping of npx/fpu st...



details:   https://anonhg.NetBSD.org/src/rev/1d3b737f5dae
branches:  trunk
changeset: 790826:1d3b737f5dae
user:      drochner <drochner%NetBSD.org@localhost>
date:      Wed Oct 23 20:18:50 2013 +0000

description:
Use the MI "pcu" framework for bookkeeping of npx/fpu states on x86.
This reduces the amount of MD code enormously, and makes it easier
to implement support for newer CPU features which require more fpu
state, or for fpu usage by the kernel.
For access to FPU state across CPUs, an xcall kthread is used now
rather than a dedicated IPI.
No user visible changes intended.

diffstat:

 sys/arch/amd64/amd64/fpu.c                      |  204 +++++----------------
 sys/arch/amd64/amd64/genassym.cf                |    4 +-
 sys/arch/amd64/amd64/locore.S                   |   15 +-
 sys/arch/amd64/amd64/machdep.c                  |   46 +---
 sys/arch/amd64/amd64/netbsd32_machdep.c         |   34 +--
 sys/arch/amd64/amd64/process_machdep.c          |   19 +-
 sys/arch/amd64/include/fpu.h                    |    7 +-
 sys/arch/amd64/include/pcb.h                    |    3 +-
 sys/arch/amd64/include/proc.h                   |    3 +-
 sys/arch/amd64/include/types.h                  |    8 +-
 sys/arch/i386/i386/compat_16_machdep.c          |    6 +-
 sys/arch/i386/i386/genassym.cf                  |    4 +-
 sys/arch/i386/i386/locore.S                     |   17 +-
 sys/arch/i386/i386/machdep.c                    |   49 +---
 sys/arch/i386/i386/process_machdep.c            |   43 +---
 sys/arch/i386/include/pcb.h                     |    3 +-
 sys/arch/i386/include/proc.h                    |    3 +-
 sys/arch/i386/include/types.h                   |    8 +-
 sys/arch/i386/isa/npx.c                         |  222 +++++++----------------
 sys/arch/x86/acpi/acpi_wakeup.c                 |   12 +-
 sys/arch/x86/include/cpu.h                      |    8 +-
 sys/arch/x86/include/intrdefs.h                 |    4 +-
 sys/arch/x86/x86/cpu.c                          |   27 +--
 sys/arch/x86/x86/ipi.c                          |   29 +--
 sys/arch/x86/x86/vm_machdep.c                   |   30 +--
 sys/arch/xen/x86/cpu.c                          |   25 +--
 sys/arch/xen/x86/xen_ipi.c                      |   27 +--
 sys/compat/linux/arch/amd64/linux_machdep.c     |   13 +-
 sys/compat/linux/arch/i386/linux_machdep.c      |    6 +-
 sys/compat/linux32/arch/amd64/linux32_machdep.c |   12 +-
 30 files changed, 257 insertions(+), 634 deletions(-)

diffs (truncated from 1967 to 300 lines):

diff -r 25386ff93b58 -r 1d3b737f5dae sys/arch/amd64/amd64/fpu.c
--- a/sys/arch/amd64/amd64/fpu.c        Wed Oct 23 18:57:40 2013 +0000
+++ b/sys/arch/amd64/amd64/fpu.c        Wed Oct 23 20:18:50 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu.c,v 1.40 2012/12/31 16:20:17 dsl Exp $     */
+/*     $NetBSD: fpu.c,v 1.41 2013/10/23 20:18:50 drochner Exp $        */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.  All
@@ -100,7 +100,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.40 2012/12/31 16:20:17 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.41 2013/10/23 20:18:50 drochner Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -178,7 +178,7 @@
 void
 fputrap(struct trapframe *frame)
 {
-       register struct lwp *l = curcpu()->ci_fpcurlwp;
+       register struct lwp *l = curlwp;
        struct pcb *pcb = lwp_getpcb(l);
        struct savefpu *sfp = &pcb->pcb_savefpu;
        uint32_t mxcsr, statbits;
@@ -188,11 +188,6 @@
        KPREEMPT_DISABLE(l);
        x86_enable_intr();
 
-       /*
-        * At this point, fpcurlwp should be curlwp.  If it wasn't, the TS bit
-        * should be set, and we should have gotten a DNA exception.
-        */
-       KASSERT(l == curlwp);
        fxsave(sfp);
        pcb->pcb_savefpu_i387.fp_ex_tw = sfp->fp_fxsave.fx_ftw;
        pcb->pcb_savefpu_i387.fp_ex_sw = sfp->fp_fxsave.fx_fsw;
@@ -249,70 +244,35 @@
  * Otherwise, we save the previous state, if necessary, and restore
  * our last saved state.
  */
+
+extern const pcu_ops_t fpu_ops;
+
 void
 fpudna(struct cpu_info *ci)
 {
+
+       pcu_load(&fpu_ops);
+}
+
+
+static void
+fpu_state_load(struct lwp *l, u_int flags)
+{
        uint16_t cw;
        uint32_t mxcsr;
-       struct lwp *l, *fl;
-       struct pcb *pcb;
-       int s;
-
-       if (ci->ci_fpsaving) {
-               /* Recursive trap. */
-               x86_enable_intr();
-               return;
-       }
-
-       /* Lock out IPIs and disable preemption. */
-       s = splhigh();
-       x86_enable_intr();
+       struct pcb * const pcb = lwp_getpcb(l);
 
-       /* Save state on current CPU. */
-       l = ci->ci_curlwp;
-       pcb = lwp_getpcb(l);
-       fl = ci->ci_fpcurlwp;
-       if (fl != NULL) {
-               /*
-                * It seems we can get here on Xen even if we didn't
-                * switch lwp.  In this case do nothing
-                */
-               if (fl == l) {
-                       KASSERT(pcb->pcb_fpcpu == ci);
-                       clts();
-                       splx(s);
-                       return;
-               }
-               KASSERT(fl != l);
-               fpusave_cpu(true);
-               KASSERT(ci->ci_fpcurlwp == NULL);
-       }
+       clts();
+       pcb->pcb_cr0 &= ~CR0_TS;
+       if (!(flags & PCU_RELOAD))
+               return;
 
-       /* Save our state if on a remote CPU. */
-       if (pcb->pcb_fpcpu != NULL) {
-               /* Explicitly disable preemption before dropping spl. */
-               KPREEMPT_DISABLE(l);
-               splx(s);
-               fpusave_lwp(l, true);
-               KASSERT(pcb->pcb_fpcpu == NULL);
-               s = splhigh();
-               KPREEMPT_ENABLE(l);
-       }
-
-       /*
-        * Restore state on this CPU, or initialize.  Ensure that
-        * the entire update is atomic with respect to FPU-sync IPIs.
-        */
-       clts();
-       ci->ci_fpcurlwp = l;
-       pcb->pcb_fpcpu = ci;
-       if ((l->l_md.md_flags & MDL_USEDFPU) == 0) {
+       if (!(flags & PCU_LOADED)) {
                fninit();
                cw = pcb->pcb_savefpu.fp_fxsave.fx_fcw;
                fldcw(&cw);
                mxcsr = pcb->pcb_savefpu.fp_fxsave.fx_mxcsr;
                x86_ldmxcsr(&mxcsr);
-               l->l_md.md_flags |= MDL_USEDFPU;
        } else {
                /*
                 * AMD FPU's do not restore FIP, FDP, and FOP on fxrstor,
@@ -336,97 +296,43 @@
                fldummy(&zero);
                fxrstor(&pcb->pcb_savefpu);
        }
-
-       KASSERT(ci == curcpu());
-       splx(s);
-}
-
-/*
- * Save current CPU's FPU state.  Must be called at IPL_HIGH.
- */
-void
-fpusave_cpu(bool save)
-{
-       struct cpu_info *ci;
-       struct pcb *pcb;
-       struct lwp *l;
-
-       KASSERT(curcpu()->ci_ilevel == IPL_HIGH);
-
-       ci = curcpu();
-       l = ci->ci_fpcurlwp;
-       if (l == NULL) {
-               return;
-       }
-       pcb = lwp_getpcb(l);
-
-       if (save) {
-                /*
-                 * Set ci->ci_fpsaving, so that any pending exception will
-                 * be thrown away.  It will be caught again if/when the
-                 * FPU state is restored.
-                 */
-               KASSERT(ci->ci_fpsaving == 0);
-               clts();
-               ci->ci_fpsaving = 1;
-               fxsave(&pcb->pcb_savefpu);
-               ci->ci_fpsaving = 0;
-       }
-
-       stts();
-       pcb->pcb_fpcpu = NULL;
-       ci->ci_fpcurlwp = NULL;
 }
 
-/*
- * Save l's FPU state, which may be on this processor or another processor.
- * It may take some time, so we avoid disabling preemption where possible.
- * Caller must know that the target LWP is stopped, otherwise this routine
- * may race against it.
- */
-void
-fpusave_lwp(struct lwp *l, bool save)
+static void
+fpu_state_save(struct lwp *l, u_int flags)
 {
-       struct cpu_info *oci;
-       struct pcb *pcb;
-       int s, spins, ticks;
+       struct cpu_info *ci;
+       struct pcb * const pcb = lwp_getpcb(l);
+
+       ci = curcpu();
+       /*
+        * Set ci->ci_fpsaving, so that any pending exception will
+        * be thrown away.  It will be caught again if/when the
+        * FPU state is restored.
+        */
+       KASSERT(ci->ci_fpsaving == 0);
+       clts();
+       ci->ci_fpsaving = 1;
+       fxsave(&pcb->pcb_savefpu);
+       ci->ci_fpsaving = 0;
+}
 
-       spins = 0;
-       ticks = hardclock_ticks;
-       for (;;) {
-               s = splhigh();
-               pcb = lwp_getpcb(l);
-               oci = pcb->pcb_fpcpu;
-               if (oci == NULL) {
-                       splx(s);
-                       break;
-               }
-               if (oci == curcpu()) {
-                       KASSERT(oci->ci_fpcurlwp == l);
-                       fpusave_cpu(save);
-                       splx(s);
-                       break;
-               }
-               splx(s);
-#ifdef XEN
-               if (xen_send_ipi(oci, XEN_IPI_SYNCH_FPU) != 0) {
-                       panic("xen_send_ipi(%s, XEN_IPI_SYNCH_FPU) failed.",
-                           cpu_name(oci));
-               }
-#else /* XEN */
-               x86_send_ipi(oci, X86_IPI_SYNCH_FPU);
-#endif
-               while (pcb->pcb_fpcpu == oci && ticks == hardclock_ticks) {
-                       x86_pause();
-                       spins++;
-               }
-               if (spins > 100000000) {
-                       panic("fpusave_lwp: did not");
-               }
-       }
+static void
+fpu_state_release(struct lwp *l, u_int flags)
+{
+       struct pcb * const pcb = lwp_getpcb(l);
+
+       stts();
+       pcb->pcb_cr0 |= CR0_TS;
+}
 
-       if (!save) {
-               /* Ensure we restart with a clean slate. */
-               l->l_md.md_flags &= ~MDL_USEDFPU;
-       }
-}
+const pcu_ops_t fpu_ops = {
+       .pcu_id = PCU_FPU,
+       .pcu_state_load = fpu_state_load,
+       .pcu_state_save = fpu_state_save,
+       .pcu_state_release = fpu_state_release,
+};
+
+const pcu_ops_t * const pcu_ops_md_defs[PCU_UNIT_COUNT] = {
+       [PCU_FPU] = &fpu_ops,
+};
diff -r 25386ff93b58 -r 1d3b737f5dae sys/arch/amd64/amd64/genassym.cf
--- a/sys/arch/amd64/amd64/genassym.cf  Wed Oct 23 18:57:40 2013 +0000
+++ b/sys/arch/amd64/amd64/genassym.cf  Wed Oct 23 20:18:50 2013 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: genassym.cf,v 1.52 2012/07/15 15:17:56 dsl Exp $
+#      $NetBSD: genassym.cf,v 1.53 2013/10/23 20:18:50 drochner Exp $
 
 #
 # Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -185,7 +185,6 @@
 define PCB_RSP0                offsetof(struct pcb, pcb_rsp0)
 define PCB_CR0                 offsetof(struct pcb, pcb_cr0)
 define PCB_ONFAULT             offsetof(struct pcb, pcb_onfault)
-define PCB_FPCPU               offsetof(struct pcb, pcb_fpcpu)
 define PCB_FLAGS               offsetof(struct pcb, pcb_flags)
 define PCB_COMPAT32            PCB_COMPAT32
 define PCB_FS                  offsetof(struct pcb, pcb_fs)
@@ -238,7 +237,6 @@
 define CPU_INFO_NTRAP          offsetof(struct cpu_info, ci_data.cpu_ntrap)
 define CPU_INFO_NINTR          offsetof(struct cpu_info, ci_data.cpu_nintr)
 define CPU_INFO_CURPRIORITY    offsetof(struct cpu_info, ci_schedstate.spc_curpriority)
-define CPU_INFO_FPCURLWP       offsetof(struct cpu_info, ci_fpcurlwp)
 
 define CPU_INFO_GDT            offsetof(struct cpu_info, ci_gdt)
 define CPU_INFO_IPENDING       offsetof(struct cpu_info, ci_ipending)
diff -r 25386ff93b58 -r 1d3b737f5dae sys/arch/amd64/amd64/locore.S
--- a/sys/arch/amd64/amd64/locore.S     Wed Oct 23 18:57:40 2013 +0000
+++ b/sys/arch/amd64/amd64/locore.S     Wed Oct 23 20:18:50 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.73 2013/06/23 09:00:37 uebayasi Exp $     */
+/*     $NetBSD: locore.S,v 1.74 2013/10/23 20:18:50 drochner Exp $     */
 
 /*
  * Copyright-o-rama!
@@ -1023,20 +1023,11 @@
         */
 2:
 #ifndef XEN
-       movl    $IPL_HIGH,CPUVAR(ILEVEL)
-       movl    PCB_CR0(%r14),%ecx      /* has CR0_TS clear */



Home | Main Index | Thread Index | Old Index