1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include "qemu/osdep.h"
24#include "qemu-common.h"
25#include "cpu.h"
26#include "x86.h"
27#include "vmx.h"
28#include "sysemu/hvf.h"
29
30static bool xgetbv(uint32_t cpuid_ecx, uint32_t idx, uint64_t *xcr)
31{
32 uint32_t xcrl, xcrh;
33
34 if (cpuid_ecx & CPUID_EXT_OSXSAVE) {
35
36
37
38
39 asm(".byte 0x0f, 0x01, 0xd0" : "=a" (xcrl), "=d" (xcrh) : "c" (idx));
40
41 *xcr = (((uint64_t)xcrh) << 32) | xcrl;
42 return true;
43 }
44
45 return false;
46}
47
48uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
49 int reg)
50{
51 uint64_t cap;
52 uint32_t eax, ebx, ecx, edx;
53
54 host_cpuid(func, idx, &eax, &ebx, &ecx, &edx);
55
56 switch (func) {
57 case 0:
58 eax = eax < (uint32_t)0xd ? eax : (uint32_t)0xd;
59 break;
60 case 1:
61 edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
62 CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
63 CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
64 CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX |
65 CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS;
66 ecx &= CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 |
67 CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID |
68 CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_MOVBE |
69 CPUID_EXT_POPCNT | CPUID_EXT_AES | CPUID_EXT_XSAVE |
70 CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND;
71 ecx |= CPUID_EXT_HYPERVISOR;
72 break;
73 case 6:
74 eax = CPUID_6_EAX_ARAT;
75 ebx = 0;
76 ecx = 0;
77 edx = 0;
78 break;
79 case 7:
80 if (idx == 0) {
81 ebx &= CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
82 CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 |
83 CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 |
84 CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_RTM |
85 CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
86 CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_AVX512IFMA |
87 CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512PF |
88 CPUID_7_0_EBX_AVX512ER | CPUID_7_0_EBX_AVX512CD |
89 CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_CLWB |
90 CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_SHA_NI |
91 CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL |
92 CPUID_7_0_EBX_INVPCID;
93
94 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
95 if (!(cap & CPU_BASED2_INVPCID)) {
96 ebx &= ~CPUID_7_0_EBX_INVPCID;
97 }
98
99 ecx &= CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_AVX512_VPOPCNTDQ;
100 edx &= CPUID_7_0_EDX_AVX512_4VNNIW | CPUID_7_0_EDX_AVX512_4FMAPS;
101 } else {
102 ebx = 0;
103 ecx = 0;
104 edx = 0;
105 }
106 eax = 0;
107 break;
108 case 0xD:
109 if (idx == 0) {
110 uint64_t host_xcr0;
111 if (xgetbv(ecx, 0, &host_xcr0)) {
112 uint64_t supp_xcr0 = host_xcr0 & (XSTATE_FP_MASK |
113 XSTATE_SSE_MASK | XSTATE_YMM_MASK |
114 XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK |
115 XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK |
116 XSTATE_Hi16_ZMM_MASK);
117 eax &= supp_xcr0;
118 }
119 } else if (idx == 1) {
120 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
121 eax &= CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1;
122 if (!(cap & CPU_BASED2_XSAVES_XRSTORS)) {
123 eax &= ~CPUID_XSAVE_XSAVES;
124 }
125 }
126 break;
127 case 0x80000001:
128
129 edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
130 CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
131 CPUID_EXT2_SYSCALL | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
132 CPUID_PAT | CPUID_PSE36 | CPUID_EXT2_MMXEXT | CPUID_MMX |
133 CPUID_FXSR | CPUID_EXT2_FXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_3DNOWEXT |
134 CPUID_EXT2_3DNOW | CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX;
135 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
136 if (!(cap & CPU_BASED2_RDTSCP)) {
137 edx &= ~CPUID_EXT2_RDTSCP;
138 }
139 hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &cap);
140 if (!(cap & CPU_BASED_TSC_OFFSET)) {
141 edx &= ~CPUID_EXT2_RDTSCP;
142 }
143 ecx &= CPUID_EXT3_LAHF_LM | CPUID_EXT3_CMP_LEG | CPUID_EXT3_CR8LEG |
144 CPUID_EXT3_ABM | CPUID_EXT3_SSE4A | CPUID_EXT3_MISALIGNSSE |
145 CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_OSVW | CPUID_EXT3_XOP |
146 CPUID_EXT3_FMA4 | CPUID_EXT3_TBM;
147 break;
148 default:
149 return 0;
150 }
151
152 switch (reg) {
153 case R_EAX:
154 return eax;
155 case R_EBX:
156 return ebx;
157 case R_ECX:
158 return ecx;
159 case R_EDX:
160 return edx;
161 default:
162 return 0;
163 }
164}
165