26 #include <linux/types.h>
28 #include <asm/required-features.h>
32 static u32 cpu_vendor[3];
35 static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY;
49 #define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
51 static int is_amd(
void)
53 return cpu_vendor[0] ==
A32(
'A',
'u',
't',
'h') &&
54 cpu_vendor[1] ==
A32(
'e',
'n',
't',
'i') &&
55 cpu_vendor[2] ==
A32(
'c',
'A',
'M',
'D');
58 static int is_centaur(
void)
60 return cpu_vendor[0] ==
A32(
'C',
'e',
'n',
't') &&
61 cpu_vendor[1] ==
A32(
'a',
'u',
'r',
'H') &&
62 cpu_vendor[2] ==
A32(
'a',
'u',
'l',
's');
65 static int is_transmeta(
void)
67 return cpu_vendor[0] ==
A32(
'G',
'e',
'n',
'u') &&
68 cpu_vendor[1] ==
A32(
'i',
'n',
'e',
'T') &&
69 cpu_vendor[2] ==
A32(
'M',
'x',
'8',
'6');
72 static int has_fpu(
void)
74 u16 fcw = -1, fsw = -1;
77 asm(
"movl %%cr0,%0" :
"=r" (
cr0));
80 asm volatile(
"movl %0,%%cr0" : :
"r" (
cr0));
83 asm volatile(
"fninit ; fnstsw %0 ; fnstcw %1"
84 :
"+m" (fsw),
"+m" (fcw));
86 return fsw == 0 && (fcw & 0x103f) == 0x003f;
103 :
"=&r" (
f0),
"=&r" (f1)
106 return !!((f0^
f1) & mask);
109 static void get_flags(
void)
111 u32 max_intel_level, max_amd_level;
119 :
"=a" (max_intel_level),
120 "=b" (cpu_vendor[0]),
121 "=d" (cpu_vendor[1]),
125 if (max_intel_level >= 0x00000001 &&
126 max_intel_level <= 0x0000ffff) {
133 cpu.level = (tfms >> 8) & 15;
134 cpu.model = (tfms >> 4) & 15;
136 cpu.model += ((tfms >> 16) & 0xf) << 4;
140 :
"=a" (max_amd_level)
142 :
"ebx",
"ecx",
"edx");
144 if (max_amd_level >= 0x80000001 &&
145 max_amd_level <= 0x8000ffff) {
146 u32 eax = 0x80000001;
157 static int check_flags(
void)
164 err_flags[
i] = req_flags[
i] & ~
cpu.flags[
i];
180 int check_cpu(
int *cpu_level_ptr,
int *req_level_ptr,
u32 **err_flags_ptr)
206 asm(
"rdmsr" :
"=a" (eax),
"=d" (edx) :
"c" (
ecx));
208 asm(
"wrmsr" : :
"a" (eax),
"d" (edx),
"c" (
ecx));
212 }
else if (err == 0x01 &&
214 is_centaur() &&
cpu.model >= 6) {
221 asm(
"rdmsr" :
"=a" (eax),
"=d" (edx) :
"c" (
ecx));
222 eax |= (1<<1)|(1<<7);
223 asm(
"wrmsr" : :
"a" (eax),
"d" (edx),
"c" (
ecx));
227 }
else if (err == 0x01 && is_transmeta()) {
234 asm(
"rdmsr" :
"=a" (eax),
"=d" (edx) :
"c" (
ecx));
235 asm(
"wrmsr" : :
"a" (~0),
"d" (edx),
"c" (
ecx));
239 asm(
"wrmsr" : :
"a" (eax),
"d" (edx),
"c" (
ecx));
245 *err_flags_ptr = err ? err_flags :
NULL;
247 *cpu_level_ptr =
cpu.level;
249 *req_level_ptr = req_level;
251 return (
cpu.level < req_level || err) ? -1 : 0;