cpuinfo.c revision 1.1.1.7
1/* Get CPU type and Features for x86 processors.
2   Copyright (C) 2012-2017 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
43
44/* Get the specific type of AMD CPU.  */
45
46static void
47get_amd_cpu (unsigned int family, unsigned int model)
48{
49  switch (family)
50    {
51    /* AMD Family 10h.  */
52    case 0x10:
53      __cpu_model.__cpu_type = AMDFAM10H;
54      switch (model)
55	{
56	case 0x2:
57	  /* Barcelona.  */
58	  __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
59	  break;
60	case 0x4:
61	  /* Shanghai.  */
62	  __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
63	  break;
64	case 0x8:
65	  /* Istanbul.  */
66	  __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
67	  break;
68	default:
69	  break;
70	}
71      break;
72    /* AMD Family 14h "btver1". */
73    case 0x14:
74      __cpu_model.__cpu_type = AMD_BTVER1;
75      break;
76    /* AMD Family 15h "Bulldozer".  */
77    case 0x15:
78      __cpu_model.__cpu_type = AMDFAM15H;
79      /* Bulldozer version 1.  */
80      if ( model <= 0xf)
81	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
82      /* Bulldozer version 2 "Piledriver" */
83      if (model >= 0x10 && model <= 0x2f)
84	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
85      /* Bulldozer version 3 "Steamroller"  */
86      if (model >= 0x30 && model <= 0x4f)
87	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
88      /* Bulldozer version 4 "Excavator"   */
89      if (model >= 0x60 && model <= 0x7f)
90	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
91      break;
92    /* AMD Family 16h "btver2" */
93    case 0x16:
94      __cpu_model.__cpu_type = AMD_BTVER2;
95      break;
96    case 0x17:
97      __cpu_model.__cpu_type = AMDFAM17H;
98      /* AMD family 17h version 1.  */
99      if (model <= 0x1f)
100	__cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
101      break;
102    default:
103      break;
104    }
105}
106
107/* Get the specific type of Intel CPU.  */
108
109static void
110get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
111{
112  /* Parse family and model only if brand ID is 0. */
113  if (brand_id == 0)
114    {
115      switch (family)
116	{
117	case 0x5:
118	  /* Pentium.  */
119	  break;
120	case 0x6:
121	  switch (model)
122	    {
123	    case 0x1c:
124	    case 0x26:
125	      /* Bonnell.  */
126	      __cpu_model.__cpu_type = INTEL_BONNELL;
127	      break;
128	    case 0x37:
129	    case 0x4a:
130	    case 0x4d:
131	    case 0x5a:
132	    case 0x5d:
133	      /* Silvermont.  */
134	      __cpu_model.__cpu_type = INTEL_SILVERMONT;
135	      break;
136	    case 0x57:
137	      /* Knights Landing.  */
138	      __cpu_model.__cpu_type = INTEL_KNL;
139	      break;
140	    case 0x1a:
141	    case 0x1e:
142	    case 0x1f:
143	    case 0x2e:
144	      /* Nehalem.  */
145	      __cpu_model.__cpu_type = INTEL_COREI7;
146	      __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
147	      break;
148	    case 0x25:
149	    case 0x2c:
150	    case 0x2f:
151	      /* Westmere.  */
152	      __cpu_model.__cpu_type = INTEL_COREI7;
153	      __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
154	      break;
155	    case 0x2a:
156	    case 0x2d:
157	      /* Sandy Bridge.  */
158	      __cpu_model.__cpu_type = INTEL_COREI7;
159	      __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
160	      break;
161	    case 0x3a:
162	    case 0x3e:
163	      /* Ivy Bridge.  */
164	      __cpu_model.__cpu_type = INTEL_COREI7;
165	      __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
166	      break;
167	    case 0x3c:
168	    case 0x3f:
169	    case 0x45:
170	    case 0x46:
171	      /* Haswell.  */
172	      __cpu_model.__cpu_type = INTEL_COREI7;
173	      __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
174	      break;
175	    case 0x3d:
176	    case 0x47:
177	    case 0x4f:
178	    case 0x56:
179	      /* Broadwell.  */
180	      __cpu_model.__cpu_type = INTEL_COREI7;
181	      __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
182	      break;
183	    case 0x4e:
184	    case 0x5e:
185	      /* Skylake.  */
186	      __cpu_model.__cpu_type = INTEL_COREI7;
187	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
188	      break;
189	    case 0x55:
190	      /* Skylake with AVX-512 support.  */
191	      __cpu_model.__cpu_type = INTEL_COREI7;
192	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
193	      break;
194	    case 0x17:
195	    case 0x1d:
196	      /* Penryn.  */
197	    case 0x0f:
198	      /* Merom.  */
199	      __cpu_model.__cpu_type = INTEL_CORE2;
200	      break;
201	    default:
202	      break;
203	    }
204	  break;
205	default:
206	  /* We have no idea.  */
207	  break;
208	}
209    }
210}
211
212/* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
213   the max possible level of CPUID insn.  */
214static void
215get_available_features (unsigned int ecx, unsigned int edx,
216			int max_cpuid_level)
217{
218  unsigned int eax, ebx;
219  unsigned int ext_level;
220
221  unsigned int features = 0;
222
223  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
224#define XCR_XFEATURE_ENABLED_MASK	0x0
225#define XSTATE_FP			0x1
226#define XSTATE_SSE			0x2
227#define XSTATE_YMM			0x4
228#define XSTATE_OPMASK			0x20
229#define XSTATE_ZMM			0x40
230#define XSTATE_HI_ZMM			0x80
231
232#define XCR_AVX_ENABLED_MASK \
233  (XSTATE_SSE | XSTATE_YMM)
234#define XCR_AVX512F_ENABLED_MASK \
235  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
236
237  /* Check if AVX and AVX512 are usable.  */
238  int avx_usable = 0;
239  int avx512_usable = 0;
240  if ((ecx & bit_OSXSAVE))
241    {
242      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
243         ZMM16-ZMM31 states are supported by OSXSAVE.  */
244      unsigned int xcrlow;
245      unsigned int xcrhigh;
246      asm (".byte 0x0f, 0x01, 0xd0"
247	   : "=a" (xcrlow), "=d" (xcrhigh)
248	   : "c" (XCR_XFEATURE_ENABLED_MASK));
249      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
250	{
251	  avx_usable = 1;
252	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
253			   == XCR_AVX512F_ENABLED_MASK);
254	}
255    }
256
257  if (edx & bit_CMOV)
258    features |= (1 << FEATURE_CMOV);
259  if (edx & bit_MMX)
260    features |= (1 << FEATURE_MMX);
261  if (edx & bit_SSE)
262    features |= (1 << FEATURE_SSE);
263  if (edx & bit_SSE2)
264    features |= (1 << FEATURE_SSE2);
265  if (ecx & bit_POPCNT)
266    features |= (1 << FEATURE_POPCNT);
267  if (ecx & bit_AES)
268    features |= (1 << FEATURE_AES);
269  if (ecx & bit_PCLMUL)
270    features |= (1 << FEATURE_PCLMUL);
271  if (ecx & bit_SSE3)
272    features |= (1 << FEATURE_SSE3);
273  if (ecx & bit_SSSE3)
274    features |= (1 << FEATURE_SSSE3);
275  if (ecx & bit_SSE4_1)
276    features |= (1 << FEATURE_SSE4_1);
277  if (ecx & bit_SSE4_2)
278    features |= (1 << FEATURE_SSE4_2);
279  if (avx_usable)
280    {
281      if (ecx & bit_AVX)
282	features |= (1 << FEATURE_AVX);
283      if (ecx & bit_FMA)
284	features |= (1 << FEATURE_FMA);
285    }
286
287  /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
288  if (max_cpuid_level >= 7)
289    {
290      __cpuid_count (7, 0, eax, ebx, ecx, edx);
291      if (ebx & bit_BMI)
292        features |= (1 << FEATURE_BMI);
293      if (avx_usable)
294	{
295	  if (ebx & bit_AVX2)
296	    features |= (1 << FEATURE_AVX2);
297	}
298      if (ebx & bit_BMI2)
299        features |= (1 << FEATURE_BMI2);
300      if (avx512_usable)
301	{
302	  if (ebx & bit_AVX512F)
303	    features |= (1 << FEATURE_AVX512F);
304	  if (ebx & bit_AVX512VL)
305	    features |= (1 << FEATURE_AVX512VL);
306	  if (ebx & bit_AVX512BW)
307	    features |= (1 << FEATURE_AVX512BW);
308	  if (ebx & bit_AVX512DQ)
309	    features |= (1 << FEATURE_AVX512DQ);
310	  if (ebx & bit_AVX512CD)
311	    features |= (1 << FEATURE_AVX512CD);
312	  if (ebx & bit_AVX512PF)
313	    features |= (1 << FEATURE_AVX512PF);
314	  if (ebx & bit_AVX512ER)
315	    features |= (1 << FEATURE_AVX512ER);
316	  if (ebx & bit_AVX512IFMA)
317	    features |= (1 << FEATURE_AVX512IFMA);
318	  if (ecx & bit_AVX512VBMI)
319	    features |= (1 << FEATURE_AVX512VBMI);
320	  if (ecx & bit_AVX512VPOPCNTDQ)
321	    features |= (1 << FEATURE_AVX512VPOPCNTDQ);
322	  if (edx & bit_AVX5124VNNIW)
323	    features |= (1 << FEATURE_AVX5124VNNIW);
324	  if (edx & bit_AVX5124FMAPS)
325	    features |= (1 << FEATURE_AVX5124FMAPS);
326	}
327    }
328
329  /* Check cpuid level of extended features.  */
330  __cpuid (0x80000000, ext_level, ebx, ecx, edx);
331
332  if (ext_level >= 0x80000001)
333    {
334      __cpuid (0x80000001, eax, ebx, ecx, edx);
335
336      if (ecx & bit_SSE4a)
337	features |= (1 << FEATURE_SSE4_A);
338      if (avx_usable)
339	{
340	  if (ecx & bit_FMA4)
341	    features |= (1 << FEATURE_FMA4);
342	  if (ecx & bit_XOP)
343	    features |= (1 << FEATURE_XOP);
344	}
345    }
346
347  __cpu_model.__cpu_features[0] = features;
348}
349
350/* A constructor function that is sets __cpu_model and __cpu_features with
351   the right values.  This needs to run only once.  This constructor is
352   given the highest priority and it should run before constructors without
353   the priority set.  However, it still runs after ifunc initializers and
354   needs to be called explicitly there.  */
355
356int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
357__cpu_indicator_init (void)
358{
359  unsigned int eax, ebx, ecx, edx;
360
361  int max_level;
362  unsigned int vendor;
363  unsigned int model, family, brand_id;
364  unsigned int extended_model, extended_family;
365
366  /* This function needs to run just once.  */
367  if (__cpu_model.__cpu_vendor)
368    return 0;
369
370  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
371  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
372    {
373      __cpu_model.__cpu_vendor = VENDOR_OTHER;
374      return -1;
375    }
376
377  vendor = ebx;
378  max_level = eax;
379
380  if (max_level < 1)
381    {
382      __cpu_model.__cpu_vendor = VENDOR_OTHER;
383      return -1;
384    }
385
386  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
387    {
388      __cpu_model.__cpu_vendor = VENDOR_OTHER;
389      return -1;
390    }
391
392  model = (eax >> 4) & 0x0f;
393  family = (eax >> 8) & 0x0f;
394  brand_id = ebx & 0xff;
395  extended_model = (eax >> 12) & 0xf0;
396  extended_family = (eax >> 20) & 0xff;
397
398  if (vendor == signature_INTEL_ebx)
399    {
400      /* Adjust model and family for Intel CPUS. */
401      if (family == 0x0f)
402	{
403	  family += extended_family;
404	  model += extended_model;
405	}
406      else if (family == 0x06)
407	model += extended_model;
408
409      /* Get CPU type.  */
410      get_intel_cpu (family, model, brand_id);
411      /* Find available features. */
412      get_available_features (ecx, edx, max_level);
413      __cpu_model.__cpu_vendor = VENDOR_INTEL;
414    }
415  else if (vendor == signature_AMD_ebx)
416    {
417      /* Adjust model and family for AMD CPUS. */
418      if (family == 0x0f)
419	{
420	  family += extended_family;
421	  model += extended_model;
422	}
423
424      /* Get CPU type.  */
425      get_amd_cpu (family, model);
426      /* Find available features. */
427      get_available_features (ecx, edx, max_level);
428      __cpu_model.__cpu_vendor = VENDOR_AMD;
429    }
430  else
431    __cpu_model.__cpu_vendor = VENDOR_OTHER;
432
433  gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
434  gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
435  gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
436
437  return 0;
438}
439
440#if defined SHARED && defined USE_ELF_SYMVER
441__asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
442__asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");
443#endif
444