Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/x86/x86 Reduce the noise, reorder and rename some t...



details:   https://anonhg.NetBSD.org/src/rev/d4131b390ca0
branches:  trunk
changeset: 433504:d4131b390ca0
user:      maxv <maxv%NetBSD.org@localhost>
date:      Mon Sep 17 15:53:06 2018 +0000

description:
Reduce the noise, reorder and rename some things for clarity.

diffstat:

 sys/arch/x86/x86/fpu.c |  414 ++++++++++++++++++++++--------------------------
 1 files changed, 193 insertions(+), 221 deletions(-)

diffs (truncated from 573 to 300 lines):

diff -r da8252f01448 -r d4131b390ca0 sys/arch/x86/x86/fpu.c
--- a/sys/arch/x86/x86/fpu.c    Mon Sep 17 15:19:29 2018 +0000
+++ b/sys/arch/x86/x86/fpu.c    Mon Sep 17 15:53:06 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu.c,v 1.46 2018/07/01 08:32:41 maxv Exp $    */
+/*     $NetBSD: fpu.c,v 1.47 2018/09/17 15:53:06 maxv Exp $    */
 
 /*
  * Copyright (c) 2008 The NetBSD Foundation, Inc.  All
@@ -96,7 +96,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.46 2018/07/01 08:32:41 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.47 2018/09/17 15:53:06 maxv Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -121,9 +121,6 @@
 #include <x86/cpu.h>
 #include <x86/fpu.h>
 
-/* Check some duplicate definitions match */
-#include <machine/fenv.h>
-
 #ifdef XEN
 #define clts() HYPERVISOR_fpu_taskswitch(0)
 #define stts() HYPERVISOR_fpu_taskswitch(1)
@@ -134,13 +131,169 @@
 static uint32_t x86_fpu_mxcsr_mask __read_mostly = 0;
 
 static inline union savefpu *
-process_fpframe(struct lwp *lwp)
+lwp_fpuarea(struct lwp *l)
 {
-       struct pcb *pcb = lwp_getpcb(lwp);
+       struct pcb *pcb = lwp_getpcb(l);
 
        return &pcb->pcb_savefpu;
 }
 
+void
+fpuinit(struct cpu_info *ci)
+{
+       /*
+        * This might not be strictly necessary since it will be initialized
+        * for each process. However it does no harm.
+        */
+       clts();
+       fninit();
+       stts();
+}
+
+void
+fpuinit_mxcsr_mask(void)
+{
+#ifndef XEN
+       union savefpu fpusave __aligned(16);
+       u_long psl;
+
+       memset(&fpusave, 0, sizeof(fpusave));
+
+       /* Disable interrupts, and enable FPU */
+       psl = x86_read_psl();
+       x86_disable_intr();
+       clts();
+
+       /* Fill in the FPU area */
+       fxsave(&fpusave);
+
+       /* Restore previous state */
+       stts();
+       x86_write_psl(psl);
+
+       if (fpusave.sv_xmm.fx_mxcsr_mask == 0) {
+               x86_fpu_mxcsr_mask = __INITIAL_MXCSR_MASK__;
+       } else {
+               x86_fpu_mxcsr_mask = fpusave.sv_xmm.fx_mxcsr_mask;
+       }
+#else
+       /*
+        * XXX XXX XXX: On Xen the FXSAVE above faults. That's because
+        * &fpusave is not 16-byte aligned. Stack alignment problem
+        * somewhere, it seems.
+        */
+       x86_fpu_mxcsr_mask = __INITIAL_MXCSR_MASK__;
+#endif
+}
+
+static void
+fpu_clear_amd(void)
+{
+       /*
+        * AMD FPUs do not restore FIP, FDP, and FOP on fxrstor and xrstor
+        * when FSW.ES=0, leaking other threads' execution history.
+        *
+        * Clear them manually by loading a zero (fldummy). We do this
+        * unconditionally, regardless of FSW.ES.
+        *
+        * Before that, clear the ES bit in the x87 status word if it is
+        * currently set, in order to avoid causing a fault in the
+        * upcoming load.
+        *
+        * Newer generations of AMD CPUs have CPUID_Fn80000008_EBX[2],
+        * which indicates that FIP/FDP/FOP are restored (same behavior
+        * as Intel). We're not using it though.
+        */
+       if (fngetsw() & 0x80)
+               fnclex();
+       fldummy();
+}
+
+static void
+fpu_area_save(void *area)
+{
+       clts();
+
+       switch (x86_fpu_save) {
+       case FPU_SAVE_FSAVE:
+               fnsave(area);
+               break;
+       case FPU_SAVE_FXSAVE:
+               fxsave(area);
+               break;
+       case FPU_SAVE_XSAVE:
+               xsave(area, x86_xsave_features);
+               break;
+       case FPU_SAVE_XSAVEOPT:
+               xsaveopt(area, x86_xsave_features);
+               break;
+       }
+}
+
+static void
+fpu_area_restore(void *area)
+{
+       clts();
+
+       switch (x86_fpu_save) {
+       case FPU_SAVE_FSAVE:
+               frstor(area);
+               break;
+       case FPU_SAVE_FXSAVE:
+               if (cpu_vendor == CPUVENDOR_AMD)
+                       fpu_clear_amd();
+               fxrstor(area);
+               break;
+       case FPU_SAVE_XSAVE:
+       case FPU_SAVE_XSAVEOPT:
+               if (cpu_vendor == CPUVENDOR_AMD)
+                       fpu_clear_amd();
+               xrstor(area, x86_xsave_features);
+               break;
+       }
+}
+
+static void
+fpu_lwp_install(struct lwp *l)
+{
+       struct pcb *pcb = lwp_getpcb(l);
+       struct cpu_info *ci = curcpu();
+
+       KASSERT(ci->ci_fpcurlwp == NULL);
+       KASSERT(pcb->pcb_fpcpu == NULL);
+       ci->ci_fpcurlwp = l;
+       pcb->pcb_fpcpu = ci;
+       fpu_area_restore(&pcb->pcb_savefpu);
+}
+
+void
+fpu_eagerswitch(struct lwp *oldlwp, struct lwp *newlwp)
+{
+       int s;
+
+       s = splhigh();
+#ifdef DIAGNOSTIC
+       if (oldlwp != NULL) {
+               struct pcb *pcb = lwp_getpcb(oldlwp);
+               struct cpu_info *ci = curcpu();
+               if (pcb->pcb_fpcpu == NULL) {
+                       KASSERT(ci->ci_fpcurlwp != oldlwp);
+               } else if (pcb->pcb_fpcpu == ci) {
+                       KASSERT(ci->ci_fpcurlwp == oldlwp);
+               } else {
+                       panic("%s: oldlwp's state installed elsewhere",
+                           __func__);
+               }
+       }
+#endif
+       fpusave_cpu(true);
+       if (!(newlwp->l_flag & LW_SYSTEM))
+               fpu_lwp_install(newlwp);
+       splx(s);
+}
+
+/* -------------------------------------------------------------------------- */
+
 /*
  * The following table is used to ensure that the FPE_... value
  * that is passed as a trapcode to the signal handler of the user
@@ -219,202 +372,29 @@
 #undef FPE_xxx32
 
 /*
- * Init the FPU.
+ * This is a synchronous trap on either an x87 instruction (due to an unmasked
+ * error on the previous x87 instruction) or on an SSE/SSE2/etc instruction due
+ * to an error on the instruction itself.
  *
- * This might not be strictly necessary since it will be initialised
- * for each process.  However it does no harm.
- */
-void
-fpuinit(struct cpu_info *ci)
-{
-
-       clts();
-       fninit();
-       stts();
-}
-
-/*
- * Get the value of MXCSR_MASK supported by the CPU.
+ * If trap actually generates a signal, then the fpu state is saved and then
+ * copied onto the lwp's user-stack, and then recovered from there when the
+ * signal returns.
+ *
+ * All this code needs to do is save the reason for the trap. For x87 traps the
+ * status word bits need clearing to stop the trap re-occurring. For SSE traps
+ * the mxcsr bits are 'sticky' and need clearing to not confuse a later trap.
+ *
+ * We come here with interrupts disabled.
  */
 void
