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
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
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
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))
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