]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/x86/kernel/cpu/bugs.c
Merge branch 'for-3.10' of git://linux-nfs.org/~bfields/linux
[karo-tx-linux.git] / arch / x86 / kernel / cpu / bugs.c
1 /*
2  *  Copyright (C) 1994  Linus Torvalds
3  *
4  *  Cyrix stuff, June 1998 by:
5  *      - Rafael R. Reilova (moved everything from head.S),
6  *        <rreilova@ececs.uc.edu>
7  *      - Channing Corn (tests & fixes),
8  *      - Andrew D. Balsa (code cleanup).
9  */
10 #include <linux/init.h>
11 #include <linux/utsname.h>
12 #include <asm/bugs.h>
13 #include <asm/processor.h>
14 #include <asm/processor-flags.h>
15 #include <asm/i387.h>
16 #include <asm/msr.h>
17 #include <asm/paravirt.h>
18 #include <asm/alternative.h>
19
20 static int __init no_387(char *s)
21 {
22         boot_cpu_data.hard_math = 0;
23         write_cr0(X86_CR0_TS | X86_CR0_EM | X86_CR0_MP | read_cr0());
24         return 1;
25 }
26
27 __setup("no387", no_387);
28
29 static double __initdata x = 4195835.0;
30 static double __initdata y = 3145727.0;
31
32 /*
33  * This used to check for exceptions..
34  * However, it turns out that to support that,
35  * the XMM trap handlers basically had to
36  * be buggy. So let's have a correct XMM trap
37  * handler, and forget about printing out
38  * some status at boot.
39  *
40  * We should really only care about bugs here
41  * anyway. Not features.
42  */
43 static void __init check_fpu(void)
44 {
45         s32 fdiv_bug;
46
47         if (!boot_cpu_data.hard_math) {
48 #ifndef CONFIG_MATH_EMULATION
49                 pr_emerg("No coprocessor found and no math emulation present\n");
50                 pr_emerg("Giving up\n");
51                 for (;;) ;
52 #endif
53                 return;
54         }
55
56         kernel_fpu_begin();
57
58         /*
59          * trap_init() enabled FXSR and company _before_ testing for FP
60          * problems here.
61          *
62          * Test for the divl bug: http://en.wikipedia.org/wiki/Fdiv_bug
63          */
64         __asm__("fninit\n\t"
65                 "fldl %1\n\t"
66                 "fdivl %2\n\t"
67                 "fmull %2\n\t"
68                 "fldl %1\n\t"
69                 "fsubp %%st,%%st(1)\n\t"
70                 "fistpl %0\n\t"
71                 "fwait\n\t"
72                 "fninit"
73                 : "=m" (*&fdiv_bug)
74                 : "m" (*&x), "m" (*&y));
75
76         kernel_fpu_end();
77
78         if (fdiv_bug) {
79                 set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV);
80                 pr_warn("Hmm, FPU with FDIV bug\n");
81         }
82 }
83
84 void __init check_bugs(void)
85 {
86         identify_boot_cpu();
87 #ifndef CONFIG_SMP
88         pr_info("CPU: ");
89         print_cpu_info(&boot_cpu_data);
90 #endif
91
92         /*
93          * Check whether we are able to run this kernel safely on SMP.
94          *
95          * - i386 is no longer supported.
96          * - In order to run on anything without a TSC, we need to be
97          *   compiled for a i486.
98          */
99         if (boot_cpu_data.x86 < 4)
100                 panic("Kernel requires i486+ for 'invlpg' and other features");
101
102         init_utsname()->machine[1] =
103                 '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
104         alternative_instructions();
105
106         /*
107          * kernel_fpu_begin/end() in check_fpu() relies on the patched
108          * alternative instructions.
109          */
110         check_fpu();
111 }