-fpuinit_mxcsr_mask(void)
-{
-#ifndef XEN
-       union savefpu fpusave __aligned(16);
-       u_long psl;
-
-       memset(&fpusave, 0, sizeof(fpusave));
-
-       /* Disable interrupts, and enable FPU */
-       psl = x86_read_psl();
-       x86_disable_intr();
-       clts();
-
-       /* Fill in the FPU area */
-       fxsave(&fpusave);
-
-       /* Restore previous state */
-       stts();
-       x86_write_psl(psl);
-
-       if (fpusave.sv_xmm.fx_mxcsr_mask == 0) {
-               x86_fpu_mxcsr_mask = __INITIAL_MXCSR_MASK__;
-       } else {
-               x86_fpu_mxcsr_mask = fpusave.sv_xmm.fx_mxcsr_mask;
-       }
-#else
-       /*
-        * XXX XXX XXX: On Xen the FXSAVE above faults. That's because
-        * &fpusave is not 16-byte aligned. Stack alignment problem
-        * somewhere, it seems.
-        */
-       x86_fpu_mxcsr_mask = __INITIAL_MXCSR_MASK__;
-#endif
-}
-
-static void
-fpu_clear_amd(void)
-{
-       /*
-        * AMD FPUs do not restore FIP, FDP, and FOP on fxrstor and xrstor
-        * when FSW.ES=0, leaking other threads' execution history.
-        *
-        * Clear them manually by loading a zero (fldummy). We do this
-        * unconditionally, regardless of FSW.ES.
-        *
-        * Before that, clear the ES bit in the x87 status word if it is
-        * currently set, in order to avoid causing a fault in the
-        * upcoming load.
-        *
-        * Newer generations of AMD CPUs have CPUID_Fn80000008_EBX[2],
-        * which indicates that FIP/FDP/FOP are restored (same behavior
-        * as Intel). We're not using it though.
-        */
-       if (fngetsw() & 0x80)
-               fnclex();
-       fldummy();
-}
-
-static void
-fpu_save(struct lwp *l)
-{
-       struct pcb *pcb = lwp_getpcb(l);
-
-       switch (x86_fpu_save) {
-       case FPU_SAVE_FSAVE:
-               fnsave(&pcb->pcb_savefpu);



Home | Main Index | Thread Index | Old Index