16bc12fd0SRichard Henderson /* 26bc12fd0SRichard Henderson * SPDX-License-Identifier: GPL-2.0-or-later 3d02d06f8SMichael Tokarev * Host specific cpu identification for x86. 46bc12fd0SRichard Henderson */ 56bc12fd0SRichard Henderson 66bc12fd0SRichard Henderson #include "qemu/osdep.h" 76bc12fd0SRichard Henderson #include "host/cpuinfo.h" 86bc12fd0SRichard Henderson #ifdef CONFIG_CPUID_H 96bc12fd0SRichard Henderson # include "qemu/cpuid.h" 106bc12fd0SRichard Henderson #endif 116bc12fd0SRichard Henderson 126bc12fd0SRichard Henderson unsigned cpuinfo; 136bc12fd0SRichard Henderson 146bc12fd0SRichard Henderson /* Called both as constructor and (possibly) via other constructors. */ 156bc12fd0SRichard Henderson unsigned __attribute__((constructor)) cpuinfo_init(void) 166bc12fd0SRichard Henderson { 176bc12fd0SRichard Henderson unsigned info = cpuinfo; 186bc12fd0SRichard Henderson 196bc12fd0SRichard Henderson if (info) { 206bc12fd0SRichard Henderson return info; 216bc12fd0SRichard Henderson } 226bc12fd0SRichard Henderson 236bc12fd0SRichard Henderson #ifdef CONFIG_CPUID_H 246bc12fd0SRichard Henderson unsigned max, a, b, c, d, b7 = 0, c7 = 0; 256bc12fd0SRichard Henderson 266bc12fd0SRichard Henderson max = __get_cpuid_max(0, 0); 276bc12fd0SRichard Henderson 286bc12fd0SRichard Henderson if (max >= 7) { 296bc12fd0SRichard Henderson __cpuid_count(7, 0, a, b7, c7, d); 306bc12fd0SRichard Henderson info |= (b7 & bit_BMI ? CPUINFO_BMI1 : 0); 316bc12fd0SRichard Henderson info |= (b7 & bit_BMI2 ? CPUINFO_BMI2 : 0); 326bc12fd0SRichard Henderson } 336bc12fd0SRichard Henderson 346bc12fd0SRichard Henderson if (max >= 1) { 356bc12fd0SRichard Henderson __cpuid(1, a, b, c, d); 366bc12fd0SRichard Henderson 376bc12fd0SRichard Henderson info |= (c & bit_MOVBE ? CPUINFO_MOVBE : 0); 38fe721c19SPaolo Bonzini info |= (c & bit_POPCNT ? CPUINFO_POPCNT : 0); 39d6493dbbSRichard Henderson info |= (c & bit_PCLMUL ? CPUINFO_PCLMUL : 0); 406bc12fd0SRichard Henderson 41*39a367a4SPaolo Bonzini /* Our AES support requires PSHUFB as well. */ 42*39a367a4SPaolo Bonzini info |= ((c & bit_AES) && (c & bit_SSSE3) ? CPUINFO_AES : 0); 43d6a24436SRichard Henderson 446bc12fd0SRichard Henderson /* For AVX features, we must check available and usable. */ 456bc12fd0SRichard Henderson if ((c & bit_AVX) && (c & bit_OSXSAVE)) { 466bc12fd0SRichard Henderson unsigned bv = xgetbv_low(0); 476bc12fd0SRichard Henderson 486bc12fd0SRichard Henderson if ((bv & 6) == 6) { 496bc12fd0SRichard Henderson info |= CPUINFO_AVX1; 506bc12fd0SRichard Henderson info |= (b7 & bit_AVX2 ? CPUINFO_AVX2 : 0); 516bc12fd0SRichard Henderson 526bc12fd0SRichard Henderson if ((bv & 0xe0) == 0xe0) { 536bc12fd0SRichard Henderson info |= (b7 & bit_AVX512F ? CPUINFO_AVX512F : 0); 546bc12fd0SRichard Henderson info |= (b7 & bit_AVX512VL ? CPUINFO_AVX512VL : 0); 556bc12fd0SRichard Henderson info |= (b7 & bit_AVX512BW ? CPUINFO_AVX512BW : 0); 566bc12fd0SRichard Henderson info |= (b7 & bit_AVX512DQ ? CPUINFO_AVX512DQ : 0); 576bc12fd0SRichard Henderson info |= (c7 & bit_AVX512VBMI2 ? CPUINFO_AVX512VBMI2 : 0); 586bc12fd0SRichard Henderson } 596bc12fd0SRichard Henderson 606bc12fd0SRichard Henderson /* 616bc12fd0SRichard Henderson * The Intel SDM has added: 626bc12fd0SRichard Henderson * Processors that enumerate support for Intel® AVX 636bc12fd0SRichard Henderson * (by setting the feature flag CPUID.01H:ECX.AVX[bit 28]) 646bc12fd0SRichard Henderson * guarantee that the 16-byte memory operations performed 656bc12fd0SRichard Henderson * by the following instructions will always be carried 666bc12fd0SRichard Henderson * out atomically: 676bc12fd0SRichard Henderson * - MOVAPD, MOVAPS, and MOVDQA. 686bc12fd0SRichard Henderson * - VMOVAPD, VMOVAPS, and VMOVDQA when encoded with VEX.128. 696bc12fd0SRichard Henderson * - VMOVAPD, VMOVAPS, VMOVDQA32, and VMOVDQA64 when encoded 706bc12fd0SRichard Henderson * with EVEX.128 and k0 (masking disabled). 716bc12fd0SRichard Henderson * Note that these instructions require the linear addresses 726bc12fd0SRichard Henderson * of their memory operands to be 16-byte aligned. 736bc12fd0SRichard Henderson * 746bc12fd0SRichard Henderson * AMD has provided an even stronger guarantee that processors 75d02d06f8SMichael Tokarev * with AVX provide 16-byte atomicity for all cacheable, 766bc12fd0SRichard Henderson * naturally aligned single loads and stores, e.g. MOVDQU. 776bc12fd0SRichard Henderson * 786bc12fd0SRichard Henderson * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 796bc12fd0SRichard Henderson */ 806bc12fd0SRichard Henderson __cpuid(0, a, b, c, d); 81a48b6afeSRichard Henderson if (c == signature_INTEL_ecx) { 826bc12fd0SRichard Henderson info |= CPUINFO_ATOMIC_VMOVDQA; 83a48b6afeSRichard Henderson } else if (c == signature_AMD_ecx) { 84a48b6afeSRichard Henderson info |= CPUINFO_ATOMIC_VMOVDQA | CPUINFO_ATOMIC_VMOVDQU; 856bc12fd0SRichard Henderson } 866bc12fd0SRichard Henderson } 876bc12fd0SRichard Henderson } 886bc12fd0SRichard Henderson } 896bc12fd0SRichard Henderson 906bc12fd0SRichard Henderson max = __get_cpuid_max(0x8000000, 0); 916bc12fd0SRichard Henderson if (max >= 1) { 926bc12fd0SRichard Henderson __cpuid(0x80000001, a, b, c, d); 936bc12fd0SRichard Henderson info |= (c & bit_LZCNT ? CPUINFO_LZCNT : 0); 946bc12fd0SRichard Henderson } 956bc12fd0SRichard Henderson #endif 966bc12fd0SRichard Henderson 976bc12fd0SRichard Henderson info |= CPUINFO_ALWAYS; 986bc12fd0SRichard Henderson cpuinfo = info; 996bc12fd0SRichard Henderson return info; 1006bc12fd0SRichard Henderson } 101