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;

Reply via email to