1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/config.h>
24#include <asm/processor.h>
25#include <asm/i387.h>
26#include <asm/msr.h>
27
28static int __init no_halt(char *s)
29{
30 boot_cpu_data.hlt_works_ok = 0;
31 return 1;
32}
33
34__setup("no-hlt", no_halt);
35
36static int __init mca_pentium(char *s)
37{
38 mca_pentium_flag = 1;
39 return 1;
40}
41
42__setup("mca-pentium", mca_pentium);
43
44static int __init no_387(char *s)
45{
46 boot_cpu_data.hard_math = 0;
47 write_cr0(0xE | read_cr0());
48 return 1;
49}
50
51__setup("no387", no_387);
52
53static double __initdata x = 4195835.0;
54static double __initdata y = 3145727.0;
55
56
57
58
59
60
61
62
63
64
65
66
67static void __init check_fpu(void)
68{
69 if (!boot_cpu_data.hard_math) {
70#ifndef CONFIG_MATH_EMULATION
71 printk(KERN_EMERG "No coprocessor found and no math emulation present.\n");
72 printk(KERN_EMERG "Giving up.\n");
73 for (;;) ;
74#endif
75 return;
76 }
77
78
79
80
81
82 if (offsetof(struct task_struct, thread.i387.fxsave) & 15) {
83 extern void __buggy_fxsr_alignment(void);
84 __buggy_fxsr_alignment();
85 }
86 if (cpu_has_fxsr) {
87 printk(KERN_INFO "Enabling fast FPU save and restore... ");
88 set_in_cr4(X86_CR4_OSFXSR);
89 printk("done.\n");
90 }
91 if (cpu_has_xmm) {
92 printk(KERN_INFO "Enabling unmasked SIMD FPU exception support... ");
93 set_in_cr4(X86_CR4_OSXMMEXCPT);
94 printk("done.\n");
95 }
96
97
98 __asm__("fninit\n\t"
99 "fldl %1\n\t"
100 "fdivl %2\n\t"
101 "fmull %2\n\t"
102 "fldl %1\n\t"
103 "fsubp %%st,%%st(1)\n\t"
104 "fistpl %0\n\t"
105 "fwait\n\t"
106 "fninit"
107 : "=m" (*&boot_cpu_data.fdiv_bug)
108 : "m" (*&x), "m" (*&y));
109 if (boot_cpu_data.fdiv_bug)
110 printk("Hmm, FPU with FDIV bug.\n");
111}
112
113static void __init check_hlt(void)
114{
115 printk(KERN_INFO "Checking 'hlt' instruction... ");
116 if (!boot_cpu_data.hlt_works_ok) {
117 printk("disabled\n");
118 return;
119 }
120 __asm__ __volatile__("hlt ; hlt ; hlt ; hlt");
121 printk("OK.\n");
122}
123
124
125
126
127
128
129static void __init check_popad(void)
130{
131#ifndef CONFIG_X86_POPAD_OK
132 int res, inp = (int) &res;
133
134 printk(KERN_INFO "Checking for popad bug... ");
135 __asm__ __volatile__(
136 "movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx "
137 : "=&a" (res)
138 : "d" (inp)
139 : "ecx", "edi" );
140
141 if (res != 12345678) printk( "Buggy.\n" );
142 else printk( "OK.\n" );
143#endif
144}
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161static void __init check_config(void)
162{
163
164
165
166
167
168#if defined(CONFIG_X86_WP_WORKS_OK) || defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_BSWAP)
169 if (boot_cpu_data.x86 == 3)
170 panic("Kernel requires i486+ for 'invlpg' and other features");
171#endif
172
173
174
175
176#ifdef CONFIG_X86_TSC
177 if (!cpu_has_tsc)
178 panic("Kernel compiled for Pentium+, requires TSC feature!");
179#endif
180
181
182
183
184#ifdef CONFIG_X86_PGE
185 if (!cpu_has_pge)
186 panic("Kernel compiled for PPro+, requires PGE feature!");
187#endif
188
189
190
191
192
193
194
195#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_GOOD_APIC)
196 if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
197 && test_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability)
198 && boot_cpu_data.x86 == 5
199 && boot_cpu_data.x86_model == 2
200 && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11))
201 panic("Kernel compiled for PMMX+, assumes a local APIC without the read-before-write bug!");
202#endif
203}
204
205static void __init check_bugs(void)
206{
207 extern void __init boot_init_fpu(void);
208
209 identify_cpu(&boot_cpu_data);
210 boot_init_fpu();
211#ifndef CONFIG_SMP
212 printk("CPU: ");
213 print_cpu_info(&boot_cpu_data);
214#endif
215 check_config();
216 check_fpu();
217 check_hlt();
218 check_popad();
219 system_utsname.machine[1] = '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
220}
221