1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * x86 FPU bug checks: 4*4882a593Smuzhiyun */ 5*4882a593Smuzhiyun #include <asm/fpu/internal.h> 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun /* 8*4882a593Smuzhiyun * Boot time CPU/FPU FDIV bug detection code: 9*4882a593Smuzhiyun */ 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun static double __initdata x = 4195835.0; 12*4882a593Smuzhiyun static double __initdata y = 3145727.0; 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun /* 15*4882a593Smuzhiyun * This used to check for exceptions.. 16*4882a593Smuzhiyun * However, it turns out that to support that, 17*4882a593Smuzhiyun * the XMM trap handlers basically had to 18*4882a593Smuzhiyun * be buggy. So let's have a correct XMM trap 19*4882a593Smuzhiyun * handler, and forget about printing out 20*4882a593Smuzhiyun * some status at boot. 21*4882a593Smuzhiyun * 22*4882a593Smuzhiyun * We should really only care about bugs here 23*4882a593Smuzhiyun * anyway. Not features. 24*4882a593Smuzhiyun */ fpu__init_check_bugs(void)25*4882a593Smuzhiyunvoid __init fpu__init_check_bugs(void) 26*4882a593Smuzhiyun { 27*4882a593Smuzhiyun s32 fdiv_bug; 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun /* kernel_fpu_begin/end() relies on patched alternative instructions. */ 30*4882a593Smuzhiyun if (!boot_cpu_has(X86_FEATURE_FPU)) 31*4882a593Smuzhiyun return; 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun kernel_fpu_begin(); 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun /* 36*4882a593Smuzhiyun * trap_init() enabled FXSR and company _before_ testing for FP 37*4882a593Smuzhiyun * problems here. 38*4882a593Smuzhiyun * 39*4882a593Smuzhiyun * Test for the divl bug: http://en.wikipedia.org/wiki/Fdiv_bug 40*4882a593Smuzhiyun */ 41*4882a593Smuzhiyun __asm__("fninit\n\t" 42*4882a593Smuzhiyun "fldl %1\n\t" 43*4882a593Smuzhiyun "fdivl %2\n\t" 44*4882a593Smuzhiyun "fmull %2\n\t" 45*4882a593Smuzhiyun "fldl %1\n\t" 46*4882a593Smuzhiyun "fsubp %%st,%%st(1)\n\t" 47*4882a593Smuzhiyun "fistpl %0\n\t" 48*4882a593Smuzhiyun "fwait\n\t" 49*4882a593Smuzhiyun "fninit" 50*4882a593Smuzhiyun : "=m" (*&fdiv_bug) 51*4882a593Smuzhiyun : "m" (*&x), "m" (*&y)); 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun kernel_fpu_end(); 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun if (fdiv_bug) { 56*4882a593Smuzhiyun set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV); 57*4882a593Smuzhiyun pr_warn("Hmm, FPU with FDIV bug\n"); 58*4882a593Smuzhiyun } 59*4882a593Smuzhiyun } 60