cpuinfo.c revision 1.1.1.3
1/* Get CPU type and Features for x86 processors. 2 Copyright (C) 2012-2016 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 30#ifdef HAVE_INIT_PRIORITY 31#define CONSTRUCTOR_PRIORITY (101) 32#else 33#define CONSTRUCTOR_PRIORITY 34#endif 35 36int __cpu_indicator_init (void) 37 __attribute__ ((constructor CONSTRUCTOR_PRIORITY)); 38 39/* Processor Vendor and Models. */ 40 41enum processor_vendor 42{ 43 VENDOR_INTEL = 1, 44 VENDOR_AMD, 45 VENDOR_OTHER, 46 VENDOR_MAX 47}; 48 49/* Any new types or subtypes have to be inserted at the end. */ 50 51enum processor_types 52{ 53 INTEL_BONNELL = 1, 54 INTEL_CORE2, 55 INTEL_COREI7, 56 AMDFAM10H, 57 AMDFAM15H, 58 INTEL_SILVERMONT, 59 INTEL_KNL, 60 AMD_BTVER1, 61 AMD_BTVER2, 62 AMDFAM17H, 63 CPU_TYPE_MAX 64}; 65 66enum processor_subtypes 67{ 68 INTEL_COREI7_NEHALEM = 1, 69 INTEL_COREI7_WESTMERE, 70 INTEL_COREI7_SANDYBRIDGE, 71 AMDFAM10H_BARCELONA, 72 AMDFAM10H_SHANGHAI, 73 AMDFAM10H_ISTANBUL, 74 AMDFAM15H_BDVER1, 75 AMDFAM15H_BDVER2, 76 AMDFAM15H_BDVER3, 77 AMDFAM15H_BDVER4, 78 AMDFAM17H_ZNVER1, 79 INTEL_COREI7_IVYBRIDGE, 80 INTEL_COREI7_HASWELL, 81 INTEL_COREI7_BROADWELL, 82 INTEL_COREI7_SKYLAKE, 83 INTEL_COREI7_SKYLAKE_AVX512, 84 CPU_SUBTYPE_MAX 85}; 86 87/* ISA Features supported. New features have to be inserted at the end. */ 88 89enum processor_features 90{ 91 FEATURE_CMOV = 0, 92 FEATURE_MMX, 93 FEATURE_POPCNT, 94 FEATURE_SSE, 95 FEATURE_SSE2, 96 FEATURE_SSE3, 97 FEATURE_SSSE3, 98 FEATURE_SSE4_1, 99 FEATURE_SSE4_2, 100 FEATURE_AVX, 101 FEATURE_AVX2, 102 FEATURE_SSE4_A, 103 FEATURE_FMA4, 104 FEATURE_XOP, 105 FEATURE_FMA, 106 FEATURE_AVX512F, 107 FEATURE_BMI, 108 FEATURE_BMI2, 109 FEATURE_AES, 110 FEATURE_PCLMUL, 111 FEATURE_AVX512VL, 112 FEATURE_AVX512BW, 113 FEATURE_AVX512DQ, 114 FEATURE_AVX512CD, 115 FEATURE_AVX512ER, 116 FEATURE_AVX512PF, 117 FEATURE_AVX512VBMI, 118 FEATURE_AVX512IFMA 119}; 120 121struct __processor_model 122{ 123 unsigned int __cpu_vendor; 124 unsigned int __cpu_type; 125 unsigned int __cpu_subtype; 126 unsigned int __cpu_features[1]; 127} __cpu_model = { }; 128 129 130/* Get the specific type of AMD CPU. */ 131 132static void 133get_amd_cpu (unsigned int family, unsigned int model) 134{ 135 switch (family) 136 { 137 /* AMD Family 10h. */ 138 case 0x10: 139 __cpu_model.__cpu_type = AMDFAM10H; 140 switch (model) 141 { 142 case 0x2: 143 /* Barcelona. */ 144 __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA; 145 break; 146 case 0x4: 147 /* Shanghai. */ 148 __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI; 149 break; 150 case 0x8: 151 /* Istanbul. */ 152 __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL; 153 break; 154 default: 155 break; 156 } 157 break; 158 /* AMD Family 14h "btver1". */ 159 case 0x14: 160 __cpu_model.__cpu_type = AMD_BTVER1; 161 break; 162 /* AMD Family 15h "Bulldozer". */ 163 case 0x15: 164 __cpu_model.__cpu_type = AMDFAM15H; 165 /* Bulldozer version 1. */ 166 if ( model <= 0xf) 167 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1; 168 /* Bulldozer version 2 "Piledriver" */ 169 if (model >= 0x10 && model <= 0x2f) 170 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2; 171 /* Bulldozer version 3 "Steamroller" */ 172 if (model >= 0x30 && model <= 0x4f) 173 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3; 174 /* Bulldozer version 4 "Excavator" */ 175 if (model >= 0x60 && model <= 0x7f) 176 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4; 177 break; 178 /* AMD Family 16h "btver2" */ 179 case 0x16: 180 __cpu_model.__cpu_type = AMD_BTVER2; 181 break; 182 case 0x17: 183 __cpu_model.__cpu_type = AMDFAM17H; 184 /* AMD family 17h version 1. */ 185 if (model <= 0x1f) 186 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1; 187 break; 188 default: 189 break; 190 } 191} 192 193/* Get the specific type of Intel CPU. */ 194 195static void 196get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id) 197{ 198 /* Parse family and model only if brand ID is 0. */ 199 if (brand_id == 0) 200 { 201 switch (family) 202 { 203 case 0x5: 204 /* Pentium. */ 205 break; 206 case 0x6: 207 switch (model) 208 { 209 case 0x1c: 210 case 0x26: 211 /* Bonnell. */ 212 __cpu_model.__cpu_type = INTEL_BONNELL; 213 break; 214 case 0x37: 215 case 0x4a: 216 case 0x4d: 217 case 0x5a: 218 case 0x5d: 219 /* Silvermont. */ 220 __cpu_model.__cpu_type = INTEL_SILVERMONT; 221 break; 222 case 0x57: 223 /* Knights Landing. */ 224 __cpu_model.__cpu_type = INTEL_KNL; 225 break; 226 case 0x1a: 227 case 0x1e: 228 case 0x1f: 229 case 0x2e: 230 /* Nehalem. */ 231 __cpu_model.__cpu_type = INTEL_COREI7; 232 __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM; 233 break; 234 case 0x25: 235 case 0x2c: 236 case 0x2f: 237 /* Westmere. */ 238 __cpu_model.__cpu_type = INTEL_COREI7; 239 __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE; 240 break; 241 case 0x2a: 242 case 0x2d: 243 /* Sandy Bridge. */ 244 __cpu_model.__cpu_type = INTEL_COREI7; 245 __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE; 246 break; 247 case 0x3a: 248 case 0x3e: 249 /* Ivy Bridge. */ 250 __cpu_model.__cpu_type = INTEL_COREI7; 251 __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE; 252 break; 253 case 0x3c: 254 case 0x3f: 255 case 0x45: 256 case 0x46: 257 /* Haswell. */ 258 __cpu_model.__cpu_type = INTEL_COREI7; 259 __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL; 260 break; 261 case 0x3d: 262 case 0x47: 263 case 0x4f: 264 case 0x56: 265 /* Broadwell. */ 266 __cpu_model.__cpu_type = INTEL_COREI7; 267 __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL; 268 break; 269 case 0x4e: 270 case 0x5e: 271 /* Skylake. */ 272 __cpu_model.__cpu_type = INTEL_COREI7; 273 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE; 274 break; 275 case 0x55: 276 /* Skylake with AVX-512 support. */ 277 __cpu_model.__cpu_type = INTEL_COREI7; 278 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512; 279 break; 280 case 0x17: 281 case 0x1d: 282 /* Penryn. */ 283 case 0x0f: 284 /* Merom. */ 285 __cpu_model.__cpu_type = INTEL_CORE2; 286 break; 287 default: 288 break; 289 } 290 break; 291 default: 292 /* We have no idea. */ 293 break; 294 } 295 } 296} 297 298/* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is 299 the max possible level of CPUID insn. */ 300static void 301get_available_features (unsigned int ecx, unsigned int edx, 302 int max_cpuid_level) 303{ 304 unsigned int features = 0; 305 306 if (edx & bit_CMOV) 307 features |= (1 << FEATURE_CMOV); 308 if (edx & bit_MMX) 309 features |= (1 << FEATURE_MMX); 310 if (edx & bit_SSE) 311 features |= (1 << FEATURE_SSE); 312 if (edx & bit_SSE2) 313 features |= (1 << FEATURE_SSE2); 314 if (ecx & bit_POPCNT) 315 features |= (1 << FEATURE_POPCNT); 316 if (ecx & bit_AES) 317 features |= (1 << FEATURE_AES); 318 if (ecx & bit_PCLMUL) 319 features |= (1 << FEATURE_PCLMUL); 320 if (ecx & bit_SSE3) 321 features |= (1 << FEATURE_SSE3); 322 if (ecx & bit_SSSE3) 323 features |= (1 << FEATURE_SSSE3); 324 if (ecx & bit_SSE4_1) 325 features |= (1 << FEATURE_SSE4_1); 326 if (ecx & bit_SSE4_2) 327 features |= (1 << FEATURE_SSE4_2); 328 if (ecx & bit_AVX) 329 features |= (1 << FEATURE_AVX); 330 if (ecx & bit_FMA) 331 features |= (1 << FEATURE_FMA); 332 333 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */ 334 if (max_cpuid_level >= 7) 335 { 336 unsigned int eax, ebx, ecx, edx; 337 __cpuid_count (7, 0, eax, ebx, ecx, edx); 338 if (ebx & bit_BMI) 339 features |= (1 << FEATURE_BMI); 340 if (ebx & bit_AVX2) 341 features |= (1 << FEATURE_AVX2); 342 if (ebx & bit_BMI2) 343 features |= (1 << FEATURE_BMI2); 344 if (ebx & bit_AVX512F) 345 features |= (1 << FEATURE_AVX512F); 346 if (ebx & bit_AVX512VL) 347 features |= (1 << FEATURE_AVX512VL); 348 if (ebx & bit_AVX512BW) 349 features |= (1 << FEATURE_AVX512BW); 350 if (ebx & bit_AVX512DQ) 351 features |= (1 << FEATURE_AVX512DQ); 352 if (ebx & bit_AVX512CD) 353 features |= (1 << FEATURE_AVX512CD); 354 if (ebx & bit_AVX512PF) 355 features |= (1 << FEATURE_AVX512PF); 356 if (ebx & bit_AVX512ER) 357 features |= (1 << FEATURE_AVX512ER); 358 if (ebx & bit_AVX512IFMA) 359 features |= (1 << FEATURE_AVX512IFMA); 360 if (ecx & bit_AVX512VBMI) 361 features |= (1 << FEATURE_AVX512VBMI); 362 } 363 364 unsigned int ext_level; 365 unsigned int eax, ebx; 366 /* Check cpuid level of extended features. */ 367 __cpuid (0x80000000, ext_level, ebx, ecx, edx); 368 369 if (ext_level > 0x80000000) 370 { 371 __cpuid (0x80000001, eax, ebx, ecx, edx); 372 373 if (ecx & bit_SSE4a) 374 features |= (1 << FEATURE_SSE4_A); 375 if (ecx & bit_FMA4) 376 features |= (1 << FEATURE_FMA4); 377 if (ecx & bit_XOP) 378 features |= (1 << FEATURE_XOP); 379 } 380 381 __cpu_model.__cpu_features[0] = features; 382} 383 384/* A noinline function calling __get_cpuid. Having many calls to 385 cpuid in one function in 32-bit mode causes GCC to complain: 386 "can't find a register in class CLOBBERED_REGS". This is 387 related to PR rtl-optimization 44174. */ 388 389static int __attribute__ ((noinline)) 390__get_cpuid_output (unsigned int __level, 391 unsigned int *__eax, unsigned int *__ebx, 392 unsigned int *__ecx, unsigned int *__edx) 393{ 394 return __get_cpuid (__level, __eax, __ebx, __ecx, __edx); 395} 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 404int __attribute__ ((constructor CONSTRUCTOR_PRIORITY)) 405__cpu_indicator_init (void) 406{ 407 unsigned int eax, ebx, ecx, edx; 408 409 int max_level = 5; 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_output (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_output (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