File: /usr/include/asm/bugs.h

1     /*
2      *  include/asm-i386/bugs.h
3      *
4      *  Copyright (C) 1994  Linus Torvalds
5      *
6      *  Cyrix stuff, June 1998 by:
7      *	- Rafael R. Reilova (moved everything from head.S),
8      *        <rreilova@ececs.uc.edu>
9      *	- Channing Corn (tests & fixes),
10      *	- Andrew D. Balsa (code cleanup).
11      *
12      *  Pentium III FXSR, SSE support
13      *	Gareth Hughes <gareth@valinux.com>, May 2000
14      */
15     
16     /*
17      * This is included by init/main.c to check for architecture-dependent bugs.
18      *
19      * Needs:
20      *	void check_bugs(void);
21      */
22     
23     #include <linux/config.h>
24     #include <asm/processor.h>
25     #include <asm/i387.h>
26     #include <asm/msr.h>
27     
28     static 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     
36     static int __init mca_pentium(char *s)
37     {
38     	mca_pentium_flag = 1;
39     	return 1;
40     }
41     
42     __setup("mca-pentium", mca_pentium);
43     
44     static 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     
53     static double __initdata x = 4195835.0;
54     static double __initdata y = 3145727.0;
55     
56     /*
57      * This used to check for exceptions.. 
58      * However, it turns out that to support that,
59      * the XMM trap handlers basically had to
60      * be buggy. So let's have a correct XMM trap
61      * handler, and forget about printing out
62      * some status at boot.
63      *
64      * We should really only care about bugs here
65      * anyway. Not features.
66      */
67     static 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     /* Enable FXSR and company _before_ testing for FP problems. */
79     	/*
80     	 * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
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     	/* Test for the divl bug.. */
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     
113     static 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      *	Most 386 processors have a bug where a POPAD can lock the 
126      *	machine even from user space.
127      */
128      
129     static 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     	/* If this fails, it means that any user program may lock the CPU hard. Too bad. */
141     	if (res != 12345678) printk( "Buggy.\n" );
142     		        else printk( "OK.\n" );
143     #endif
144     }
145     
146     /*
147      * Check whether we are able to run this kernel safely on SMP.
148      *
149      * - In order to run on a i386, we need to be compiled for i386
150      *   (for due to lack of "invlpg" and working WP on a i386)
151      * - In order to run on anything without a TSC, we need to be
152      *   compiled for a i486.
153      * - In order to support the local APIC on a buggy Pentium machine,
154      *   we need to be compiled with CONFIG_X86_GOOD_APIC disabled,
155      *   which happens implicitly if compiled for a Pentium or lower
156      *   (unless an advanced selection of CPU features is used) as an
157      *   otherwise config implies a properly working local APIC without
158      *   the need to do extra reads from the APIC.
159     */
160     
161     static void __init check_config(void)
162     {
163     /*
164      * We'd better not be a i386 if we're configured to use some
165      * i486+ only features! (WP works in supervisor mode and the
166      * new "invlpg" and "bswap" instructions)
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      * If we configured ourselves for a TSC, we'd better have one!
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      * If we configured ourselves for PGE, we'd better have it.
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      * If we were told we had a good local APIC, check for buggy Pentia,
191      * i.e. all B steppings and the C2 stepping of P54C when using their
192      * integrated APIC (see 11AP erratum in "Pentium Processor
193      * Specification Update").
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     
205     static void __init check_bugs(void)
206     {
207     	identify_cpu(&boot_cpu_data);
208     #ifndef CONFIG_SMP
209     	printk("CPU: ");
210     	print_cpu_info(&boot_cpu_data);
211     #endif
212     	check_config();
213     	check_fpu();
214     	check_hlt();
215     	check_popad();
216     	system_utsname.machine[1] = '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
217     }
218