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 uint32_t hvf_get_supported_cpuid(uint32_t func
, uint32_t idx
,
45 uint32_t eax
, ebx
, ecx
, edx
;
47 host_cpuid(func
, idx
, &eax
, &ebx
, &ecx
, &edx
);
51 eax
= eax
< (uint32_t)0xd ? eax
: (uint32_t)0xd;
54 edx
&= CPUID_FP87
| CPUID_VME
| CPUID_DE
| CPUID_PSE
| CPUID_TSC
|
55 CPUID_MSR
| CPUID_PAE
| CPUID_MCE
| CPUID_CX8
| CPUID_APIC
|
56 CPUID_SEP
| CPUID_MTRR
| CPUID_PGE
| CPUID_MCA
| CPUID_CMOV
|
57 CPUID_PAT
| CPUID_PSE36
| CPUID_CLFLUSH
| CPUID_MMX
|
58 CPUID_FXSR
| CPUID_SSE
| CPUID_SSE2
| CPUID_SS
;
59 ecx
&= CPUID_EXT_SSE3
| CPUID_EXT_PCLMULQDQ
| CPUID_EXT_SSSE3
|
60 CPUID_EXT_FMA
| CPUID_EXT_CX16
| CPUID_EXT_PCID
|
61 CPUID_EXT_SSE41
| CPUID_EXT_SSE42
| CPUID_EXT_MOVBE
|
62 CPUID_EXT_POPCNT
| CPUID_EXT_AES
| CPUID_EXT_XSAVE
|
63 CPUID_EXT_AVX
| CPUID_EXT_F16C
| CPUID_EXT_RDRAND
;
64 ecx
|= CPUID_EXT_HYPERVISOR
;
67 eax
= CPUID_6_EAX_ARAT
;
74 ebx
&= CPUID_7_0_EBX_FSGSBASE
| CPUID_7_0_EBX_BMI1
|
75 CPUID_7_0_EBX_HLE
| CPUID_7_0_EBX_AVX2
|
76 CPUID_7_0_EBX_SMEP
| CPUID_7_0_EBX_BMI2
|
77 CPUID_7_0_EBX_ERMS
| CPUID_7_0_EBX_RTM
|
78 CPUID_7_0_EBX_RDSEED
| CPUID_7_0_EBX_ADX
|
79 CPUID_7_0_EBX_SMAP
| CPUID_7_0_EBX_AVX512IFMA
|
80 CPUID_7_0_EBX_AVX512F
| CPUID_7_0_EBX_AVX512PF
|
81 CPUID_7_0_EBX_AVX512ER
| CPUID_7_0_EBX_AVX512CD
|
82 CPUID_7_0_EBX_CLFLUSHOPT
| CPUID_7_0_EBX_CLWB
|
83 CPUID_7_0_EBX_AVX512DQ
| CPUID_7_0_EBX_SHA_NI
|
84 CPUID_7_0_EBX_AVX512BW
| CPUID_7_0_EBX_AVX512VL
|
85 CPUID_7_0_EBX_INVPCID
;
87 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2
, &cap
);
88 if (!(cap
& CPU_BASED2_INVPCID
)) {
89 ebx
&= ~CPUID_7_0_EBX_INVPCID
;
92 ecx
&= CPUID_7_0_ECX_AVX512BMI
| CPUID_7_0_ECX_AVX512_VPOPCNTDQ
;
93 edx
&= CPUID_7_0_EDX_AVX512_4VNNIW
| CPUID_7_0_EDX_AVX512_4FMAPS
;
103 uint64_t host_xcr0
= xgetbv(0);
104 uint64_t supp_xcr0
= host_xcr0
& (XSTATE_FP_MASK
| XSTATE_SSE_MASK
|
105 XSTATE_YMM_MASK
| XSTATE_BNDREGS_MASK
|
106 XSTATE_BNDCSR_MASK
| XSTATE_OPMASK_MASK
|
107 XSTATE_ZMM_Hi256_MASK
| XSTATE_Hi16_ZMM_MASK
);
109 } else if (idx
== 1) {
110 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2
, &cap
);
111 eax
&= CPUID_XSAVE_XSAVEOPT
| CPUID_XSAVE_XGETBV1
;
112 if (!(cap
& CPU_BASED2_XSAVES_XRSTORS
)) {
113 eax
&= ~CPUID_XSAVE_XSAVES
;
118 /* LM only if HVF in 64-bit mode */
119 edx
&= CPUID_FP87
| CPUID_VME
| CPUID_DE
| CPUID_PSE
| CPUID_TSC
|
120 CPUID_MSR
| CPUID_PAE
| CPUID_MCE
| CPUID_CX8
| CPUID_APIC
|
121 CPUID_EXT2_SYSCALL
| CPUID_MTRR
| CPUID_PGE
| CPUID_MCA
| CPUID_CMOV
|
122 CPUID_PAT
| CPUID_PSE36
| CPUID_EXT2_MMXEXT
| CPUID_MMX
|
123 CPUID_FXSR
| CPUID_EXT2_FXSR
| CPUID_EXT2_PDPE1GB
| CPUID_EXT2_3DNOWEXT
|
124 CPUID_EXT2_3DNOW
| CPUID_EXT2_LM
| CPUID_EXT2_RDTSCP
| CPUID_EXT2_NX
;
125 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED
, &cap
);
126 if (!(cap
& CPU_BASED_TSC_OFFSET
)) {
127 edx
&= ~CPUID_EXT2_RDTSCP
;
129 ecx
&= CPUID_EXT3_LAHF_LM
| CPUID_EXT3_CMP_LEG
| CPUID_EXT3_CR8LEG
|
130 CPUID_EXT3_ABM
| CPUID_EXT3_SSE4A
| CPUID_EXT3_MISALIGNSSE
|
131 CPUID_EXT3_3DNOWPREFETCH
| CPUID_EXT3_OSVW
| CPUID_EXT3_XOP
|
132 CPUID_EXT3_FMA4
| CPUID_EXT3_TBM
;