1 /////////////////////////////////////////////////////////////////////////
2 // $Id: vmcs.cc 14256 2021-05-25 06:27:49Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //   Copyright (c) 2009-2019 Stanislav Shwartsman
6 //          Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 //  You should have received a copy of the GNU Lesser General Public
19 //  License along with this library; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
21 //
22 /////////////////////////////////////////////////////////////////////////
23 
24 #define NEED_CPU_REG_SHORTCUTS 1
25 #include "bochs.h"
26 #include "cpu.h"
27 
28 #define LOG_THIS BX_CPU(0)->
29 
30 #if BX_SUPPORT_VMX
31 
32 #define VMCS_REVISION_ID_FIELD_ADDR              (0x0000)
33 #define VMCS_VMX_ABORT_FIELD_ADDR                (0x0004)
34 #define VMCS_LAUNCH_STATE_FIELD_ADDR             (0x0008)
35 
VMCS_Mapping(Bit32u revision)36 VMCS_Mapping::VMCS_Mapping(Bit32u revision): revision_id(revision), ar_format(VMCS_AR_ROTATE)
37 {
38   clear();
39   init_generic_mapping();
40 }
41 
VMCS_Mapping(Bit32u revision,const char * filename)42 VMCS_Mapping::VMCS_Mapping(Bit32u revision, const char *filename): revision_id(revision), ar_format(VMCS_AR_ROTATE)
43 {
44   clear();
45 
46   // read mapping from file
47   BX_PANIC(("Reading VMCS mapping from file not implemented yet"));
48 
49   init_generic_mapping(); // for now
50 }
51 
vmcs_encoding(Bit32u type,Bit32u field)52 BX_CPP_INLINE Bit32u vmcs_encoding(Bit32u type, Bit32u field)
53 {
54   Bit32u encoding = ((type & 0xc) << 11) + ((type & 0x3) << 10) + field;
55   return encoding;
56 }
57 
init_generic_mapping()58 void VMCS_Mapping::init_generic_mapping()
59 {
60   vmcs_revision_id_field_offset = VMCS_REVISION_ID_FIELD_ADDR;
61   vmx_abort_field_offset = VMCS_VMX_ABORT_FIELD_ADDR;
62   vmcs_launch_state_field_offset = VMCS_LAUNCH_STATE_FIELD_ADDR;
63 
64   // try to build generic VMCS map
65   // 16 types, 48 encodings (0x30), 4 bytes each field => 3072 bytes
66   // reserve VMCS_DATA_OFFSET bytes in the beginning for special (hidden) VMCS fields
67   for (unsigned type=0; type<16; type++) {
68     for (unsigned field=0; field < VMX_HIGHEST_VMCS_ENCODING; field++) {
69        Bit32u encoding = vmcs_encoding(type, field);
70        if (vmcs_map[type][field] != 0xffffffff) {
71           BX_PANIC(("VMCS type %d field %d (encoding = 0x%08x) is already initialized", type, field, encoding));
72        }
73        // allocate 64 fields (4 byte each) per type (even more than 48 which is required now)
74        vmcs_map[type][field] = VMCS_DATA_OFFSET + (type*64 + field) * 4;
75        if(vmcs_map[type][field] >= VMX_VMCS_AREA_SIZE) {
76           BX_PANIC(("VMCS type %d field %d (encoding = 0x%08x) is out of VMCS boundaries", type, field, encoding));
77        }
78        BX_DEBUG(("VMCS field 0x%08x located at 0x%08x", encoding, vmcs_map[type][field]));
79     }
80   }
81 }
82 
clear()83 void VMCS_Mapping::clear()
84 {
85   for (unsigned type=0; type<16; type++) {
86     for (unsigned field=0; field < VMX_HIGHEST_VMCS_ENCODING; field++) {
87        vmcs_map[type][field] = 0xffffffff;
88     }
89   }
90 }
91 
clear_mapping(Bit32u encoding)92 bool VMCS_Mapping::clear_mapping(Bit32u encoding)
93 {
94   return set_mapping(encoding, 0xffffffff);
95 }
96 
set_mapping(Bit32u encoding,Bit32u offset)97 bool VMCS_Mapping::set_mapping(Bit32u encoding, Bit32u offset)
98 {
99   if (is_reserved(encoding))
100     return false;
101 
102   unsigned field = VMCS_FIELD(encoding);
103   if (field >= VMX_HIGHEST_VMCS_ENCODING)
104     return false;
105 
106   vmcs_map[VMCS_FIELD_INDEX(encoding)][field] = offset;
107   return true;
108 }
109 
vmcs_field_offset(Bit32u encoding) const110 unsigned VMCS_Mapping::vmcs_field_offset(Bit32u encoding) const
111 {
112   if (is_reserved(encoding)) {
113     switch(encoding) {
114       case VMCS_REVISION_ID_FIELD_ENCODING:  return vmcs_revision_id_field_offset;
115       case VMCS_VMX_ABORT_FIELD_ENCODING:    return vmx_abort_field_offset;
116       case VMCS_LAUNCH_STATE_FIELD_ENCODING: return vmcs_launch_state_field_offset;
117     }
118     return 0xffffffff;
119   }
120 
121   unsigned field = VMCS_FIELD(encoding);
122   if (field >= VMX_HIGHEST_VMCS_ENCODING)
123     return 0xffffffff;
124 
125   return vmcs_map[VMCS_FIELD_INDEX(encoding)][field];
126 }
127 
init_VMCS(void)128 void BX_CPU_C::init_VMCS(void)
129 {
130   BX_CPU_THIS_PTR vmcs_map = BX_CPU_THIS_PTR cpuid->get_vmcs();
131 
132   init_vmx_capabilities();
133 
134   static bool vmcs_map_ready = false;
135   if (vmcs_map_ready) return;
136   vmcs_map_ready = true;
137 
138   // disable not supported encodings
139   for (unsigned type=0; type<16; type++) {
140     for (unsigned field=0; field <= VMX_HIGHEST_VMCS_ENCODING; field++) {
141       Bit32u encoding = vmcs_encoding(type, field);
142       if (! vmcs_field_supported(encoding)) {
143         BX_CPU_THIS_PTR vmcs_map->clear_mapping(encoding);
144         BX_DEBUG(("VMCS field 0x%08x is not supported", encoding));
145       }
146     }
147   }
148 }
149 
150 #undef LOG_THIS
151 #define LOG_THIS BX_CPU_THIS_PTR
152 
vmcs_field_supported(Bit32u encoding)153 bool BX_CPU_C::vmcs_field_supported(Bit32u encoding)
154 {
155   switch(encoding)
156   {
157 #if BX_SUPPORT_VMX >= 2
158     /* VMCS 16-bit control fields */
159     /* binary 0000_00xx_xxxx_xxx0 */
160     case VMCS_16BIT_CONTROL_VPID:
161       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_VPID);
162 
163     case VMCS_16BIT_CONTROL_EPTP_INDEX:
164       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT_EXCEPTION);
165 #endif
166 
167     /* VMCS 16-bit guest-state fields */
168     /* binary 0000_10xx_xxxx_xxx0 */
169     case VMCS_16BIT_GUEST_ES_SELECTOR:
170     case VMCS_16BIT_GUEST_CS_SELECTOR:
171     case VMCS_16BIT_GUEST_SS_SELECTOR:
172     case VMCS_16BIT_GUEST_DS_SELECTOR:
173     case VMCS_16BIT_GUEST_FS_SELECTOR:
174     case VMCS_16BIT_GUEST_GS_SELECTOR:
175     case VMCS_16BIT_GUEST_LDTR_SELECTOR:
176     case VMCS_16BIT_GUEST_TR_SELECTOR:
177       return 1;
178 
179 #if BX_SUPPORT_VMX >= 2
180     case VMCS_16BIT_GUEST_INTERRUPT_STATUS:
181       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_VINTR_DELIVERY);
182 
183     case VMCS_16BIT_GUEST_PML_INDEX:
184       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PML);
185 #endif
186 
187     /* VMCS 16-bit host-state fields */
188     /* binary 0000_11xx_xxxx_xxx0 */
189     case VMCS_16BIT_HOST_ES_SELECTOR:
190     case VMCS_16BIT_HOST_CS_SELECTOR:
191     case VMCS_16BIT_HOST_SS_SELECTOR:
192     case VMCS_16BIT_HOST_DS_SELECTOR:
193     case VMCS_16BIT_HOST_FS_SELECTOR:
194     case VMCS_16BIT_HOST_GS_SELECTOR:
195     case VMCS_16BIT_HOST_TR_SELECTOR:
196       return 1;
197 
198     /* VMCS 32_bit control fields */
199     /* binary 0100_00xx_xxxx_xxx0 */
200     case VMCS_32BIT_CONTROL_PIN_BASED_EXEC_CONTROLS:
201     case VMCS_32BIT_CONTROL_PROCESSOR_BASED_VMEXEC_CONTROLS:
202     case VMCS_32BIT_CONTROL_EXECUTION_BITMAP:
203     case VMCS_32BIT_CONTROL_PAGE_FAULT_ERR_CODE_MASK:
204     case VMCS_32BIT_CONTROL_PAGE_FAULT_ERR_CODE_MATCH:
205     case VMCS_32BIT_CONTROL_CR3_TARGET_COUNT:
206     case VMCS_32BIT_CONTROL_VMEXIT_CONTROLS:
207     case VMCS_32BIT_CONTROL_VMEXIT_MSR_STORE_COUNT:
208     case VMCS_32BIT_CONTROL_VMEXIT_MSR_LOAD_COUNT:
209     case VMCS_32BIT_CONTROL_VMENTRY_CONTROLS:
210     case VMCS_32BIT_CONTROL_VMENTRY_MSR_LOAD_COUNT:
211     case VMCS_32BIT_CONTROL_VMENTRY_INTERRUPTION_INFO:
212     case VMCS_32BIT_CONTROL_VMENTRY_EXCEPTION_ERR_CODE:
213     case VMCS_32BIT_CONTROL_VMENTRY_INSTRUCTION_LENGTH:
214       return 1;
215 
216 #if BX_SUPPORT_X86_64
217     case VMCS_32BIT_CONTROL_TPR_THRESHOLD:
218       if (is_cpu_extension_supported(BX_ISA_LONG_MODE))
219         return BX_SUPPORT_VMX_EXTENSION(BX_VMX_TPR_SHADOW);
220       else
221         return 0;
222 #endif
223 
224     case VMCS_32BIT_CONTROL_SECONDARY_VMEXEC_CONTROLS:
225       return BX_CPU_THIS_PTR vmx_cap.vmx_vmexec_ctrl2_supported_bits;
226 
227 #if BX_SUPPORT_VMX >= 2
228     case VMCS_32BIT_CONTROL_PAUSE_LOOP_EXITING_GAP:
229     case VMCS_32BIT_CONTROL_PAUSE_LOOP_EXITING_WINDOW:
230       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAUSE_LOOP_EXITING);
231 #endif
232 
233     /* VMCS 32-bit read only data fields */
234     /* binary 0100_01xx_xxxx_xxx0 */
235     case VMCS_32BIT_INSTRUCTION_ERROR:
236     case VMCS_32BIT_VMEXIT_REASON:
237     case VMCS_32BIT_VMEXIT_INTERRUPTION_INFO:
238     case VMCS_32BIT_VMEXIT_INTERRUPTION_ERR_CODE:
239     case VMCS_32BIT_IDT_VECTORING_INFO:
240     case VMCS_32BIT_IDT_VECTORING_ERR_CODE:
241     case VMCS_32BIT_VMEXIT_INSTRUCTION_LENGTH:
242     case VMCS_32BIT_VMEXIT_INSTRUCTION_INFO:
243       return 1;
244 
245     /* VMCS 32-bit guest-state fields */
246     /* binary 0100_10xx_xxxx_xxx0 */
247     case VMCS_32BIT_GUEST_ES_LIMIT:
248     case VMCS_32BIT_GUEST_CS_LIMIT:
249     case VMCS_32BIT_GUEST_SS_LIMIT:
250     case VMCS_32BIT_GUEST_DS_LIMIT:
251     case VMCS_32BIT_GUEST_FS_LIMIT:
252     case VMCS_32BIT_GUEST_GS_LIMIT:
253     case VMCS_32BIT_GUEST_LDTR_LIMIT:
254     case VMCS_32BIT_GUEST_TR_LIMIT:
255     case VMCS_32BIT_GUEST_GDTR_LIMIT:
256     case VMCS_32BIT_GUEST_IDTR_LIMIT:
257     case VMCS_32BIT_GUEST_ES_ACCESS_RIGHTS:
258     case VMCS_32BIT_GUEST_CS_ACCESS_RIGHTS:
259     case VMCS_32BIT_GUEST_SS_ACCESS_RIGHTS:
260     case VMCS_32BIT_GUEST_DS_ACCESS_RIGHTS:
261     case VMCS_32BIT_GUEST_FS_ACCESS_RIGHTS:
262     case VMCS_32BIT_GUEST_GS_ACCESS_RIGHTS:
263     case VMCS_32BIT_GUEST_LDTR_ACCESS_RIGHTS:
264     case VMCS_32BIT_GUEST_TR_ACCESS_RIGHTS:
265     case VMCS_32BIT_GUEST_INTERRUPTIBILITY_STATE:
266     case VMCS_32BIT_GUEST_ACTIVITY_STATE:
267     case VMCS_32BIT_GUEST_SMBASE:
268     case VMCS_32BIT_GUEST_IA32_SYSENTER_CS_MSR:
269       return 1;
270 
271 #if BX_SUPPORT_VMX >= 2
272     case VMCS_32BIT_GUEST_PREEMPTION_TIMER_VALUE:
273        return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PREEMPTION_TIMER);
274 #endif
275 
276     /* VMCS 32-bit host-state fields */
277     /* binary 0100_11xx_xxxx_xxx0 */
278     case VMCS_32BIT_HOST_IA32_SYSENTER_CS_MSR:
279       return 1;
280 
281     /* VMCS 64-bit control fields */
282     /* binary 0010_00xx_xxxx_xxx0 */
283     case VMCS_64BIT_CONTROL_IO_BITMAP_A:
284     case VMCS_64BIT_CONTROL_IO_BITMAP_A_HI:
285     case VMCS_64BIT_CONTROL_IO_BITMAP_B:
286     case VMCS_64BIT_CONTROL_IO_BITMAP_B_HI:
287     case VMCS_64BIT_CONTROL_MSR_BITMAPS:
288     case VMCS_64BIT_CONTROL_MSR_BITMAPS_HI:
289     case VMCS_64BIT_CONTROL_VMEXIT_MSR_STORE_ADDR:
290     case VMCS_64BIT_CONTROL_VMEXIT_MSR_STORE_ADDR_HI:
291     case VMCS_64BIT_CONTROL_VMEXIT_MSR_LOAD_ADDR:
292     case VMCS_64BIT_CONTROL_VMEXIT_MSR_LOAD_ADDR_HI:
293     case VMCS_64BIT_CONTROL_VMENTRY_MSR_LOAD_ADDR:
294     case VMCS_64BIT_CONTROL_VMENTRY_MSR_LOAD_ADDR_HI:
295     case VMCS_64BIT_CONTROL_EXECUTIVE_VMCS_PTR:
296     case VMCS_64BIT_CONTROL_EXECUTIVE_VMCS_PTR_HI:
297       return 1;
298 
299 #if BX_SUPPORT_VMX >= 2
300     case VMCS_64BIT_CONTROL_PML_ADDRESS:
301     case VMCS_64BIT_CONTROL_PML_ADDRESS_HI:
302       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PML);
303 #endif
304 
305     case VMCS_64BIT_CONTROL_TSC_OFFSET:
306     case VMCS_64BIT_CONTROL_TSC_OFFSET_HI:
307       return 1;
308 
309 #if BX_SUPPORT_X86_64
310     case VMCS_64BIT_CONTROL_VIRTUAL_APIC_PAGE_ADDR:
311     case VMCS_64BIT_CONTROL_VIRTUAL_APIC_PAGE_ADDR_HI:
312       if (is_cpu_extension_supported(BX_ISA_LONG_MODE))
313         return BX_SUPPORT_VMX_EXTENSION(BX_VMX_TPR_SHADOW);
314       else
315         return 0;
316 
317     case VMCS_64BIT_CONTROL_APIC_ACCESS_ADDR:
318     case VMCS_64BIT_CONTROL_APIC_ACCESS_ADDR_HI:
319       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_APIC_VIRTUALIZATION);
320 #endif
321 
322 #if BX_SUPPORT_VMX >= 2
323     case VMCS_64BIT_CONTROL_VMFUNC_CTRLS:
324     case VMCS_64BIT_CONTROL_VMFUNC_CTRLS_HI:
325       return BX_CPU_THIS_PTR vmx_cap.vmx_vmfunc_supported_bits != 0;
326 
327     case VMCS_64BIT_CONTROL_EPTPTR:
328     case VMCS_64BIT_CONTROL_EPTPTR_HI:
329       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT);
330 
331     case VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP0:
332     case VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP0_HI:
333     case VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP1:
334     case VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP1_HI:
335     case VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP2:
336     case VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP2_HI:
337     case VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP3:
338     case VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP3_HI:
339       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_VINTR_DELIVERY);
340 
341     case VMCS_64BIT_CONTROL_EPTP_LIST_ADDRESS:
342     case VMCS_64BIT_CONTROL_EPTP_LIST_ADDRESS_HI:
343       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPTP_SWITCHING);
344 
345     case VMCS_64BIT_CONTROL_VMREAD_BITMAP_ADDR:
346     case VMCS_64BIT_CONTROL_VMREAD_BITMAP_ADDR_HI:
347     case VMCS_64BIT_CONTROL_VMWRITE_BITMAP_ADDR:
348     case VMCS_64BIT_CONTROL_VMWRITE_BITMAP_ADDR_HI:
349       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_VMCS_SHADOWING);
350 
351     case VMCS_64BIT_CONTROL_VE_EXCEPTION_INFO_ADDR:
352     case VMCS_64BIT_CONTROL_VE_EXCEPTION_INFO_ADDR_HI:
353       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT_EXCEPTION);
354 
355     case VMCS_64BIT_CONTROL_XSS_EXITING_BITMAP:
356     case VMCS_64BIT_CONTROL_XSS_EXITING_BITMAP_HI:
357       return is_cpu_extension_supported(BX_ISA_XSAVES);
358 
359     case VMCS_64BIT_CONTROL_SPPTP:
360     case VMCS_64BIT_CONTROL_SPPTP_HI:
361       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_SPP);
362 #endif
363 
364     case VMCS_64BIT_CONTROL_TSC_MULTIPLIER:
365     case VMCS_64BIT_CONTROL_TSC_MULTIPLIER_HI:
366       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_TSC_SCALING);
367 
368 #if BX_SUPPORT_VMX >= 2
369     /* VMCS 64-bit read only data fields */
370     /* binary 0010_01xx_xxxx_xxx0 */
371     case VMCS_64BIT_GUEST_PHYSICAL_ADDR:
372     case VMCS_64BIT_GUEST_PHYSICAL_ADDR_HI:
373       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT);
374 #endif
375 
376     /* VMCS 64-bit guest state fields */
377     /* binary 0010_10xx_xxxx_xxx0 */
378     case VMCS_64BIT_GUEST_LINK_POINTER:
379     case VMCS_64BIT_GUEST_LINK_POINTER_HI:
380     case VMCS_64BIT_GUEST_IA32_DEBUGCTL:
381     case VMCS_64BIT_GUEST_IA32_DEBUGCTL_HI:
382       return 1;
383 
384 #if BX_SUPPORT_VMX >= 2
385     case VMCS_64BIT_GUEST_IA32_PAT:
386     case VMCS_64BIT_GUEST_IA32_PAT_HI:
387       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAT);
388 
389     case VMCS_64BIT_GUEST_IA32_EFER:
390     case VMCS_64BIT_GUEST_IA32_EFER_HI:
391       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EFER);
392 #endif
393 
394     case VMCS_64BIT_GUEST_IA32_PERF_GLOBAL_CTRL:
395     case VMCS_64BIT_GUEST_IA32_PERF_GLOBAL_CTRL_HI:
396       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PERF_GLOBAL_CTRL);
397 
398 #if BX_SUPPORT_VMX >= 2
399     case VMCS_64BIT_GUEST_IA32_PDPTE0:
400     case VMCS_64BIT_GUEST_IA32_PDPTE0_HI:
401     case VMCS_64BIT_GUEST_IA32_PDPTE1:
402     case VMCS_64BIT_GUEST_IA32_PDPTE1_HI:
403     case VMCS_64BIT_GUEST_IA32_PDPTE2:
404     case VMCS_64BIT_GUEST_IA32_PDPTE2_HI:
405     case VMCS_64BIT_GUEST_IA32_PDPTE3:
406     case VMCS_64BIT_GUEST_IA32_PDPTE3_HI:
407       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT);
408 #endif
409 
410 #if BX_SUPPORT_PKEYS
411     case VMCS_64BIT_GUEST_IA32_PKRS:
412     case VMCS_64BIT_GUEST_IA32_PKRS_HI:
413       return is_cpu_extension_supported(BX_ISA_PKS);
414 #endif
415 
416 #if BX_SUPPORT_VMX >= 2
417     /* VMCS 64-bit host state fields */
418     /* binary 0010_11xx_xxxx_xxx0 */
419     case VMCS_64BIT_HOST_IA32_PAT:
420     case VMCS_64BIT_HOST_IA32_PAT_HI:
421       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAT);
422 
423     case VMCS_64BIT_HOST_IA32_EFER:
424     case VMCS_64BIT_HOST_IA32_EFER_HI:
425       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EFER);
426 #endif
427 
428     case VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL:
429     case VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL_HI:
430       return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PERF_GLOBAL_CTRL);
431 
432 #if BX_SUPPORT_PKEYS
433     case VMCS_64BIT_HOST_IA32_PKRS:
434     case VMCS_64BIT_HOST_IA32_PKRS_HI:
435       return is_cpu_extension_supported(BX_ISA_PKS);
436 #endif
437 
438     /* VMCS natural width control fields */
439     /* binary 0110_00xx_xxxx_xxx0 */
440     case VMCS_CONTROL_CR0_GUEST_HOST_MASK:
441     case VMCS_CONTROL_CR4_GUEST_HOST_MASK:
442     case VMCS_CONTROL_CR0_READ_SHADOW:
443     case VMCS_CONTROL_CR4_READ_SHADOW:
444     case VMCS_CR3_TARGET0:
445     case VMCS_CR3_TARGET1:
446     case VMCS_CR3_TARGET2:
447     case VMCS_CR3_TARGET3:
448       return 1;
449 
450     /* VMCS natural width read only data fields */
451     /* binary 0110_01xx_xxxx_xxx0 */
452     case VMCS_VMEXIT_QUALIFICATION:
453     case VMCS_IO_RCX:
454     case VMCS_IO_RSI:
455     case VMCS_IO_RDI:
456     case VMCS_IO_RIP:
457     case VMCS_GUEST_LINEAR_ADDR:
458       return 1;
459 
460     /* VMCS natural width guest state fields */
461     /* binary 0110_10xx_xxxx_xxx0 */
462     case VMCS_GUEST_CR0:
463     case VMCS_GUEST_CR3:
464     case VMCS_GUEST_CR4:
465     case VMCS_GUEST_ES_BASE:
466     case VMCS_GUEST_CS_BASE:
467     case VMCS_GUEST_SS_BASE:
468     case VMCS_GUEST_DS_BASE:
469     case VMCS_GUEST_FS_BASE:
470     case VMCS_GUEST_GS_BASE:
471     case VMCS_GUEST_LDTR_BASE:
472     case VMCS_GUEST_TR_BASE:
473     case VMCS_GUEST_GDTR_BASE:
474     case VMCS_GUEST_IDTR_BASE:
475     case VMCS_GUEST_DR7:
476     case VMCS_GUEST_RSP:
477     case VMCS_GUEST_RIP:
478     case VMCS_GUEST_RFLAGS:
479     case VMCS_GUEST_PENDING_DBG_EXCEPTIONS:
480     case VMCS_GUEST_IA32_SYSENTER_ESP_MSR:
481     case VMCS_GUEST_IA32_SYSENTER_EIP_MSR:
482       return 1;
483     case VMCS_GUEST_IA32_S_CET:
484     case VMCS_GUEST_SSP:
485     case VMCS_GUEST_INTERRUPT_SSP_TABLE_ADDR:
486       return is_cpu_extension_supported(BX_ISA_CET);
487 
488     /* VMCS natural width host state fields */
489     /* binary 0110_11xx_xxxx_xxx0 */
490     case VMCS_HOST_CR0:
491     case VMCS_HOST_CR3:
492     case VMCS_HOST_CR4:
493     case VMCS_HOST_FS_BASE:
494     case VMCS_HOST_GS_BASE:
495     case VMCS_HOST_TR_BASE:
496     case VMCS_HOST_GDTR_BASE:
497     case VMCS_HOST_IDTR_BASE:
498     case VMCS_HOST_IA32_SYSENTER_ESP_MSR:
499     case VMCS_HOST_IA32_SYSENTER_EIP_MSR:
500     case VMCS_HOST_RSP:
501     case VMCS_HOST_RIP:
502       return 1;
503     case VMCS_HOST_IA32_S_CET:
504     case VMCS_HOST_SSP:
505     case VMCS_HOST_INTERRUPT_SSP_TABLE_ADDR:
506       return is_cpu_extension_supported(BX_ISA_CET);
507 
508     default:
509       return 0;
510   }
511 
512   return 0;
513 }
514 
init_vmx_capabilities(void)515 void BX_CPU_C::init_vmx_capabilities(void)
516 {
517   // initialization order is important !
518 #if BX_SUPPORT_VMX >= 2
519   init_ept_vpid_capabilities();
520   init_vmfunc_capabilities();
521 #endif
522   init_pin_based_vmexec_ctrls();
523   init_secondary_proc_based_vmexec_ctrls();
524   init_primary_proc_based_vmexec_ctrls();
525   init_vmexit_ctrls();
526   init_vmentry_ctrls();
527 }
528 
529 #if BX_SUPPORT_VMX >= 2
init_ept_vpid_capabilities(void)530 void BX_CPU_C::init_ept_vpid_capabilities(void)
531 {
532   struct bx_VMX_Cap *cap = &BX_CPU_THIS_PTR vmx_cap;
533 
534   // EPT/VPID capabilities
535   // -----------------------------------------------------------
536   //  [0] - BX_EPT_ENTRY_EXECUTE_ONLY support
537   //  [6] - 4-levels EPT page walk length
538   //  [8] - allow UC EPT paging structure memory type
539   // [14] - allow WB EPT paging structure memory type
540   // [16] - EPT 2M pages support
541   // [17] - EPT 1G pages support
542   // [20] - INVEPT instruction supported
543   // [21] - EPT A/D bits supported
544   // [22] - advanced VM-exit information for EPT violations (not implemented yet)
545   // [23] - Enable Shadow Stack control bit is supported in EPTP (CET)
546   // [25] - INVEPT single-context invalidation supported
547   // [26] - INVEPT all-context invalidation supported
548   // [32] - INVVPID instruction supported
549   // [40] - individual-address INVVPID is supported
550   // [41] - single-context INVVPID is supported
551   // [42] - all-context INVVPID is supported
552   // [43] - single-context-retaining-globals INVVPID is supported
553 
554   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT)) {
555     cap->vmx_ept_vpid_cap_supported_bits = BX_CONST64(0x06114141);
556     if (is_cpu_extension_supported(BX_ISA_1G_PAGES))
557       cap->vmx_ept_vpid_cap_supported_bits |= (1 << 17);
558     if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT_ACCESS_DIRTY))
559       cap->vmx_ept_vpid_cap_supported_bits |= (1 << 21);
560     if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CET))
561       cap->vmx_ept_vpid_cap_supported_bits |= (1 << 23);
562   }
563   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VPID))
564     cap->vmx_ept_vpid_cap_supported_bits |= BX_CONST64(0x00000f01) << 32;
565 }
566 
init_vmfunc_capabilities(void)567 void BX_CPU_C::init_vmfunc_capabilities(void)
568 {
569   struct bx_VMX_Cap *cap = &BX_CPU_THIS_PTR vmx_cap;
570 
571   // vm functions
572   // -----------------------------------------------------------
573   //    [00] EPTP switching
574   // [63-01] reserved
575 
576   cap->vmx_vmfunc_supported_bits = 0;
577 
578   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPTP_SWITCHING))
579     cap->vmx_vmfunc_supported_bits |= VMX_VMFUNC_EPTP_SWITCHING_MASK;
580 }
581 #endif
582 
init_pin_based_vmexec_ctrls(void)583 void BX_CPU_C::init_pin_based_vmexec_ctrls(void)
584 {
585   struct bx_VMX_Cap *cap = &BX_CPU_THIS_PTR vmx_cap;
586 
587   // pin based vm exec controls
588   // -----------------------------------------------------------
589   //   [00] External Interrupt Exiting
590   // 1 [01] Reserved (must be '1)
591   // 1 [02] Reserved (must be '1)
592   //   [03] NMI Exiting
593   // 1 [04] Reserved (must be '1)
594   //   [05] Virtual NMI (require Virtual NMI support)
595   //   [06] Activate VMX Preemption Timer (require VMX Preemption Timer support)
596   //   [07] Process Posted interrupts
597 
598   cap->vmx_pin_vmexec_ctrl_supported_bits =
599        VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT |
600        VMX_VM_EXEC_CTRL1_NMI_EXITING;
601   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VIRTUAL_NMI))
602     cap->vmx_pin_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL1_VIRTUAL_NMI;
603 #if BX_SUPPORT_VMX >= 2
604   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PREEMPTION_TIMER))
605     cap->vmx_pin_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL1_VMX_PREEMPTION_TIMER_VMEXIT;
606 #endif
607 }
608 
init_primary_proc_based_vmexec_ctrls(void)609 void BX_CPU_C::init_primary_proc_based_vmexec_ctrls(void)
610 {
611   struct bx_VMX_Cap *cap = &BX_CPU_THIS_PTR vmx_cap;
612 
613   // proc based vm exec controls
614   // -----------------------------------------------------------
615   // 0    [00] Reserved (must be '0)
616   // 1    [01] Reserved (must be '1)
617   //      [02] Interrupt Window Exiting
618   //      [03] TSC Offset Enable
619   // 1 [06-04] Reserved (must be '1)
620   //      [07] HLT Exiting
621   // 1    [08] Reserved (must be '1)
622   //      [09] INVLPG Exiting
623   //      [10] MWAIT Exiting (require MONITOR/MWAIT support)
624   //      [11] RDPMC Exiting
625   //      [12] RDTSC Exiting
626   // 1 [14-13] Reserved (must be '1)
627   // 1    [15] CR3 Write Exiting (legacy must be '1, introduced with EPT support)
628   // 1    [16] CR3 Read Exiting (legacy must be '1, introduced with EPT support)
629   // 0 [18-17] Reserved (must be '0)
630   //      [19] CR8 Write Exiting (require TPR Shadow support, require x86-64 support)
631   //      [20] CR8 Read Exiting (require TPR Shadow support, require x86-64 support)
632   //      [21] TPR Shadow Enable (require TPR Shadow support, require x86-64 support)
633   //      [22] NMI Window Exiting (require Virtual NMI support)
634   //      [23] DRx Access Exiting
635   //      [24] I/O Access Exiting
636   //      [25] I/O Bitmaps
637   // 1    [26] Reserved (must be '1)
638   //      [27] Monitor Trap Flag Enable (require Monitor Trap Flag support)
639   //      [28] MSR Bitmaps
640   //      [29] MONITOR Exiting (require MONITOR/MWAIT support)
641   //      [30] PAUSE Exiting
642   //      [31] Secondary proc-based vmexec controls
643 
644   cap->vmx_proc_vmexec_ctrl_supported_bits =
645        VMX_VM_EXEC_CTRL2_INTERRUPT_WINDOW_VMEXIT |
646        VMX_VM_EXEC_CTRL2_TSC_OFFSET |
647        VMX_VM_EXEC_CTRL2_HLT_VMEXIT |
648        VMX_VM_EXEC_CTRL2_INVLPG_VMEXIT |
649        VMX_VM_EXEC_CTRL2_RDPMC_VMEXIT |
650        VMX_VM_EXEC_CTRL2_RDTSC_VMEXIT |
651        VMX_VM_EXEC_CTRL2_DRx_ACCESS_VMEXIT |
652        VMX_VM_EXEC_CTRL2_IO_VMEXIT |
653        VMX_VM_EXEC_CTRL2_IO_BITMAPS |
654        VMX_VM_EXEC_CTRL2_MSR_BITMAPS |
655        VMX_VM_EXEC_CTRL2_PAUSE_VMEXIT;
656 
657 #if BX_SUPPORT_MONITOR_MWAIT
658   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MONITOR_MWAIT)) {
659     cap->vmx_proc_vmexec_ctrl_supported_bits |=
660        VMX_VM_EXEC_CTRL2_MWAIT_VMEXIT | VMX_VM_EXEC_CTRL2_MONITOR_VMEXIT;
661   }
662 #endif
663 #if BX_SUPPORT_X86_64
664   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_TPR_SHADOW)) {
665     cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_TPR_SHADOW;
666     if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_LONG_MODE))
667       cap->vmx_proc_vmexec_ctrl_supported_bits |=
668           VMX_VM_EXEC_CTRL2_CR8_WRITE_VMEXIT | VMX_VM_EXEC_CTRL2_CR8_READ_VMEXIT;
669   }
670 #endif
671   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VIRTUAL_NMI))
672     cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_NMI_WINDOW_EXITING;
673   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_MONITOR_TRAP_FLAG))
674     cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_MONITOR_TRAP_FLAG;
675 #if BX_SUPPORT_VMX >= 2
676   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT)) {
677     cap->vmx_proc_vmexec_ctrl_supported_bits |=
678         VMX_VM_EXEC_CTRL2_CR3_WRITE_VMEXIT | VMX_VM_EXEC_CTRL2_CR3_READ_VMEXIT;
679   }
680 #endif
681 
682   // enable secondary vm exec controls if there are secondary proc-based vmexec controls present
683   if (cap->vmx_vmexec_ctrl2_supported_bits != 0)
684     cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_SECONDARY_CONTROLS;
685 }
686 
init_secondary_proc_based_vmexec_ctrls(void)687 void BX_CPU_C::init_secondary_proc_based_vmexec_ctrls(void)
688 {
689   struct bx_VMX_Cap *cap = &BX_CPU_THIS_PTR vmx_cap;
690 
691   // secondary proc based vm exec controls
692   // -----------------------------------------------------------
693   //   [00] Apic Virtualization (require x86-64 for TPR shadow)
694   //   [01] EPT Enable (require x86-64 for 4-level page walk)
695   //   [02] Descriptor Table Exiting
696   //   [03] Enable RDTSCP instruction (RDTSCP will #UD if not set)
697   //   [04] Virtualize X2APIC Mode (doesn't require actual X2APIC to be enabled)
698   //   [05] VPID Enable
699   //   [06] WBINVD Exiting
700   //   [07] Unrestricted Guest (require EPT)
701   //   [08] Virtualize Apic Registers
702   //   [09] Virtualize Interrupt Delivery
703   //   [10] PAUSE Loop Exiting
704   //   [11] RDRAND Exiting (require RDRAND instruction support)
705   //   [12] Enable INVPCID instruction (require INVPCID instruction support)
706   //   [13] Enable VM Functions
707   //   [14] Enable VMCS Shadowing
708   //   [15] Reserved (must be '0)
709   //   [16] RDSEED Exiting (require RDSEED instruction support)
710   //   [17] Page Modification Logging Enable
711   //   [18] Support for EPT Violation (#VE) exception
712   //   [19] Reserved (must be '0)
713   //   [20] XSAVES Exiting
714   //   [21] Reserved (must be '0)
715   //   [22] Mode Based Execution Control (MBE) (not implemented yet)
716   //   [23] Sub Page Protection
717   //   [24] Reserved (must be '0)
718   //   [25] Enable TSC Scaling
719 
720   cap->vmx_vmexec_ctrl2_supported_bits = 0;
721 
722 #if BX_SUPPORT_X86_64
723   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_APIC_VIRTUALIZATION))
724     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES;
725 #endif
726 #if BX_SUPPORT_VMX >= 2
727   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT))
728     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_EPT_ENABLE;
729   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_DESCRIPTOR_TABLE_EXIT))
730     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT;
731 #endif
732   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_RDTSCP))
733     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_RDTSCP;
734 #if BX_SUPPORT_VMX >= 2
735   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_X2APIC_VIRTUALIZATION))
736     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_VIRTUALIZE_X2APIC_MODE;
737   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VPID))
738     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_VPID_ENABLE;
739 #endif
740   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_WBINVD_VMEXIT))
741     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_WBINVD_VMEXIT;
742 #if BX_SUPPORT_VMX >= 2
743   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_UNRESTRICTED_GUEST))
744     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST;
745   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VINTR_DELIVERY))
746     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_REGISTERS | VMX_VM_EXEC_CTRL3_VIRTUAL_INT_DELIVERY;
747   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAUSE_LOOP_EXITING))
748     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_PAUSE_LOOP_VMEXIT;
749   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_INVPCID))
750     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_INVPCID;
751 #endif
752   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_RDRAND))
753     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_RDRAND_VMEXIT;
754 #if BX_SUPPORT_VMX >= 2
755   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VMCS_SHADOWING))
756     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_VMCS_SHADOWING;
757 #endif
758   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_RDSEED))
759     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_RDSEED_VMEXIT;
760 #if BX_SUPPORT_VMX >= 2
761   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PML)) {
762     if (! BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT))
763       BX_PANIC(("VMX PML feature requires EPT support !"));
764     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_PML_ENABLE;
765   }
766   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT_EXCEPTION)) {
767     if (! BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPTP_SWITCHING))
768       BX_PANIC(("#VE exception feature requires EPTP switching support !"));
769     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_EPT_VIOLATION_EXCEPTION;
770   }
771 #endif
772 #if BX_SUPPORT_VMX >= 2
773   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XSAVES)) {
774     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_XSAVES_XRSTORS;
775   }
776 #endif
777 #if BX_SUPPORT_VMX >= 2
778   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_SPP)) {
779     if (! BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT))
780       BX_PANIC(("VMX SPP feature requires EPT support !"));
781     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_SUBPAGE_WR_PROTECT_CTRL;
782   }
783 #endif
784   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_TSC_SCALING)) {
785     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_TSC_SCALING;
786   }
787 
788 #if BX_SUPPORT_VMX >= 2
789   // enable vm functions secondary vmexec control if there are supported vmfunctions
790   if (cap->vmx_vmfunc_supported_bits != 0)
791     cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_VMFUNC_ENABLE;
792 #endif
793 }
794 
init_vmexit_ctrls(void)795 void BX_CPU_C::init_vmexit_ctrls(void)
796 {
797   struct bx_VMX_Cap *cap = &BX_CPU_THIS_PTR vmx_cap;
798 
799   // vmexit controls
800   // -----------------------------------------------------------
801   // 1 [01-00] Reserved (must be '1)
802   // 1    [02] Save guest MSR_DEBUGCTL on VMEXIT (legacy must be '1)
803   // 1 [08-03] Reserved (must be '1)
804   //      [09] Host Address Space Size (x86-64 host, x86-64 support required)
805   // 1 [11-10] Reserved (must be '1)
806   //      [12] Load host MSR_PERF_GLOBAL_CTRL on VMEXIT
807   // 1 [14-13] Reserved (must be '1)
808   //      [15] Acknowledge interrupts on VMEXIT
809   // 1 [17-16] Reserved (must be '1)
810   //      [18] Save guest MSR_PAT on VMEXIT
811   //      [19] Load host MSR_PAT on VMEXIT
812   //      [20] Save guest MSR_EFER on VMEXIT
813   //      [21] Load host MSR_EFER on VMEXIT
814   //      [22] Save VMX preemption timer counter on VMEXIT
815   //      [28] Save host CET state on VMEXIT
816   //      [29] Save host MSR_IA32_PKRS on VMEXIT
817 
818   cap->vmx_vmexit_ctrl_supported_bits =
819       VMX_VMEXIT_CTRL1_INTA_ON_VMEXIT | VMX_VMEXIT_CTRL1_SAVE_DBG_CTRLS;
820 
821 #if BX_SUPPORT_X86_64
822   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_LONG_MODE))
823     cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_HOST_ADDR_SPACE_SIZE;
824 #endif
825   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PERF_GLOBAL_CTRL))
826     cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_LOAD_PERF_GLOBAL_CTRL_MSR;
827 #if BX_SUPPORT_VMX >= 2
828   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAT)) {
829     cap->vmx_vmexit_ctrl_supported_bits |=
830       VMX_VMEXIT_CTRL1_STORE_PAT_MSR | VMX_VMEXIT_CTRL1_LOAD_PAT_MSR;
831   }
832   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EFER)) {
833     cap->vmx_vmexit_ctrl_supported_bits |=
834       VMX_VMEXIT_CTRL1_STORE_EFER_MSR | VMX_VMEXIT_CTRL1_LOAD_EFER_MSR;
835   }
836   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PREEMPTION_TIMER))
837     cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_STORE_VMX_PREEMPTION_TIMER;
838 #endif
839 #if BX_SUPPORT_CET
840   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CET))
841     cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_LOAD_HOST_CET_STATE;
842 #endif
843 #if BX_SUPPORT_PKEYS
844   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_PKS))
845     cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_LOAD_HOST_PKRS;
846 #endif
847 }
848 
init_vmentry_ctrls(void)849 void BX_CPU_C::init_vmentry_ctrls(void)
850 {
851   struct bx_VMX_Cap *cap = &BX_CPU_THIS_PTR vmx_cap;
852 
853   // vmentry controls
854   // -----------------------------------------------------------
855   // 1 [01-00] Reserved (must be '1)
856   // 1    [02] Load MSR_DEBUGCTL on VMEXIT (legacy must be '1)
857   // 1 [08-03] Reserved (must be '1)
858   //      [09] x86-64 guest (x86-64 support required)
859   //      [10] Enter to SMM mode
860   //      [11] Deactivate Dual SMM Monitor treatment
861   // 1    [12] Reserved (must be '1)
862   //      [13] Load guest MSR_PERF_GLOBAL_CTRL
863   //      [14] Load guest MSR_PAT
864   //      [15] Load guest MSR_EFER
865   //      [17] Load guest CET state
866   //      [22] Load guest MSR_IA32_PKRS value
867 
868   cap->vmx_vmentry_ctrl_supported_bits = VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS |
869                                          VMX_VMENTRY_CTRL1_SMM_ENTER |
870                                          VMX_VMENTRY_CTRL1_DEACTIVATE_DUAL_MONITOR_TREATMENT;
871 
872 #if BX_SUPPORT_X86_64
873   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_LONG_MODE))
874     cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_X86_64_GUEST;
875 #endif
876   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PERF_GLOBAL_CTRL))
877     cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_PERF_GLOBAL_CTRL_MSR;
878 #if BX_SUPPORT_VMX >= 2
879   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAT))
880     cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_PAT_MSR;
881   if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EFER))
882     cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_EFER_MSR;
883 #endif
884 #if BX_SUPPORT_CET
885   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CET))
886     cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_GUEST_CET_STATE;
887 #endif
888 #if BX_SUPPORT_PKEYS
889   if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_PKS))
890     cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS;
891 #endif
892 }
893 
894 #endif // BX_SUPPORT_VMX
895