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