Module Name: src Committed By: maxv Date: Fri Nov 3 07:14:24 UTC 2017
Modified Files: src/sys/arch/x86/include: fpu.h src/sys/arch/x86/x86: fpu.c identcpu.c Log Message: Fix MXCSR_MASK, it needs to be detected dynamically, otherwise when masking MXCSR we are losing some features (eg DAZ). To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/arch/x86/include/fpu.h cvs rdiff -u -r1.20 -r1.21 src/sys/arch/x86/x86/fpu.c cvs rdiff -u -r1.61 -r1.62 src/sys/arch/x86/x86/identcpu.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/include/fpu.h diff -u src/sys/arch/x86/include/fpu.h:1.6 src/sys/arch/x86/include/fpu.h:1.7 --- src/sys/arch/x86/include/fpu.h:1.6 Tue Feb 25 22:16:52 2014 +++ src/sys/arch/x86/include/fpu.h Fri Nov 3 07:14:24 2017 @@ -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 lwp; struct trapframe; void fpuinit(struct cpu_info *); +void fpuinit_mxcsr_mask(void); void fpusave_lwp(struct lwp *, bool); void fpusave_cpu(bool); Index: src/sys/arch/x86/x86/fpu.c diff -u src/sys/arch/x86/x86/fpu.c:1.20 src/sys/arch/x86/x86/fpu.c:1.21 --- src/sys/arch/x86/x86/fpu.c:1.20 Tue Oct 31 18:23:29 2017 +++ src/sys/arch/x86/x86/fpu.c Fri Nov 3 07:14:24 2017 @@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.20 #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 @@ fpuinit(struct cpu_info *ci) } /* + * 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 @@ fpu_save_area_clear(struct lwp *l, unsig 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 @@ fpu_save_area_reset(struct lwp *l) */ 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 @@ process_write_fpregs_xmm(struct lwp *l, /* * 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; /* Index: src/sys/arch/x86/x86/identcpu.c diff -u src/sys/arch/x86/x86/identcpu.c:1.61 src/sys/arch/x86/x86/identcpu.c:1.62 --- src/sys/arch/x86/x86/identcpu.c:1.61 Tue Oct 31 11:37:05 2017 +++ src/sys/arch/x86/x86/identcpu.c Fri Nov 3 07:14:24 2017 @@ -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 @@ cpu_probe_fpu(struct cpu_info *ci) 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;