1 /* Get CPU type and Features for x86 processors. 2 Copyright (C) 2012-2022 Free Software Foundation, Inc. 3 Contributed by Sriraman Tallam (tmsriram (at) 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 struct __processor_model 27 { 28 unsigned int __cpu_vendor; 29 unsigned int __cpu_type; 30 unsigned int __cpu_subtype; 31 /* The first 32 features are stored as bitmasks in __cpu_features. 32 The rest of features are stored as bitmasks in a separate array 33 of unsigned int. */ 34 unsigned int __cpu_features[1]; 35 }; 36 37 struct __processor_model2 38 { 39 unsigned int __cpu_family; 40 unsigned int __cpu_model; 41 unsigned int __cpu_max_level; 42 unsigned int __cpu_ext_level; 43 }; 44 45 #ifndef CHECK___builtin_cpu_is 46 # define CHECK___builtin_cpu_is(cpu) 47 #endif 48 49 #ifndef CHECK___builtin_cpu_supports 50 # define CHECK___builtin_cpu_supports(isa) 51 #endif 52 53 /* Return non-zero if the processor has feature F. */ 54 55 static inline int 56 has_cpu_feature (struct __processor_model *cpu_model, 57 unsigned int *cpu_features2, 58 enum processor_features feature) 59 { 60 unsigned index, offset; 61 unsigned f = feature; 62 63 if (f < 32) 64 { 65 /* The first 32 features. */ 66 return cpu_model->__cpu_features[0] & (1U << f); 67 } 68 else 69 { 70 /* The rest of features. cpu_features2[i] contains features from 71 (32 + i * 32) to (31 + 32 + i * 32), inclusively. */ 72 f -= 32; 73 index = f / 32; 74 offset = f % 32; 75 return cpu_features2[index] & (1U << offset); 76 } 77 } 78 79 static inline void 80 set_cpu_feature (struct __processor_model *cpu_model, 81 unsigned int *cpu_features2, 82 enum processor_features feature) 83 { 84 unsigned index, offset; 85 unsigned f = feature; 86 87 if (f < 32) 88 { 89 /* The first 32 features. */ 90 cpu_model->__cpu_features[0] |= (1U << f); 91 } 92 else 93 { 94 /* The rest of features. cpu_features2[i] contains features from 95 (32 + i * 32) to (31 + 32 + i * 32), inclusively. */ 96 f -= 32; 97 index = f / 32; 98 offset = f % 32; 99 cpu_features2[index] |= (1U << offset); 100 } 101 } 102 103 /* Get the specific type of AMD CPU and return AMD CPU name. Return 104 NULL for unknown AMD CPU. */ 105 106 static inline const char * 107 get_amd_cpu (struct __processor_model *cpu_model, 108 struct __processor_model2 *cpu_model2, 109 unsigned int *cpu_features2) 110 { 111 const char *cpu = NULL; 112 unsigned int family = cpu_model2->__cpu_family; 113 unsigned int model = cpu_model2->__cpu_model; 114 115 switch (family) 116 { 117 case 0x10: 118 /* AMD Family 10h. */ 119 cpu = "amdfam10"; 120 cpu_model->__cpu_type = AMDFAM10H; 121 switch (model) 122 { 123 case 0x2: 124 /* Barcelona. */ 125 CHECK___builtin_cpu_is ("amdfam10h"); 126 CHECK___builtin_cpu_is ("barcelona"); 127 cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA; 128 break; 129 case 0x4: 130 /* Shanghai. */ 131 CHECK___builtin_cpu_is ("amdfam10h"); 132 CHECK___builtin_cpu_is ("shanghai"); 133 cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI; 134 break; 135 case 0x8: 136 /* Istanbul. */ 137 CHECK___builtin_cpu_is ("amdfam10h"); 138 CHECK___builtin_cpu_is ("istanbul"); 139 cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL; 140 break; 141 default: 142 break; 143 } 144 break; 145 case 0x14: 146 /* AMD Family 14h "btver1". */ 147 cpu = "btver1"; 148 CHECK___builtin_cpu_is ("btver1"); 149 cpu_model->__cpu_type = AMD_BTVER1; 150 break; 151 case 0x15: 152 /* AMD Family 15h "Bulldozer". */ 153 cpu_model->__cpu_type = AMDFAM15H; 154 if (model == 0x2) 155 { 156 /* Bulldozer version 2 "Piledriver" */ 157 cpu = "bdver2"; 158 CHECK___builtin_cpu_is ("bdver2"); 159 cpu_model->__cpu_subtype = AMDFAM15H_BDVER2; 160 } 161 else if (model <= 0xf) 162 { 163 /* Bulldozer version 1. */ 164 cpu = "bdver1"; 165 CHECK___builtin_cpu_is ("bdver1"); 166 cpu_model->__cpu_subtype = AMDFAM15H_BDVER1; 167 } 168 else if (model <= 0x2f) 169 { 170 /* Bulldozer version 2 "Piledriver" */ 171 cpu = "bdver2"; 172 CHECK___builtin_cpu_is ("bdver2"); 173 cpu_model->__cpu_subtype = AMDFAM15H_BDVER2; 174 } 175 else if (model <= 0x4f) 176 { 177 /* Bulldozer version 3 "Steamroller" */ 178 cpu = "bdver3"; 179 CHECK___builtin_cpu_is ("bdver3"); 180 cpu_model->__cpu_subtype = AMDFAM15H_BDVER3; 181 } 182 else if (model <= 0x7f) 183 { 184 /* Bulldozer version 4 "Excavator" */ 185 cpu = "bdver4"; 186 CHECK___builtin_cpu_is ("bdver4"); 187 cpu_model->__cpu_subtype = AMDFAM15H_BDVER4; 188 } 189 else if (has_cpu_feature (cpu_model, cpu_features2, 190 FEATURE_AVX2)) 191 { 192 cpu = "bdver4"; 193 CHECK___builtin_cpu_is ("bdver4"); 194 cpu_model->__cpu_subtype = AMDFAM15H_BDVER4; 195 } 196 else if (has_cpu_feature (cpu_model, cpu_features2, 197 FEATURE_XSAVEOPT)) 198 { 199 cpu = "bdver3"; 200 CHECK___builtin_cpu_is ("bdver3"); 201 cpu_model->__cpu_subtype = AMDFAM15H_BDVER3; 202 } 203 else if (has_cpu_feature (cpu_model, cpu_features2, 204 FEATURE_BMI)) 205 { 206 cpu = "bdver2"; 207 CHECK___builtin_cpu_is ("bdver2"); 208 cpu_model->__cpu_subtype = AMDFAM15H_BDVER2; 209 } 210 else if (has_cpu_feature (cpu_model, cpu_features2, 211 FEATURE_XOP)) 212 { 213 cpu = "bdver1"; 214 CHECK___builtin_cpu_is ("bdver1"); 215 cpu_model->__cpu_subtype = AMDFAM15H_BDVER1; 216 } 217 break; 218 case 0x16: 219 /* AMD Family 16h "btver2" */ 220 cpu = "btver2"; 221 CHECK___builtin_cpu_is ("btver2"); 222 cpu_model->__cpu_type = AMD_BTVER2; 223 break; 224 case 0x17: 225 cpu_model->__cpu_type = AMDFAM17H; 226 if (model <= 0x1f) 227 { 228 /* AMD family 17h version 1. */ 229 cpu = "znver1"; 230 CHECK___builtin_cpu_is ("znver1"); 231 cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1; 232 } 233 else if (model >= 0x30) 234 { 235 cpu = "znver2"; 236 CHECK___builtin_cpu_is ("znver2"); 237 cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2; 238 } 239 else if (has_cpu_feature (cpu_model, cpu_features2, 240 FEATURE_CLWB)) 241 { 242 cpu = "znver2"; 243 CHECK___builtin_cpu_is ("znver2"); 244 cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2; 245 } 246 else if (has_cpu_feature (cpu_model, cpu_features2, 247 FEATURE_CLZERO)) 248 { 249 cpu = "znver1"; 250 CHECK___builtin_cpu_is ("znver1"); 251 cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1; 252 } 253 break; 254 case 0x19: 255 cpu_model->__cpu_type = AMDFAM19H; 256 /* AMD family 19h. */ 257 if (model <= 0x0f) 258 { 259 cpu = "znver3"; 260 CHECK___builtin_cpu_is ("znver3"); 261 cpu_model->__cpu_subtype = AMDFAM19H_ZNVER3; 262 } 263 else if ((model >= 0x10 && model <= 0x1f) 264 || (model >= 0x60 && model <= 0xaf)) 265 { 266 cpu = "znver4"; 267 CHECK___builtin_cpu_is ("znver4"); 268 cpu_model->__cpu_subtype = AMDFAM19H_ZNVER4; 269 } 270 else if (has_cpu_feature (cpu_model, cpu_features2, 271 FEATURE_AVX512F)) 272 { 273 cpu = "znver4"; 274 CHECK___builtin_cpu_is ("znver4"); 275 cpu_model->__cpu_subtype = AMDFAM19H_ZNVER4; 276 } 277 else if (has_cpu_feature (cpu_model, cpu_features2, 278 FEATURE_VAES)) 279 { 280 cpu = "znver3"; 281 CHECK___builtin_cpu_is ("znver3"); 282 cpu_model->__cpu_subtype = AMDFAM19H_ZNVER3; 283 } 284 break; 285 case 0x1a: 286 cpu_model->__cpu_type = AMDFAM1AH; 287 if (model <= 0x77) 288 { 289 cpu = "znver5"; 290 CHECK___builtin_cpu_is ("znver5"); 291 cpu_model->__cpu_subtype = AMDFAM1AH_ZNVER5; 292 } 293 else if (has_cpu_feature (cpu_model, cpu_features2, 294 FEATURE_AVX512VP2INTERSECT)) 295 { 296 cpu = "znver5"; 297 CHECK___builtin_cpu_is ("znver5"); 298 cpu_model->__cpu_subtype = AMDFAM1AH_ZNVER5; 299 } 300 break; 301 default: 302 break; 303 } 304 305 return cpu; 306 } 307 308 /* Get the specific type of Intel CPU and return Intel CPU name. Return 309 NULL for unknown Intel CPU. */ 310 311 static inline const char * 312 get_intel_cpu (struct __processor_model *cpu_model, 313 struct __processor_model2 *cpu_model2, 314 unsigned int *cpu_features2) 315 { 316 const char *cpu = NULL; 317 318 /* Parse family and model only for model 6. */ 319 if (cpu_model2->__cpu_family != 0x6) 320 return cpu; 321 322 switch (cpu_model2->__cpu_model) 323 { 324 case 0x1c: 325 case 0x26: 326 /* Bonnell. */ 327 cpu = "bonnell"; 328 CHECK___builtin_cpu_is ("atom"); 329 cpu_model->__cpu_type = INTEL_BONNELL; 330 break; 331 case 0x37: 332 case 0x4a: 333 case 0x4d: 334 case 0x5d: 335 /* Silvermont. */ 336 case 0x4c: 337 case 0x5a: 338 case 0x75: 339 /* Airmont. */ 340 cpu = "silvermont"; 341 CHECK___builtin_cpu_is ("silvermont"); 342 cpu_model->__cpu_type = INTEL_SILVERMONT; 343 break; 344 case 0x5c: 345 case 0x5f: 346 /* Goldmont. */ 347 cpu = "goldmont"; 348 CHECK___builtin_cpu_is ("goldmont"); 349 cpu_model->__cpu_type = INTEL_GOLDMONT; 350 break; 351 case 0x7a: 352 /* Goldmont Plus. */ 353 cpu = "goldmont-plus"; 354 CHECK___builtin_cpu_is ("goldmont-plus"); 355 cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS; 356 break; 357 case 0x86: 358 case 0x96: 359 case 0x9c: 360 /* Tremont. */ 361 cpu = "tremont"; 362 CHECK___builtin_cpu_is ("tremont"); 363 cpu_model->__cpu_type = INTEL_TREMONT; 364 break; 365 case 0x57: 366 /* Knights Landing. */ 367 cpu = "knl"; 368 CHECK___builtin_cpu_is ("knl"); 369 cpu_model->__cpu_type = INTEL_KNL; 370 break; 371 case 0x85: 372 /* Knights Mill. */ 373 cpu = "knm"; 374 CHECK___builtin_cpu_is ("knm"); 375 cpu_model->__cpu_type = INTEL_KNM; 376 break; 377 case 0x1a: 378 case 0x1e: 379 case 0x1f: 380 case 0x2e: 381 /* Nehalem. */ 382 cpu = "nehalem"; 383 CHECK___builtin_cpu_is ("corei7"); 384 CHECK___builtin_cpu_is ("nehalem"); 385 cpu_model->__cpu_type = INTEL_COREI7; 386 cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM; 387 break; 388 case 0x25: 389 case 0x2c: 390 case 0x2f: 391 /* Westmere. */ 392 cpu = "westmere"; 393 CHECK___builtin_cpu_is ("corei7"); 394 CHECK___builtin_cpu_is ("westmere"); 395 cpu_model->__cpu_type = INTEL_COREI7; 396 cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE; 397 break; 398 case 0x2a: 399 case 0x2d: 400 /* Sandy Bridge. */ 401 cpu = "sandybridge"; 402 CHECK___builtin_cpu_is ("corei7"); 403 CHECK___builtin_cpu_is ("sandybridge"); 404 cpu_model->__cpu_type = INTEL_COREI7; 405 cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE; 406 break; 407 case 0x3a: 408 case 0x3e: 409 /* Ivy Bridge. */ 410 cpu = "ivybridge"; 411 CHECK___builtin_cpu_is ("corei7"); 412 CHECK___builtin_cpu_is ("ivybridge"); 413 cpu_model->__cpu_type = INTEL_COREI7; 414 cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE; 415 break; 416 case 0x3c: 417 case 0x3f: 418 case 0x45: 419 case 0x46: 420 /* Haswell. */ 421 cpu = "haswell"; 422 CHECK___builtin_cpu_is ("corei7"); 423 CHECK___builtin_cpu_is ("haswell"); 424 cpu_model->__cpu_type = INTEL_COREI7; 425 cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL; 426 break; 427 case 0x3d: 428 case 0x47: 429 case 0x4f: 430 case 0x56: 431 /* Broadwell. */ 432 cpu = "broadwell"; 433 CHECK___builtin_cpu_is ("corei7"); 434 CHECK___builtin_cpu_is ("broadwell"); 435 cpu_model->__cpu_type = INTEL_COREI7; 436 cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL; 437 break; 438 case 0x4e: 439 case 0x5e: 440 /* Skylake. */ 441 case 0x8e: 442 case 0x9e: 443 /* Kaby Lake. */ 444 case 0xa5: 445 case 0xa6: 446 /* Comet Lake. */ 447 cpu = "skylake"; 448 CHECK___builtin_cpu_is ("corei7"); 449 CHECK___builtin_cpu_is ("skylake"); 450 cpu_model->__cpu_type = INTEL_COREI7; 451 cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE; 452 break; 453 case 0xa7: 454 /* Rocket Lake. */ 455 cpu = "rocketlake"; 456 CHECK___builtin_cpu_is ("corei7"); 457 CHECK___builtin_cpu_is ("rocketlake"); 458 cpu_model->__cpu_type = INTEL_COREI7; 459 cpu_model->__cpu_subtype = INTEL_COREI7_ROCKETLAKE; 460 break; 461 case 0x55: 462 CHECK___builtin_cpu_is ("corei7"); 463 cpu_model->__cpu_type = INTEL_COREI7; 464 if (has_cpu_feature (cpu_model, cpu_features2, 465 FEATURE_AVX512BF16)) 466 { 467 /* Cooper Lake. */ 468 cpu = "cooperlake"; 469 CHECK___builtin_cpu_is ("cooperlake"); 470 cpu_model->__cpu_subtype = INTEL_COREI7_COOPERLAKE; 471 } 472 else if (has_cpu_feature (cpu_model, cpu_features2, 473 FEATURE_AVX512VNNI)) 474 { 475 /* Cascade Lake. */ 476 cpu = "cascadelake"; 477 CHECK___builtin_cpu_is ("cascadelake"); 478 cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE; 479 } 480 else 481 { 482 /* Skylake with AVX-512 support. */ 483 cpu = "skylake-avx512"; 484 CHECK___builtin_cpu_is ("skylake-avx512"); 485 cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512; 486 } 487 break; 488 case 0x66: 489 /* Cannon Lake. */ 490 cpu = "cannonlake"; 491 CHECK___builtin_cpu_is ("corei7"); 492 CHECK___builtin_cpu_is ("cannonlake"); 493 cpu_model->__cpu_type = INTEL_COREI7; 494 cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE; 495 break; 496 case 0x6a: 497 case 0x6c: 498 /* Ice Lake server. */ 499 cpu = "icelake-server"; 500 CHECK___builtin_cpu_is ("corei7"); 501 CHECK___builtin_cpu_is ("icelake-server"); 502 cpu_model->__cpu_type = INTEL_COREI7; 503 cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER; 504 break; 505 case 0x7e: 506 case 0x7d: 507 case 0x9d: 508 /* Ice Lake client. */ 509 cpu = "icelake-client"; 510 CHECK___builtin_cpu_is ("corei7"); 511 CHECK___builtin_cpu_is ("icelake-client"); 512 cpu_model->__cpu_type = INTEL_COREI7; 513 cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT; 514 break; 515 case 0x8c: 516 case 0x8d: 517 /* Tiger Lake. */ 518 cpu = "tigerlake"; 519 CHECK___builtin_cpu_is ("corei7"); 520 CHECK___builtin_cpu_is ("tigerlake"); 521 cpu_model->__cpu_type = INTEL_COREI7; 522 cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE; 523 break; 524 case 0x97: 525 case 0x9a: 526 /* Alder Lake. */ 527 cpu = "alderlake"; 528 CHECK___builtin_cpu_is ("corei7"); 529 CHECK___builtin_cpu_is ("alderlake"); 530 cpu_model->__cpu_type = INTEL_COREI7; 531 cpu_model->__cpu_subtype = INTEL_COREI7_ALDERLAKE; 532 break; 533 case 0x8f: 534 /* Sapphire Rapids. */ 535 cpu = "sapphirerapids"; 536 CHECK___builtin_cpu_is ("corei7"); 537 CHECK___builtin_cpu_is ("sapphirerapids"); 538 cpu_model->__cpu_type = INTEL_COREI7; 539 cpu_model->__cpu_subtype = INTEL_COREI7_SAPPHIRERAPIDS; 540 break; 541 case 0x17: 542 case 0x1d: 543 /* Penryn. */ 544 case 0x0f: 545 /* Merom. */ 546 cpu = "core2"; 547 CHECK___builtin_cpu_is ("core2"); 548 cpu_model->__cpu_type = INTEL_CORE2; 549 break; 550 default: 551 break; 552 } 553 554 return cpu; 555 } 556 557 /* ECX and EDX are output of CPUID at level one. */ 558 static inline void 559 get_available_features (struct __processor_model *cpu_model, 560 struct __processor_model2 *cpu_model2, 561 unsigned int *cpu_features2, 562 unsigned int ecx, unsigned int edx) 563 { 564 unsigned int max_cpuid_level = cpu_model2->__cpu_max_level; 565 unsigned int eax, ebx; 566 unsigned int ext_level; 567 568 /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */ 569 #define XCR_XFEATURE_ENABLED_MASK 0x0 570 #define XSTATE_FP 0x1 571 #define XSTATE_SSE 0x2 572 #define XSTATE_YMM 0x4 573 #define XSTATE_OPMASK 0x20 574 #define XSTATE_ZMM 0x40 575 #define XSTATE_HI_ZMM 0x80 576 #define XSTATE_TILECFG 0x20000 577 #define XSTATE_TILEDATA 0x40000 578 579 #define XCR_AVX_ENABLED_MASK \ 580 (XSTATE_SSE | XSTATE_YMM) 581 #define XCR_AVX512F_ENABLED_MASK \ 582 (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM) 583 #define XCR_AMX_ENABLED_MASK \ 584 (XSTATE_TILECFG | XSTATE_TILEDATA) 585 586 /* Check if AVX and AVX512 are usable. */ 587 int avx_usable = 0; 588 int avx512_usable = 0; 589 int amx_usable = 0; 590 /* Check if KL is usable. */ 591 int has_kl = 0; 592 if ((ecx & bit_OSXSAVE)) 593 { 594 /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and 595 ZMM16-ZMM31 states are supported by OSXSAVE. */ 596 unsigned int xcrlow; 597 unsigned int xcrhigh; 598 __asm__ (".byte 0x0f, 0x01, 0xd0" 599 : "=a" (xcrlow), "=d" (xcrhigh) 600 : "c" (XCR_XFEATURE_ENABLED_MASK)); 601 if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK) 602 { 603 avx_usable = 1; 604 avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK) 605 == XCR_AVX512F_ENABLED_MASK); 606 } 607 amx_usable = ((xcrlow & XCR_AMX_ENABLED_MASK) 608 == XCR_AMX_ENABLED_MASK); 609 } 610 611 #define set_feature(f) \ 612 set_cpu_feature (cpu_model, cpu_features2, f) 613 614 if (edx & bit_CMOV) 615 set_feature (FEATURE_CMOV); 616 if (edx & bit_MMX) 617 set_feature (FEATURE_MMX); 618 if (edx & bit_SSE) 619 set_feature (FEATURE_SSE); 620 if (edx & bit_SSE2) 621 set_feature (FEATURE_SSE2); 622 if (edx & bit_CMPXCHG8B) 623 set_feature (FEATURE_CMPXCHG8B); 624 if (edx & bit_FXSAVE) 625 set_feature (FEATURE_FXSAVE); 626 627 if (ecx & bit_POPCNT) 628 set_feature (FEATURE_POPCNT); 629 if (ecx & bit_AES) 630 set_feature (FEATURE_AES); 631 if (ecx & bit_PCLMUL) 632 set_feature (FEATURE_PCLMUL); 633 if (ecx & bit_SSE3) 634 set_feature (FEATURE_SSE3); 635 if (ecx & bit_SSSE3) 636 set_feature (FEATURE_SSSE3); 637 if (ecx & bit_SSE4_1) 638 set_feature (FEATURE_SSE4_1); 639 if (ecx & bit_SSE4_2) 640 set_feature (FEATURE_SSE4_2); 641 if (ecx & bit_OSXSAVE) 642 set_feature (FEATURE_OSXSAVE); 643 if (ecx & bit_CMPXCHG16B) 644 set_feature (FEATURE_CMPXCHG16B); 645 if (ecx & bit_MOVBE) 646 set_feature (FEATURE_MOVBE); 647 if (ecx & bit_AES) 648 set_feature (FEATURE_AES); 649 if (ecx & bit_RDRND) 650 set_feature (FEATURE_RDRND); 651 if (ecx & bit_XSAVE) 652 set_feature (FEATURE_XSAVE); 653 if (avx_usable) 654 { 655 if (ecx & bit_AVX) 656 set_feature (FEATURE_AVX); 657 if (ecx & bit_FMA) 658 set_feature (FEATURE_FMA); 659 if (ecx & bit_F16C) 660 set_feature (FEATURE_F16C); 661 } 662 663 /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */ 664 if (max_cpuid_level >= 7) 665 { 666 unsigned int max_subleaf_level; 667 668 __cpuid_count (7, 0, max_subleaf_level, ebx, ecx, edx); 669 if (ebx & bit_BMI) 670 set_feature (FEATURE_BMI); 671 if (ebx & bit_SGX) 672 set_feature (FEATURE_SGX); 673 if (ebx & bit_HLE) 674 set_feature (FEATURE_HLE); 675 if (ebx & bit_RTM) 676 set_feature (FEATURE_RTM); 677 if (avx_usable) 678 { 679 if (ebx & bit_AVX2) 680 set_feature (FEATURE_AVX2); 681 if (ecx & bit_VPCLMULQDQ) 682 set_feature (FEATURE_VPCLMULQDQ); 683 if (ecx & bit_VAES) 684 set_feature (FEATURE_VAES); 685 } 686 if (ebx & bit_BMI2) 687 set_feature (FEATURE_BMI2); 688 if (ebx & bit_FSGSBASE) 689 set_feature (FEATURE_FSGSBASE); 690 if (ebx & bit_RDSEED) 691 set_feature (FEATURE_RDSEED); 692 if (ebx & bit_ADX) 693 set_feature (FEATURE_ADX); 694 if (ebx & bit_SHA) 695 set_feature (FEATURE_SHA); 696 if (ebx & bit_CLFLUSHOPT) 697 set_feature (FEATURE_CLFLUSHOPT); 698 if (ebx & bit_CLWB) 699 set_feature (FEATURE_CLWB); 700 if (ecx & bit_PREFETCHWT1) 701 set_feature (FEATURE_PREFETCHWT1); 702 /* NB: bit_OSPKE indicates that OS supports PKU. */ 703 if (ecx & bit_OSPKE) 704 set_feature (FEATURE_PKU); 705 if (ecx & bit_RDPID) 706 set_feature (FEATURE_RDPID); 707 if (ecx & bit_GFNI) 708 set_feature (FEATURE_GFNI); 709 if (ecx & bit_MOVDIRI) 710 set_feature (FEATURE_MOVDIRI); 711 if (ecx & bit_MOVDIR64B) 712 set_feature (FEATURE_MOVDIR64B); 713 if (ecx & bit_ENQCMD) 714 set_feature (FEATURE_ENQCMD); 715 if (ecx & bit_CLDEMOTE) 716 set_feature (FEATURE_CLDEMOTE); 717 if (ecx & bit_WAITPKG) 718 set_feature (FEATURE_WAITPKG); 719 if (ecx & bit_SHSTK) 720 set_feature (FEATURE_SHSTK); 721 if (ecx & bit_KL) 722 has_kl = 1; 723 if (edx & bit_SERIALIZE) 724 set_feature (FEATURE_SERIALIZE); 725 if (edx & bit_TSXLDTRK) 726 set_feature (FEATURE_TSXLDTRK); 727 if (edx & bit_PCONFIG) 728 set_feature (FEATURE_PCONFIG); 729 if (edx & bit_IBT) 730 set_feature (FEATURE_IBT); 731 if (edx & bit_UINTR) 732 set_feature (FEATURE_UINTR); 733 if (amx_usable) 734 { 735 if (edx & bit_AMX_TILE) 736 set_feature (FEATURE_AMX_TILE); 737 if (edx & bit_AMX_INT8) 738 set_feature (FEATURE_AMX_INT8); 739 if (edx & bit_AMX_BF16) 740 set_feature (FEATURE_AMX_BF16); 741 } 742 if (avx512_usable) 743 { 744 if (ebx & bit_AVX512F) 745 set_feature (FEATURE_AVX512F); 746 if (ebx & bit_AVX512VL) 747 set_feature (FEATURE_AVX512VL); 748 if (ebx & bit_AVX512BW) 749 set_feature (FEATURE_AVX512BW); 750 if (ebx & bit_AVX512DQ) 751 set_feature (FEATURE_AVX512DQ); 752 if (ebx & bit_AVX512CD) 753 set_feature (FEATURE_AVX512CD); 754 if (ebx & bit_AVX512PF) 755 set_feature (FEATURE_AVX512PF); 756 if (ebx & bit_AVX512ER) 757 set_feature (FEATURE_AVX512ER); 758 if (ebx & bit_AVX512IFMA) 759 set_feature (FEATURE_AVX512IFMA); 760 if (ecx & bit_AVX512VBMI) 761 set_feature (FEATURE_AVX512VBMI); 762 if (ecx & bit_AVX512VBMI2) 763 set_feature (FEATURE_AVX512VBMI2); 764 if (ecx & bit_AVX512VNNI) 765 set_feature (FEATURE_AVX512VNNI); 766 if (ecx & bit_AVX512BITALG) 767 set_feature (FEATURE_AVX512BITALG); 768 if (ecx & bit_AVX512VPOPCNTDQ) 769 set_feature (FEATURE_AVX512VPOPCNTDQ); 770 if (edx & bit_AVX5124VNNIW) 771 set_feature (FEATURE_AVX5124VNNIW); 772 if (edx & bit_AVX5124FMAPS) 773 set_feature (FEATURE_AVX5124FMAPS); 774 if (edx & bit_AVX512VP2INTERSECT) 775 set_feature (FEATURE_AVX512VP2INTERSECT); 776 if (edx & bit_AVX512FP16) 777 set_feature (FEATURE_AVX512FP16); 778 } 779 780 if (max_subleaf_level >= 1) 781 { 782 __cpuid_count (7, 1, eax, ebx, ecx, edx); 783 if (eax & bit_HRESET) 784 set_feature (FEATURE_HRESET); 785 if (avx_usable) 786 { 787 if (eax & bit_AVXVNNI) 788 set_feature (FEATURE_AVXVNNI); 789 } 790 if (avx512_usable) 791 { 792 if (eax & bit_AVX512BF16) 793 set_feature (FEATURE_AVX512BF16); 794 } 795 } 796 } 797 798 /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */ 799 if (max_cpuid_level >= 0xd) 800 { 801 __cpuid_count (0xd, 1, eax, ebx, ecx, edx); 802 if (eax & bit_XSAVEOPT) 803 set_feature (FEATURE_XSAVEOPT); 804 if (eax & bit_XSAVEC) 805 set_feature (FEATURE_XSAVEC); 806 if (eax & bit_XSAVES) 807 set_feature (FEATURE_XSAVES); 808 } 809 810 /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */ 811 if (max_cpuid_level >= 0x14) 812 { 813 __cpuid_count (0x14, 0, eax, ebx, ecx, edx); 814 if (ebx & bit_PTWRITE) 815 set_feature (FEATURE_PTWRITE); 816 } 817 818 /* Get Advanced Features at level 0x19 (eax = 0x19). */ 819 if (max_cpuid_level >= 0x19) 820 { 821 __cpuid (0x19, eax, ebx, ecx, edx); 822 /* Check if OS support keylocker. */ 823 if (ebx & bit_AESKLE) 824 { 825 set_feature (FEATURE_AESKLE); 826 if (ebx & bit_WIDEKL) 827 set_feature (FEATURE_WIDEKL); 828 if (has_kl) 829 set_feature (FEATURE_KL); 830 } 831 } 832 833 /* Check cpuid level of extended features. */ 834 __cpuid (0x80000000, ext_level, ebx, ecx, edx); 835 836 cpu_model2->__cpu_ext_level = ext_level; 837 838 if (ext_level >= 0x80000001) 839 { 840 __cpuid (0x80000001, eax, ebx, ecx, edx); 841 842 if (ecx & bit_SSE4a) 843 set_feature (FEATURE_SSE4_A); 844 if (ecx & bit_LAHF_LM) 845 set_feature (FEATURE_LAHF_LM); 846 if (ecx & bit_ABM) 847 set_feature (FEATURE_ABM); 848 if (ecx & bit_LWP) 849 set_feature (FEATURE_LWP); 850 if (ecx & bit_TBM) 851 set_feature (FEATURE_TBM); 852 if (ecx & bit_LZCNT) 853 set_feature (FEATURE_LZCNT); 854 if (ecx & bit_PRFCHW) 855 set_feature (FEATURE_PRFCHW); 856 if (ecx & bit_MWAITX) 857 set_feature (FEATURE_MWAITX); 858 859 if (edx & bit_LM) 860 set_feature (FEATURE_LM); 861 if (edx & bit_3DNOWP) 862 set_feature (FEATURE_3DNOWP); 863 if (edx & bit_3DNOW) 864 set_feature (FEATURE_3DNOW); 865 866 if (avx_usable) 867 { 868 if (ecx & bit_FMA4) 869 set_feature (FEATURE_FMA4); 870 if (ecx & bit_XOP) 871 set_feature (FEATURE_XOP); 872 } 873 } 874 875 if (ext_level >= 0x80000008) 876 { 877 __cpuid (0x80000008, eax, ebx, ecx, edx); 878 if (ebx & bit_CLZERO) 879 set_feature (FEATURE_CLZERO); 880 if (ebx & bit_WBNOINVD) 881 set_feature (FEATURE_WBNOINVD); 882 } 883 884 #undef set_feature 885 } 886 887 static inline int 888 cpu_indicator_init (struct __processor_model *cpu_model, 889 struct __processor_model2 *cpu_model2, 890 unsigned int *cpu_features2) 891 { 892 unsigned int eax, ebx, ecx, edx; 893 894 int max_level; 895 unsigned int vendor; 896 unsigned int model, family; 897 unsigned int extended_model, extended_family; 898 899 /* This function needs to run just once. */ 900 if (cpu_model->__cpu_vendor) 901 return 0; 902 903 /* Assume cpuid insn present. Run in level 0 to get vendor id. */ 904 if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx)) 905 { 906 cpu_model->__cpu_vendor = VENDOR_OTHER; 907 return -1; 908 } 909 910 vendor = ebx; 911 max_level = eax; 912 913 if (max_level < 1) 914 { 915 cpu_model->__cpu_vendor = VENDOR_OTHER; 916 return -1; 917 } 918 919 if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) 920 { 921 cpu_model->__cpu_vendor = VENDOR_OTHER; 922 return -1; 923 } 924 925 cpu_model2->__cpu_max_level = max_level; 926 927 model = (eax >> 4) & 0x0f; 928 family = (eax >> 8) & 0x0f; 929 extended_model = (eax >> 12) & 0xf0; 930 extended_family = (eax >> 20) & 0xff; 931 932 /* Find available features. */ 933 get_available_features (cpu_model, cpu_model2, cpu_features2, 934 ecx, edx); 935 936 if (vendor == signature_INTEL_ebx) 937 { 938 /* Adjust model and family for Intel CPUS. */ 939 if (family == 0x0f) 940 { 941 family += extended_family; 942 model += extended_model; 943 } 944 else if (family == 0x06) 945 model += extended_model; 946 947 cpu_model2->__cpu_family = family; 948 cpu_model2->__cpu_model = model; 949 950 /* Get CPU type. */ 951 get_intel_cpu (cpu_model, cpu_model2, cpu_features2); 952 cpu_model->__cpu_vendor = VENDOR_INTEL; 953 } 954 else if (vendor == signature_AMD_ebx) 955 { 956 /* Adjust model and family for AMD CPUS. */ 957 if (family == 0x0f) 958 { 959 family += extended_family; 960 model += extended_model; 961 } 962 963 cpu_model2->__cpu_family = family; 964 cpu_model2->__cpu_model = model; 965 966 /* Get CPU type. */ 967 get_amd_cpu (cpu_model, cpu_model2, cpu_features2); 968 cpu_model->__cpu_vendor = VENDOR_AMD; 969 } 970 else if (vendor == signature_CENTAUR_ebx) 971 cpu_model->__cpu_vendor = VENDOR_CENTAUR; 972 else if (vendor == signature_CYRIX_ebx) 973 cpu_model->__cpu_vendor = VENDOR_CYRIX; 974 else if (vendor == signature_NSC_ebx) 975 cpu_model->__cpu_vendor = VENDOR_NSC; 976 else 977 cpu_model->__cpu_vendor = VENDOR_OTHER; 978 979 if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_LM) 980 && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE2)) 981 { 982 CHECK___builtin_cpu_supports ("x86-64"); 983 set_cpu_feature (cpu_model, cpu_features2, 984 FEATURE_X86_64_BASELINE); 985 if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_CMPXCHG16B) 986 && has_cpu_feature (cpu_model, cpu_features2, FEATURE_POPCNT) 987 && has_cpu_feature (cpu_model, cpu_features2, FEATURE_LAHF_LM) 988 && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE4_2)) 989 { 990 CHECK___builtin_cpu_supports ("x86-64-v2"); 991 set_cpu_feature (cpu_model, cpu_features2, 992 FEATURE_X86_64_V2); 993 if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_AVX2) 994 && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI) 995 && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI2) 996 && has_cpu_feature (cpu_model, cpu_features2, FEATURE_F16C) 997 && has_cpu_feature (cpu_model, cpu_features2, FEATURE_FMA) 998 && has_cpu_feature (cpu_model, cpu_features2, 999 FEATURE_LZCNT) 1000 && has_cpu_feature (cpu_model, cpu_features2, 1001 FEATURE_MOVBE)) 1002 { 1003 CHECK___builtin_cpu_supports ("x86-64-v3"); 1004 set_cpu_feature (cpu_model, cpu_features2, 1005 FEATURE_X86_64_V3); 1006 if (has_cpu_feature (cpu_model, cpu_features2, 1007 FEATURE_AVX512BW) 1008 && has_cpu_feature (cpu_model, cpu_features2, 1009 FEATURE_AVX512CD) 1010 && has_cpu_feature (cpu_model, cpu_features2, 1011 FEATURE_AVX512DQ) 1012 && has_cpu_feature (cpu_model, cpu_features2, 1013 FEATURE_AVX512VL)) 1014 { 1015 CHECK___builtin_cpu_supports ("x86-64-v4"); 1016 set_cpu_feature (cpu_model, cpu_features2, 1017 FEATURE_X86_64_V4); 1018 } 1019 } 1020 } 1021 } 1022 1023 gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX); 1024 gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX); 1025 gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX); 1026 1027 return 0; 1028 } 1029