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.1 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"
27 #include "sysemu/hvf.h"
29 static bool xgetbv(uint32_t cpuid_ecx
, uint32_t idx
, uint64_t *xcr
)
33 if (cpuid_ecx
& CPUID_EXT_OSXSAVE
) {
35 * The xgetbv instruction is not available to older versions of
36 * the assembler, so we encode the instruction manually.
38 asm(".byte 0x0f, 0x01, 0xd0" : "=a" (xcrl
), "=d" (xcrh
) : "c" (idx
));
40 *xcr
= (((uint64_t)xcrh
) << 32) | xcrl
;
47 uint32_t hvf_get_supported_cpuid(uint32_t func
, uint32_t idx
,
51 uint32_t eax
, ebx
, ecx
, edx
;
53 host_cpuid(func
, idx
, &eax
, &ebx
, &ecx
, &edx
);
57 eax
= eax
< (uint32_t)0xd ? eax
: (uint32_t)0xd;
60 edx
&= CPUID_FP87
| CPUID_VME
| CPUID_DE
| CPUID_PSE
| CPUID_TSC
|
61 CPUID_MSR
| CPUID_PAE
| CPUID_MCE
| CPUID_CX8
| CPUID_APIC
|
62 CPUID_SEP
| CPUID_MTRR
| CPUID_PGE
| CPUID_MCA
| CPUID_CMOV
|
63 CPUID_PAT
| CPUID_PSE36
| CPUID_CLFLUSH
| CPUID_MMX
|
64 CPUID_FXSR
| CPUID_SSE
| CPUID_SSE2
| CPUID_SS
;
65 ecx
&= CPUID_EXT_SSE3
| CPUID_EXT_PCLMULQDQ
| CPUID_EXT_SSSE3
|
66 CPUID_EXT_FMA
| CPUID_EXT_CX16
| CPUID_EXT_PCID
|
67 CPUID_EXT_SSE41
| CPUID_EXT_SSE42
| CPUID_EXT_MOVBE
|
68 CPUID_EXT_POPCNT
| CPUID_EXT_AES
| CPUID_EXT_XSAVE
|
69 CPUID_EXT_AVX
| CPUID_EXT_F16C
| CPUID_EXT_RDRAND
;
70 ecx
|= CPUID_EXT_HYPERVISOR
;
73 eax
= CPUID_6_EAX_ARAT
;
80 ebx
&= CPUID_7_0_EBX_FSGSBASE
| CPUID_7_0_EBX_BMI1
|
81 CPUID_7_0_EBX_HLE
| CPUID_7_0_EBX_AVX2
|
82 CPUID_7_0_EBX_SMEP
| CPUID_7_0_EBX_BMI2
|
83 CPUID_7_0_EBX_ERMS
| CPUID_7_0_EBX_RTM
|
84 CPUID_7_0_EBX_RDSEED
| CPUID_7_0_EBX_ADX
|
85 CPUID_7_0_EBX_SMAP
| CPUID_7_0_EBX_AVX512IFMA
|
86 CPUID_7_0_EBX_AVX512F
| CPUID_7_0_EBX_AVX512PF
|
87 CPUID_7_0_EBX_AVX512ER
| CPUID_7_0_EBX_AVX512CD
|
88 CPUID_7_0_EBX_CLFLUSHOPT
| CPUID_7_0_EBX_CLWB
|
89 CPUID_7_0_EBX_AVX512DQ
| CPUID_7_0_EBX_SHA_NI
|
90 CPUID_7_0_EBX_AVX512BW
| CPUID_7_0_EBX_AVX512VL
|
91 CPUID_7_0_EBX_INVPCID
;
93 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2
, &cap
);
94 if (!(cap
& CPU_BASED2_INVPCID
)) {
95 ebx
&= ~CPUID_7_0_EBX_INVPCID
;
98 ecx
&= CPUID_7_0_ECX_AVX512_VBMI
| CPUID_7_0_ECX_AVX512_VPOPCNTDQ
;
99 edx
&= CPUID_7_0_EDX_AVX512_4VNNIW
| CPUID_7_0_EDX_AVX512_4FMAPS
;
110 if (xgetbv(ecx
, 0, &host_xcr0
)) {
111 uint64_t supp_xcr0
= host_xcr0
& (XSTATE_FP_MASK
|
112 XSTATE_SSE_MASK
| XSTATE_YMM_MASK
|
113 XSTATE_BNDREGS_MASK
| XSTATE_BNDCSR_MASK
|
114 XSTATE_OPMASK_MASK
| XSTATE_ZMM_Hi256_MASK
|
115 XSTATE_Hi16_ZMM_MASK
);
118 } else if (idx
== 1) {
119 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2
, &cap
);
120 eax
&= CPUID_XSAVE_XSAVEOPT
| CPUID_XSAVE_XGETBV1
;
121 if (!(cap
& CPU_BASED2_XSAVES_XRSTORS
)) {
122 eax
&= ~CPUID_XSAVE_XSAVES
;
127 /* LM only if HVF in 64-bit mode */
128 edx
&= CPUID_FP87
| CPUID_VME
| CPUID_DE
| CPUID_PSE
| CPUID_TSC
|
129 CPUID_MSR
| CPUID_PAE
| CPUID_MCE
| CPUID_CX8
| CPUID_APIC
|
130 CPUID_EXT2_SYSCALL
| CPUID_MTRR
| CPUID_PGE
| CPUID_MCA
| CPUID_CMOV
|
131 CPUID_PAT
| CPUID_PSE36
| CPUID_EXT2_MMXEXT
| CPUID_MMX
|
132 CPUID_FXSR
| CPUID_EXT2_FXSR
| CPUID_EXT2_PDPE1GB
| CPUID_EXT2_3DNOWEXT
|
133 CPUID_EXT2_3DNOW
| CPUID_EXT2_LM
| CPUID_EXT2_RDTSCP
| CPUID_EXT2_NX
;
134 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2
, &cap
);
135 if (!(cap
& CPU_BASED2_RDTSCP
)) {
136 edx
&= ~CPUID_EXT2_RDTSCP
;
138 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED
, &cap
);
139 if (!(cap
& CPU_BASED_TSC_OFFSET
)) {
140 edx
&= ~CPUID_EXT2_RDTSCP
;
142 ecx
&= CPUID_EXT3_LAHF_LM
| CPUID_EXT3_CMP_LEG
| CPUID_EXT3_CR8LEG
|
143 CPUID_EXT3_ABM
| CPUID_EXT3_SSE4A
| CPUID_EXT3_MISALIGNSSE
|
144 CPUID_EXT3_3DNOWPREFETCH
| CPUID_EXT3_OSVW
| CPUID_EXT3_XOP
|
145 CPUID_EXT3_FMA4
| CPUID_EXT3_TBM
;