2 * i386 CPUID helper functions
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2017 Google Inc.
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 of the License, or (at your option) any later version.
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.
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/>.
23 #include "qemu/osdep.h"
24 #include "qemu-common.h"
28 #include "sysemu/hvf.h"
30 static uint64_t xgetbv(uint32_t xcr
)
34 __asm__
volatile ("xgetbv"
35 : "=a" (eax
), "=d" (edx
)
38 return (((uint64_t)edx
) << 32) | eax
;
41 static bool vmx_mpx_supported()
43 uint64_t cap_exit
, cap_entry
;
45 hv_vmx_read_capability(HV_VMX_CAP_ENTRY
, &cap_entry
);
46 hv_vmx_read_capability(HV_VMX_CAP_EXIT
, &cap_exit
);
48 return ((cap_exit
& (1 << 23)) && (cap_entry
& (1 << 16)));
51 uint32_t hvf_get_supported_cpuid(uint32_t func
, uint32_t idx
,
55 uint32_t eax
, ebx
, ecx
, edx
;
57 host_cpuid(func
, idx
, &eax
, &ebx
, &ecx
, &edx
);
61 eax
= eax
< (uint32_t)0xd ? eax
: (uint32_t)0xd;
64 edx
&= CPUID_FP87
| CPUID_VME
| CPUID_DE
| CPUID_PSE
| CPUID_TSC
|
65 CPUID_MSR
| CPUID_PAE
| CPUID_MCE
| CPUID_CX8
| CPUID_APIC
|
66 CPUID_SEP
| CPUID_MTRR
| CPUID_PGE
| CPUID_MCA
| CPUID_CMOV
|
67 CPUID_PAT
| CPUID_PSE36
| CPUID_CLFLUSH
| CPUID_MMX
|
68 CPUID_FXSR
| CPUID_SSE
| CPUID_SSE2
| CPUID_SS
;
69 ecx
&= CPUID_EXT_SSE3
| CPUID_EXT_PCLMULQDQ
| CPUID_EXT_SSSE3
|
70 CPUID_EXT_FMA
| CPUID_EXT_CX16
| CPUID_EXT_PCID
|
71 CPUID_EXT_SSE41
| CPUID_EXT_SSE42
| CPUID_EXT_MOVBE
|
72 CPUID_EXT_POPCNT
| CPUID_EXT_AES
| CPUID_EXT_XSAVE
|
73 CPUID_EXT_AVX
| CPUID_EXT_F16C
| CPUID_EXT_RDRAND
;
74 ecx
|= CPUID_EXT_HYPERVISOR
;
77 eax
= CPUID_6_EAX_ARAT
;
84 ebx
&= CPUID_7_0_EBX_FSGSBASE
| CPUID_7_0_EBX_BMI1
|
85 CPUID_7_0_EBX_HLE
| CPUID_7_0_EBX_AVX2
|
86 CPUID_7_0_EBX_SMEP
| CPUID_7_0_EBX_BMI2
|
87 CPUID_7_0_EBX_ERMS
| CPUID_7_0_EBX_RTM
|
88 CPUID_7_0_EBX_RDSEED
| CPUID_7_0_EBX_ADX
|
89 CPUID_7_0_EBX_SMAP
| CPUID_7_0_EBX_AVX512IFMA
|
90 CPUID_7_0_EBX_AVX512F
| CPUID_7_0_EBX_AVX512PF
|
91 CPUID_7_0_EBX_AVX512ER
| CPUID_7_0_EBX_AVX512CD
|
92 CPUID_7_0_EBX_CLFLUSHOPT
| CPUID_7_0_EBX_CLWB
|
93 CPUID_7_0_EBX_AVX512DQ
| CPUID_7_0_EBX_SHA_NI
|
94 CPUID_7_0_EBX_AVX512BW
| CPUID_7_0_EBX_AVX512VL
|
95 CPUID_7_0_EBX_INVPCID
| CPUID_7_0_EBX_MPX
;
97 if (!vmx_mpx_supported()) {
98 ebx
&= ~CPUID_7_0_EBX_MPX
;
100 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2
, &cap
);
101 if (!(cap
& CPU_BASED2_INVPCID
)) {
102 ebx
&= ~CPUID_7_0_EBX_INVPCID
;
105 ecx
&= CPUID_7_0_ECX_AVX512BMI
| CPUID_7_0_ECX_AVX512_VPOPCNTDQ
;
106 edx
&= CPUID_7_0_EDX_AVX512_4VNNIW
| CPUID_7_0_EDX_AVX512_4FMAPS
;
116 uint64_t host_xcr0
= xgetbv(0);
117 uint64_t supp_xcr0
= host_xcr0
& (XSTATE_FP_MASK
| XSTATE_SSE_MASK
|
118 XSTATE_YMM_MASK
| XSTATE_BNDREGS_MASK
|
119 XSTATE_BNDCSR_MASK
| XSTATE_OPMASK_MASK
|
120 XSTATE_ZMM_Hi256_MASK
| XSTATE_Hi16_ZMM_MASK
);
122 if (!vmx_mpx_supported()) {
123 eax
&= ~(XSTATE_BNDREGS_MASK
| XSTATE_BNDCSR_MASK
);
125 } else if (idx
== 1) {
126 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2
, &cap
);
127 eax
&= CPUID_XSAVE_XSAVEOPT
| CPUID_XSAVE_XGETBV1
;
128 if (!(cap
& CPU_BASED2_XSAVES_XRSTORS
)) {
129 eax
&= ~CPUID_XSAVE_XSAVES
;
134 /* LM only if HVF in 64-bit mode */
135 edx
&= CPUID_FP87
| CPUID_VME
| CPUID_DE
| CPUID_PSE
| CPUID_TSC
|
136 CPUID_MSR
| CPUID_PAE
| CPUID_MCE
| CPUID_CX8
| CPUID_APIC
|
137 CPUID_EXT2_SYSCALL
| CPUID_MTRR
| CPUID_PGE
| CPUID_MCA
| CPUID_CMOV
|
138 CPUID_PAT
| CPUID_PSE36
| CPUID_EXT2_MMXEXT
| CPUID_MMX
|
139 CPUID_FXSR
| CPUID_EXT2_FXSR
| CPUID_EXT2_PDPE1GB
| CPUID_EXT2_3DNOWEXT
|
140 CPUID_EXT2_3DNOW
| CPUID_EXT2_LM
| CPUID_EXT2_RDTSCP
| CPUID_EXT2_NX
;
141 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED
, &cap
);
142 if (!(cap
& CPU_BASED_TSC_OFFSET
)) {
143 edx
&= ~CPUID_EXT2_RDTSCP
;
145 ecx
&= CPUID_EXT3_LAHF_LM
| CPUID_EXT3_CMP_LEG
| CPUID_EXT3_CR8LEG
|
146 CPUID_EXT3_ABM
| CPUID_EXT3_SSE4A
| CPUID_EXT3_MISALIGNSSE
|
147 CPUID_EXT3_3DNOWPREFETCH
| CPUID_EXT3_OSVW
| CPUID_EXT3_XOP
|
148 CPUID_EXT3_FMA4
| CPUID_EXT3_TBM
;