]>
Commit | Line | Data |
---|---|---|
1d67953f VP |
1 | /* |
2 | * Routines to indentify additional cpu features that are scattered in | |
3 | * cpuid space. | |
4 | */ | |
1d67953f VP |
5 | #include <linux/cpu.h> |
6 | ||
8d4a4300 | 7 | #include <asm/pat.h> |
1d67953f VP |
8 | #include <asm/processor.h> |
9 | ||
bbb65d2d SS |
10 | #include <mach_apic.h> |
11 | ||
1d67953f VP |
12 | struct cpuid_bit { |
13 | u16 feature; | |
14 | u8 reg; | |
15 | u8 bit; | |
16 | u32 level; | |
17 | }; | |
18 | ||
19 | enum cpuid_regs { | |
20 | CR_EAX = 0, | |
21 | CR_ECX, | |
22 | CR_EDX, | |
23 | CR_EBX | |
24 | }; | |
25 | ||
26 | void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | |
27 | { | |
28 | u32 max_level; | |
29 | u32 regs[4]; | |
30 | const struct cpuid_bit *cb; | |
31 | ||
32 | static const struct cpuid_bit cpuid_bits[] = { | |
33 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, | |
34 | { 0, 0, 0, 0 } | |
35 | }; | |
36 | ||
37 | for (cb = cpuid_bits; cb->feature; cb++) { | |
38 | ||
39 | /* Verify that the level is valid */ | |
40 | max_level = cpuid_eax(cb->level & 0xffff0000); | |
41 | if (max_level < cb->level || | |
42 | max_level > (cb->level | 0xffff)) | |
43 | continue; | |
44 | ||
45 | cpuid(cb->level, ®s[CR_EAX], ®s[CR_EBX], | |
46 | ®s[CR_ECX], ®s[CR_EDX]); | |
47 | ||
48 | if (regs[cb->reg] & (1 << cb->bit)) | |
53756d37 | 49 | set_cpu_cap(c, cb->feature); |
1d67953f VP |
50 | } |
51 | } | |
8d4a4300 | 52 | |
bbb65d2d SS |
53 | /* leaf 0xb SMT level */ |
54 | #define SMT_LEVEL 0 | |
55 | ||
56 | /* leaf 0xb sub-leaf types */ | |
57 | #define INVALID_TYPE 0 | |
58 | #define SMT_TYPE 1 | |
59 | #define CORE_TYPE 2 | |
60 | ||
61 | #define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff) | |
62 | #define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f) | |
63 | #define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff) | |
64 | ||
65 | /* | |
66 | * Check for extended topology enumeration cpuid leaf 0xb and if it | |
67 | * exists, use it for populating initial_apicid and cpu topology | |
68 | * detection. | |
69 | */ | |
70 | void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) | |
71 | { | |
72 | unsigned int eax, ebx, ecx, edx, sub_index; | |
73 | unsigned int ht_mask_width, core_plus_mask_width; | |
74 | unsigned int core_select_mask, core_level_siblings; | |
75 | ||
76 | if (c->cpuid_level < 0xb) | |
77 | return; | |
78 | ||
79 | cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx); | |
80 | ||
81 | /* | |
82 | * check if the cpuid leaf 0xb is actually implemented. | |
83 | */ | |
84 | if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE)) | |
85 | return; | |
86 | ||
87 | set_cpu_cap(c, X86_FEATURE_XTOPOLOGY); | |
88 | ||
89 | /* | |
90 | * initial apic id, which also represents 32-bit extended x2apic id. | |
91 | */ | |
92 | c->initial_apicid = edx; | |
93 | ||
94 | /* | |
95 | * Populate HT related information from sub-leaf level 0. | |
96 | */ | |
97 | core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); | |
98 | core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); | |
99 | ||
100 | sub_index = 1; | |
101 | do { | |
102 | cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx); | |
103 | ||
104 | /* | |
105 | * Check for the Core type in the implemented sub leaves. | |
106 | */ | |
107 | if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) { | |
108 | core_level_siblings = LEVEL_MAX_SIBLINGS(ebx); | |
109 | core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); | |
110 | break; | |
111 | } | |
112 | ||
113 | sub_index++; | |
114 | } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE); | |
115 | ||
116 | core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width; | |
117 | ||
118 | #ifdef CONFIG_X86_32 | |
119 | c->cpu_core_id = phys_pkg_id(c->initial_apicid, ht_mask_width) | |
120 | & core_select_mask; | |
121 | c->phys_proc_id = phys_pkg_id(c->initial_apicid, core_plus_mask_width); | |
122 | #else | |
123 | c->cpu_core_id = phys_pkg_id(ht_mask_width) & core_select_mask; | |
124 | c->phys_proc_id = phys_pkg_id(core_plus_mask_width); | |
125 | #endif | |
126 | c->x86_max_cores = (core_level_siblings / smp_num_siblings); | |
127 | ||
128 | ||
129 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", | |
130 | c->phys_proc_id); | |
131 | if (c->x86_max_cores > 1) | |
132 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", | |
133 | c->cpu_core_id); | |
134 | return; | |
135 | } | |
136 | ||
8d4a4300 TG |
137 | #ifdef CONFIG_X86_PAT |
138 | void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) | |
139 | { | |
97cfab6a AH |
140 | if (!cpu_has_pat) |
141 | pat_disable("PAT not supported by CPU."); | |
142 | ||
8d4a4300 | 143 | switch (c->x86_vendor) { |
8d4a4300 TG |
144 | case X86_VENDOR_INTEL: |
145 | if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) | |
146 | return; | |
147 | break; | |
ee863ba7 | 148 | case X86_VENDOR_AMD: |
873b274a DJ |
149 | case X86_VENDOR_CENTAUR: |
150 | case X86_VENDOR_TRANSMETA: | |
151 | return; | |
8d4a4300 TG |
152 | } |
153 | ||
97cfab6a | 154 | pat_disable("PAT disabled. Not yet verified on this CPU type."); |
8d4a4300 TG |
155 | } |
156 | #endif |