1*6bc12fd0SRichard Henderson /* 2*6bc12fd0SRichard Henderson * SPDX-License-Identifier: GPL-2.0-or-later 3*6bc12fd0SRichard Henderson * Host specific cpu indentification for x86. 4*6bc12fd0SRichard Henderson */ 5*6bc12fd0SRichard Henderson 6*6bc12fd0SRichard Henderson #include "qemu/osdep.h" 7*6bc12fd0SRichard Henderson #include "host/cpuinfo.h" 8*6bc12fd0SRichard Henderson #ifdef CONFIG_CPUID_H 9*6bc12fd0SRichard Henderson # include "qemu/cpuid.h" 10*6bc12fd0SRichard Henderson #endif 11*6bc12fd0SRichard Henderson 12*6bc12fd0SRichard Henderson unsigned cpuinfo; 13*6bc12fd0SRichard Henderson 14*6bc12fd0SRichard Henderson /* Called both as constructor and (possibly) via other constructors. */ 15*6bc12fd0SRichard Henderson unsigned __attribute__((constructor)) cpuinfo_init(void) 16*6bc12fd0SRichard Henderson { 17*6bc12fd0SRichard Henderson unsigned info = cpuinfo; 18*6bc12fd0SRichard Henderson 19*6bc12fd0SRichard Henderson if (info) { 20*6bc12fd0SRichard Henderson return info; 21*6bc12fd0SRichard Henderson } 22*6bc12fd0SRichard Henderson 23*6bc12fd0SRichard Henderson #ifdef CONFIG_CPUID_H 24*6bc12fd0SRichard Henderson unsigned max, a, b, c, d, b7 = 0, c7 = 0; 25*6bc12fd0SRichard Henderson 26*6bc12fd0SRichard Henderson max = __get_cpuid_max(0, 0); 27*6bc12fd0SRichard Henderson 28*6bc12fd0SRichard Henderson if (max >= 7) { 29*6bc12fd0SRichard Henderson __cpuid_count(7, 0, a, b7, c7, d); 30*6bc12fd0SRichard Henderson info |= (b7 & bit_BMI ? CPUINFO_BMI1 : 0); 31*6bc12fd0SRichard Henderson info |= (b7 & bit_BMI2 ? CPUINFO_BMI2 : 0); 32*6bc12fd0SRichard Henderson } 33*6bc12fd0SRichard Henderson 34*6bc12fd0SRichard Henderson if (max >= 1) { 35*6bc12fd0SRichard Henderson __cpuid(1, a, b, c, d); 36*6bc12fd0SRichard Henderson 37*6bc12fd0SRichard Henderson info |= (d & bit_CMOV ? CPUINFO_CMOV : 0); 38*6bc12fd0SRichard Henderson info |= (d & bit_SSE2 ? CPUINFO_SSE2 : 0); 39*6bc12fd0SRichard Henderson info |= (c & bit_SSE4_1 ? CPUINFO_SSE4 : 0); 40*6bc12fd0SRichard Henderson info |= (c & bit_MOVBE ? CPUINFO_MOVBE : 0); 41*6bc12fd0SRichard Henderson info |= (c & bit_POPCNT ? CPUINFO_POPCNT : 0); 42*6bc12fd0SRichard Henderson 43*6bc12fd0SRichard Henderson /* For AVX features, we must check available and usable. */ 44*6bc12fd0SRichard Henderson if ((c & bit_AVX) && (c & bit_OSXSAVE)) { 45*6bc12fd0SRichard Henderson unsigned bv = xgetbv_low(0); 46*6bc12fd0SRichard Henderson 47*6bc12fd0SRichard Henderson if ((bv & 6) == 6) { 48*6bc12fd0SRichard Henderson info |= CPUINFO_AVX1; 49*6bc12fd0SRichard Henderson info |= (b7 & bit_AVX2 ? CPUINFO_AVX2 : 0); 50*6bc12fd0SRichard Henderson 51*6bc12fd0SRichard Henderson if ((bv & 0xe0) == 0xe0) { 52*6bc12fd0SRichard Henderson info |= (b7 & bit_AVX512F ? CPUINFO_AVX512F : 0); 53*6bc12fd0SRichard Henderson info |= (b7 & bit_AVX512VL ? CPUINFO_AVX512VL : 0); 54*6bc12fd0SRichard Henderson info |= (b7 & bit_AVX512BW ? CPUINFO_AVX512BW : 0); 55*6bc12fd0SRichard Henderson info |= (b7 & bit_AVX512DQ ? CPUINFO_AVX512DQ : 0); 56*6bc12fd0SRichard Henderson info |= (c7 & bit_AVX512VBMI2 ? CPUINFO_AVX512VBMI2 : 0); 57*6bc12fd0SRichard Henderson } 58*6bc12fd0SRichard Henderson 59*6bc12fd0SRichard Henderson /* 60*6bc12fd0SRichard Henderson * The Intel SDM has added: 61*6bc12fd0SRichard Henderson * Processors that enumerate support for Intel® AVX 62*6bc12fd0SRichard Henderson * (by setting the feature flag CPUID.01H:ECX.AVX[bit 28]) 63*6bc12fd0SRichard Henderson * guarantee that the 16-byte memory operations performed 64*6bc12fd0SRichard Henderson * by the following instructions will always be carried 65*6bc12fd0SRichard Henderson * out atomically: 66*6bc12fd0SRichard Henderson * - MOVAPD, MOVAPS, and MOVDQA. 67*6bc12fd0SRichard Henderson * - VMOVAPD, VMOVAPS, and VMOVDQA when encoded with VEX.128. 68*6bc12fd0SRichard Henderson * - VMOVAPD, VMOVAPS, VMOVDQA32, and VMOVDQA64 when encoded 69*6bc12fd0SRichard Henderson * with EVEX.128 and k0 (masking disabled). 70*6bc12fd0SRichard Henderson * Note that these instructions require the linear addresses 71*6bc12fd0SRichard Henderson * of their memory operands to be 16-byte aligned. 72*6bc12fd0SRichard Henderson * 73*6bc12fd0SRichard Henderson * AMD has provided an even stronger guarantee that processors 74*6bc12fd0SRichard Henderson * with AVX provide 16-byte atomicity for all cachable, 75*6bc12fd0SRichard Henderson * naturally aligned single loads and stores, e.g. MOVDQU. 76*6bc12fd0SRichard Henderson * 77*6bc12fd0SRichard Henderson * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 78*6bc12fd0SRichard Henderson */ 79*6bc12fd0SRichard Henderson __cpuid(0, a, b, c, d); 80*6bc12fd0SRichard Henderson if (c == signature_INTEL_ecx || c == signature_AMD_ecx) { 81*6bc12fd0SRichard Henderson info |= CPUINFO_ATOMIC_VMOVDQA; 82*6bc12fd0SRichard Henderson } 83*6bc12fd0SRichard Henderson } 84*6bc12fd0SRichard Henderson } 85*6bc12fd0SRichard Henderson } 86*6bc12fd0SRichard Henderson 87*6bc12fd0SRichard Henderson max = __get_cpuid_max(0x8000000, 0); 88*6bc12fd0SRichard Henderson if (max >= 1) { 89*6bc12fd0SRichard Henderson __cpuid(0x80000001, a, b, c, d); 90*6bc12fd0SRichard Henderson info |= (c & bit_LZCNT ? CPUINFO_LZCNT : 0); 91*6bc12fd0SRichard Henderson } 92*6bc12fd0SRichard Henderson #endif 93*6bc12fd0SRichard Henderson 94*6bc12fd0SRichard Henderson info |= CPUINFO_ALWAYS; 95*6bc12fd0SRichard Henderson cpuinfo = info; 96*6bc12fd0SRichard Henderson return info; 97*6bc12fd0SRichard Henderson } 98