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