1 /* 2 * i386 CPUID helper functions 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * Copyright (c) 2017 Google Inc. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this program; if not, see <http://www.gnu.org/licenses/>. 19 * 20 * cpuid 21 */ 22 23 #include "qemu/osdep.h" 24 #include "qemu/cpuid.h" 25 #include "host/cpuinfo.h" 26 #include "cpu.h" 27 #include "x86.h" 28 #include "vmx.h" 29 #include "sysemu/hvf.h" 30 #include "hvf-i386.h" 31 32 static bool cached_xcr0; 33 static uint64_t supported_xcr0; 34 35 static void cache_host_xcr0(void) 36 { 37 if (cached_xcr0) { 38 return; 39 } 40 41 if (cpuinfo & CPUINFO_OSXSAVE) { 42 uint64_t host_xcr0 = xgetbv_low(0); 43 44 /* Only show xcr0 bits corresponding to usable features. */ 45 supported_xcr0 = host_xcr0 & (XSTATE_FP_MASK | 46 XSTATE_SSE_MASK | XSTATE_YMM_MASK | 47 XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK | 48 XSTATE_Hi16_ZMM_MASK); 49 if ((supported_xcr0 & (XSTATE_FP_MASK | XSTATE_SSE_MASK)) != 50 (XSTATE_FP_MASK | XSTATE_SSE_MASK)) { 51 supported_xcr0 = 0; 52 } 53 } 54 55 cached_xcr0 = true; 56 } 57 58 uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, 59 int reg) 60 { 61 uint64_t cap; 62 uint32_t eax, ebx, ecx, edx; 63 64 cache_host_xcr0(); 65 host_cpuid(func, idx, &eax, &ebx, &ecx, &edx); 66 67 switch (func) { 68 case 0: 69 eax = eax < (uint32_t)0xd ? eax : (uint32_t)0xd; 70 break; 71 case 1: 72 edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | 73 CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | 74 CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | 75 CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX | 76 CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS; 77 ecx &= CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 | 78 CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID | 79 CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_MOVBE | 80 CPUID_EXT_POPCNT | CPUID_EXT_AES | CPUID_EXT_X2APIC | 81 (supported_xcr0 ? CPUID_EXT_XSAVE : 0) | 82 CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND; 83 ecx |= CPUID_EXT_HYPERVISOR; 84 break; 85 case 6: 86 eax = CPUID_6_EAX_ARAT; 87 ebx = 0; 88 ecx = 0; 89 edx = 0; 90 break; 91 case 7: 92 if (idx == 0) { 93 ebx &= CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | 94 CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | 95 CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | 96 CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_RTM | 97 CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | 98 CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_AVX512IFMA | 99 CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512PF | 100 CPUID_7_0_EBX_AVX512ER | CPUID_7_0_EBX_AVX512CD | 101 CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_CLWB | 102 CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_SHA_NI | 103 CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL | 104 CPUID_7_0_EBX_INVPCID; 105 106 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap); 107 if (!(cap & CPU_BASED2_INVPCID)) { 108 ebx &= ~CPUID_7_0_EBX_INVPCID; 109 } 110 111 ecx &= CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_AVX512_VPOPCNTDQ | 112 CPUID_7_0_ECX_RDPID; 113 edx &= CPUID_7_0_EDX_AVX512_4VNNIW | CPUID_7_0_EDX_AVX512_4FMAPS; 114 } else { 115 ebx = 0; 116 ecx = 0; 117 edx = 0; 118 } 119 eax = 0; 120 break; 121 case 0xD: 122 if (!supported_xcr0 || idx >= 63 || 123 (idx > 1 && !(supported_xcr0 & (UINT64_C(1) << idx)))) { 124 eax = ebx = ecx = edx = 0; 125 break; 126 } 127 128 if (idx == 0) { 129 eax = supported_xcr0; 130 } else if (idx == 1) { 131 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap); 132 eax &= CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1; 133 if (!(cap & CPU_BASED2_XSAVES_XRSTORS)) { 134 eax &= ~CPUID_XSAVE_XSAVES; 135 } 136 } 137 break; 138 case 0x80000001: 139 /* LM only if HVF in 64-bit mode */ 140 edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | 141 CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | 142 CPUID_EXT2_SYSCALL | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | 143 CPUID_PAT | CPUID_PSE36 | CPUID_EXT2_MMXEXT | CPUID_MMX | 144 CPUID_FXSR | CPUID_EXT2_FXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_3DNOWEXT | 145 CPUID_EXT2_3DNOW | CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX; 146 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap); 147 if (!(cap2ctrl(cap, CPU_BASED2_RDTSCP) & CPU_BASED2_RDTSCP)) { 148 edx &= ~CPUID_EXT2_RDTSCP; 149 } 150 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &cap); 151 if (!(cap2ctrl(cap, CPU_BASED_TSC_OFFSET) & CPU_BASED_TSC_OFFSET)) { 152 edx &= ~CPUID_EXT2_RDTSCP; 153 } 154 ecx &= CPUID_EXT3_LAHF_LM | CPUID_EXT3_CMP_LEG | CPUID_EXT3_CR8LEG | 155 CPUID_EXT3_ABM | CPUID_EXT3_SSE4A | CPUID_EXT3_MISALIGNSSE | 156 CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_OSVW | CPUID_EXT3_XOP | 157 CPUID_EXT3_FMA4 | CPUID_EXT3_TBM; 158 break; 159 case 0x80000007: 160 edx &= CPUID_APM_INVTSC; 161 eax = ebx = ecx = 0; 162 break; 163 default: 164 return 0; 165 } 166 167 switch (reg) { 168 case R_EAX: 169 return eax; 170 case R_EBX: 171 return ebx; 172 case R_ECX: 173 return ecx; 174 case R_EDX: 175 return edx; 176 default: 177 return 0; 178 } 179 } 180