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