| 109 | have_hypervisor_(0) {} |
| 110 | |
| 111 | static void Initialize() { |
| 112 | // Initialize cpuid struct |
| 113 | CHECK(cpuid == nullptr) << __func__ << " ran more than once"; |
| 114 | cpuid = new CPUIDInfo; |
| 115 | |
| 116 | uint32 eax, ebx, ecx, edx; |
| 117 | |
| 118 | // Get vendor string (issue CPUID with eax = 0) |
| 119 | GETCPUID(eax, ebx, ecx, edx, 0, 0); |
| 120 | cpuid->vendor_str_.append(reinterpret_cast<char *>(&ebx), 4); |
| 121 | cpuid->vendor_str_.append(reinterpret_cast<char *>(&edx), 4); |
| 122 | cpuid->vendor_str_.append(reinterpret_cast<char *>(&ecx), 4); |
| 123 | |
| 124 | // To get general information and extended features we send eax = 1 and |
| 125 | // ecx = 0 to cpuid. The response is returned in eax, ebx, ecx and edx. |
| 126 | // (See Intel 64 and IA-32 Architectures Software Developer's Manual |
| 127 | // Volume 2A: Instruction Set Reference, A-M CPUID). |
| 128 | GETCPUID(eax, ebx, ecx, edx, 1, 0); |
| 129 | |
| 130 | cpuid->model_num_ = static_cast<int>((eax >> 4) & 0xf); |
| 131 | cpuid->family_ = static_cast<int>((eax >> 8) & 0xf); |
| 132 | |
| 133 | cpuid->have_aes_ = (ecx >> 25) & 0x1; |
| 134 | cpuid->have_cmov_ = (edx >> 15) & 0x1; |
| 135 | cpuid->have_cmpxchg16b_ = (ecx >> 13) & 0x1; |
| 136 | cpuid->have_cmpxchg8b_ = (edx >> 8) & 0x1; |
| 137 | cpuid->have_mmx_ = (edx >> 23) & 0x1; |
| 138 | cpuid->have_pclmulqdq_ = (ecx >> 1) & 0x1; |
| 139 | cpuid->have_popcnt_ = (ecx >> 23) & 0x1; |
| 140 | cpuid->have_rdrand_ = (ecx >> 30) & 0x1; |
| 141 | cpuid->have_sse2_ = (edx >> 26) & 0x1; |
| 142 | cpuid->have_sse3_ = ecx & 0x1; |
| 143 | cpuid->have_sse4_1_ = (ecx >> 19) & 0x1; |
| 144 | cpuid->have_sse4_2_ = (ecx >> 20) & 0x1; |
| 145 | cpuid->have_sse_ = (edx >> 25) & 0x1; |
| 146 | cpuid->have_ssse3_ = (ecx >> 9) & 0x1; |
| 147 | cpuid->have_hypervisor_ = (ecx >> 31) & 1; |
| 148 | |
| 149 | const uint64 xcr0_xmm_mask = 0x2; |
| 150 | const uint64 xcr0_ymm_mask = 0x4; |
| 151 | const uint64 xcr0_maskreg_mask = 0x20; |
| 152 | const uint64 xcr0_zmm0_15_mask = 0x40; |
| 153 | const uint64 xcr0_zmm16_31_mask = 0x80; |
| 154 | |
| 155 | const uint64 xcr0_avx_mask = xcr0_xmm_mask | xcr0_ymm_mask; |
| 156 | const uint64 xcr0_avx512_mask = xcr0_avx_mask | xcr0_maskreg_mask | |
| 157 | xcr0_zmm0_15_mask | xcr0_zmm16_31_mask; |
| 158 | |
| 159 | const bool have_avx = |
| 160 | // Does the OS support XGETBV instruction use by applications? |
| 161 | ((ecx >> 27) & 0x1) && |
| 162 | // Does the OS save/restore XMM and YMM state? |
| 163 | ((GetXCR0EAX() & xcr0_avx_mask) == xcr0_avx_mask) && |
| 164 | // Is AVX supported in hardware? |
| 165 | ((ecx >> 28) & 0x1); |
| 166 | |
| 167 | const bool have_avx512 = |
| 168 | // Does the OS support XGETBV instruction use by applications? |