Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/x86 Fix MXCSR_MASK, it needs to be detected dynamic...



details:   https://anonhg.NetBSD.org/src/rev/f5a291a08173
branches:  trunk
changeset: 827556:f5a291a08173
user:      maxv <maxv%NetBSD.org@localhost>
date:      Fri Nov 03 07:14:24 2017 +0000

description:
Fix MXCSR_MASK, it needs to be detected dynamically, otherwise when masking
MXCSR we are losing some features (eg DAZ).

diffstat:

 sys/arch/x86/include/fpu.h  |   3 ++-
 sys/arch/x86/x86/fpu.c      |  43 ++++++++++++++++++++++++++++++++++++++-----
 sys/arch/x86/x86/identcpu.c |   6 ++++--
 3 files changed, 44 insertions(+), 8 deletions(-)

diffs (136 lines):

diff -r 821f45267a0a -r f5a291a08173 sys/arch/x86/include/fpu.h
--- a/sys/arch/x86/include/fpu.h        Fri Nov 03 05:31:38 2017 +0000
+++ b/sys/arch/x86/include/fpu.h        Fri Nov 03 07:14:24 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu.h,v 1.6 2014/02/25 22:16:52 dsl Exp $      */
+/*     $NetBSD: fpu.h,v 1.7 2017/11/03 07:14:24 maxv Exp $     */
 
 #ifndef        _X86_FPU_H_
 #define        _X86_FPU_H_
@@ -12,6 +12,7 @@
 struct trapframe;
 
 void fpuinit(struct cpu_info *);
+void fpuinit_mxcsr_mask(void);
 void fpusave_lwp(struct lwp *, bool);
 void fpusave_cpu(bool);
 
diff -r 821f45267a0a -r f5a291a08173 sys/arch/x86/x86/fpu.c
--- a/sys/arch/x86/x86/fpu.c    Fri Nov 03 05:31:38 2017 +0000
+++ b/sys/arch/x86/x86/fpu.c    Fri Nov 03 07:14:24 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu.c,v 1.20 2017/10/31 18:23:29 maxv Exp $    */
+/*     $NetBSD: fpu.c,v 1.21 2017/11/03 07:14:24 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.20 2017/10/31 18:23:29 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.21 2017/11/03 07:14:24 maxv Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -125,6 +125,8 @@
 #define stts() HYPERVISOR_fpu_taskswitch(1)
 #endif
 
+static uint32_t x86_fpu_mxcsr_mask __read_mostly = 0;
+
 static inline union savefpu *
 process_fpframe(struct lwp *lwp)
 {
@@ -226,6 +228,37 @@
 }
 
 /*
+ * Get the value of MXCSR_MASK supported by the CPU.
+ */
+void
+fpuinit_mxcsr_mask(void)
+{
+       union savefpu fpusave __aligned(16);
+       u_long cr0, psl;
+
+       memset(&fpusave, 0, sizeof(fpusave));
+
+       /* Disable interrupts, and enable FPU */
+       psl = x86_read_psl();
+       x86_disable_intr();
+       cr0 = rcr0();
+       lcr0(cr0 & ~(CR0_EM|CR0_TS));
+
+       /* Fill in the FPU area */
+       fxsave(&fpusave);
+
+       /* Restore previous state */
+       lcr0(cr0);
+       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;
+       }
+}
+
+/*
  * 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.
@@ -515,7 +548,7 @@
        if (i386_use_fxsave) {
                memset(&fpu_save->sv_xmm, 0, x86_fpu_save_size);
                fpu_save->sv_xmm.fx_mxcsr = __INITIAL_MXCSR__;
-               fpu_save->sv_xmm.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
+               fpu_save->sv_xmm.fx_mxcsr_mask = x86_fpu_mxcsr_mask;
                fpu_save->sv_xmm.fx_cw = x87_cw;
        } else {
                memset(&fpu_save->sv_87, 0, x86_fpu_save_size);
@@ -537,7 +570,7 @@
         */
        if (i386_use_fxsave) {
                fpu_save->sv_xmm.fx_mxcsr = __INITIAL_MXCSR__;
-               fpu_save->sv_xmm.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
+               fpu_save->sv_xmm.fx_mxcsr_mask = x86_fpu_mxcsr_mask;
                fpu_save->sv_xmm.fx_tw = 0;
                fpu_save->sv_xmm.fx_cw = pcb->pcb_fpu_dflt_cw;
        } else {
@@ -576,7 +609,7 @@
                /*
                 * Invalid bits in mxcsr or mxcsr_mask will cause faults.
                 */
-               fpu_save->sv_xmm.fx_mxcsr_mask &= __INITIAL_MXCSR_MASK__;
+               fpu_save->sv_xmm.fx_mxcsr_mask &= x86_fpu_mxcsr_mask;
                fpu_save->sv_xmm.fx_mxcsr &= fpu_save->sv_xmm.fx_mxcsr_mask;
 
                /*
diff -r 821f45267a0a -r f5a291a08173 sys/arch/x86/x86/identcpu.c
--- a/sys/arch/x86/x86/identcpu.c       Fri Nov 03 05:31:38 2017 +0000
+++ b/sys/arch/x86/x86/identcpu.c       Fri Nov 03 07:14:24 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: identcpu.c,v 1.61 2017/10/31 11:37:05 maxv Exp $       */
+/*     $NetBSD: identcpu.c,v 1.62 2017/11/03 07:14:24 maxv Exp $       */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.61 2017/10/31 11:37:05 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.62 2017/11/03 07:14:24 maxv Exp $");
 
 #include "opt_xen.h"
 
@@ -752,6 +752,8 @@
 
        x86_fpu_save = FPU_SAVE_FXSAVE;
 
+       fpuinit_mxcsr_mask();
+
        /* See if xsave (for AVX) is supported */
        if ((ci->ci_feat_val[1] & CPUID2_XSAVE) == 0)
                return;



Home | Main Index | Thread Index | Old Index