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 37*87b8bde5SPaolo Bonzini info |= (d & bit_SSE2 ? CPUINFO_SSE2 : 0); 386bc12fd0SRichard Henderson info |= (c & bit_MOVBE ? CPUINFO_MOVBE : 0); 39fe721c19SPaolo Bonzini info |= (c & bit_POPCNT ? CPUINFO_POPCNT : 0); 40d6493dbbSRichard Henderson info |= (c & bit_PCLMUL ? CPUINFO_PCLMUL : 0); 416bc12fd0SRichard Henderson 4239a367a4SPaolo Bonzini /* Our AES support requires PSHUFB as well. */ 4339a367a4SPaolo Bonzini info |= ((c & bit_AES) && (c & bit_SSSE3) ? CPUINFO_AES : 0); 44d6a24436SRichard Henderson 456bc12fd0SRichard Henderson /* For AVX features, we must check available and usable. */ 466bc12fd0SRichard Henderson if ((c & bit_AVX) && (c & bit_OSXSAVE)) { 476bc12fd0SRichard Henderson unsigned bv = xgetbv_low(0); 486bc12fd0SRichard Henderson 496bc12fd0SRichard Henderson if ((bv & 6) == 6) { 506bc12fd0SRichard Henderson info |= CPUINFO_AVX1; 516bc12fd0SRichard Henderson info |= (b7 & bit_AVX2 ? CPUINFO_AVX2 : 0); 526bc12fd0SRichard Henderson 536bc12fd0SRichard Henderson if ((bv & 0xe0) == 0xe0) { 546bc12fd0SRichard Henderson info |= (b7 & bit_AVX512F ? CPUINFO_AVX512F : 0); 556bc12fd0SRichard Henderson info |= (b7 & bit_AVX512VL ? CPUINFO_AVX512VL : 0); 566bc12fd0SRichard Henderson info |= (b7 & bit_AVX512BW ? CPUINFO_AVX512BW : 0); 576bc12fd0SRichard Henderson info |= (b7 & bit_AVX512DQ ? CPUINFO_AVX512DQ : 0); 586bc12fd0SRichard Henderson info |= (c7 & bit_AVX512VBMI2 ? CPUINFO_AVX512VBMI2 : 0); 596bc12fd0SRichard Henderson } 606bc12fd0SRichard Henderson 616bc12fd0SRichard Henderson /* 626bc12fd0SRichard Henderson * The Intel SDM has added: 636bc12fd0SRichard Henderson * Processors that enumerate support for Intel® AVX 646bc12fd0SRichard Henderson * (by setting the feature flag CPUID.01H:ECX.AVX[bit 28]) 656bc12fd0SRichard Henderson * guarantee that the 16-byte memory operations performed 666bc12fd0SRichard Henderson * by the following instructions will always be carried 676bc12fd0SRichard Henderson * out atomically: 686bc12fd0SRichard Henderson * - MOVAPD, MOVAPS, and MOVDQA. 696bc12fd0SRichard Henderson * - VMOVAPD, VMOVAPS, and VMOVDQA when encoded with VEX.128. 706bc12fd0SRichard Henderson * - VMOVAPD, VMOVAPS, VMOVDQA32, and VMOVDQA64 when encoded 716bc12fd0SRichard Henderson * with EVEX.128 and k0 (masking disabled). 726bc12fd0SRichard Henderson * Note that these instructions require the linear addresses 736bc12fd0SRichard Henderson * of their memory operands to be 16-byte aligned. 746bc12fd0SRichard Henderson * 756bc12fd0SRichard Henderson * AMD has provided an even stronger guarantee that processors 76d02d06f8SMichael Tokarev * with AVX provide 16-byte atomicity for all cacheable, 776bc12fd0SRichard Henderson * naturally aligned single loads and stores, e.g. MOVDQU. 786bc12fd0SRichard Henderson * 796bc12fd0SRichard Henderson * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 806bc12fd0SRichard Henderson */ 816bc12fd0SRichard Henderson __cpuid(0, a, b, c, d); 82a48b6afeSRichard Henderson if (c == signature_INTEL_ecx) { 836bc12fd0SRichard Henderson info |= CPUINFO_ATOMIC_VMOVDQA; 84a48b6afeSRichard Henderson } else if (c == signature_AMD_ecx) { 85a48b6afeSRichard Henderson info |= CPUINFO_ATOMIC_VMOVDQA | CPUINFO_ATOMIC_VMOVDQU; 866bc12fd0SRichard Henderson } 876bc12fd0SRichard Henderson } 886bc12fd0SRichard Henderson } 896bc12fd0SRichard Henderson } 906bc12fd0SRichard Henderson 916bc12fd0SRichard Henderson max = __get_cpuid_max(0x8000000, 0); 926bc12fd0SRichard Henderson if (max >= 1) { 936bc12fd0SRichard Henderson __cpuid(0x80000001, a, b, c, d); 946bc12fd0SRichard Henderson info |= (c & bit_LZCNT ? CPUINFO_LZCNT : 0); 956bc12fd0SRichard Henderson } 966bc12fd0SRichard Henderson #endif 976bc12fd0SRichard Henderson 986bc12fd0SRichard Henderson info |= CPUINFO_ALWAYS; 996bc12fd0SRichard Henderson cpuinfo = info; 1006bc12fd0SRichard Henderson return info; 1016bc12fd0SRichard Henderson } 102