18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * x86 FPU bug checks: 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#include <asm/fpu/internal.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci/* 88c2ecf20Sopenharmony_ci * Boot time CPU/FPU FDIV bug detection code: 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistatic double __initdata x = 4195835.0; 128c2ecf20Sopenharmony_cistatic double __initdata y = 3145727.0; 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* 158c2ecf20Sopenharmony_ci * This used to check for exceptions.. 168c2ecf20Sopenharmony_ci * However, it turns out that to support that, 178c2ecf20Sopenharmony_ci * the XMM trap handlers basically had to 188c2ecf20Sopenharmony_ci * be buggy. So let's have a correct XMM trap 198c2ecf20Sopenharmony_ci * handler, and forget about printing out 208c2ecf20Sopenharmony_ci * some status at boot. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * We should really only care about bugs here 238c2ecf20Sopenharmony_ci * anyway. Not features. 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_civoid __init fpu__init_check_bugs(void) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci s32 fdiv_bug; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci /* kernel_fpu_begin/end() relies on patched alternative instructions. */ 308c2ecf20Sopenharmony_ci if (!boot_cpu_has(X86_FEATURE_FPU)) 318c2ecf20Sopenharmony_ci return; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci kernel_fpu_begin(); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* 368c2ecf20Sopenharmony_ci * trap_init() enabled FXSR and company _before_ testing for FP 378c2ecf20Sopenharmony_ci * problems here. 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * Test for the divl bug: http://en.wikipedia.org/wiki/Fdiv_bug 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci __asm__("fninit\n\t" 428c2ecf20Sopenharmony_ci "fldl %1\n\t" 438c2ecf20Sopenharmony_ci "fdivl %2\n\t" 448c2ecf20Sopenharmony_ci "fmull %2\n\t" 458c2ecf20Sopenharmony_ci "fldl %1\n\t" 468c2ecf20Sopenharmony_ci "fsubp %%st,%%st(1)\n\t" 478c2ecf20Sopenharmony_ci "fistpl %0\n\t" 488c2ecf20Sopenharmony_ci "fwait\n\t" 498c2ecf20Sopenharmony_ci "fninit" 508c2ecf20Sopenharmony_ci : "=m" (*&fdiv_bug) 518c2ecf20Sopenharmony_ci : "m" (*&x), "m" (*&y)); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci kernel_fpu_end(); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (fdiv_bug) { 568c2ecf20Sopenharmony_ci set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV); 578c2ecf20Sopenharmony_ci pr_warn("Hmm, FPU with FDIV bug\n"); 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci} 60