Commit | Line | Data |
---|---|---|
2decb194 PA |
1 | /* |
2 | * Routines to indentify additional cpu features that are scattered in | |
3 | * cpuid space. | |
4 | */ | |
5 | #include <linux/cpu.h> | |
6 | ||
7 | #include <asm/pat.h> | |
8 | #include <asm/processor.h> | |
9 | ||
10 | #include <asm/apic.h> | |
11 | ||
12 | struct cpuid_bit { | |
13 | u16 feature; | |
14 | u8 reg; | |
15 | u8 bit; | |
16 | u32 level; | |
17 | u32 sub_leaf; | |
18 | }; | |
19 | ||
20 | enum cpuid_regs { | |
21 | CR_EAX = 0, | |
22 | CR_ECX, | |
23 | CR_EDX, | |
24 | CR_EBX | |
25 | }; | |
26 | ||
27 | void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | |
28 | { | |
29 | u32 max_level; | |
30 | u32 regs[4]; | |
31 | const struct cpuid_bit *cb; | |
32 | ||
33 | static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { | |
34 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 }, | |
35 | { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 }, | |
9792db61 FY |
36 | { X86_FEATURE_PLN, CR_EAX, 4, 0x00000006, 0 }, |
37 | { X86_FEATURE_PTS, CR_EAX, 6, 0x00000006, 0 }, | |
2decb194 PA |
38 | { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 }, |
39 | { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 }, | |
40 | { X86_FEATURE_XSAVEOPT, CR_EAX, 0, 0x0000000d, 1 }, | |
41 | { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 }, | |
42 | { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a, 0 }, | |
43 | { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 }, | |
44 | { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 }, | |
45 | { X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a, 0 }, | |
aeb9c7d6 AP |
46 | { X86_FEATURE_TSCRATEMSR, CR_EDX, 4, 0x8000000a, 0 }, |
47 | { X86_FEATURE_VMCBCLEAN, CR_EDX, 5, 0x8000000a, 0 }, | |
48 | { X86_FEATURE_FLUSHBYASID, CR_EDX, 6, 0x8000000a, 0 }, | |
49 | { X86_FEATURE_DECODEASSISTS, CR_EDX, 7, 0x8000000a, 0 }, | |
50 | { X86_FEATURE_PAUSEFILTER, CR_EDX,10, 0x8000000a, 0 }, | |
51 | { X86_FEATURE_PFTHRESHOLD, CR_EDX,12, 0x8000000a, 0 }, | |
2decb194 PA |
52 | { 0, 0, 0, 0, 0 } |
53 | }; | |
54 | ||
55 | for (cb = cpuid_bits; cb->feature; cb++) { | |
56 | ||
57 | /* Verify that the level is valid */ | |
58 | max_level = cpuid_eax(cb->level & 0xffff0000); | |
59 | if (max_level < cb->level || | |
60 | max_level > (cb->level | 0xffff)) | |
61 | continue; | |
62 | ||
63 | cpuid_count(cb->level, cb->sub_leaf, ®s[CR_EAX], | |
64 | ®s[CR_EBX], ®s[CR_ECX], ®s[CR_EDX]); | |
65 | ||
66 | if (regs[cb->reg] & (1 << cb->bit)) | |
67 | set_cpu_cap(c, cb->feature); | |
68 | } | |
69 | } |