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