Module Name: src Committed By: jdolecek Date: Tue Jun 19 19:50:19 UTC 2018
Modified Files: src/sys/arch/x86/include: fpu.h src/sys/arch/x86/x86: cpu.c fpu.c identcpu.c src/sys/arch/xen/x86: cpu.c Log Message: fix FPU initialization on Xen to allow e.g. AVX when supported by hardware; only use XSAVE when the the CPUID OSXSAVE bit is set, as this seems to be reliable indication tested with Xen 4.2.6 DOM0/DOMU on Intel CPU, without and with no-xsave flag, so should work also on those AMD CPUs, which have XSAVE disabled by default; also tested with Xen DOM0 4.8.3 fixes PR kern/50332 by Torbjorn Granlund; sorry it took three years to address XXX pullup netbsd-8 To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/arch/x86/include/fpu.h cvs rdiff -u -r1.155 -r1.156 src/sys/arch/x86/x86/cpu.c cvs rdiff -u -r1.39 -r1.40 src/sys/arch/x86/x86/fpu.c cvs rdiff -u -r1.72 -r1.73 src/sys/arch/x86/x86/identcpu.c cvs rdiff -u -r1.117 -r1.118 src/sys/arch/xen/x86/cpu.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.9 src/sys/arch/x86/include/fpu.h:1.10 --- src/sys/arch/x86/include/fpu.h:1.9 Thu Jun 14 14:36:46 2018 +++ src/sys/arch/x86/include/fpu.h Tue Jun 19 19:50:19 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu.h,v 1.9 2018/06/14 14:36:46 maxv Exp $ */ +/* $NetBSD: fpu.h,v 1.10 2018/06/19 19:50:19 jdolecek Exp $ */ #ifndef _X86_FPU_H_ #define _X86_FPU_H_ @@ -12,7 +12,7 @@ struct lwp; struct trapframe; void fpuinit(struct cpu_info *); -void fpuinit_mxcsr_mask(void); +void fpuinit_mxcsr_mask(uint32_t); void fpusave_lwp(struct lwp *, bool); void fpusave_cpu(bool); Index: src/sys/arch/x86/x86/cpu.c diff -u src/sys/arch/x86/x86/cpu.c:1.155 src/sys/arch/x86/x86/cpu.c:1.156 --- src/sys/arch/x86/x86/cpu.c:1.155 Thu Apr 5 08:43:07 2018 +++ src/sys/arch/x86/x86/cpu.c Tue Jun 19 19:50:19 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.155 2018/04/05 08:43:07 maxv Exp $ */ +/* $NetBSD: cpu.c,v 1.156 2018/06/19 19:50:19 jdolecek Exp $ */ /* * Copyright (c) 2000-2012 NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.155 2018/04/05 08:43:07 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.156 2018/06/19 19:50:19 jdolecek Exp $"); #include "opt_ddb.h" #include "opt_mpbios.h" /* for MPDEBUG */ @@ -638,7 +638,7 @@ cpu_init(struct cpu_info *ci) } if (x86_fpu_save >= FPU_SAVE_FXSAVE) { - fpuinit_mxcsr_mask(); + fpuinit_mxcsr_mask(cr4); } /* If xsave is enabled, enable all fpu features */ Index: src/sys/arch/x86/x86/fpu.c diff -u src/sys/arch/x86/x86/fpu.c:1.39 src/sys/arch/x86/x86/fpu.c:1.40 --- src/sys/arch/x86/x86/fpu.c:1.39 Tue Jun 19 09:25:13 2018 +++ src/sys/arch/x86/x86/fpu.c Tue Jun 19 19:50:19 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu.c,v 1.39 2018/06/19 09:25:13 maxv Exp $ */ +/* $NetBSD: fpu.c,v 1.40 2018/06/19 19:50:19 jdolecek 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.39 2018/06/19 09:25:13 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.40 2018/06/19 19:50:19 jdolecek Exp $"); #include "opt_multiprocessor.h" @@ -237,9 +237,14 @@ fpuinit(struct cpu_info *ci) * Get the value of MXCSR_MASK supported by the CPU. */ void -fpuinit_mxcsr_mask(void) +fpuinit_mxcsr_mask(uint32_t cr4) { -#ifndef XEN + + if ((cr4 & CR4_OSXSAVE) == 0) { + x86_fpu_mxcsr_mask = __INITIAL_MXCSR_MASK__; + return; + } + union savefpu fpusave __aligned(16); u_long psl; @@ -262,9 +267,6 @@ fpuinit_mxcsr_mask(void) } else { x86_fpu_mxcsr_mask = fpusave.sv_xmm.fx_mxcsr_mask; } -#else - x86_fpu_mxcsr_mask = __INITIAL_MXCSR_MASK__; -#endif } static void Index: src/sys/arch/x86/x86/identcpu.c diff -u src/sys/arch/x86/x86/identcpu.c:1.72 src/sys/arch/x86/x86/identcpu.c:1.73 --- src/sys/arch/x86/x86/identcpu.c:1.72 Sun Jun 17 07:13:02 2018 +++ src/sys/arch/x86/x86/identcpu.c Tue Jun 19 19:50:19 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: identcpu.c,v 1.72 2018/06/17 07:13:02 maxv Exp $ */ +/* $NetBSD: identcpu.c,v 1.73 2018/06/19 19:50:19 jdolecek 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.72 2018/06/17 07:13:02 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.73 2018/06/19 19:50:19 jdolecek Exp $"); #include "opt_xen.h" @@ -819,12 +819,7 @@ cpu_probe_fpu(struct cpu_info *ci) if (descs[2] > 512) x86_fpu_save_size = descs[2]; -#ifdef XEN - /* Don't use xsave, force fxsave with x86_xsave_features = 0. */ - x86_fpu_save = FPU_SAVE_FXSAVE; -#else x86_xsave_features = (uint64_t)descs[3] << 32 | descs[0]; -#endif } void Index: src/sys/arch/xen/x86/cpu.c diff -u src/sys/arch/xen/x86/cpu.c:1.117 src/sys/arch/xen/x86/cpu.c:1.118 --- src/sys/arch/xen/x86/cpu.c:1.117 Sat Jan 13 14:48:13 2018 +++ src/sys/arch/xen/x86/cpu.c Tue Jun 19 19:50:19 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.117 2018/01/13 14:48:13 bouyer Exp $ */ +/* $NetBSD: cpu.c,v 1.118 2018/06/19 19:50:19 jdolecek Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -65,7 +65,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.117 2018/01/13 14:48:13 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.118 2018/06/19 19:50:19 jdolecek Exp $"); #include "opt_ddb.h" #include "opt_multiprocessor.h" @@ -527,22 +527,62 @@ cpu_attach_common(device_t parent, devic void cpu_init(struct cpu_info *ci) { + uint32_t cr4 = 0; /* * If we have FXSAVE/FXRESTOR, use them. */ if (cpu_feature[0] & CPUID_FXSR) { - lcr4(rcr4() | CR4_OSFXSR); + cr4 |= CR4_OSFXSR; /* * If we have SSE/SSE2, enable XMM exceptions. */ if (cpu_feature[0] & (CPUID_SSE|CPUID_SSE2)) - lcr4(rcr4() | CR4_OSXMMEXCPT); + cr4 |= CR4_OSXMMEXCPT; + } + + /* + * Xen kernel sets OSXSAVE if appropriate for the hardware, + * or disables it with no-xsave flag or due to security bugs with + * particular CPUs. + * If it's unset, it also means the xrstor() et.al. are privileged + * and trigger supervisor trap. So, contrary to what regular x86 + * does, here we only set CR4_OSXSAVE if the feature is already + * enabled according to CPUID. + */ + if (cpu_feature[1] & CPUID2_OSXSAVE) + cr4 |= CR4_OSXSAVE; + else { + x86_xsave_features = 0; + x86_fpu_save = FPU_SAVE_FXSAVE; + } + + if (cr4) { + cr4 |= rcr4(); + lcr4(cr4); } if (x86_fpu_save >= FPU_SAVE_FXSAVE) { - fpuinit_mxcsr_mask(); + fpuinit_mxcsr_mask(cr4); + } + + /* + * Changing CR4 register may change cpuid values. For example, setting + * CR4_OSXSAVE sets CPUID2_OSXSAVE. The CPUID2_OSXSAVE is in + * ci_feat_val[1], so update it. + * XXX Other than ci_feat_val[1] might be changed. + */ + if (cpuid_level >= 1) { + u_int descs[4]; + + x86_cpuid(1, descs); + ci->ci_feat_val[1] = descs[2]; + } + + /* If xsave is enabled, enable all fpu features */ + if (cr4 & CR4_OSXSAVE) { + wrxcr(0, x86_xsave_features & XCR0_FPU); } atomic_or_32(&ci->ci_flags, CPUF_RUNNING);