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