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
108af82b8eSChetan Pant * version 2.1 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"
247cac7aa7SPaolo Bonzini #include "qemu/cpuid.h"
257cac7aa7SPaolo Bonzini #include "host/cpuinfo.h"
26ff2de166SPaolo Bonzini #include "cpu.h"
2727458df8SWei Liu #include "emulate/x86.h"
28db5cb9a0SSergio Andres Gomez Del Real #include "vmx.h"
2932cad1ffSPhilippe Mathieu-Daudé #include "system/hvf.h"
30044431cfSPhilippe Mathieu-Daudé #include "hvf-i386.h"
31db5cb9a0SSergio Andres Gomez Del Real
327cac7aa7SPaolo Bonzini static bool cached_xcr0;
337cac7aa7SPaolo Bonzini static uint64_t supported_xcr0;
347cac7aa7SPaolo Bonzini
cache_host_xcr0(void)35520c0bb2SPierrick Bouvier static void cache_host_xcr0(void)
36db5cb9a0SSergio Andres Gomez Del Real {
377cac7aa7SPaolo Bonzini if (cached_xcr0) {
387cac7aa7SPaolo Bonzini return;
39118f2aadSHill Ma }
40118f2aadSHill Ma
417cac7aa7SPaolo Bonzini if (cpuinfo & CPUINFO_OSXSAVE) {
427cac7aa7SPaolo Bonzini uint64_t host_xcr0 = xgetbv_low(0);
437cac7aa7SPaolo Bonzini
447cac7aa7SPaolo Bonzini /* Only show xcr0 bits corresponding to usable features. */
457cac7aa7SPaolo Bonzini supported_xcr0 = host_xcr0 & (XSTATE_FP_MASK |
467cac7aa7SPaolo Bonzini XSTATE_SSE_MASK | XSTATE_YMM_MASK |
477cac7aa7SPaolo Bonzini XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK |
487cac7aa7SPaolo Bonzini XSTATE_Hi16_ZMM_MASK);
497cac7aa7SPaolo Bonzini if ((supported_xcr0 & (XSTATE_FP_MASK | XSTATE_SSE_MASK)) !=
507cac7aa7SPaolo Bonzini (XSTATE_FP_MASK | XSTATE_SSE_MASK)) {
517cac7aa7SPaolo Bonzini supported_xcr0 = 0;
527cac7aa7SPaolo Bonzini }
537cac7aa7SPaolo Bonzini }
547cac7aa7SPaolo Bonzini
557cac7aa7SPaolo Bonzini cached_xcr0 = true;
56db5cb9a0SSergio Andres Gomez Del Real }
57db5cb9a0SSergio Andres Gomez Del Real
hvf_get_supported_cpuid(uint32_t func,uint32_t idx,int reg)58db5cb9a0SSergio Andres Gomez Del Real uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
59db5cb9a0SSergio Andres Gomez Del Real int reg)
60db5cb9a0SSergio Andres Gomez Del Real {
61db5cb9a0SSergio Andres Gomez Del Real uint64_t cap;
62db5cb9a0SSergio Andres Gomez Del Real uint32_t eax, ebx, ecx, edx;
63db5cb9a0SSergio Andres Gomez Del Real
647cac7aa7SPaolo Bonzini cache_host_xcr0();
65db5cb9a0SSergio Andres Gomez Del Real host_cpuid(func, idx, &eax, &ebx, &ecx, &edx);
66db5cb9a0SSergio Andres Gomez Del Real
67db5cb9a0SSergio Andres Gomez Del Real switch (func) {
68db5cb9a0SSergio Andres Gomez Del Real case 0:
69db5cb9a0SSergio Andres Gomez Del Real eax = eax < (uint32_t)0xd ? eax : (uint32_t)0xd;
70db5cb9a0SSergio Andres Gomez Del Real break;
71db5cb9a0SSergio Andres Gomez Del Real case 1:
72db5cb9a0SSergio Andres Gomez Del Real edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
73db5cb9a0SSergio Andres Gomez Del Real CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
74db5cb9a0SSergio Andres Gomez Del Real CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
75db5cb9a0SSergio Andres Gomez Del Real CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX |
76*7a486123SXiaoyao Li CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS | CPUID_HT;
77db5cb9a0SSergio Andres Gomez Del Real ecx &= CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 |
78db5cb9a0SSergio Andres Gomez Del Real CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID |
79db5cb9a0SSergio Andres Gomez Del Real CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_MOVBE |
800e27f3a5SPhil Dennis-Jordan CPUID_EXT_POPCNT | CPUID_EXT_AES | CPUID_EXT_X2APIC |
817cac7aa7SPaolo Bonzini (supported_xcr0 ? CPUID_EXT_XSAVE : 0) |
82db5cb9a0SSergio Andres Gomez Del Real CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND;
83db5cb9a0SSergio Andres Gomez Del Real ecx |= CPUID_EXT_HYPERVISOR;
84db5cb9a0SSergio Andres Gomez Del Real break;
85db5cb9a0SSergio Andres Gomez Del Real case 6:
86db5cb9a0SSergio Andres Gomez Del Real eax = CPUID_6_EAX_ARAT;
87db5cb9a0SSergio Andres Gomez Del Real ebx = 0;
88db5cb9a0SSergio Andres Gomez Del Real ecx = 0;
89db5cb9a0SSergio Andres Gomez Del Real edx = 0;
90db5cb9a0SSergio Andres Gomez Del Real break;
91db5cb9a0SSergio Andres Gomez Del Real case 7:
92db5cb9a0SSergio Andres Gomez Del Real if (idx == 0) {
93db5cb9a0SSergio Andres Gomez Del Real ebx &= CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
94db5cb9a0SSergio Andres Gomez Del Real CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 |
95db5cb9a0SSergio Andres Gomez Del Real CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 |
96db5cb9a0SSergio Andres Gomez Del Real CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_RTM |
97db5cb9a0SSergio Andres Gomez Del Real CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
98db5cb9a0SSergio Andres Gomez Del Real CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_AVX512IFMA |
99db5cb9a0SSergio Andres Gomez Del Real CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512PF |
100db5cb9a0SSergio Andres Gomez Del Real CPUID_7_0_EBX_AVX512ER | CPUID_7_0_EBX_AVX512CD |
101db5cb9a0SSergio Andres Gomez Del Real CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_CLWB |
102db5cb9a0SSergio Andres Gomez Del Real CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_SHA_NI |
103db5cb9a0SSergio Andres Gomez Del Real CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL |
104c29b48dbSPaolo Bonzini CPUID_7_0_EBX_INVPCID;
105db5cb9a0SSergio Andres Gomez Del Real
106db5cb9a0SSergio Andres Gomez Del Real hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
107db5cb9a0SSergio Andres Gomez Del Real if (!(cap & CPU_BASED2_INVPCID)) {
108db5cb9a0SSergio Andres Gomez Del Real ebx &= ~CPUID_7_0_EBX_INVPCID;
109db5cb9a0SSergio Andres Gomez Del Real }
110db5cb9a0SSergio Andres Gomez Del Real
111d8cf2c29SCameron Esfahani ecx &= CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_AVX512_VPOPCNTDQ |
112d8cf2c29SCameron Esfahani CPUID_7_0_ECX_RDPID;
113db5cb9a0SSergio Andres Gomez Del Real edx &= CPUID_7_0_EDX_AVX512_4VNNIW | CPUID_7_0_EDX_AVX512_4FMAPS;
114db5cb9a0SSergio Andres Gomez Del Real } else {
115db5cb9a0SSergio Andres Gomez Del Real ebx = 0;
116db5cb9a0SSergio Andres Gomez Del Real ecx = 0;
117db5cb9a0SSergio Andres Gomez Del Real edx = 0;
118db5cb9a0SSergio Andres Gomez Del Real }
119db5cb9a0SSergio Andres Gomez Del Real eax = 0;
120db5cb9a0SSergio Andres Gomez Del Real break;
121db5cb9a0SSergio Andres Gomez Del Real case 0xD:
122e3150028SPhil Dennis-Jordan if (!supported_xcr0 || idx >= 63 ||
123e3150028SPhil Dennis-Jordan (idx > 1 && !(supported_xcr0 & (UINT64_C(1) << idx)))) {
1247cac7aa7SPaolo Bonzini eax = ebx = ecx = edx = 0;
1257cac7aa7SPaolo Bonzini break;
126118f2aadSHill Ma }
1277cac7aa7SPaolo Bonzini
1287cac7aa7SPaolo Bonzini if (idx == 0) {
1297cac7aa7SPaolo Bonzini eax = supported_xcr0;
130db5cb9a0SSergio Andres Gomez Del Real } else if (idx == 1) {
131db5cb9a0SSergio Andres Gomez Del Real hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
132db5cb9a0SSergio Andres Gomez Del Real eax &= CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1;
133db5cb9a0SSergio Andres Gomez Del Real if (!(cap & CPU_BASED2_XSAVES_XRSTORS)) {
134db5cb9a0SSergio Andres Gomez Del Real eax &= ~CPUID_XSAVE_XSAVES;
135db5cb9a0SSergio Andres Gomez Del Real }
136db5cb9a0SSergio Andres Gomez Del Real }
137db5cb9a0SSergio Andres Gomez Del Real break;
138db5cb9a0SSergio Andres Gomez Del Real case 0x80000001:
139db5cb9a0SSergio Andres Gomez Del Real /* LM only if HVF in 64-bit mode */
140db5cb9a0SSergio Andres Gomez Del Real edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
141db5cb9a0SSergio Andres Gomez Del Real CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
142db5cb9a0SSergio Andres Gomez Del Real CPUID_EXT2_SYSCALL | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
143db5cb9a0SSergio Andres Gomez Del Real CPUID_PAT | CPUID_PSE36 | CPUID_EXT2_MMXEXT | CPUID_MMX |
144db5cb9a0SSergio Andres Gomez Del Real CPUID_FXSR | CPUID_EXT2_FXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_3DNOWEXT |
145db5cb9a0SSergio Andres Gomez Del Real CPUID_EXT2_3DNOW | CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX;
14665baabcaSJessica Clarke hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
147d8cf2c29SCameron Esfahani if (!(cap2ctrl(cap, CPU_BASED2_RDTSCP) & CPU_BASED2_RDTSCP)) {
14865baabcaSJessica Clarke edx &= ~CPUID_EXT2_RDTSCP;
14965baabcaSJessica Clarke }
150db5cb9a0SSergio Andres Gomez Del Real hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &cap);
151d8cf2c29SCameron Esfahani if (!(cap2ctrl(cap, CPU_BASED_TSC_OFFSET) & CPU_BASED_TSC_OFFSET)) {
152db5cb9a0SSergio Andres Gomez Del Real edx &= ~CPUID_EXT2_RDTSCP;
153db5cb9a0SSergio Andres Gomez Del Real }
154db5cb9a0SSergio Andres Gomez Del Real ecx &= CPUID_EXT3_LAHF_LM | CPUID_EXT3_CMP_LEG | CPUID_EXT3_CR8LEG |
155db5cb9a0SSergio Andres Gomez Del Real CPUID_EXT3_ABM | CPUID_EXT3_SSE4A | CPUID_EXT3_MISALIGNSSE |
156db5cb9a0SSergio Andres Gomez Del Real CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_OSVW | CPUID_EXT3_XOP |
157db5cb9a0SSergio Andres Gomez Del Real CPUID_EXT3_FMA4 | CPUID_EXT3_TBM;
158db5cb9a0SSergio Andres Gomez Del Real break;
1599c267239SPhil Dennis-Jordan case 0x80000007:
1609c267239SPhil Dennis-Jordan edx &= CPUID_APM_INVTSC;
1619c267239SPhil Dennis-Jordan eax = ebx = ecx = 0;
1629c267239SPhil Dennis-Jordan break;
163db5cb9a0SSergio Andres Gomez Del Real default:
164db5cb9a0SSergio Andres Gomez Del Real return 0;
165db5cb9a0SSergio Andres Gomez Del Real }
166db5cb9a0SSergio Andres Gomez Del Real
167db5cb9a0SSergio Andres Gomez Del Real switch (reg) {
168db5cb9a0SSergio Andres Gomez Del Real case R_EAX:
169db5cb9a0SSergio Andres Gomez Del Real return eax;
170db5cb9a0SSergio Andres Gomez Del Real case R_EBX:
171db5cb9a0SSergio Andres Gomez Del Real return ebx;
172db5cb9a0SSergio Andres Gomez Del Real case R_ECX:
173db5cb9a0SSergio Andres Gomez Del Real return ecx;
174db5cb9a0SSergio Andres Gomez Del Real case R_EDX:
175db5cb9a0SSergio Andres Gomez Del Real return edx;
176db5cb9a0SSergio Andres Gomez Del Real default:
177db5cb9a0SSergio Andres Gomez Del Real return 0;
178db5cb9a0SSergio Andres Gomez Del Real }
179db5cb9a0SSergio Andres Gomez Del Real }
180