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;