aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2017-01-18 14:15:41 -0500
committerIngo Molnar <mingo@kernel.org>2017-01-25 04:12:43 -0500
commit37ac78b67b3384d1ced5424d5a13ee146041bda3 (patch)
tree911aa9ecc1363a13287cf52e918ed1b95b9dd6b0
parent9170fb409437b246078bcad3f1481d32dfe2ca28 (diff)
x86/fpu: Fix CPUID-less FPU detection
The old code didn't work at all because it adjusted the current caps instead of the forced caps. Anything it did would be undone later during CPU identification. Fix that and, while we're at it, improve the logging and don't bother running it if CPUID is available. Reported-by: Matthew Whitehead <tedheadster@gmail.com> Signed-off-by: Andy Lutomirski <luto@kernel.org> Reviewed-by: Borislav Petkov <bp@suse.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rik van Riel <riel@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Yu-cheng Yu <yu-cheng.yu@intel.com> Link: http://lkml.kernel.org/r/f1134e30cafa73c4e2e68119e9741793622cfd15.1484705016.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/kernel/fpu/init.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index 60dece392b3a..8b526c5fc306 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -48,13 +48,7 @@ void fpu__init_cpu(void)
48 fpu__init_cpu_xstate(); 48 fpu__init_cpu_xstate();
49} 49}
50 50
51/* 51static bool fpu__probe_without_cpuid(void)
52 * The earliest FPU detection code.
53 *
54 * Set the X86_FEATURE_FPU CPU-capability bit based on
55 * trying to execute an actual sequence of FPU instructions:
56 */
57static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
58{ 52{
59 unsigned long cr0; 53 unsigned long cr0;
60 u16 fsw, fcw; 54 u16 fsw, fcw;
@@ -65,14 +59,21 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
65 cr0 &= ~(X86_CR0_TS | X86_CR0_EM); 59 cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
66 write_cr0(cr0); 60 write_cr0(cr0);
67 61
68 if (!test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) { 62 asm volatile("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw));
69 asm volatile("fninit ; fnstsw %0 ; fnstcw %1" 63
70 : "+m" (fsw), "+m" (fcw)); 64 pr_info("x86/fpu: Probing for FPU: FSW=0x%04hx FCW=0x%04hx\n", fsw, fcw);
71 65
72 if (fsw == 0 && (fcw & 0x103f) == 0x003f) 66 return fsw == 0 && (fcw & 0x103f) == 0x003f;
73 set_cpu_cap(c, X86_FEATURE_FPU); 67}
68
69static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
70{
71 if (!boot_cpu_has(X86_FEATURE_CPUID) &&
72 !test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
73 if (fpu__probe_without_cpuid())
74 setup_force_cpu_cap(X86_FEATURE_FPU);
74 else 75 else
75 clear_cpu_cap(c, X86_FEATURE_FPU); 76 setup_clear_cpu_cap(X86_FEATURE_FPU);
76 } 77 }
77 78
78#ifndef CONFIG_MATH_EMULATION 79#ifndef CONFIG_MATH_EMULATION