Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
x86
kernel
cpu
bugs.c
Go to the documentation of this file.
1
/*
2
* Copyright (C) 1994 Linus Torvalds
3
*
4
* Cyrix stuff, June 1998 by:
5
* - Rafael R. Reilova (moved everything from head.S),
6
* <
[email protected]
>
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_halt(
char
*
s
)
21
{
22
WARN_ONCE
(1,
"\"no-hlt\" is deprecated, please use \"idle=poll\"\n"
);
23
boot_cpu_data
.hlt_works_ok = 0;
24
return
1;
25
}
26
27
__setup
(
"no-hlt"
, no_halt);
28
29
static
int
__init
no_387(
char
*
s
)
30
{
31
boot_cpu_data
.hard_math = 0;
32
write_cr0(
X86_CR0_TS
|
X86_CR0_EM
|
X86_CR0_MP
| read_cr0());
33
return
1;
34
}
35
36
__setup
(
"no387"
, no_387);
37
38
static
double
__initdata
x
= 4195835.0;
39
static
double
__initdata
y
= 3145727.0;
40
41
/*
42
* This used to check for exceptions..
43
* However, it turns out that to support that,
44
* the XMM trap handlers basically had to
45
* be buggy. So let's have a correct XMM trap
46
* handler, and forget about printing out
47
* some status at boot.
48
*
49
* We should really only care about bugs here
50
* anyway. Not features.
51
*/
52
static
void
__init
check_fpu(
void
)
53
{
54
s32
fdiv_bug;
55
56
if
(!
boot_cpu_data
.hard_math) {
57
#ifndef CONFIG_MATH_EMULATION
58
pr_emerg
(
"No coprocessor found and no math emulation present\n"
);
59
pr_emerg
(
"Giving up\n"
);
60
for
(;;) ;
61
#endif
62
return
;
63
}
64
65
kernel_fpu_begin();
66
67
/*
68
* trap_init() enabled FXSR and company _before_ testing for FP
69
* problems here.
70
*
71
* Test for the divl bug..
72
*/
73
__asm__
(
"fninit\n\t"
74
"fldl %1\n\t"
75
"fdivl %2\n\t"
76
"fmull %2\n\t"
77
"fldl %1\n\t"
78
"fsubp %%st,%%st(1)\n\t"
79
"fistpl %0\n\t"
80
"fwait\n\t"
81
"fninit"
82
:
"=m"
(*&fdiv_bug)
83
:
"m"
(*&x),
"m"
(*&y));
84
85
kernel_fpu_end
();
86
87
boot_cpu_data
.fdiv_bug = fdiv_bug;
88
if
(
boot_cpu_data
.fdiv_bug)
89
pr_warn
(
"Hmm, FPU with FDIV bug\n"
);
90
}
91
92
static
void
__init
check_hlt(
void
)
93
{
94
if
(
boot_cpu_data
.x86 >= 5 ||
paravirt_enabled
())
95
return
;
96
97
pr_info
(
"Checking 'hlt' instruction... "
);
98
if
(!
boot_cpu_data
.hlt_works_ok) {
99
pr_cont
(
"disabled\n"
);
100
return
;
101
}
102
halt();
103
halt();
104
halt();
105
halt();
106
pr_cont
(
"OK\n"
);
107
}
108
109
/*
110
* Most 386 processors have a bug where a POPAD can lock the
111
* machine even from user space.
112
*/
113
114
static
void
__init
check_popad(
void
)
115
{
116
#ifndef CONFIG_X86_POPAD_OK
117
int
res
,
inp
= (
int
) &res;
118
119
pr_info
(
"Checking for popad bug... "
);
120
__asm__
__volatile__(
121
"movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx "
122
:
"=&a"
(res)
123
:
"d"
(inp)
124
:
"ecx"
,
"edi"
);
125
/*
126
* If this fails, it means that any user program may lock the
127
* CPU hard. Too bad.
128
*/
129
if
(res != 12345678)
130
pr_cont
(
"Buggy\n"
);
131
else
132
pr_cont
(
"OK\n"
);
133
#endif
134
}
135
136
/*
137
* Check whether we are able to run this kernel safely on SMP.
138
*
139
* - In order to run on a i386, we need to be compiled for i386
140
* (for due to lack of "invlpg" and working WP on a i386)
141
* - In order to run on anything without a TSC, we need to be
142
* compiled for a i486.
143
*/
144
145
static
void
__init
check_config(
void
)
146
{
147
/*
148
* We'd better not be a i386 if we're configured to use some
149
* i486+ only features! (WP works in supervisor mode and the
150
* new "invlpg" and "bswap" instructions)
151
*/
152
#if defined(CONFIG_X86_WP_WORKS_OK) || defined(CONFIG_X86_INVLPG) || \
153
defined(CONFIG_X86_BSWAP)
154
if
(
boot_cpu_data
.x86 == 3)
155
panic
(
"Kernel requires i486+ for 'invlpg' and other features"
);
156
#endif
157
}
158
159
160
void
__init
check_bugs
(
void
)
161
{
162
identify_boot_cpu
();
163
#ifndef CONFIG_SMP
164
pr_info
(
"CPU: "
);
165
print_cpu_info
(&
boot_cpu_data
);
166
#endif
167
check_config();
168
check_hlt();
169
check_popad();
170
init_utsname()->machine[1] =
171
'0'
+ (
boot_cpu_data
.x86 > 6 ? 6 :
boot_cpu_data
.x86);
172
alternative_instructions
();
173
174
/*
175
* kernel_fpu_begin/end() in check_fpu() relies on the patched
176
* alternative instructions.
177
*/
178
check_fpu();
179
}
Generated on Thu Jan 10 2013 13:20:25 for Linux Kernel by
1.8.2