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