1 /* Get CPU type and Features for x86 processors.
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 Contributed by Sriraman Tallam (tmsriram@google.com)
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
20
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
25
26 #include "cpuid.h"
27 #include "tsystem.h"
28 #include "auto-target.h"
29 #include "cpuinfo.h"
30
31 #ifdef HAVE_INIT_PRIORITY
32 #define CONSTRUCTOR_PRIORITY (101)
33 #else
34 #define CONSTRUCTOR_PRIORITY
35 #endif
36
37 int __cpu_indicator_init (void)
38 __attribute__ ((constructor CONSTRUCTOR_PRIORITY));
39
40
41 struct __processor_model __cpu_model = { };
42 #ifndef SHARED
43 /* We want to move away from __cpu_model in libgcc_s.so.1 and the
44 size of __cpu_model is part of ABI. So, new features that don't
45 fit into __cpu_model.__cpu_features[0] go into extra variables
46 in libgcc.a only, preferrably hidden. */
47 unsigned int __cpu_features2;
48 #endif
49
50
51 /* Get the specific type of AMD CPU. */
52
53 static void
get_amd_cpu(unsigned int family,unsigned int model)54 get_amd_cpu (unsigned int family, unsigned int model)
55 {
56 switch (family)
57 {
58 /* AMD Family 10h. */
59 case 0x10:
60 __cpu_model.__cpu_type = AMDFAM10H;
61 switch (model)
62 {
63 case 0x2:
64 /* Barcelona. */
65 __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
66 break;
67 case 0x4:
68 /* Shanghai. */
69 __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
70 break;
71 case 0x8:
72 /* Istanbul. */
73 __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
74 break;
75 default:
76 break;
77 }
78 break;
79 /* AMD Family 14h "btver1". */
80 case 0x14:
81 __cpu_model.__cpu_type = AMD_BTVER1;
82 break;
83 /* AMD Family 15h "Bulldozer". */
84 case 0x15:
85 __cpu_model.__cpu_type = AMDFAM15H;
86
87 if (model == 0x2)
88 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
89 /* Bulldozer version 1. */
90 else if (model <= 0xf)
91 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
92 /* Bulldozer version 2 "Piledriver" */
93 else if (model <= 0x2f)
94 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
95 /* Bulldozer version 3 "Steamroller" */
96 else if (model <= 0x4f)
97 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
98 /* Bulldozer version 4 "Excavator" */
99 else if (model <= 0x7f)
100 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
101 break;
102 /* AMD Family 16h "btver2" */
103 case 0x16:
104 __cpu_model.__cpu_type = AMD_BTVER2;
105 break;
106 case 0x17:
107 __cpu_model.__cpu_type = AMDFAM17H;
108 /* AMD family 17h version 1. */
109 if (model <= 0x1f)
110 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
111 break;
112 default:
113 break;
114 }
115 }
116
117 /* Get the specific type of Intel CPU. */
118
119 static void
get_intel_cpu(unsigned int family,unsigned int model,unsigned int brand_id)120 get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
121 {
122 /* Parse family and model only if brand ID is 0. */
123 if (brand_id == 0)
124 {
125 switch (family)
126 {
127 case 0x5:
128 /* Pentium. */
129 break;
130 case 0x6:
131 switch (model)
132 {
133 case 0x1c:
134 case 0x26:
135 /* Bonnell. */
136 __cpu_model.__cpu_type = INTEL_BONNELL;
137 break;
138 case 0x37:
139 case 0x4a:
140 case 0x4d:
141 case 0x5a:
142 case 0x5d:
143 /* Silvermont. */
144 __cpu_model.__cpu_type = INTEL_SILVERMONT;
145 break;
146 case 0x57:
147 /* Knights Landing. */
148 __cpu_model.__cpu_type = INTEL_KNL;
149 break;
150 case 0x85:
151 /* Knights Mill. */
152 __cpu_model.__cpu_type = INTEL_KNM;
153 break;
154 case 0x1a:
155 case 0x1e:
156 case 0x1f:
157 case 0x2e:
158 /* Nehalem. */
159 __cpu_model.__cpu_type = INTEL_COREI7;
160 __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
161 break;
162 case 0x25:
163 case 0x2c:
164 case 0x2f:
165 /* Westmere. */
166 __cpu_model.__cpu_type = INTEL_COREI7;
167 __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
168 break;
169 case 0x2a:
170 case 0x2d:
171 /* Sandy Bridge. */
172 __cpu_model.__cpu_type = INTEL_COREI7;
173 __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
174 break;
175 case 0x3a:
176 case 0x3e:
177 /* Ivy Bridge. */
178 __cpu_model.__cpu_type = INTEL_COREI7;
179 __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
180 break;
181 case 0x3c:
182 case 0x3f:
183 case 0x45:
184 case 0x46:
185 /* Haswell. */
186 __cpu_model.__cpu_type = INTEL_COREI7;
187 __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
188 break;
189 case 0x3d:
190 case 0x47:
191 case 0x4f:
192 case 0x56:
193 /* Broadwell. */
194 __cpu_model.__cpu_type = INTEL_COREI7;
195 __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
196 break;
197 case 0x4e:
198 case 0x5e:
199 /* Skylake. */
200 case 0x8e:
201 case 0x9e:
202 /* Kaby Lake. */
203 __cpu_model.__cpu_type = INTEL_COREI7;
204 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
205 break;
206 case 0x55:
207 /* Skylake with AVX-512 support. */
208 __cpu_model.__cpu_type = INTEL_COREI7;
209 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
210 break;
211 case 0x66:
212 /* Cannon Lake. */
213 __cpu_model.__cpu_type = INTEL_COREI7;
214 __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
215 break;
216 case 0x17:
217 case 0x1d:
218 /* Penryn. */
219 case 0x0f:
220 /* Merom. */
221 __cpu_model.__cpu_type = INTEL_CORE2;
222 break;
223 default:
224 break;
225 }
226 break;
227 default:
228 /* We have no idea. */
229 break;
230 }
231 }
232 }
233
234 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
235 the max possible level of CPUID insn. */
236 static void
get_available_features(unsigned int ecx,unsigned int edx,int max_cpuid_level)237 get_available_features (unsigned int ecx, unsigned int edx,
238 int max_cpuid_level)
239 {
240 unsigned int eax, ebx;
241 unsigned int ext_level;
242
243 unsigned int features = 0;
244 unsigned int features2 = 0;
245
246 /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */
247 #define XCR_XFEATURE_ENABLED_MASK 0x0
248 #define XSTATE_FP 0x1
249 #define XSTATE_SSE 0x2
250 #define XSTATE_YMM 0x4
251 #define XSTATE_OPMASK 0x20
252 #define XSTATE_ZMM 0x40
253 #define XSTATE_HI_ZMM 0x80
254
255 #define XCR_AVX_ENABLED_MASK \
256 (XSTATE_SSE | XSTATE_YMM)
257 #define XCR_AVX512F_ENABLED_MASK \
258 (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
259
260 /* Check if AVX and AVX512 are usable. */
261 int avx_usable = 0;
262 int avx512_usable = 0;
263 if ((ecx & bit_OSXSAVE))
264 {
265 /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
266 ZMM16-ZMM31 states are supported by OSXSAVE. */
267 unsigned int xcrlow;
268 unsigned int xcrhigh;
269 asm (".byte 0x0f, 0x01, 0xd0"
270 : "=a" (xcrlow), "=d" (xcrhigh)
271 : "c" (XCR_XFEATURE_ENABLED_MASK));
272 if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
273 {
274 avx_usable = 1;
275 avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
276 == XCR_AVX512F_ENABLED_MASK);
277 }
278 }
279
280 #define set_feature(f) \
281 do \
282 { \
283 if (f < 32) \
284 features |= (1U << (f & 31)); \
285 else \
286 features2 |= (1U << ((f - 32) & 31)); \
287 } \
288 while (0)
289
290 if (edx & bit_CMOV)
291 set_feature (FEATURE_CMOV);
292 if (edx & bit_MMX)
293 set_feature (FEATURE_MMX);
294 if (edx & bit_SSE)
295 set_feature (FEATURE_SSE);
296 if (edx & bit_SSE2)
297 set_feature (FEATURE_SSE2);
298 if (ecx & bit_POPCNT)
299 set_feature (FEATURE_POPCNT);
300 if (ecx & bit_AES)
301 set_feature (FEATURE_AES);
302 if (ecx & bit_PCLMUL)
303 set_feature (FEATURE_PCLMUL);
304 if (ecx & bit_SSE3)
305 set_feature (FEATURE_SSE3);
306 if (ecx & bit_SSSE3)
307 set_feature (FEATURE_SSSE3);
308 if (ecx & bit_SSE4_1)
309 set_feature (FEATURE_SSE4_1);
310 if (ecx & bit_SSE4_2)
311 set_feature (FEATURE_SSE4_2);
312 if (avx_usable)
313 {
314 if (ecx & bit_AVX)
315 set_feature (FEATURE_AVX);
316 if (ecx & bit_FMA)
317 set_feature (FEATURE_FMA);
318 }
319
320 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
321 if (max_cpuid_level >= 7)
322 {
323 __cpuid_count (7, 0, eax, ebx, ecx, edx);
324 if (ebx & bit_BMI)
325 set_feature (FEATURE_BMI);
326 if (avx_usable)
327 {
328 if (ebx & bit_AVX2)
329 set_feature (FEATURE_AVX2);
330 }
331 if (ebx & bit_BMI2)
332 set_feature (FEATURE_BMI2);
333 if (avx512_usable)
334 {
335 if (ebx & bit_AVX512F)
336 set_feature (FEATURE_AVX512F);
337 if (ebx & bit_AVX512VL)
338 set_feature (FEATURE_AVX512VL);
339 if (ebx & bit_AVX512BW)
340 set_feature (FEATURE_AVX512BW);
341 if (ebx & bit_AVX512DQ)
342 set_feature (FEATURE_AVX512DQ);
343 if (ebx & bit_AVX512CD)
344 set_feature (FEATURE_AVX512CD);
345 if (ebx & bit_AVX512PF)
346 set_feature (FEATURE_AVX512PF);
347 if (ebx & bit_AVX512ER)
348 set_feature (FEATURE_AVX512ER);
349 if (ebx & bit_AVX512IFMA)
350 set_feature (FEATURE_AVX512IFMA);
351 if (ecx & bit_AVX512VBMI)
352 set_feature (FEATURE_AVX512VBMI);
353 if (ecx & bit_AVX512VBMI2)
354 set_feature (FEATURE_AVX512VBMI2);
355 if (ecx & bit_GFNI)
356 set_feature (FEATURE_GFNI);
357 if (ecx & bit_VPCLMULQDQ)
358 set_feature (FEATURE_VPCLMULQDQ);
359 if (ecx & bit_AVX512VNNI)
360 set_feature (FEATURE_AVX512VNNI);
361 if (ecx & bit_AVX512BITALG)
362 set_feature (FEATURE_AVX512BITALG);
363 if (ecx & bit_AVX512VPOPCNTDQ)
364 set_feature (FEATURE_AVX512VPOPCNTDQ);
365 if (edx & bit_AVX5124VNNIW)
366 set_feature (FEATURE_AVX5124VNNIW);
367 if (edx & bit_AVX5124FMAPS)
368 set_feature (FEATURE_AVX5124FMAPS);
369 }
370 }
371
372 /* Check cpuid level of extended features. */
373 __cpuid (0x80000000, ext_level, ebx, ecx, edx);
374
375 if (ext_level >= 0x80000001)
376 {
377 __cpuid (0x80000001, eax, ebx, ecx, edx);
378
379 if (ecx & bit_SSE4a)
380 set_feature (FEATURE_SSE4_A);
381 if (avx_usable)
382 {
383 if (ecx & bit_FMA4)
384 set_feature (FEATURE_FMA4);
385 if (ecx & bit_XOP)
386 set_feature (FEATURE_XOP);
387 }
388 }
389
390 __cpu_model.__cpu_features[0] = features;
391 #ifndef SHARED
392 __cpu_features2 = features2;
393 #else
394 (void) features2;
395 #endif
396 }
397
398 /* A constructor function that is sets __cpu_model and __cpu_features with
399 the right values. This needs to run only once. This constructor is
400 given the highest priority and it should run before constructors without
401 the priority set. However, it still runs after ifunc initializers and
402 needs to be called explicitly there. */
403
404 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
__cpu_indicator_init(void)405 __cpu_indicator_init (void)
406 {
407 unsigned int eax, ebx, ecx, edx;
408
409 int max_level;
410 unsigned int vendor;
411 unsigned int model, family, brand_id;
412 unsigned int extended_model, extended_family;
413
414 /* This function needs to run just once. */
415 if (__cpu_model.__cpu_vendor)
416 return 0;
417
418 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
419 if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
420 {
421 __cpu_model.__cpu_vendor = VENDOR_OTHER;
422 return -1;
423 }
424
425 vendor = ebx;
426 max_level = eax;
427
428 if (max_level < 1)
429 {
430 __cpu_model.__cpu_vendor = VENDOR_OTHER;
431 return -1;
432 }
433
434 if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
435 {
436 __cpu_model.__cpu_vendor = VENDOR_OTHER;
437 return -1;
438 }
439
440 model = (eax >> 4) & 0x0f;
441 family = (eax >> 8) & 0x0f;
442 brand_id = ebx & 0xff;
443 extended_model = (eax >> 12) & 0xf0;
444 extended_family = (eax >> 20) & 0xff;
445
446 if (vendor == signature_INTEL_ebx)
447 {
448 /* Adjust model and family for Intel CPUS. */
449 if (family == 0x0f)
450 {
451 family += extended_family;
452 model += extended_model;
453 }
454 else if (family == 0x06)
455 model += extended_model;
456
457 /* Get CPU type. */
458 get_intel_cpu (family, model, brand_id);
459 /* Find available features. */
460 get_available_features (ecx, edx, max_level);
461 __cpu_model.__cpu_vendor = VENDOR_INTEL;
462 }
463 else if (vendor == signature_AMD_ebx)
464 {
465 /* Adjust model and family for AMD CPUS. */
466 if (family == 0x0f)
467 {
468 family += extended_family;
469 model += extended_model;
470 }
471
472 /* Get CPU type. */
473 get_amd_cpu (family, model);
474 /* Find available features. */
475 get_available_features (ecx, edx, max_level);
476 __cpu_model.__cpu_vendor = VENDOR_AMD;
477 }
478 else
479 __cpu_model.__cpu_vendor = VENDOR_OTHER;
480
481 gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
482 gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
483 gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
484
485 return 0;
486 }
487
488 #if defined SHARED && defined USE_ELF_SYMVER
489 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
490 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");
491 #endif
492