cpuinfo.c revision 1.1.1.8
1/* Get CPU type and Features for x86 processors. 2 Copyright (C) 2012-2018 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 break; 112 default: 113 break; 114 } 115} 116 117/* Get the specific type of Intel CPU. */ 118 119static void 120get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id) 121{ 122 /* Parse family and model only if brand ID is 0. */ 123 if (brand_id == 0) 124 { 125 switch (family) 126 { 127 case 0x5: 128 /* Pentium. */ 129 break; 130 case 0x6: 131 switch (model) 132 { 133 case 0x1c: 134 case 0x26: 135 /* Bonnell. */ 136 __cpu_model.__cpu_type = INTEL_BONNELL; 137 break; 138 case 0x37: 139 case 0x4a: 140 case 0x4d: 141 case 0x5a: 142 case 0x5d: 143 /* Silvermont. */ 144 __cpu_model.__cpu_type = INTEL_SILVERMONT; 145 break; 146 case 0x57: 147 /* Knights Landing. */ 148 __cpu_model.__cpu_type = INTEL_KNL; 149 break; 150 case 0x85: 151 /* Knights Mill. */ 152 __cpu_model.__cpu_type = INTEL_KNM; 153 break; 154 case 0x1a: 155 case 0x1e: 156 case 0x1f: 157 case 0x2e: 158 /* Nehalem. */ 159 __cpu_model.__cpu_type = INTEL_COREI7; 160 __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM; 161 break; 162 case 0x25: 163 case 0x2c: 164 case 0x2f: 165 /* Westmere. */ 166 __cpu_model.__cpu_type = INTEL_COREI7; 167 __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE; 168 break; 169 case 0x2a: 170 case 0x2d: 171 /* Sandy Bridge. */ 172 __cpu_model.__cpu_type = INTEL_COREI7; 173 __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE; 174 break; 175 case 0x3a: 176 case 0x3e: 177 /* Ivy Bridge. */ 178 __cpu_model.__cpu_type = INTEL_COREI7; 179 __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE; 180 break; 181 case 0x3c: 182 case 0x3f: 183 case 0x45: 184 case 0x46: 185 /* Haswell. */ 186 __cpu_model.__cpu_type = INTEL_COREI7; 187 __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL; 188 break; 189 case 0x3d: 190 case 0x47: 191 case 0x4f: 192 case 0x56: 193 /* Broadwell. */ 194 __cpu_model.__cpu_type = INTEL_COREI7; 195 __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL; 196 break; 197 case 0x4e: 198 case 0x5e: 199 /* Skylake. */ 200 case 0x8e: 201 case 0x9e: 202 /* Kaby Lake. */ 203 __cpu_model.__cpu_type = INTEL_COREI7; 204 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE; 205 break; 206 case 0x55: 207 /* Skylake with AVX-512 support. */ 208 __cpu_model.__cpu_type = INTEL_COREI7; 209 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512; 210 break; 211 case 0x66: 212 /* Cannon Lake. */ 213 __cpu_model.__cpu_type = INTEL_COREI7; 214 __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE; 215 break; 216 case 0x17: 217 case 0x1d: 218 /* Penryn. */ 219 case 0x0f: 220 /* Merom. */ 221 __cpu_model.__cpu_type = INTEL_CORE2; 222 break; 223 default: 224 break; 225 } 226 break; 227 default: 228 /* We have no idea. */ 229 break; 230 } 231 } 232} 233 234/* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is 235 the max possible level of CPUID insn. */ 236static void 237get_available_features (unsigned int ecx, unsigned int edx, 238 int max_cpuid_level) 239{ 240 unsigned int eax, ebx; 241 unsigned int ext_level; 242 243 unsigned int features = 0; 244 unsigned int features2 = 0; 245 246 /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */ 247#define XCR_XFEATURE_ENABLED_MASK 0x0 248#define XSTATE_FP 0x1 249#define XSTATE_SSE 0x2 250#define XSTATE_YMM 0x4 251#define XSTATE_OPMASK 0x20 252#define XSTATE_ZMM 0x40 253#define XSTATE_HI_ZMM 0x80 254 255#define XCR_AVX_ENABLED_MASK \ 256 (XSTATE_SSE | XSTATE_YMM) 257#define XCR_AVX512F_ENABLED_MASK \ 258 (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM) 259 260 /* Check if AVX and AVX512 are usable. */ 261 int avx_usable = 0; 262 int avx512_usable = 0; 263 if ((ecx & bit_OSXSAVE)) 264 { 265 /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and 266 ZMM16-ZMM31 states are supported by OSXSAVE. */ 267 unsigned int xcrlow; 268 unsigned int xcrhigh; 269 asm (".byte 0x0f, 0x01, 0xd0" 270 : "=a" (xcrlow), "=d" (xcrhigh) 271 : "c" (XCR_XFEATURE_ENABLED_MASK)); 272 if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK) 273 { 274 avx_usable = 1; 275 avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK) 276 == XCR_AVX512F_ENABLED_MASK); 277 } 278 } 279 280#define set_feature(f) \ 281 do \ 282 { \ 283 if (f < 32) \ 284 features |= (1U << (f & 31)); \ 285 else \ 286 features2 |= (1U << ((f - 32) & 31)); \ 287 } \ 288 while (0) 289 290 if (edx & bit_CMOV) 291 set_feature (FEATURE_CMOV); 292 if (edx & bit_MMX) 293 set_feature (FEATURE_MMX); 294 if (edx & bit_SSE) 295 set_feature (FEATURE_SSE); 296 if (edx & bit_SSE2) 297 set_feature (FEATURE_SSE2); 298 if (ecx & bit_POPCNT) 299 set_feature (FEATURE_POPCNT); 300 if (ecx & bit_AES) 301 set_feature (FEATURE_AES); 302 if (ecx & bit_PCLMUL) 303 set_feature (FEATURE_PCLMUL); 304 if (ecx & bit_SSE3) 305 set_feature (FEATURE_SSE3); 306 if (ecx & bit_SSSE3) 307 set_feature (FEATURE_SSSE3); 308 if (ecx & bit_SSE4_1) 309 set_feature (FEATURE_SSE4_1); 310 if (ecx & bit_SSE4_2) 311 set_feature (FEATURE_SSE4_2); 312 if (avx_usable) 313 { 314 if (ecx & bit_AVX) 315 set_feature (FEATURE_AVX); 316 if (ecx & bit_FMA) 317 set_feature (FEATURE_FMA); 318 } 319 320 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */ 321 if (max_cpuid_level >= 7) 322 { 323 __cpuid_count (7, 0, eax, ebx, ecx, edx); 324 if (ebx & bit_BMI) 325 set_feature (FEATURE_BMI); 326 if (avx_usable) 327 { 328 if (ebx & bit_AVX2) 329 set_feature (FEATURE_AVX2); 330 } 331 if (ebx & bit_BMI2) 332 set_feature (FEATURE_BMI2); 333 if (avx512_usable) 334 { 335 if (ebx & bit_AVX512F) 336 set_feature (FEATURE_AVX512F); 337 if (ebx & bit_AVX512VL) 338 set_feature (FEATURE_AVX512VL); 339 if (ebx & bit_AVX512BW) 340 set_feature (FEATURE_AVX512BW); 341 if (ebx & bit_AVX512DQ) 342 set_feature (FEATURE_AVX512DQ); 343 if (ebx & bit_AVX512CD) 344 set_feature (FEATURE_AVX512CD); 345 if (ebx & bit_AVX512PF) 346 set_feature (FEATURE_AVX512PF); 347 if (ebx & bit_AVX512ER) 348 set_feature (FEATURE_AVX512ER); 349 if (ebx & bit_AVX512IFMA) 350 set_feature (FEATURE_AVX512IFMA); 351 if (ecx & bit_AVX512VBMI) 352 set_feature (FEATURE_AVX512VBMI); 353 if (ecx & bit_AVX512VBMI2) 354 set_feature (FEATURE_AVX512VBMI2); 355 if (ecx & bit_GFNI) 356 set_feature (FEATURE_GFNI); 357 if (ecx & bit_VPCLMULQDQ) 358 set_feature (FEATURE_VPCLMULQDQ); 359 if (ecx & bit_AVX512VNNI) 360 set_feature (FEATURE_AVX512VNNI); 361 if (ecx & bit_AVX512BITALG) 362 set_feature (FEATURE_AVX512BITALG); 363 if (ecx & bit_AVX512VPOPCNTDQ) 364 set_feature (FEATURE_AVX512VPOPCNTDQ); 365 if (edx & bit_AVX5124VNNIW) 366 set_feature (FEATURE_AVX5124VNNIW); 367 if (edx & bit_AVX5124FMAPS) 368 set_feature (FEATURE_AVX5124FMAPS); 369 } 370 } 371 372 /* Check cpuid level of extended features. */ 373 __cpuid (0x80000000, ext_level, ebx, ecx, edx); 374 375 if (ext_level >= 0x80000001) 376 { 377 __cpuid (0x80000001, eax, ebx, ecx, edx); 378 379 if (ecx & bit_SSE4a) 380 set_feature (FEATURE_SSE4_A); 381 if (avx_usable) 382 { 383 if (ecx & bit_FMA4) 384 set_feature (FEATURE_FMA4); 385 if (ecx & bit_XOP) 386 set_feature (FEATURE_XOP); 387 } 388 } 389 390 __cpu_model.__cpu_features[0] = features; 391#ifndef SHARED 392 __cpu_features2 = features2; 393#else 394 (void) features2; 395#endif 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; 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 (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 (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