1 #include <stdbool.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "uarch.h"
7 #include "../common/global.h"
8
9 /*
10 * - cpuid codes are based on Todd Allen's cpuid program
11 * http://www.etallen.com/cpuid.html
12 * - This should be updated from time to time, to support newer CPUs. A good reference to look at:
13 * https://en.wikichip.org/
14 * http://instlatx64.atw.hu/
15 */
16
17 // From Todd Allen:
18 //
19 // MSR_CPUID_table* is a table that appears in Intel document 325462, "Intel 64
20 // and IA-32 Architectures Software Developer's Manual Combined Volumes: 1, 2A,
21 // 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4" (the name changes from version to version
22 // as more volumes are added). The table moves around from version to version,
23 // but in version 071US, was in "Volume 4: Model-Specific Registers", Table 2-1:
24 // "CPUID Signature Values of DisplayFamily_DisplayModel".
25
26 // MRG* is a table that forms the bulk of Intel Microcode Revision Guidance (or
27 // Microcode Update Guidance). Its purpose is not to list CPUID values, but
28 // it does so, and sometimes lists values that appear nowhere else.
29
30 // LX* indicates features that I have seen no documentation for, but which are
31 // used by the Linux kernel (which is good evidence that they're correct).
32 // The "hook" to find these generally is an X86_FEATURE_* flag in:
33 // arch/x86/include/asm/cpufeatures.h
34 // For (synth) and (uarch synth) decoding, it often indicates
35 // family/model/stepping value which are documented nowhere else. These usually
36 // can be found in:
37 // arch/x86/include/asm/intel-family.h
38
39 typedef uint32_t MICROARCH;
40
41 // Data not available
42 #define NA -1
43
44 // Unknown manufacturing process
45 #define UNK -1
46
47 enum {
48 UARCH_UNKNOWN,
49 // INTEL //
50 UARCH_P5,
51 UARCH_P6,
52 UARCH_DOTHAN,
53 UARCH_YONAH,
54 UARCH_MEROM,
55 UARCH_PENYR,
56 UARCH_NEHALEM,
57 UARCH_WESTMERE,
58 UARCH_BONNELL,
59 UARCH_SALTWELL,
60 UARCH_SANDY_BRIDGE,
61 UARCH_SILVERMONT,
62 UARCH_IVY_BRIDGE,
63 UARCH_HASWELL,
64 UARCH_BROADWELL,
65 UARCH_AIRMONT,
66 UARCH_KABY_LAKE,
67 UARCH_COMET_LAKE,
68 UARCH_ROCKET_LAKE,
69 UARCH_AMBER_LAKE,
70 UARCH_WHISKEY_LAKE,
71 UARCH_SKYLAKE,
72 UARCH_CASCADE_LAKE,
73 UARCH_COOPER_LAKE,
74 UARCH_KNIGHTS_LANDING,
75 UARCH_KNIGHTS_MILL,
76 UARCH_GOLDMONT,
77 UARCH_PALM_COVE,
78 UARCH_SUNNY_COVE,
79 UARCH_GOLDMONT_PLUS,
80 UARCH_TREMONT,
81 UARCH_WILLOW_COVE,
82 UARCH_COFFE_LAKE,
83 UARCH_ITANIUM,
84 UARCH_KNIGHTS_FERRY,
85 UARCH_KNIGHTS_CORNER,
86 UARCH_WILLAMETTE,
87 UARCH_NORTHWOOD,
88 UARCH_PRESCOTT,
89 UARCH_CEDAR_MILL,
90 UARCH_ITANIUM2,
91 UARCH_ICE_LAKE,
92 // AMD //
93 UARCH_AM486,
94 UARCH_AM5X86,
95 UARCH_K6,
96 UARCH_K7,
97 UARCH_K8,
98 UARCH_K10,
99 UARCH_PUMA_2008,
100 UARCH_BOBCAT,
101 UARCH_BULLDOZER,
102 UARCH_PILEDRIVER,
103 UARCH_STEAMROLLER,
104 UARCH_EXCAVATOR,
105 UARCH_JAGUAR,
106 UARCH_PUMA_2014,
107 UARCH_ZEN,
108 UARCH_ZEN_PLUS,
109 UARCH_ZEN2,
110 UARCH_ZEN3
111 };
112
113 struct uarch {
114 MICROARCH uarch;
115 char* uarch_str;
116 int32_t process; // measured in nanometers
117 };
118
119 #define UARCH_START if (false) {}
120 #define CHECK_UARCH(arch, ef_, f_, em_, m_, s_, str, uarch, process) \
121 else if (ef_ == ef && f_ == f && (em_ == NA || em_ == em) && (m_ == NA || m_ == m) && (s_ == NA || s_ == s)) fill_uarch(arch, str, uarch, process);
122 #define UARCH_END else { printBug("Unknown microarchitecture detected: M=0x%.8X EM=0x%.8X F=0x%.8X EF=0x%.8X S=0x%.8X", m, em, f, ef, s); fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, 0); }
123
fill_uarch(struct uarch * arch,char * str,MICROARCH u,uint32_t process)124 void fill_uarch(struct uarch* arch, char* str, MICROARCH u, uint32_t process) {
125 arch->uarch_str = emalloc(sizeof(char) * (strlen(str)+1));
126 strcpy(arch->uarch_str, str);
127 arch->uarch = u;
128 arch->process= process;
129 }
130
131 // Inspired in Todd Allen's decode_uarch_intel
get_uarch_from_cpuid_intel(uint32_t ef,uint32_t f,uint32_t em,uint32_t m,int s)132 struct uarch* get_uarch_from_cpuid_intel(uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
133 struct uarch* arch = emalloc(sizeof(struct uarch));
134
135 // EF: Extended Family //
136 // F: Family //
137 // EM: Extended Model //
138 // M: Model //
139 // S: Stepping //
140 // ----------------------------------------------------------------------------- //
141 // EF F EM M S //
142 UARCH_START
143 CHECK_UARCH(arch, 0, 5, 0, 0, NA, "P5", UARCH_P5, 800)
144 CHECK_UARCH(arch, 0, 5, 0, 1, NA, "P5", UARCH_P5, 800)
145 CHECK_UARCH(arch, 0, 5, 0, 2, NA, "P5", UARCH_P5, UNK)
146 CHECK_UARCH(arch, 0, 5, 0, 3, NA, "P5", UARCH_P5, 600)
147 CHECK_UARCH(arch, 0, 5, 0, 4, NA, "P5 MMX", UARCH_P5, UNK)
148 CHECK_UARCH(arch, 0, 5, 0, 7, NA, "P5 MMX", UARCH_P5, UNK)
149 CHECK_UARCH(arch, 0, 5, 0, 8, NA, "P5 MMX", UARCH_P5, 250)
150 CHECK_UARCH(arch, 0, 5, 0, 9, NA, "P5 MMX", UARCH_P5, UNK)
151 CHECK_UARCH(arch, 0, 6, 0, 0, NA, "P6 Pentium II", UARCH_P6, UNK)
152 CHECK_UARCH(arch, 0, 6, 0, 1, NA, "P6 Pentium II", UARCH_P6, UNK) // process depends on core
153 CHECK_UARCH(arch, 0, 6, 0, 2, NA, "P6 Pentium II", UARCH_P6, UNK)
154 CHECK_UARCH(arch, 0, 6, 0, 3, NA, "P6 Pentium II", UARCH_P6, 350)
155 CHECK_UARCH(arch, 0, 6, 0, 4, NA, "P6 Pentium II", UARCH_P6, UNK)
156 CHECK_UARCH(arch, 0, 6, 0, 5, NA, "P6 Pentium II", UARCH_P6, 250)
157 CHECK_UARCH(arch, 0, 6, 0, 6, NA, "P6 Pentium II", UARCH_P6, UNK)
158 CHECK_UARCH(arch, 0, 6, 0, 7, NA, "P6 Pentium III", UARCH_P6, 250)
159 CHECK_UARCH(arch, 0, 6, 0, 8, NA, "P6 Pentium III", UARCH_P6, 180)
160 CHECK_UARCH(arch, 0, 6, 0, 9, NA, "P6 Pentium M", UARCH_P6, 130)
161 CHECK_UARCH(arch, 0, 6, 0, 10, NA, "P6 Pentium III", UARCH_P6, 180)
162 CHECK_UARCH(arch, 0, 6, 0, 11, NA, "P6 Pentium III", UARCH_P6, 130)
163 CHECK_UARCH(arch, 0, 6, 0, 13, NA, "Dothan", UARCH_DOTHAN, UNK) // process depends on core
164 CHECK_UARCH(arch, 0, 6, 0, 14, NA, "Yonah", UARCH_YONAH, 65)
165 CHECK_UARCH(arch, 0, 6, 0, 15, NA, "Merom", UARCH_MEROM, 65)
166 CHECK_UARCH(arch, 0, 6, 1, 5, NA, "Dothan", UARCH_DOTHAN, 90)
167 CHECK_UARCH(arch, 0, 6, 1, 6, NA, "Merom", UARCH_MEROM, 65)
168 CHECK_UARCH(arch, 0, 6, 1, 7, NA, "Penryn", UARCH_PENYR, 45)
169 CHECK_UARCH(arch, 0, 6, 1, 10, NA, "Nehalem", UARCH_NEHALEM, 45)
170 CHECK_UARCH(arch, 0, 6, 1, 12, NA, "Bonnell", UARCH_BONNELL, 45)
171 CHECK_UARCH(arch, 0, 6, 1, 13, NA, "Penryn", UARCH_PENYR, 45)
172 CHECK_UARCH(arch, 0, 6, 1, 14, NA, "Nehalem", UARCH_NEHALEM, 45)
173 CHECK_UARCH(arch, 0, 6, 1, 15, NA, "Nehalem", UARCH_NEHALEM, 45)
174 CHECK_UARCH(arch, 0, 6, 2, 5, NA, "Westmere", UARCH_WESTMERE, 32)
175 CHECK_UARCH(arch, 0, 6, 2 , 6, NA, "Bonnell", UARCH_BONNELL, 45)
176 CHECK_UARCH(arch, 0, 6, 2, 7, NA, "Saltwell", UARCH_SALTWELL, 32)
177 CHECK_UARCH(arch, 0, 6, 2, 10, NA, "Sandy Bridge", UARCH_SANDY_BRIDGE, 32)
178 CHECK_UARCH(arch, 0, 6, 2, 12, NA, "Westmere", UARCH_WESTMERE, 32)
179 CHECK_UARCH(arch, 0, 6, 2, 13, NA, "Sandy Bridge", UARCH_SANDY_BRIDGE, 32)
180 CHECK_UARCH(arch, 0, 6, 2, 14, NA, "Nehalem", UARCH_NEHALEM, 45)
181 CHECK_UARCH(arch, 0, 6, 2, 15, NA, "Westmere", UARCH_WESTMERE, 32)
182 CHECK_UARCH(arch, 0, 6, 3, 5, NA, "Saltwell", UARCH_SALTWELL, 14)
183 CHECK_UARCH(arch, 0, 6, 3, 6, NA, "Saltwell", UARCH_SALTWELL, 32)
184 CHECK_UARCH(arch, 0, 6, 3, 7, NA, "Silvermont", UARCH_SILVERMONT, 22)
185 CHECK_UARCH(arch, 0, 6, 3, 10, NA, "Ivy Bridge", UARCH_IVY_BRIDGE, 22)
186 CHECK_UARCH(arch, 0, 6, 3, 12, NA, "Haswell", UARCH_HASWELL, 22)
187 CHECK_UARCH(arch, 0, 6, 3, 13, NA, "Broadwell", UARCH_BROADWELL, 14)
188 CHECK_UARCH(arch, 0, 6, 3, 14, NA, "Ivy Bridge", UARCH_IVY_BRIDGE, 22)
189 CHECK_UARCH(arch, 0, 6, 3, 15, NA, "Haswell", UARCH_HASWELL, 22)
190 CHECK_UARCH(arch, 0, 6, 4, 5, NA, "Haswell", UARCH_HASWELL, 22)
191 CHECK_UARCH(arch, 0, 6, 4, 6, NA, "Haswell", UARCH_HASWELL, 22)
192 CHECK_UARCH(arch, 0, 6, 4, 7, NA, "Broadwell", UARCH_BROADWELL, 14)
193 CHECK_UARCH(arch, 0, 6, 4, 10, NA, "Silvermont", UARCH_SILVERMONT, 22) // no docs, but /proc/cpuinfo seen in wild
194 CHECK_UARCH(arch, 0, 6, 4, 12, NA, "Airmont", UARCH_AIRMONT, 14)
195 CHECK_UARCH(arch, 0, 6, 4, 13, NA, "Silvermont", UARCH_SILVERMONT, 22)
196 CHECK_UARCH(arch, 0, 6, 4, 14, 8, "Kaby Lake", UARCH_KABY_LAKE, 14)
197 CHECK_UARCH(arch, 0, 6, 4, 14, NA, "Skylake", UARCH_SKYLAKE, 14)
198 CHECK_UARCH(arch, 0, 6, 4, 15, NA, "Broadwell", UARCH_BROADWELL, 14)
199 CHECK_UARCH(arch, 0, 6, 5, 5, 6, "Cascade Lake", UARCH_CASCADE_LAKE, 14) // no docs, but example from Greg Stewart
200 CHECK_UARCH(arch, 0, 6, 5, 5, 7, "Cascade Lake", UARCH_CASCADE_LAKE, 14)
201 CHECK_UARCH(arch, 0, 6, 5, 5, 10, "Cooper Lake", UARCH_COOPER_LAKE, 14)
202 CHECK_UARCH(arch, 0, 6, 5, 5, NA, "Skylake", UARCH_SKYLAKE, 14)
203 CHECK_UARCH(arch, 0, 6, 5, 6, NA, "Broadwell", UARCH_BROADWELL, 14)
204 CHECK_UARCH(arch, 0, 6, 5, 7, NA, "Knights Landing", UARCH_KNIGHTS_LANDING, 14)
205 CHECK_UARCH(arch, 0, 6, 5, 10, NA, "Silvermont", UARCH_SILVERMONT, 22) // no spec update; only MSR_CPUID_table* so far
206 CHECK_UARCH(arch, 0, 6, 5, 12, NA, "Goldmont", UARCH_GOLDMONT, 14)
207 CHECK_UARCH(arch, 0, 6, 5, 13, NA, "Silvermont", UARCH_SILVERMONT, 22) // no spec update; only MSR_CPUID_table* so far
208 CHECK_UARCH(arch, 0, 6, 5, 14, 8, "Kaby Lake", UARCH_KABY_LAKE, 14)
209 CHECK_UARCH(arch, 0, 6, 5, 14, NA, "Skylake", UARCH_SKYLAKE, 14)
210 CHECK_UARCH(arch, 0, 6, 5, 15, NA, "Goldmont", UARCH_GOLDMONT, 14)
211 CHECK_UARCH(arch, 0, 6, 6, 6, NA, "Palm Cove", UARCH_PALM_COVE, 10) // no spec update; only MSR_CPUID_table* so far
212 CHECK_UARCH(arch, 0, 6, 6, 10, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far
213 CHECK_UARCH(arch, 0, 6, 6, 12, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far
214 CHECK_UARCH(arch, 0, 6, 7, 5, NA, "Airmont", UARCH_AIRMONT, 14) // no spec update; whispers & rumors
215 CHECK_UARCH(arch, 0, 6, 7, 10, NA, "Goldmont Plus", UARCH_GOLDMONT_PLUS, 14)
216 CHECK_UARCH(arch, 0, 6, 7, 13, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far
217 CHECK_UARCH(arch, 0, 6, 7, 14, NA, "Ice Lake", UARCH_ICE_LAKE, 10)
218 CHECK_UARCH(arch, 0, 6, 8, 5, NA, "Knights Mill", UARCH_KNIGHTS_MILL, 14) // no spec update; only MSR_CPUID_table* so far
219 CHECK_UARCH(arch, 0, 6, 8, 6, NA, "Tremont", UARCH_TREMONT, 10) // LX*
220 CHECK_UARCH(arch, 0, 6, 8, 10, NA, "Tremont", UARCH_TREMONT, 10) // no spec update; only geekbench.com example
221 CHECK_UARCH(arch, 0, 6, 8, 12, NA, "Willow Cove", UARCH_WILLOW_COVE, 10) // found only on en.wikichip.org
222 CHECK_UARCH(arch, 0, 6, 8, 13, NA, "Willow Cove", UARCH_WILLOW_COVE, 10) // LX*
223 CHECK_UARCH(arch, 0, 6, 8, 14, 9, "Amber Lake", UARCH_AMBER_LAKE, 14) // wikichip
224 CHECK_UARCH(arch, 0, 6, 8, 14, 10, "Kaby Lake", UARCH_KABY_LAKE, 14) // wikichip
225 CHECK_UARCH(arch, 0, 6, 8, 14, 11, "Whiskey Lake", UARCH_WHISKEY_LAKE, 14) // wikichip
226 CHECK_UARCH(arch, 0, 6, 8, 14, 12, "Comet Lake", UARCH_COMET_LAKE, 14) // wikichip
227 CHECK_UARCH(arch, 0, 6, 9, 6, NA, "Tremont", UARCH_TREMONT, 10) // LX*
228 CHECK_UARCH(arch, 0, 6, 9, 12, NA, "Tremont", UARCH_TREMONT, 10) // LX*
229 CHECK_UARCH(arch, 0, 6, 9, 13, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // LX*
230 CHECK_UARCH(arch, 0, 6, 9, 14, 9, "Kaby Lake", UARCH_KABY_LAKE, 14)
231 CHECK_UARCH(arch, 0, 6, 9, 14, 10, "Coffee Lake", UARCH_COFFE_LAKE, 14)
232 CHECK_UARCH(arch, 0, 6, 9, 14, 11, "Coffee Lake", UARCH_COFFE_LAKE, 14)
233 CHECK_UARCH(arch, 0, 6, 9, 14, 12, "Coffee Lake", UARCH_COFFE_LAKE, 14)
234 CHECK_UARCH(arch, 0, 6, 9, 14, 13, "Coffee Lake", UARCH_COFFE_LAKE, 14)
235 CHECK_UARCH(arch, 0, 6, 10, 5, NA, "Comet Lake", UARCH_COMET_LAKE, 14) // wikichip
236 CHECK_UARCH(arch, 0, 6, 10, 6, NA, "Comet Lake", UARCH_COMET_LAKE, 14) // instlatx64.atw.hu (i7-10710U)
237 CHECK_UARCH(arch, 0, 6, 10, 7, NA, "Rocket Lake", UARCH_ROCKET_LAKE, 14) // instlatx64.atw.hu (i7-11700K)
238 CHECK_UARCH(arch, 0, 11, 0, 0, NA, "Knights Ferry", UARCH_KNIGHTS_FERRY, 45) // found only on en.wikichip.org
239 CHECK_UARCH(arch, 0, 11, 0, 1, NA, "Knights Corner", UARCH_KNIGHTS_CORNER, 22)
240 CHECK_UARCH(arch, 0, 15, 0, 0, NA, "Willamette", UARCH_WILLAMETTE, 180)
241 CHECK_UARCH(arch, 0, 15, 0, 1, NA, "Willamette", UARCH_WILLAMETTE, 180)
242 CHECK_UARCH(arch, 0, 15, 0, 2, NA, "Northwood", UARCH_NORTHWOOD, 130)
243 CHECK_UARCH(arch, 0, 15, 0, 3, NA, "Prescott", UARCH_PRESCOTT, 90)
244 CHECK_UARCH(arch, 0, 15, 0, 4, NA, "Prescott", UARCH_PRESCOTT, 90)
245 CHECK_UARCH(arch, 0, 15, 0, 6, NA, "Cedar Mill", UARCH_CEDAR_MILL, 65)
246 CHECK_UARCH(arch, 1, 15, 0, 0, NA, "Itanium2", UARCH_ITANIUM2, 180)
247 CHECK_UARCH(arch, 1, 15, 0, 1, NA, "Itanium2", UARCH_ITANIUM2, 130)
248 CHECK_UARCH(arch, 1, 15, 0, 2, NA, "Itanium2", UARCH_ITANIUM2, 130)
249 UARCH_END
250
251 return arch;
252 }
253
254 // iNApired in Todd Allen's decode_uarch_amd
get_uarch_from_cpuid_amd(uint32_t ef,uint32_t f,uint32_t em,uint32_t m,int s)255 struct uarch* get_uarch_from_cpuid_amd(uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
256 struct uarch* arch = emalloc(sizeof(struct uarch));
257
258 // EF: Extended Family //
259 // F: Family //
260 // EM: Extended Model //
261 // M: Model //
262 // S: Stepping //
263 // ----------------------------------------------------------------------------- //
264 // EF F EM M S //
265 UARCH_START
266 CHECK_UARCH(arch, 0, 4, 0, 3, NA, "Am486", UARCH_AM486, UNK)
267 CHECK_UARCH(arch, 0, 4, 0, 7, NA, "Am486", UARCH_AM486, UNK)
268 CHECK_UARCH(arch, 0, 4, 0, 8, NA, "Am486", UARCH_AM486, UNK)
269 CHECK_UARCH(arch, 0, 4, 0, 9, NA, "Am486", UARCH_AM486, UNK)
270 CHECK_UARCH(arch, 0, 4, NA, NA, NA, "Am5x86", UARCH_AM5X86, UNK)
271 CHECK_UARCH(arch, 0, 5, 0, 6, NA, "K6", UARCH_K6, 300)
272 CHECK_UARCH(arch, 0, 5, 0, 7, NA, "K6", UARCH_K6, 250) // *p from sandpile.org
273 CHECK_UARCH(arch, 0, 5, 0, 13, NA, "K6", UARCH_K6, 80) // *p from sandpile.org
274 CHECK_UARCH(arch, 0, 5, NA, NA, NA, "K6", UARCH_K6, UNK)
275 CHECK_UARCH(arch, 0, 6, 0, 1, NA, "K7", UARCH_K7, 250)
276 CHECK_UARCH(arch, 0, 6, 0, 2, NA, "K7", UARCH_K7, 180)
277 CHECK_UARCH(arch, 0, 6, NA, NA, NA, "K7", UARCH_K7, UNK)
278 CHECK_UARCH(arch, 0, 15, 0, 4, 8, "K8", UARCH_K8, 130)
279 CHECK_UARCH(arch, 0, 15, 0, 4, NA, "K8", UARCH_K8, 130)
280 CHECK_UARCH(arch, 0, 15, 0, 5, NA, "K8", UARCH_K8, 130)
281 CHECK_UARCH(arch, 0, 15, 0, 7, NA, "K8", UARCH_K8, 130)
282 CHECK_UARCH(arch, 0, 15, 0, 8, NA, "K8", UARCH_K8, 130)
283 CHECK_UARCH(arch, 0, 15, 0, 11, NA, "K8", UARCH_K8, 130)
284 CHECK_UARCH(arch, 0, 15, 0, 12, NA, "K8", UARCH_K8, 130)
285 CHECK_UARCH(arch, 0, 15, 0, 14, NA, "K8", UARCH_K8, 130)
286 CHECK_UARCH(arch, 0, 15, 0, 15, NA, "K8", UARCH_K8, 130)
287 CHECK_UARCH(arch, 0, 15, 1, 4, NA, "K8", UARCH_K8, 90)
288 CHECK_UARCH(arch, 0, 15, 1, 5, NA, "K8", UARCH_K8, 90)
289 CHECK_UARCH(arch, 0, 15, 1, 7, NA, "K8", UARCH_K8, 90)
290 CHECK_UARCH(arch, 0, 15, 1, 8, NA, "K8", UARCH_K8, 90)
291 CHECK_UARCH(arch, 0, 15, 1, 11, NA, "K8", UARCH_K8, 90)
292 CHECK_UARCH(arch, 0, 15, 1, 12, NA, "K8", UARCH_K8, 90)
293 CHECK_UARCH(arch, 0, 15, 1, 15, NA, "K8", UARCH_K8, 90)
294 CHECK_UARCH(arch, 0, 15, 2, 1, NA, "K8", UARCH_K8, 90)
295 CHECK_UARCH(arch, 0, 15, 2, 3, NA, "K8", UARCH_K8, 90)
296 CHECK_UARCH(arch, 0, 15, 2, 4, NA, "K8", UARCH_K8, 90)
297 CHECK_UARCH(arch, 0, 15, 2, 5, NA, "K8", UARCH_K8, 90)
298 CHECK_UARCH(arch, 0, 15, 2, 7, NA, "K8", UARCH_K8, 90)
299 CHECK_UARCH(arch, 0, 15, 2, 11, NA, "K8", UARCH_K8, 90)
300 CHECK_UARCH(arch, 0, 15, 2, 12, NA, "K8", UARCH_K8, 90)
301 CHECK_UARCH(arch, 0, 15, 2, 15, NA, "K8", UARCH_K8, 90)
302 CHECK_UARCH(arch, 0, 15, 4, 1, NA, "K8", UARCH_K8, 90)
303 CHECK_UARCH(arch, 0, 15, 4, 3, NA, "K8", UARCH_K8, 90)
304 CHECK_UARCH(arch, 0, 15, 4, 8, NA, "K8", UARCH_K8, 90)
305 CHECK_UARCH(arch, 0, 15, 4, 11, NA, "K8", UARCH_K8, 90)
306 CHECK_UARCH(arch, 0, 15, 4, 12, NA, "K8", UARCH_K8, 90)
307 CHECK_UARCH(arch, 0, 15, 4, 15, NA, "K8", UARCH_K8, 90)
308 CHECK_UARCH(arch, 0, 15, 5, 13, NA, "K8", UARCH_K8, 90)
309 CHECK_UARCH(arch, 0, 15, 5, 15, NA, "K8", UARCH_K8, 90)
310 CHECK_UARCH(arch, 0, 15, 6, 8, NA, "K8", UARCH_K8, 65)
311 CHECK_UARCH(arch, 0, 15, 6, 11, NA, "K8", UARCH_K8, 65)
312 CHECK_UARCH(arch, 0, 15, 6, 12, NA, "K8", UARCH_K8, 65)
313 CHECK_UARCH(arch, 0, 15, 6, 15, NA, "K8", UARCH_K8, 65)
314 CHECK_UARCH(arch, 0, 15, 7, 12, NA, "K8", UARCH_K8, 65)
315 CHECK_UARCH(arch, 0, 15, 7, 15, NA, "K8", UARCH_K8, 65)
316 CHECK_UARCH(arch, 0, 15, 12, 1, NA, "K8", UARCH_K8, 90)
317 CHECK_UARCH(arch, 1, 15, 0, 0, NA, "K10", UARCH_K10, 65) // sandpile.org
318 CHECK_UARCH(arch, 1, 15, 0, 2, NA, "K10", UARCH_K10, 65)
319 CHECK_UARCH(arch, 1, 15, 0, 4, NA, "K10", UARCH_K10, 45)
320 CHECK_UARCH(arch, 1, 15, 0, 5, NA, "K10", UARCH_K10, 45)
321 CHECK_UARCH(arch, 1, 15, 0, 6, NA, "K10", UARCH_K10, 45)
322 CHECK_UARCH(arch, 1, 15, 0, 8, NA, "K10", UARCH_K10, 45)
323 CHECK_UARCH(arch, 1, 15, 0, 9, NA, "K10", UARCH_K10, 45)
324 CHECK_UARCH(arch, 1, 15, 0, 10, NA, "K10", UARCH_K10, 45)
325 CHECK_UARCH(arch, 2, 15, NA, NA, NA, "Puma 2008", UARCH_PUMA_2008, 65)
326 CHECK_UARCH(arch, 3, 15, NA, NA, NA, "K10", UARCH_K10, 32)
327 CHECK_UARCH(arch, 5, 15, NA, NA, NA, "Bobcat", UARCH_BOBCAT, 40)
328 CHECK_UARCH(arch, 6, 15, 0, 0, NA, "Bulldozer", UARCH_BULLDOZER, 32) // iNAtlatx64 engr sample
329 CHECK_UARCH(arch, 6, 15, 0, 1, NA, "Bulldozer", UARCH_BULLDOZER, 32)
330 CHECK_UARCH(arch, 6, 15, 0, 2, NA, "Piledriver", UARCH_PILEDRIVER, 32)
331 CHECK_UARCH(arch, 6, 15, 1, 0, NA, "Piledriver", UARCH_PILEDRIVER, 32)
332 CHECK_UARCH(arch, 6, 15, 1, 3, NA, "Piledriver", UARCH_PILEDRIVER, 32)
333 CHECK_UARCH(arch, 6, 15, 3, 0, NA, "Steamroller", UARCH_STEAMROLLER, 28)
334 CHECK_UARCH(arch, 6, 15, 3, 8, NA, "Steamroller", UARCH_STEAMROLLER, 28)
335 CHECK_UARCH(arch, 6, 15, 4, 0, NA, "Steamroller", UARCH_STEAMROLLER, 28) // Software Optimization Guide (15h) says it has the same iNAt latencies as (6,15),(3,x).
336 CHECK_UARCH(arch, 6, 15, 6, 0, NA, "Excavator", UARCH_EXCAVATOR, 28) // undocumented, but iNAtlatx64 samples
337 CHECK_UARCH(arch, 6, 15, 6, 5, NA, "Excavator", UARCH_EXCAVATOR, 28) // undocumented, but sample from Alexandros Couloumbis
338 CHECK_UARCH(arch, 6, 15, 7, 0, NA, "Excavator", UARCH_EXCAVATOR, 28)
339 CHECK_UARCH(arch, 7, 15, 0, 0, NA, "Jaguar", UARCH_JAGUAR, 28)
340 CHECK_UARCH(arch, 7, 15, 3, 0, NA, "Puma 2014", UARCH_PUMA_2014, 28)
341 CHECK_UARCH(arch, 8, 15, 0, 0, NA, "Zen", UARCH_ZEN, 14) // iNAtlatx64 engr sample
342 CHECK_UARCH(arch, 8, 15, 0, 1, NA, "Zen", UARCH_ZEN, 14)
343 CHECK_UARCH(arch, 8, 15, 0, 8, NA, "Zen+", UARCH_ZEN_PLUS, 12)
344 CHECK_UARCH(arch, 8, 15, 1, 1, NA, "Zen", UARCH_ZEN, 14) // found only on en.wikichip.org & iNAtlatx64 examples
345 CHECK_UARCH(arch, 8, 15, 1, 8, NA, "Zen+", UARCH_ZEN_PLUS, 12) // found only on en.wikichip.org
346 CHECK_UARCH(arch, 8, 15, 3, 1, NA, "Zen 2", UARCH_ZEN2, 7) // found only on en.wikichip.org
347 CHECK_UARCH(arch, 8, 15, 6, 0, NA, "Zen 2", UARCH_ZEN2, 7) // undocumented, geekbench.com example
348 CHECK_UARCH(arch, 8, 15, 6, 8, NA, "Zen 2", UARCH_ZEN2, 7) // found on instlatx64
349 CHECK_UARCH(arch, 8, 15, 7, 1, NA, "Zen 2", UARCH_ZEN2, 7) // samples from Steven Noonan and instlatx64
350 CHECK_UARCH(arch, 10, 15, 2, 1, NA, "Zen 3", UARCH_ZEN3, 7) // instlatx64
351 CHECK_UARCH(arch, 10, 15, 5, 0, NA, "Zen 3", UARCH_ZEN3, 7) // instlatx64
352 UARCH_END
353
354 return arch;
355 }
356
get_uarch_from_cpuid(struct cpuInfo * cpu,uint32_t ef,uint32_t f,uint32_t em,uint32_t m,int s)357 struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
358 if(cpu->cpu_vendor == CPU_VENDOR_INTEL)
359 return get_uarch_from_cpuid_intel(ef, f, em, m, s);
360 else
361 return get_uarch_from_cpuid_amd(ef, f, em, m, s);
362 }
363
vpus_are_AVX512(struct cpuInfo * cpu)364 bool vpus_are_AVX512(struct cpuInfo* cpu) {
365 return cpu->arch->uarch != UARCH_ICE_LAKE;
366 }
367
is_knights_landing(struct cpuInfo * cpu)368 bool is_knights_landing(struct cpuInfo* cpu) {
369 return cpu->arch->uarch == UARCH_KNIGHTS_LANDING;
370 }
371
get_number_of_vpus(struct cpuInfo * cpu)372 int get_number_of_vpus(struct cpuInfo* cpu) {
373 switch(cpu->arch->uarch) {
374 // Intel
375 case UARCH_HASWELL:
376 case UARCH_BROADWELL:
377
378 case UARCH_SKYLAKE:
379 case UARCH_CASCADE_LAKE:
380 case UARCH_KABY_LAKE:
381 case UARCH_COMET_LAKE:
382 case UARCH_ROCKET_LAKE:
383 case UARCH_AMBER_LAKE:
384 case UARCH_WHISKEY_LAKE:
385 case UARCH_COFFE_LAKE:
386 case UARCH_PALM_COVE:
387
388 case UARCH_KNIGHTS_LANDING:
389 case UARCH_KNIGHTS_MILL:
390
391 case UARCH_ICE_LAKE:
392
393 // AMD
394 case UARCH_ZEN2:
395 case UARCH_ZEN3:
396 return 2;
397 default:
398 return 1;
399 }
400 }
401
choose_new_intel_logo_uarch(struct cpuInfo * cpu)402 bool choose_new_intel_logo_uarch(struct cpuInfo* cpu) {
403 switch(cpu->arch->uarch) {
404 case UARCH_ROCKET_LAKE:
405 // TODO: case UARCH_TIGER_LAKE: missing?
406 return true;
407 default:
408 return false;
409 }
410 }
411
get_str_uarch(struct cpuInfo * cpu)412 char* get_str_uarch(struct cpuInfo* cpu) {
413 return cpu->arch->uarch_str;
414 }
415
get_str_process(struct cpuInfo * cpu)416 char* get_str_process(struct cpuInfo* cpu) {
417 char* str = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
418 int32_t process = cpu->arch->process;
419
420 if(process == UNK) {
421 snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
422 }
423 else if(process > 100) {
424 sprintf(str, "%.2fum", (double)process/100);
425 }
426 else if(process > 0){
427 sprintf(str, "%dnm", process);
428 }
429 else {
430 snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
431 printBug("Found invalid process: '%d'", process);
432 }
433
434 return str;
435 }
436
free_uarch_struct(struct uarch * arch)437 void free_uarch_struct(struct uarch* arch) {
438 free(arch->uarch_str);
439 free(arch);
440 }
441