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