Source-Changes-HG archive

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

[src/trunk]: src/sys revert fpu/pcu changes until we figure out what's wrong; ...



details:   https://anonhg.NetBSD.org/src/rev/f0dab8fbe76b
branches:  trunk
changeset: 325031:f0dab8fbe76b
user:      christos <christos%NetBSD.org@localhost>
date:      Sun Dec 01 01:05:16 2013 +0000

description:
revert fpu/pcu changes until we figure out what's wrong; they cause random
freezes

diffstat:

 sys/arch/amd64/amd64/fpu.c                      |  196 +++++++++++++++++----
 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                         |  210 ++++++++++++++++-------
 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, 635 insertions(+), 236 deletions(-)

diffs (truncated from 1959 to 300 lines):

diff -r fa0c67402f0f -r f0dab8fbe76b sys/arch/amd64/amd64/fpu.c
--- a/sys/arch/amd64/amd64/fpu.c        Sun Dec 01 01:05:15 2013 +0000
+++ b/sys/arch/amd64/amd64/fpu.c        Sun Dec 01 01:05:16 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu.c,v 1.42 2013/10/27 16:25:01 rmind Exp $   */
+/*     $NetBSD: fpu.c,v 1.43 2013/12/01 01:05:16 christos Exp $        */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.  All
@@ -95,13 +95,24 @@
  *     @(#)npx.c       7.2 (Berkeley) 5/12/91
  */
 
+/*
+ * XXXfvdl update copyright notice. this started out as a stripped isa/npx.c
+ */
+
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.42 2013/10/27 16:25:01 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.43 2013/12/01 01:05:16 christos Exp $");
+
+#include "opt_multiprocessor.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/conf.h>
 #include <sys/cpu.h>
+#include <sys/file.h>
 #include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/vmmeter.h>
 #include <sys/kernel.h>
 
 #include <sys/bus.h>
@@ -175,6 +186,11 @@
        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;
@@ -233,34 +249,70 @@
  * 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);
-}
+       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();
 
-static void
-fpu_state_load(struct lwp *l, u_int flags)
-{
-       struct pcb *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);
+       }
 
+       /* 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();
-       pcb->pcb_cr0 &= ~CR0_TS;
-       if ((flags & PCU_RELOAD) == 0)
-               return;
-
-       if ((flags & PCU_LOADED) == 0) {
-               uint32_t mxcsr;
-               uint16_t cw;
-
+       ci->ci_fpcurlwp = l;
+       pcb->pcb_fpcpu = ci;
+       if ((l->l_md.md_flags & MDL_USEDFPU) == 0) {
                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,
@@ -286,33 +338,97 @@
                fldummy(&zero);
                fxrstor(&pcb->pcb_savefpu);
        }
+
+       KASSERT(ci == curcpu());
+       splx(s);
 }
 
-static void
-fpu_state_save(struct lwp *l, u_int flags)
+/*
+ * Save current CPU's FPU state.  Must be called at IPL_HIGH.
+ */
+void
+fpusave_cpu(bool save)
 {
-       struct pcb *pcb = lwp_getpcb(l);
+       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);
 
-       clts();
-       fxsave(&pcb->pcb_savefpu);
+       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;
 }
 
-static void
-fpu_state_release(struct lwp *l, u_int flags)
+/*
+ * 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)
 {
-       struct pcb *pcb = lwp_getpcb(l);
-
-       stts();
-       pcb->pcb_cr0 |= CR0_TS;
-}
+       struct cpu_info *oci;
+       struct pcb *pcb;
+       int s, spins, ticks;
 
-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,
-};
+       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");
+               }
+       }
 
-const pcu_ops_t * const pcu_ops_md_defs[PCU_UNIT_COUNT] = {
-       [PCU_FPU] = &fpu_ops,
-};
+       if (!save) {
+               /* Ensure we restart with a clean slate. */
+               l->l_md.md_flags &= ~MDL_USEDFPU;
+       }
+}
diff -r fa0c67402f0f -r f0dab8fbe76b sys/arch/amd64/amd64/genassym.cf
--- a/sys/arch/amd64/amd64/genassym.cf  Sun Dec 01 01:05:15 2013 +0000
+++ b/sys/arch/amd64/amd64/genassym.cf  Sun Dec 01 01:05:16 2013 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: genassym.cf,v 1.53 2013/10/23 20:18:50 drochner Exp $
+#      $NetBSD: genassym.cf,v 1.54 2013/12/01 01:05:16 christos Exp $
 
 #
 # Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -185,6 +185,7 @@
 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)
@@ -237,6 +238,7 @@
 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 fa0c67402f0f -r f0dab8fbe76b sys/arch/amd64/amd64/locore.S
--- a/sys/arch/amd64/amd64/locore.S     Sun Dec 01 01:05:15 2013 +0000
+++ b/sys/arch/amd64/amd64/locore.S     Sun Dec 01 01:05:16 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.74 2013/10/23 20:18:50 drochner Exp $     */
+/*     $NetBSD: locore.S,v 1.75 2013/12/01 01:05:16 christos Exp $     */
 
 /*
  * Copyright-o-rama!
@@ -1023,11 +1023,20 @@
         */
 2:
 #ifndef XEN
-       movl    PCB_CR0(%r14),%ecx
+       movl    $IPL_HIGH,CPUVAR(ILEVEL)
+       movl    PCB_CR0(%r14),%ecx      /* has CR0_TS clear */
        movq    %cr0,%rdx
 
+       /*
+        * If our floating point registers are on a different CPU,
+        * set CR0_TS so we'll trap rather than reuse bogus state.



Home | Main Index | Thread Index | Old Index