VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp@ 79651

Last change on this file since 79651 was 79651, checked in by vboxsync, 6 years ago

VMM/HMVMXR0: Nested VMX: bugref:9180 Build fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 728.3 KB
Line 
1/* $Id: HMVMXR0.cpp 79651 2019-07-10 05:08:52Z vboxsync $ */
2/** @file
3 * HM VMX (Intel VT-x) - Host Context Ring-0.
4 */
5
6/*
7 * Copyright (C) 2012-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_HM
23#define VMCPU_INCL_CPUM_GST_CTX
24#include <iprt/x86.h>
25#include <iprt/asm-amd64-x86.h>
26#include <iprt/thread.h>
27#include <iprt/mem.h>
28
29#include <VBox/vmm/pdmapi.h>
30#include <VBox/vmm/dbgf.h>
31#include <VBox/vmm/iem.h>
32#include <VBox/vmm/iom.h>
33#include <VBox/vmm/selm.h>
34#include <VBox/vmm/tm.h>
35#include <VBox/vmm/em.h>
36#include <VBox/vmm/gim.h>
37#include <VBox/vmm/apic.h>
38#ifdef VBOX_WITH_REM
39# include <VBox/vmm/rem.h>
40#endif
41#include "HMInternal.h"
42#include <VBox/vmm/vm.h>
43#include <VBox/vmm/hmvmxinline.h>
44#include "HMVMXR0.h"
45#include "dtrace/VBoxVMM.h"
46
47#ifdef DEBUG_ramshankar
48# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
49# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
50# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
51# define HMVMX_ALWAYS_CHECK_GUEST_STATE
52# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
53# define HMVMX_ALWAYS_TRAP_PF
54# define HMVMX_ALWAYS_FLUSH_TLB
55# define HMVMX_ALWAYS_SWAP_EFER
56#endif
57
58
59/*********************************************************************************************************************************
60* Defined Constants And Macros *
61*********************************************************************************************************************************/
62/** Use the function table. */
63#define HMVMX_USE_FUNCTION_TABLE
64
65/** Determine which tagged-TLB flush handler to use. */
66#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
67#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
68#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
69#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
70
71/** @name HMVMX_READ_XXX
72 * Flags to skip redundant reads of some common VMCS fields that are not part of
73 * the guest-CPU or VCPU state but are needed while handling VM-exits.
74 */
75#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
76#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
77#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
78#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
79#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
80#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
81#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
82#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
83/** @} */
84
85/**
86 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
87 * guest using hardware-assisted VMX.
88 *
89 * This excludes state like GPRs (other than RSP) which are always are
90 * swapped and restored across the world-switch and also registers like EFER,
91 * MSR which cannot be modified by the guest without causing a VM-exit.
92 */
93#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
94 | CPUMCTX_EXTRN_RFLAGS \
95 | CPUMCTX_EXTRN_RSP \
96 | CPUMCTX_EXTRN_SREG_MASK \
97 | CPUMCTX_EXTRN_TABLE_MASK \
98 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
99 | CPUMCTX_EXTRN_SYSCALL_MSRS \
100 | CPUMCTX_EXTRN_SYSENTER_MSRS \
101 | CPUMCTX_EXTRN_TSC_AUX \
102 | CPUMCTX_EXTRN_OTHER_MSRS \
103 | CPUMCTX_EXTRN_CR0 \
104 | CPUMCTX_EXTRN_CR3 \
105 | CPUMCTX_EXTRN_CR4 \
106 | CPUMCTX_EXTRN_DR7 \
107 | CPUMCTX_EXTRN_HWVIRT \
108 | CPUMCTX_EXTRN_HM_VMX_MASK)
109
110/**
111 * Exception bitmap mask for real-mode guests (real-on-v86).
112 *
113 * We need to intercept all exceptions manually except:
114 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
115 * due to bugs in Intel CPUs.
116 * - \#PF need not be intercepted even in real-mode if we have nested paging
117 * support.
118 */
119#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
120 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
121 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
122 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
123 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
124 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
125 | RT_BIT(X86_XCPT_XF))
126
127/** Maximum VM-instruction error number. */
128#define HMVMX_INSTR_ERROR_MAX 28
129
130/** Profiling macro. */
131#ifdef HM_PROFILE_EXIT_DISPATCH
132# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
133# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
134#else
135# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
136# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
137#endif
138
139/** Assert that preemption is disabled or covered by thread-context hooks. */
140#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
141 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
142
143/** Assert that we haven't migrated CPUs when thread-context hooks are not
144 * used. */
145#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
146 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
147 ("Illegal migration! Entered on CPU %u Current %u\n", \
148 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
149
150/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
151 * context. */
152#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
153 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
154 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
155
156/** Log the VM-exit reason with an easily visible marker to identify it in a
157 * potential sea of logging data. */
158#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
159 do { \
160 Log4(("VM-exit: vcpu[%RU32] reason=%#x -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v\n", \
161 (a_pVCpu)->idCpu, (a_uExitReason))); \
162 } while (0) \
163
164
165/*********************************************************************************************************************************
166* Structures and Typedefs *
167*********************************************************************************************************************************/
168/**
169 * VMX per-VCPU transient state.
170 *
171 * A state structure for holding miscellaneous information across
172 * VMX non-root operation and restored after the transition.
173 */
174typedef struct VMXTRANSIENT
175{
176 /** The host's rflags/eflags. */
177 RTCCUINTREG fEFlags;
178#if HC_ARCH_BITS == 32
179 uint32_t u32Alignment0;
180#endif
181 /** The guest's TPR value used for TPR shadowing. */
182 uint8_t u8GuestTpr;
183 /** Alignment. */
184 uint8_t abAlignment0[7];
185
186 /** The basic VM-exit reason. */
187 uint16_t uExitReason;
188 /** Alignment. */
189 uint16_t u16Alignment0;
190 /** The VM-exit interruption error code. */
191 uint32_t uExitIntErrorCode;
192 /** The VM-exit exit code qualification. */
193 uint64_t uExitQual;
194 /** The Guest-linear address. */
195 uint64_t uGuestLinearAddr;
196
197 /** The VM-exit interruption-information field. */
198 uint32_t uExitIntInfo;
199 /** The VM-exit instruction-length field. */
200 uint32_t cbInstr;
201 /** The VM-exit instruction-information field. */
202 VMXEXITINSTRINFO ExitInstrInfo;
203 /** Whether the VM-entry failed or not. */
204 bool fVMEntryFailed;
205 /** Whether we are currently executing a nested-guest. */
206 bool fIsNestedGuest;
207 /** Alignment. */
208 uint8_t abAlignment1[2];
209
210 /** The VM-entry interruption-information field. */
211 uint32_t uEntryIntInfo;
212 /** The VM-entry exception error code field. */
213 uint32_t uEntryXcptErrorCode;
214 /** The VM-entry instruction length field. */
215 uint32_t cbEntryInstr;
216
217 /** IDT-vectoring information field. */
218 uint32_t uIdtVectoringInfo;
219 /** IDT-vectoring error code. */
220 uint32_t uIdtVectoringErrorCode;
221
222 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
223 uint32_t fVmcsFieldsRead;
224
225 /** Whether the guest debug state was active at the time of VM-exit. */
226 bool fWasGuestDebugStateActive;
227 /** Whether the hyper debug state was active at the time of VM-exit. */
228 bool fWasHyperDebugStateActive;
229 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
230 bool fUpdatedTscOffsettingAndPreemptTimer;
231 /** Whether the VM-exit was caused by a page-fault during delivery of a
232 * contributory exception or a page-fault. */
233 bool fVectoringDoublePF;
234 /** Whether the VM-exit was caused by a page-fault during delivery of an
235 * external interrupt or NMI. */
236 bool fVectoringPF;
237 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
238 * area after VM-exit. */
239 bool fRemoveTscAuxMsr;
240 bool afAlignment0[2];
241
242 /** The VMCS info. object. */
243 PVMXVMCSINFO pVmcsInfo;
244} VMXTRANSIENT;
245AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, sizeof(uint64_t));
246AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, sizeof(uint64_t));
247AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, sizeof(uint64_t));
248AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
249AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, sizeof(uint64_t));
250AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
251/** Pointer to VMX transient state. */
252typedef VMXTRANSIENT *PVMXTRANSIENT;
253/** Pointer to a const VMX transient state. */
254typedef const VMXTRANSIENT *PCVMXTRANSIENT;
255
256/**
257 * Memory operand read or write access.
258 */
259typedef enum VMXMEMACCESS
260{
261 VMXMEMACCESS_READ = 0,
262 VMXMEMACCESS_WRITE = 1
263} VMXMEMACCESS;
264
265/**
266 * VMX VM-exit handler.
267 *
268 * @returns Strict VBox status code (i.e. informational status codes too).
269 * @param pVCpu The cross context virtual CPU structure.
270 * @param pVmxTransient The VMX-transient structure.
271 */
272#ifndef HMVMX_USE_FUNCTION_TABLE
273typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
274#else
275typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
276/** Pointer to VM-exit handler. */
277typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
278#endif
279
280/**
281 * VMX VM-exit handler, non-strict status code.
282 *
283 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
284 *
285 * @returns VBox status code, no informational status code returned.
286 * @param pVCpu The cross context virtual CPU structure.
287 * @param pVmxTransient The VMX-transient structure.
288 *
289 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
290 * use of that status code will be replaced with VINF_EM_SOMETHING
291 * later when switching over to IEM.
292 */
293#ifndef HMVMX_USE_FUNCTION_TABLE
294typedef int FNVMXEXITHANDLERNSRC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
295#else
296typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
297#endif
298
299
300/*********************************************************************************************************************************
301* Internal Functions *
302*********************************************************************************************************************************/
303#ifndef HMVMX_USE_FUNCTION_TABLE
304DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
305# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
306# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
307#else
308# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
309# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
310#endif
311#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
312DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
313#endif
314
315static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
316#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
317static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu);
318#endif
319
320/** @name VM-exit handler prototypes.
321 * @{
322 */
323static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
324static FNVMXEXITHANDLER hmR0VmxExitExtInt;
325static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
326static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
327static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
328static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
329static FNVMXEXITHANDLER hmR0VmxExitCpuid;
330static FNVMXEXITHANDLER hmR0VmxExitGetsec;
331static FNVMXEXITHANDLER hmR0VmxExitHlt;
332static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
333static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
334static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
335static FNVMXEXITHANDLER hmR0VmxExitVmcall;
336#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
337static FNVMXEXITHANDLER hmR0VmxExitVmclear;
338static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
339static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
340static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
341static FNVMXEXITHANDLER hmR0VmxExitVmread;
342static FNVMXEXITHANDLER hmR0VmxExitVmresume;
343static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
344static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
345static FNVMXEXITHANDLER hmR0VmxExitVmxon;
346static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
347#endif
348static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
349static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
350static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
351static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
352static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
353static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
354static FNVMXEXITHANDLER hmR0VmxExitMwait;
355static FNVMXEXITHANDLER hmR0VmxExitMtf;
356static FNVMXEXITHANDLER hmR0VmxExitMonitor;
357static FNVMXEXITHANDLER hmR0VmxExitPause;
358static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
359static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
360static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
361static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
362static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
363static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
364static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
365static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
366static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
367static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
368static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
369static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
370/** @} */
371
372#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
373/** @name Nested-guest VM-exit handler prototypes.
374 * @{
375 */
376static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
377static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
378static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
379static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
380static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
381static FNVMXEXITHANDLER hmR0VmxExitHltNested;
382static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
383static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
384static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
385static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
386static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
387static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
388static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
389static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
390static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
391static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
392static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
393static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
394static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
395static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
396static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
397static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
398static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
399static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
400static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
401static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
402static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
403static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
404static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
405/** @} */
406#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
407
408
409/*********************************************************************************************************************************
410* Global Variables *
411*********************************************************************************************************************************/
412#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
413/**
414 * Array of all VMCS fields.
415 * Any fields added to the VT-x spec. should be added here.
416 *
417 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
418 * of nested-guests.
419 */
420static const uint32_t g_aVmcsFields[] =
421{
422 /* 16-bit control fields. */
423 VMX_VMCS16_VPID,
424 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
425 VMX_VMCS16_EPTP_INDEX,
426
427 /* 16-bit guest-state fields. */
428 VMX_VMCS16_GUEST_ES_SEL,
429 VMX_VMCS16_GUEST_CS_SEL,
430 VMX_VMCS16_GUEST_SS_SEL,
431 VMX_VMCS16_GUEST_DS_SEL,
432 VMX_VMCS16_GUEST_FS_SEL,
433 VMX_VMCS16_GUEST_GS_SEL,
434 VMX_VMCS16_GUEST_LDTR_SEL,
435 VMX_VMCS16_GUEST_TR_SEL,
436 VMX_VMCS16_GUEST_INTR_STATUS,
437 VMX_VMCS16_GUEST_PML_INDEX,
438
439 /* 16-bits host-state fields. */
440 VMX_VMCS16_HOST_ES_SEL,
441 VMX_VMCS16_HOST_CS_SEL,
442 VMX_VMCS16_HOST_SS_SEL,
443 VMX_VMCS16_HOST_DS_SEL,
444 VMX_VMCS16_HOST_FS_SEL,
445 VMX_VMCS16_HOST_GS_SEL,
446 VMX_VMCS16_HOST_TR_SEL,
447
448 /* 64-bit control fields. */
449 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
450 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
451 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
452 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
453 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
454 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
455 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
456 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
457 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
458 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
459 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
460 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
461 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
462 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
463 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
464 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
465 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
466 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
467 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
468 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
469 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
470 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
471 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
472 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
473 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
474 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
475 VMX_VMCS64_CTRL_EPTP_FULL,
476 VMX_VMCS64_CTRL_EPTP_HIGH,
477 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
478 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
479 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
480 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
481 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
482 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
483 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
484 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
485 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
486 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
487 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
488 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
489 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
490 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
491 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
492 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
493 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
494 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
495 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
496 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
497 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
498 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
499
500 /* 64-bit read-only data fields. */
501 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
502 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
503
504 /* 64-bit guest-state fields. */
505 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
506 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
507 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
508 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
509 VMX_VMCS64_GUEST_PAT_FULL,
510 VMX_VMCS64_GUEST_PAT_HIGH,
511 VMX_VMCS64_GUEST_EFER_FULL,
512 VMX_VMCS64_GUEST_EFER_HIGH,
513 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
514 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
515 VMX_VMCS64_GUEST_PDPTE0_FULL,
516 VMX_VMCS64_GUEST_PDPTE0_HIGH,
517 VMX_VMCS64_GUEST_PDPTE1_FULL,
518 VMX_VMCS64_GUEST_PDPTE1_HIGH,
519 VMX_VMCS64_GUEST_PDPTE2_FULL,
520 VMX_VMCS64_GUEST_PDPTE2_HIGH,
521 VMX_VMCS64_GUEST_PDPTE3_FULL,
522 VMX_VMCS64_GUEST_PDPTE3_HIGH,
523 VMX_VMCS64_GUEST_BNDCFGS_FULL,
524 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
525
526 /* 64-bit host-state fields. */
527 VMX_VMCS64_HOST_PAT_FULL,
528 VMX_VMCS64_HOST_PAT_HIGH,
529 VMX_VMCS64_HOST_EFER_FULL,
530 VMX_VMCS64_HOST_EFER_HIGH,
531 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
532 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
533
534 /* 32-bit control fields. */
535 VMX_VMCS32_CTRL_PIN_EXEC,
536 VMX_VMCS32_CTRL_PROC_EXEC,
537 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
538 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
539 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
540 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
541 VMX_VMCS32_CTRL_EXIT,
542 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
543 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
544 VMX_VMCS32_CTRL_ENTRY,
545 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
546 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
547 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
548 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
549 VMX_VMCS32_CTRL_TPR_THRESHOLD,
550 VMX_VMCS32_CTRL_PROC_EXEC2,
551 VMX_VMCS32_CTRL_PLE_GAP,
552 VMX_VMCS32_CTRL_PLE_WINDOW,
553
554 /* 32-bits read-only fields. */
555 VMX_VMCS32_RO_VM_INSTR_ERROR,
556 VMX_VMCS32_RO_EXIT_REASON,
557 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
558 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
559 VMX_VMCS32_RO_IDT_VECTORING_INFO,
560 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
561 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
562 VMX_VMCS32_RO_EXIT_INSTR_INFO,
563
564 /* 32-bit guest-state fields. */
565 VMX_VMCS32_GUEST_ES_LIMIT,
566 VMX_VMCS32_GUEST_CS_LIMIT,
567 VMX_VMCS32_GUEST_SS_LIMIT,
568 VMX_VMCS32_GUEST_DS_LIMIT,
569 VMX_VMCS32_GUEST_FS_LIMIT,
570 VMX_VMCS32_GUEST_GS_LIMIT,
571 VMX_VMCS32_GUEST_LDTR_LIMIT,
572 VMX_VMCS32_GUEST_TR_LIMIT,
573 VMX_VMCS32_GUEST_GDTR_LIMIT,
574 VMX_VMCS32_GUEST_IDTR_LIMIT,
575 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
576 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
577 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
578 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
579 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
580 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
581 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
582 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
583 VMX_VMCS32_GUEST_INT_STATE,
584 VMX_VMCS32_GUEST_ACTIVITY_STATE,
585 VMX_VMCS32_GUEST_SMBASE,
586 VMX_VMCS32_GUEST_SYSENTER_CS,
587 VMX_VMCS32_PREEMPT_TIMER_VALUE,
588
589 /* 32-bit host-state fields. */
590 VMX_VMCS32_HOST_SYSENTER_CS,
591
592 /* Natural-width control fields. */
593 VMX_VMCS_CTRL_CR0_MASK,
594 VMX_VMCS_CTRL_CR4_MASK,
595 VMX_VMCS_CTRL_CR0_READ_SHADOW,
596 VMX_VMCS_CTRL_CR4_READ_SHADOW,
597 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
598 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
599 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
600 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
601
602 /* Natural-width read-only data fields. */
603 VMX_VMCS_RO_EXIT_QUALIFICATION,
604 VMX_VMCS_RO_IO_RCX,
605 VMX_VMCS_RO_IO_RSI,
606 VMX_VMCS_RO_IO_RDI,
607 VMX_VMCS_RO_IO_RIP,
608 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
609
610 /* Natural-width guest-state field */
611 VMX_VMCS_GUEST_CR0,
612 VMX_VMCS_GUEST_CR3,
613 VMX_VMCS_GUEST_CR4,
614 VMX_VMCS_GUEST_ES_BASE,
615 VMX_VMCS_GUEST_CS_BASE,
616 VMX_VMCS_GUEST_SS_BASE,
617 VMX_VMCS_GUEST_DS_BASE,
618 VMX_VMCS_GUEST_FS_BASE,
619 VMX_VMCS_GUEST_GS_BASE,
620 VMX_VMCS_GUEST_LDTR_BASE,
621 VMX_VMCS_GUEST_TR_BASE,
622 VMX_VMCS_GUEST_GDTR_BASE,
623 VMX_VMCS_GUEST_IDTR_BASE,
624 VMX_VMCS_GUEST_DR7,
625 VMX_VMCS_GUEST_RSP,
626 VMX_VMCS_GUEST_RIP,
627 VMX_VMCS_GUEST_RFLAGS,
628 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
629 VMX_VMCS_GUEST_SYSENTER_ESP,
630 VMX_VMCS_GUEST_SYSENTER_EIP,
631
632 /* Natural-width host-state fields */
633 VMX_VMCS_HOST_CR0,
634 VMX_VMCS_HOST_CR3,
635 VMX_VMCS_HOST_CR4,
636 VMX_VMCS_HOST_FS_BASE,
637 VMX_VMCS_HOST_GS_BASE,
638 VMX_VMCS_HOST_TR_BASE,
639 VMX_VMCS_HOST_GDTR_BASE,
640 VMX_VMCS_HOST_IDTR_BASE,
641 VMX_VMCS_HOST_SYSENTER_ESP,
642 VMX_VMCS_HOST_SYSENTER_EIP,
643 VMX_VMCS_HOST_RSP,
644 VMX_VMCS_HOST_RIP
645};
646#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
647
648#ifdef VMX_USE_CACHED_VMCS_ACCESSES
649static const uint32_t g_aVmcsCacheSegBase[] =
650{
651 VMX_VMCS_GUEST_ES_BASE_CACHE_IDX,
652 VMX_VMCS_GUEST_CS_BASE_CACHE_IDX,
653 VMX_VMCS_GUEST_SS_BASE_CACHE_IDX,
654 VMX_VMCS_GUEST_DS_BASE_CACHE_IDX,
655 VMX_VMCS_GUEST_FS_BASE_CACHE_IDX,
656 VMX_VMCS_GUEST_GS_BASE_CACHE_IDX
657};
658AssertCompile(RT_ELEMENTS(g_aVmcsCacheSegBase) == X86_SREG_COUNT);
659#endif
660static const uint32_t g_aVmcsSegBase[] =
661{
662 VMX_VMCS_GUEST_ES_BASE,
663 VMX_VMCS_GUEST_CS_BASE,
664 VMX_VMCS_GUEST_SS_BASE,
665 VMX_VMCS_GUEST_DS_BASE,
666 VMX_VMCS_GUEST_FS_BASE,
667 VMX_VMCS_GUEST_GS_BASE
668};
669static const uint32_t g_aVmcsSegSel[] =
670{
671 VMX_VMCS16_GUEST_ES_SEL,
672 VMX_VMCS16_GUEST_CS_SEL,
673 VMX_VMCS16_GUEST_SS_SEL,
674 VMX_VMCS16_GUEST_DS_SEL,
675 VMX_VMCS16_GUEST_FS_SEL,
676 VMX_VMCS16_GUEST_GS_SEL
677};
678static const uint32_t g_aVmcsSegLimit[] =
679{
680 VMX_VMCS32_GUEST_ES_LIMIT,
681 VMX_VMCS32_GUEST_CS_LIMIT,
682 VMX_VMCS32_GUEST_SS_LIMIT,
683 VMX_VMCS32_GUEST_DS_LIMIT,
684 VMX_VMCS32_GUEST_FS_LIMIT,
685 VMX_VMCS32_GUEST_GS_LIMIT
686};
687static const uint32_t g_aVmcsSegAttr[] =
688{
689 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
690 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
691 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
692 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
693 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
694 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
695};
696AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
697AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
698AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
699AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
700
701#ifdef HMVMX_USE_FUNCTION_TABLE
702/**
703 * VMX_EXIT dispatch table.
704 */
705static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
706{
707 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
708 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
709 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
710 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
711 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
712 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
713 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
714 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
715 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
716 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
717 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
718 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
719 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
720 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
721 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
722 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
723 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
724 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
725 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
726#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
727 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
728 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
729 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
730 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
731 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
732 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
733 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
734 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
735 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
736#else
737 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
738 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
739 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
740 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
741 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
742 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
743 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
744 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
745 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
746#endif
747 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
748 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
749 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
750 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
751 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
752 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
753 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
754 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
755 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
756 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
757 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
758 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
759 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
760 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
761 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
762 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
763 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
764 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
765 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
766 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
767 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
768 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
769 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
770 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
771 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
772#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
773 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
774#else
775 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
776#endif
777 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
778 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
779 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
780 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
781 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
782 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
783 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
784 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
785 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
786 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
787 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
788 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
789 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
790 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
791 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
792};
793#endif /* HMVMX_USE_FUNCTION_TABLE */
794
795#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
796static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
797{
798 /* 0 */ "(Not Used)",
799 /* 1 */ "VMCALL executed in VMX root operation.",
800 /* 2 */ "VMCLEAR with invalid physical address.",
801 /* 3 */ "VMCLEAR with VMXON pointer.",
802 /* 4 */ "VMLAUNCH with non-clear VMCS.",
803 /* 5 */ "VMRESUME with non-launched VMCS.",
804 /* 6 */ "VMRESUME after VMXOFF",
805 /* 7 */ "VM-entry with invalid control fields.",
806 /* 8 */ "VM-entry with invalid host state fields.",
807 /* 9 */ "VMPTRLD with invalid physical address.",
808 /* 10 */ "VMPTRLD with VMXON pointer.",
809 /* 11 */ "VMPTRLD with incorrect revision identifier.",
810 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
811 /* 13 */ "VMWRITE to read-only VMCS component.",
812 /* 14 */ "(Not Used)",
813 /* 15 */ "VMXON executed in VMX root operation.",
814 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
815 /* 17 */ "VM-entry with non-launched executing VMCS.",
816 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
817 /* 19 */ "VMCALL with non-clear VMCS.",
818 /* 20 */ "VMCALL with invalid VM-exit control fields.",
819 /* 21 */ "(Not Used)",
820 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
821 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
822 /* 24 */ "VMCALL with invalid SMM-monitor features.",
823 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
824 /* 26 */ "VM-entry with events blocked by MOV SS.",
825 /* 27 */ "(Not Used)",
826 /* 28 */ "Invalid operand to INVEPT/INVVPID."
827};
828#endif /* VBOX_STRICT && LOG_ENABLED */
829
830
831/**
832 * Get the CR0 guest/host mask that does not change through the lifetime of a VM.
833 *
834 * Any bit set in this mask is owned by the host/hypervisor and would cause a
835 * VM-exit when modified by the guest.
836 *
837 * @returns The static CR0 guest/host mask.
838 * @param pVCpu The cross context virtual CPU structure.
839 */
840DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr0Mask(PCVMCPU pVCpu)
841{
842 /*
843 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
844 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
845 */
846 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
847 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
848 * and @bugref{6944}. */
849 PVM pVM = pVCpu->CTX_SUFF(pVM);
850 return ( X86_CR0_PE
851 | X86_CR0_NE
852 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
853 | X86_CR0_PG
854 | X86_CR0_ET /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.ET */
855 | X86_CR0_CD /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.CD */
856 | X86_CR0_NW); /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.NW */
857}
858
859
860/**
861 * Gets the CR4 guest/host mask that does not change through the lifetime of a VM.
862 *
863 * Any bit set in this mask is owned by the host/hypervisor and would cause a
864 * VM-exit when modified by the guest.
865 *
866 * @returns The static CR4 guest/host mask.
867 * @param pVCpu The cross context virtual CPU structure.
868 */
869DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr4Mask(PCVMCPU pVCpu)
870{
871 /*
872 * We need to look at the host features here (for e.g. OSXSAVE, PCID) because
873 * these bits are reserved on hardware that does not support them. Since the
874 * CPU cannot refer to our virtual CPUID, we need to intercept CR4 changes to
875 * these bits and handle it depending on whether we expose them to the guest.
876 */
877 PVM pVM = pVCpu->CTX_SUFF(pVM);
878 bool const fXSaveRstor = pVM->cpum.ro.HostFeatures.fXSaveRstor;
879 bool const fPcid = pVM->cpum.ro.HostFeatures.fPcid;
880 return ( X86_CR4_VMXE
881 | X86_CR4_VME
882 | X86_CR4_PAE
883 | X86_CR4_PGE
884 | X86_CR4_PSE
885 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
886 | (fPcid ? X86_CR4_PCIDE : 0));
887}
888
889
890/**
891 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
892 * area.
893 *
894 * @returns @c true if it's different, @c false otherwise.
895 * @param pVmcsInfo The VMCS info. object.
896 */
897DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
898{
899 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
900 && pVmcsInfo->pvGuestMsrStore);
901}
902
903
904/**
905 * Checks whether one of the given Pin-based VM-execution controls are set.
906 *
907 * @returns @c true if set, @c false otherwise.
908 * @param pVCpu The cross context virtual CPU structure.
909 * @param pVmxTransient The VMX-transient structure.
910 * @param uPinCtls The Pin-based VM-execution controls to check.
911 *
912 * @remarks This will not check merged controls when executing a nested-guest
913 * but the original control specified by the guest hypervisor.
914 */
915static bool hmR0VmxIsPinCtlsSet(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uPinCtls)
916{
917 if (!pVmxTransient->fIsNestedGuest)
918 {
919 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
920 return RT_BOOL(pVmcsInfo->u32PinCtls & uPinCtls);
921 }
922 return CPUMIsGuestVmxPinCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uPinCtls);
923}
924
925
926/**
927 * Sets the given Processor-based VM-execution controls.
928 *
929 * @param pVmxTransient The VMX-transient structure.
930 * @param uProcCtls The Processor-based VM-execution controls to set.
931 */
932static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
933{
934 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
935 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
936 {
937 pVmcsInfo->u32ProcCtls |= uProcCtls;
938 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
939 AssertRC(rc);
940 }
941}
942
943
944/**
945 * Removes the given Processor-based VM-execution controls.
946 *
947 * @param pVCpu The cross context virtual CPU structure.
948 * @param pVmxTransient The VMX-transient structure.
949 * @param uProcCtls The Processor-based VM-execution controls to remove.
950 *
951 * @remarks When executing a nested-guest, this will not remove any of the specified
952 * controls if the guest hypervisor has set any one of them.
953 */
954static void hmR0VmxRemoveProcCtlsVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
955{
956#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
957 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
958 ? true
959 : !CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT);
960#else
961 NOREF(pVCpu);
962 bool const fRemoveCtls = true;
963#endif
964 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
965 if ( fRemoveCtls
966 && (pVmcsInfo->u32ProcCtls & uProcCtls))
967 {
968 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
969 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
970 AssertRC(rc);
971 }
972}
973
974
975/**
976 * Sets the TSC offset for the current VMCS.
977 *
978 * @param pVCpu The cross context virtual CPU structure.
979 * @param uTscOffset The TSC offset to set.
980 * @param pVmcsInfo The VMCS info. object.
981 */
982static void hmR0VmxSetTscOffsetVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
983{
984 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
985 if (pVmcsInfo->u64TscOffset != uTscOffset)
986 {
987 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
988 AssertRC(rc);
989 pVmcsInfo->u64TscOffset = uTscOffset;
990 }
991}
992
993
994/**
995 * Adds one or more exceptions to the exception bitmap and commits it to the current
996 * VMCS.
997 *
998 * @returns VBox status code.
999 * @param pVmxTransient The VMX-transient structure.
1000 * @param uXcptMask The exception(s) to add.
1001 */
1002static int hmR0VmxAddXcptInterceptMask(PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1003{
1004 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1005 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1006 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1007 {
1008 uXcptBitmap |= uXcptMask;
1009 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1010 AssertRCReturn(rc, rc);
1011 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1012 }
1013 return VINF_SUCCESS;
1014}
1015
1016
1017/**
1018 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1019 *
1020 * @returns VBox status code.
1021 * @param pVmxTransient The VMX-transient structure.
1022 * @param uXcpt The exception to add.
1023 */
1024static int hmR0VmxAddXcptIntercept(PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1025{
1026 Assert(uXcpt <= X86_XCPT_LAST);
1027 return hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1028}
1029
1030
1031/**
1032 * Remove one or more exceptions from the exception bitmap and commits it to the
1033 * current VMCS.
1034 *
1035 * This takes care of not removing the exception intercept if a nested-guest
1036 * requires the exception to be intercepted.
1037 *
1038 * @returns VBox status code.
1039 * @param pVCpu The cross context virtual CPU structure.
1040 * @param pVmxTransient The VMX-transient structure.
1041 * @param uXcptMask The exception(s) to remove.
1042 */
1043static int hmR0VmxRemoveXcptInterceptMask(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1044{
1045 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1046 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1047 if (u32XcptBitmap & uXcptMask)
1048 {
1049#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1050 if (!pVmxTransient->fIsNestedGuest)
1051 { /* likely */ }
1052 else
1053 {
1054 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1055 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1056 }
1057#endif
1058#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1059 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1060 | RT_BIT(X86_XCPT_DE)
1061 | RT_BIT(X86_XCPT_NM)
1062 | RT_BIT(X86_XCPT_TS)
1063 | RT_BIT(X86_XCPT_UD)
1064 | RT_BIT(X86_XCPT_NP)
1065 | RT_BIT(X86_XCPT_SS)
1066 | RT_BIT(X86_XCPT_GP)
1067 | RT_BIT(X86_XCPT_PF)
1068 | RT_BIT(X86_XCPT_MF));
1069#elif defined(HMVMX_ALWAYS_TRAP_PF)
1070 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1071#endif
1072 if (uXcptMask)
1073 {
1074 /* Validate we are not removing any essential exception intercepts. */
1075 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF))); RT_NOREF(pVCpu);
1076 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1077 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1078
1079 /* Remove it from the exception bitmap. */
1080 u32XcptBitmap &= ~uXcptMask;
1081
1082 /* Commit and update the cache if necessary. */
1083 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1084 {
1085 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1086 AssertRCReturn(rc, rc);
1087 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1088 }
1089 }
1090 }
1091 return VINF_SUCCESS;
1092}
1093
1094
1095/**
1096 * Remove an exceptions from the exception bitmap and commits it to the current
1097 * VMCS.
1098 *
1099 * @returns VBox status code.
1100 * @param pVCpu The cross context virtual CPU structure.
1101 * @param pVmxTransient The VMX-transient structure.
1102 * @param uXcpt The exception to remove.
1103 */
1104static int hmR0VmxRemoveXcptIntercept(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1105{
1106 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1107}
1108
1109
1110/**
1111 * Loads the VMCS specified by the VMCS info. object.
1112 *
1113 * @returns VBox status code.
1114 * @param pVmcsInfo The VMCS info. object.
1115 *
1116 * @remarks Can be called with interrupts disabled.
1117 */
1118static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1119{
1120 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1121 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1122
1123 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1124 if (RT_SUCCESS(rc))
1125 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1126 return rc;
1127}
1128
1129
1130/**
1131 * Clears the VMCS specified by the VMCS info. object.
1132 *
1133 * @returns VBox status code.
1134 * @param pVmcsInfo The VMCS info. object.
1135 *
1136 * @remarks Can be called with interrupts disabled.
1137 */
1138static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1139{
1140 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1141 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1142
1143 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1144 if (RT_SUCCESS(rc))
1145 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1146 return rc;
1147}
1148
1149
1150#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1151/**
1152 * Loads the shadow VMCS specified by the VMCS info. object.
1153 *
1154 * @returns VBox status code.
1155 * @param pVmcsInfo The VMCS info. object.
1156 *
1157 * @remarks Can be called with interrupts disabled.
1158 */
1159static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1160{
1161 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1162 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1163
1164 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1165 if (RT_SUCCESS(rc))
1166 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1167 return rc;
1168}
1169
1170
1171/**
1172 * Clears the shadow VMCS specified by the VMCS info. object.
1173 *
1174 * @returns VBox status code.
1175 * @param pVmcsInfo The VMCS info. object.
1176 *
1177 * @remarks Can be called with interrupts disabled.
1178 */
1179static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1180{
1181 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1182 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1183
1184 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1185 if (RT_SUCCESS(rc))
1186 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1187 return rc;
1188}
1189
1190
1191/**
1192 * Switches from and to the specified VMCSes.
1193 *
1194 * @returns VBox status code.
1195 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1196 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1197 *
1198 * @remarks Called with interrupts disabled.
1199 */
1200static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1201{
1202 /*
1203 * Clear the VMCS we are switching out if it has not already been cleared.
1204 * This will sync any CPU internal data back to the VMCS.
1205 */
1206 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1207 {
1208 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1209 if (RT_SUCCESS(rc))
1210 {
1211 /*
1212 * The shadow VMCS, if any, would not be active at this point since we
1213 * would have cleared it while importing the virtual hardware-virtualization
1214 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1215 * clear the shadow VMCS here, just assert for safety.
1216 */
1217 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1218 }
1219 else
1220 return rc;
1221 }
1222
1223 /*
1224 * Clear the VMCS we are switching to if it has not already been cleared.
1225 * This will initialize the VMCS launch state to "clear" required for loading it.
1226 *
1227 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1228 */
1229 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1230 {
1231 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1232 if (RT_SUCCESS(rc))
1233 { /* likely */ }
1234 else
1235 return rc;
1236 }
1237
1238 /*
1239 * Finally, load the VMCS we are switching to.
1240 */
1241 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1242}
1243
1244
1245/**
1246 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1247 * caller.
1248 *
1249 * @returns VBox status code.
1250 * @param pVCpu The cross context virtual CPU structure.
1251 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1252 * true) or guest VMCS (pass false).
1253 */
1254static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPU pVCpu, bool fSwitchToNstGstVmcs)
1255{
1256 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1257 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1258
1259 PVMXVMCSINFO pVmcsInfoFrom;
1260 PVMXVMCSINFO pVmcsInfoTo;
1261 if (fSwitchToNstGstVmcs)
1262 {
1263 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1264 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1265 }
1266 else
1267 {
1268 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1269 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1270 }
1271
1272 /*
1273 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1274 * preemption hook code path acquires the current VMCS.
1275 */
1276 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1277
1278 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1279 if (RT_SUCCESS(rc))
1280 {
1281 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1282
1283 /*
1284 * If we are switching to a VMCS that was executed on a different host CPU or was
1285 * never executed before, flag that we need to export the host state before executing
1286 * guest/nested-guest code using hardware-assisted VMX.
1287 *
1288 * This could probably be done in a preemptible context since the preemption hook
1289 * will flag the necessary change in host context. However, since preemption is
1290 * already disabled and to avoid making assumptions about host specific code in
1291 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1292 * disabled.
1293 */
1294 if (pVmcsInfoTo->idHostCpu == RTMpCpuId())
1295 { /* likely */ }
1296 else
1297 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1298
1299 ASMSetFlags(fEFlags);
1300
1301 /*
1302 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1303 * flag that we need to update the host MSR values there. Even if we decide in the
1304 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1305 * if its content differs, we would have to update the host MSRs anyway.
1306 */
1307 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1308 }
1309 else
1310 ASMSetFlags(fEFlags);
1311 return rc;
1312}
1313#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1314
1315
1316/**
1317 * Updates the VM's last error record.
1318 *
1319 * If there was a VMX instruction error, reads the error data from the VMCS and
1320 * updates VCPU's last error record as well.
1321 *
1322 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1323 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1324 * VERR_VMX_INVALID_VMCS_FIELD.
1325 * @param rc The error code.
1326 */
1327static void hmR0VmxUpdateErrorRecord(PVMCPU pVCpu, int rc)
1328{
1329 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1330 || rc == VERR_VMX_UNABLE_TO_START_VM)
1331 {
1332 AssertPtrReturnVoid(pVCpu);
1333 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1334 }
1335 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1336}
1337
1338
1339#ifdef VBOX_STRICT
1340/**
1341 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1342 * transient structure.
1343 *
1344 * @returns VBox status code.
1345 * @param pVmxTransient The VMX-transient structure.
1346 *
1347 * @remarks No-long-jump zone!!!
1348 */
1349DECLINLINE(int) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1350{
1351 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1352 AssertRCReturn(rc, rc);
1353 return VINF_SUCCESS;
1354}
1355
1356
1357/**
1358 * Reads the VM-entry exception error code field from the VMCS into
1359 * the VMX transient structure.
1360 *
1361 * @returns VBox status code.
1362 * @param pVmxTransient The VMX-transient structure.
1363 *
1364 * @remarks No-long-jump zone!!!
1365 */
1366DECLINLINE(int) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1367{
1368 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1369 AssertRCReturn(rc, rc);
1370 return VINF_SUCCESS;
1371}
1372
1373
1374/**
1375 * Reads the VM-entry exception error code field from the VMCS into
1376 * the VMX transient structure.
1377 *
1378 * @returns VBox status code.
1379 * @param pVmxTransient The VMX-transient structure.
1380 *
1381 * @remarks No-long-jump zone!!!
1382 */
1383DECLINLINE(int) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1384{
1385 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1386 AssertRCReturn(rc, rc);
1387 return VINF_SUCCESS;
1388}
1389#endif /* VBOX_STRICT */
1390
1391
1392/**
1393 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1394 * transient structure.
1395 *
1396 * @returns VBox status code.
1397 * @param pVmxTransient The VMX-transient structure.
1398 */
1399DECLINLINE(int) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1400{
1401 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1402 {
1403 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1404 AssertRCReturn(rc,rc);
1405 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1406 }
1407 return VINF_SUCCESS;
1408}
1409
1410
1411/**
1412 * Reads the VM-exit interruption error code from the VMCS into the VMX
1413 * transient structure.
1414 *
1415 * @returns VBox status code.
1416 * @param pVmxTransient The VMX-transient structure.
1417 */
1418DECLINLINE(int) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1419{
1420 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1421 {
1422 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1423 AssertRCReturn(rc, rc);
1424 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1425 }
1426 return VINF_SUCCESS;
1427}
1428
1429
1430/**
1431 * Reads the VM-exit instruction length field from the VMCS into the VMX
1432 * transient structure.
1433 *
1434 * @returns VBox status code.
1435 * @param pVmxTransient The VMX-transient structure.
1436 */
1437DECLINLINE(int) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1438{
1439 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1440 {
1441 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1442 AssertRCReturn(rc, rc);
1443 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1444 }
1445 return VINF_SUCCESS;
1446}
1447
1448
1449/**
1450 * Reads the VM-exit instruction-information field from the VMCS into
1451 * the VMX transient structure.
1452 *
1453 * @returns VBox status code.
1454 * @param pVmxTransient The VMX-transient structure.
1455 */
1456DECLINLINE(int) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1457{
1458 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1459 {
1460 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1461 AssertRCReturn(rc, rc);
1462 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1463 }
1464 return VINF_SUCCESS;
1465}
1466
1467
1468/**
1469 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1470 *
1471 * @returns VBox status code.
1472 * @param pVCpu The cross context virtual CPU structure of the
1473 * calling EMT. (Required for the VMCS cache case.)
1474 * @param pVmxTransient The VMX-transient structure.
1475 */
1476DECLINLINE(int) hmR0VmxReadExitQualVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1477{
1478 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1479 {
1480 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual); NOREF(pVCpu);
1481 AssertRCReturn(rc, rc);
1482 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1483 }
1484 return VINF_SUCCESS;
1485}
1486
1487
1488/**
1489 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1490 *
1491 * @returns VBox status code.
1492 * @param pVCpu The cross context virtual CPU structure of the
1493 * calling EMT. (Required for the VMCS cache case.)
1494 * @param pVmxTransient The VMX-transient structure.
1495 */
1496DECLINLINE(int) hmR0VmxReadGuestLinearAddrVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1497{
1498 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1499 {
1500 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr); NOREF(pVCpu);
1501 AssertRCReturn(rc, rc);
1502 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1503 }
1504 return VINF_SUCCESS;
1505}
1506
1507
1508/**
1509 * Reads the IDT-vectoring information field from the VMCS into the VMX
1510 * transient structure.
1511 *
1512 * @returns VBox status code.
1513 * @param pVmxTransient The VMX-transient structure.
1514 *
1515 * @remarks No-long-jump zone!!!
1516 */
1517DECLINLINE(int) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1518{
1519 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1520 {
1521 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1522 AssertRCReturn(rc, rc);
1523 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1524 }
1525 return VINF_SUCCESS;
1526}
1527
1528
1529/**
1530 * Reads the IDT-vectoring error code from the VMCS into the VMX
1531 * transient structure.
1532 *
1533 * @returns VBox status code.
1534 * @param pVmxTransient The VMX-transient structure.
1535 */
1536DECLINLINE(int) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1537{
1538 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1539 {
1540 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1541 AssertRCReturn(rc, rc);
1542 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1543 }
1544 return VINF_SUCCESS;
1545}
1546
1547
1548/**
1549 * Enters VMX root mode operation on the current CPU.
1550 *
1551 * @returns VBox status code.
1552 * @param pVM The cross context VM structure. Can be
1553 * NULL, after a resume.
1554 * @param HCPhysCpuPage Physical address of the VMXON region.
1555 * @param pvCpuPage Pointer to the VMXON region.
1556 */
1557static int hmR0VmxEnterRootMode(PVM pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1558{
1559 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1560 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1561 Assert(pvCpuPage);
1562 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1563
1564 if (pVM)
1565 {
1566 /* Write the VMCS revision identifier to the VMXON region. */
1567 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1568 }
1569
1570 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1571 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1572
1573 /* Enable the VMX bit in CR4 if necessary. */
1574 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1575
1576 /* Enter VMX root mode. */
1577 int rc = VMXEnable(HCPhysCpuPage);
1578 if (RT_FAILURE(rc))
1579 {
1580 if (!(uOldCr4 & X86_CR4_VMXE))
1581 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1582
1583 if (pVM)
1584 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1585 }
1586
1587 /* Restore interrupts. */
1588 ASMSetFlags(fEFlags);
1589 return rc;
1590}
1591
1592
1593/**
1594 * Exits VMX root mode operation on the current CPU.
1595 *
1596 * @returns VBox status code.
1597 */
1598static int hmR0VmxLeaveRootMode(void)
1599{
1600 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1601
1602 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1603 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1604
1605 /* If we're for some reason not in VMX root mode, then don't leave it. */
1606 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1607
1608 int rc;
1609 if (uHostCr4 & X86_CR4_VMXE)
1610 {
1611 /* Exit VMX root mode and clear the VMX bit in CR4. */
1612 VMXDisable();
1613 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1614 rc = VINF_SUCCESS;
1615 }
1616 else
1617 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1618
1619 /* Restore interrupts. */
1620 ASMSetFlags(fEFlags);
1621 return rc;
1622}
1623
1624
1625/**
1626 * Allocates and maps a physically contiguous page. The allocated page is
1627 * zero'd out (used by various VT-x structures).
1628 *
1629 * @returns IPRT status code.
1630 * @param pMemObj Pointer to the ring-0 memory object.
1631 * @param ppVirt Where to store the virtual address of the allocation.
1632 * @param pHCPhys Where to store the physical address of the allocation.
1633 */
1634static int hmR0VmxPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1635{
1636 AssertPtr(pMemObj);
1637 AssertPtr(ppVirt);
1638 AssertPtr(pHCPhys);
1639 int rc = RTR0MemObjAllocCont(pMemObj, X86_PAGE_4K_SIZE, false /* fExecutable */);
1640 if (RT_FAILURE(rc))
1641 return rc;
1642 *ppVirt = RTR0MemObjAddress(*pMemObj);
1643 *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
1644 ASMMemZero32(*ppVirt, X86_PAGE_4K_SIZE);
1645 return VINF_SUCCESS;
1646}
1647
1648
1649/**
1650 * Frees and unmaps an allocated, physical page.
1651 *
1652 * @param pMemObj Pointer to the ring-0 memory object.
1653 * @param ppVirt Where to re-initialize the virtual address of allocation as
1654 * 0.
1655 * @param pHCPhys Where to re-initialize the physical address of the
1656 * allocation as 0.
1657 */
1658static void hmR0VmxPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1659{
1660 AssertPtr(pMemObj);
1661 AssertPtr(ppVirt);
1662 AssertPtr(pHCPhys);
1663 /* NULL is valid, accepted and ignored by the free function below. */
1664 RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
1665 *pMemObj = NIL_RTR0MEMOBJ;
1666 *ppVirt = NULL;
1667 *pHCPhys = NIL_RTHCPHYS;
1668}
1669
1670
1671/**
1672 * Initializes a VMCS info. object.
1673 *
1674 * @param pVmcsInfo The VMCS info. object.
1675 */
1676static void hmR0VmxInitVmcsInfo(PVMXVMCSINFO pVmcsInfo)
1677{
1678 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1679
1680 Assert(pVmcsInfo->hMemObjVmcs == NIL_RTR0MEMOBJ);
1681 Assert(pVmcsInfo->hMemObjShadowVmcs == NIL_RTR0MEMOBJ);
1682 Assert(pVmcsInfo->hMemObjMsrBitmap == NIL_RTR0MEMOBJ);
1683 Assert(pVmcsInfo->hMemObjGuestMsrLoad == NIL_RTR0MEMOBJ);
1684 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1685 Assert(pVmcsInfo->hMemObjHostMsrLoad == NIL_RTR0MEMOBJ);
1686 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1687 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1688 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1689 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1690 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1691 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1692 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1693 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1694 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1695 pVmcsInfo->idHostCpu = NIL_RTCPUID;
1696}
1697
1698
1699/**
1700 * Frees the VT-x structures for a VMCS info. object.
1701 *
1702 * @param pVM The cross context VM structure.
1703 * @param pVmcsInfo The VMCS info. object.
1704 */
1705static void hmR0VmxFreeVmcsInfo(PVM pVM, PVMXVMCSINFO pVmcsInfo)
1706{
1707 hmR0VmxPageFree(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1708
1709#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1710 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1711 hmR0VmxPageFree(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1712#endif
1713
1714 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1715 hmR0VmxPageFree(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1716
1717 hmR0VmxPageFree(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad, &pVmcsInfo->HCPhysHostMsrLoad);
1718 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad, &pVmcsInfo->HCPhysGuestMsrLoad);
1719 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrStore, &pVmcsInfo->pvGuestMsrStore, &pVmcsInfo->HCPhysGuestMsrStore);
1720
1721 hmR0VmxInitVmcsInfo(pVmcsInfo);
1722}
1723
1724
1725/**
1726 * Allocates the VT-x structures for a VMCS info. object.
1727 *
1728 * @returns VBox status code.
1729 * @param pVCpu The cross context virtual CPU structure.
1730 * @param pVmcsInfo The VMCS info. object.
1731 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1732 */
1733static int hmR0VmxAllocVmcsInfo(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1734{
1735 PVM pVM = pVCpu->CTX_SUFF(pVM);
1736
1737 /* Allocate the guest VM control structure (VMCS). */
1738 int rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1739 if (RT_SUCCESS(rc))
1740 {
1741 if (!fIsNstGstVmcs)
1742 {
1743#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1744 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1745 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1746#endif
1747 if (RT_SUCCESS(rc))
1748 {
1749 /* Get the allocated virtual-APIC page from the virtual APIC device. */
1750 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
1751 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
1752 {
1753 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic,
1754 NULL /* pR3Ptr */, NULL /* pRCPtr */);
1755 }
1756 }
1757 }
1758 else
1759 {
1760 /* We don't yet support exposing VMCS shadowing to the guest. */
1761 Assert(pVmcsInfo->HCPhysShadowVmcs == NIL_RTHCPHYS);
1762 Assert(!pVmcsInfo->pvShadowVmcs);
1763
1764 /* Get the allocated virtual-APIC page from CPUM. */
1765 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1766 {
1767 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(pVCpu, &pVCpu->cpum.GstCtx,
1768 &pVmcsInfo->HCPhysVirtApic);
1769 Assert(pVmcsInfo->pbVirtApic);
1770 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1771 }
1772 }
1773
1774 if (RT_SUCCESS(rc))
1775 {
1776 /*
1777 * Allocate the MSR-bitmap if supported by the CPU. The MSR-bitmap is for
1778 * transparent accesses of specific MSRs.
1779 *
1780 * If the condition for enabling MSR bitmaps changes here, don't forget to
1781 * update HMIsMsrBitmapActive().
1782 *
1783 * We don't share MSR bitmaps between the guest and nested-guest as we then
1784 * don't need to care about carefully restoring the guest MSR bitmap.
1785 * The guest visible nested-guest MSR bitmap needs to remain unchanged.
1786 * Hence, allocate a separate MSR bitmap for the guest and nested-guest.
1787 * We also don't need to re-initialize the nested-guest MSR bitmap here as
1788 * we do that later while merging VMCS.
1789 */
1790 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1791 {
1792 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1793 if ( RT_SUCCESS(rc)
1794 && !fIsNstGstVmcs)
1795 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
1796 }
1797
1798 if (RT_SUCCESS(rc))
1799 {
1800 /*
1801 * Allocate the VM-entry MSR-load area for the guest MSRs.
1802 *
1803 * Similar to MSR-bitmaps, we do not share the auto MSR-load/store are between
1804 * the guest and nested-guest.
1805 */
1806 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad,
1807 &pVmcsInfo->HCPhysGuestMsrLoad);
1808 if (RT_SUCCESS(rc))
1809 {
1810 /*
1811 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1812 * These contain the guest MSRs to load on VM-entry and store on VM-exit.
1813 */
1814 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1815 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1816 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1817
1818 /* Allocate the VM-exit MSR-load page for the host MSRs. */
1819 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad,
1820 &pVmcsInfo->HCPhysHostMsrLoad);
1821 }
1822 }
1823 }
1824 }
1825
1826 return rc;
1827}
1828
1829
1830/**
1831 * Free all VT-x structures for the VM.
1832 *
1833 * @returns IPRT status code.
1834 * @param pVM The cross context VM structure.
1835 */
1836static void hmR0VmxStructsFree(PVM pVM)
1837{
1838#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1839 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1840#endif
1841 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess, &pVM->hm.s.vmx.HCPhysApicAccess);
1842
1843#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1844 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1845 {
1846 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1847 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1848 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap, &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1849 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap, &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1850 }
1851#endif
1852
1853 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1854 {
1855 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1856 PVMXVMCSINFO pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
1857 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1858#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1859 if (pVM->cpum.ro.GuestFeatures.fVmx)
1860 {
1861 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1862 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1863 }
1864#endif
1865 }
1866}
1867
1868
1869/**
1870 * Allocate all VT-x structures for the VM.
1871 *
1872 * @returns IPRT status code.
1873 * @param pVM The cross context VM structure.
1874 */
1875static int hmR0VmxStructsAlloc(PVM pVM)
1876{
1877 /*
1878 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1879 * The VMCS size cannot be more than 4096 bytes.
1880 *
1881 * See Intel spec. Appendix A.1 "Basic VMX Information".
1882 */
1883 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1884 if (cbVmcs <= X86_PAGE_4K_SIZE)
1885 { /* likely */ }
1886 else
1887 {
1888 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1889 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1890 }
1891
1892 /*
1893 * Initialize/check members up-front so we can cleanup en masse on allocation failures.
1894 */
1895#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1896 Assert(pVM->hm.s.vmx.hMemObjScratch == NIL_RTR0MEMOBJ);
1897 Assert(pVM->hm.s.vmx.pbScratch == NULL);
1898 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
1899#endif
1900
1901 Assert(pVM->hm.s.vmx.hMemObjApicAccess == NIL_RTR0MEMOBJ);
1902 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
1903 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
1904
1905 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1906 {
1907 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1908 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfo);
1909 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1910 }
1911
1912 /*
1913 * Allocate per-VM VT-x structures.
1914 */
1915 int rc = VINF_SUCCESS;
1916#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1917 /* Allocate crash-dump magic scratch page. */
1918 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1919 if (RT_FAILURE(rc))
1920 {
1921 hmR0VmxStructsFree(pVM);
1922 return rc;
1923 }
1924 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
1925 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
1926#endif
1927
1928 /* Allocate the APIC-access page for trapping APIC accesses from the guest. */
1929 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
1930 {
1931 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess,
1932 &pVM->hm.s.vmx.HCPhysApicAccess);
1933 if (RT_FAILURE(rc))
1934 {
1935 hmR0VmxStructsFree(pVM);
1936 return rc;
1937 }
1938 }
1939
1940#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1941 /* Allocate the shadow VMCS fields array, VMREAD, VMWRITE bitmaps.. */
1942 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1943 {
1944 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
1945 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
1946 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1947 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1948 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
1949 && pVM->hm.s.vmx.paShadowVmcsRoFields))
1950 {
1951 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap,
1952 &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1953 if (RT_SUCCESS(rc))
1954 {
1955 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap,
1956 &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1957 }
1958 }
1959 else
1960 rc = VERR_NO_MEMORY;
1961
1962 if (RT_FAILURE(rc))
1963 {
1964 hmR0VmxStructsFree(pVM);
1965 return rc;
1966 }
1967 }
1968#endif
1969
1970 /*
1971 * Initialize per-VCPU VT-x structures.
1972 */
1973 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1974 {
1975 /* Allocate the guest VMCS structures. */
1976 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1977 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
1978 if (RT_SUCCESS(rc))
1979 {
1980#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1981 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
1982 if (pVM->cpum.ro.GuestFeatures.fVmx)
1983 {
1984 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
1985 if (RT_SUCCESS(rc))
1986 { /* likely */ }
1987 else
1988 break;
1989 }
1990#endif
1991 }
1992 else
1993 break;
1994 }
1995
1996 if (RT_FAILURE(rc))
1997 {
1998 hmR0VmxStructsFree(pVM);
1999 return rc;
2000 }
2001
2002 return VINF_SUCCESS;
2003}
2004
2005#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2006/**
2007 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2008 *
2009 * @returns @c true if the MSR is intercepted, @c false otherwise.
2010 * @param pvMsrBitmap The MSR bitmap.
2011 * @param offMsr The MSR byte offset.
2012 * @param iBit The bit offset from the byte offset.
2013 */
2014DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2015{
2016 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2017 Assert(pbMsrBitmap);
2018 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2019 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2020}
2021#endif
2022
2023/**
2024 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2025 *
2026 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2027 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2028 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2029 * the read/write access of this MSR.
2030 *
2031 * @param pVCpu The cross context virtual CPU structure.
2032 * @param pVmcsInfo The VMCS info. object.
2033 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2034 * @param idMsr The MSR value.
2035 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2036 * include both a read -and- a write permission!
2037 *
2038 * @sa CPUMGetVmxMsrPermission.
2039 * @remarks Can be called with interrupts disabled.
2040 */
2041static void hmR0VmxSetMsrPermission(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2042{
2043 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2044 Assert(pbMsrBitmap);
2045 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2046
2047 /*
2048 * MSR-bitmap Layout:
2049 * Byte index MSR range Interpreted as
2050 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2051 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2052 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2053 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2054 *
2055 * A bit corresponding to an MSR within the above range causes a VM-exit
2056 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2057 * the MSR range, it always cause a VM-exit.
2058 *
2059 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2060 */
2061 uint16_t const offBitmapRead = 0;
2062 uint16_t const offBitmapWrite = 0x800;
2063 uint16_t offMsr;
2064 int32_t iBit;
2065 if (idMsr <= UINT32_C(0x00001fff))
2066 {
2067 offMsr = 0;
2068 iBit = idMsr;
2069 }
2070 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2071 {
2072 offMsr = 0x400;
2073 iBit = idMsr - UINT32_C(0xc0000000);
2074 }
2075 else
2076 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2077
2078 /*
2079 * Set the MSR read permission.
2080 */
2081 uint16_t const offMsrRead = offBitmapRead + offMsr;
2082 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2083 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2084 {
2085#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2086 bool const fClear = !fIsNstGstVmcs ? true
2087 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2088#else
2089 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2090 bool const fClear = true;
2091#endif
2092 if (fClear)
2093 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2094 }
2095 else
2096 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2097
2098 /*
2099 * Set the MSR write permission.
2100 */
2101 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2102 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2103 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2104 {
2105#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2106 bool const fClear = !fIsNstGstVmcs ? true
2107 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2108#else
2109 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2110 bool const fClear = true;
2111#endif
2112 if (fClear)
2113 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2114 }
2115 else
2116 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2117}
2118
2119
2120/**
2121 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2122 * area.
2123 *
2124 * @returns VBox status code.
2125 * @param pVCpu The cross context virtual CPU structure.
2126 * @param pVmcsInfo The VMCS info. object.
2127 * @param cMsrs The number of MSRs.
2128 */
2129static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2130{
2131 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2132 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2133 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2134 {
2135 /* Commit the MSR counts to the VMCS and update the cache. */
2136 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2137 {
2138 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs);
2139 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs);
2140 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs);
2141 AssertRCReturn(rc, rc);
2142
2143 pVmcsInfo->cEntryMsrLoad = cMsrs;
2144 pVmcsInfo->cExitMsrStore = cMsrs;
2145 pVmcsInfo->cExitMsrLoad = cMsrs;
2146 }
2147 return VINF_SUCCESS;
2148 }
2149
2150 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2151 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2152 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2153}
2154
2155
2156/**
2157 * Adds a new (or updates the value of an existing) guest/host MSR
2158 * pair to be swapped during the world-switch as part of the
2159 * auto-load/store MSR area in the VMCS.
2160 *
2161 * @returns VBox status code.
2162 * @param pVCpu The cross context virtual CPU structure.
2163 * @param pVmxTransient The VMX-transient structure.
2164 * @param idMsr The MSR.
2165 * @param uGuestMsrValue Value of the guest MSR.
2166 * @param fSetReadWrite Whether to set the guest read/write access of this
2167 * MSR (thus not causing a VM-exit).
2168 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2169 * necessary.
2170 */
2171static int hmR0VmxAddAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2172 bool fSetReadWrite, bool fUpdateHostMsr)
2173{
2174 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2175 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2176 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2177 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2178 uint32_t i;
2179
2180 /* Paranoia. */
2181 Assert(pGuestMsrLoad);
2182
2183 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2184
2185 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2186 for (i = 0; i < cMsrs; i++)
2187 {
2188 if (pGuestMsrLoad[i].u32Msr == idMsr)
2189 break;
2190 }
2191
2192 bool fAdded = false;
2193 if (i == cMsrs)
2194 {
2195 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2196 ++cMsrs;
2197 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2198 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2199
2200 /* Set the guest to read/write this MSR without causing VM-exits. */
2201 if ( fSetReadWrite
2202 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2203 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2204
2205 LogFlowFunc(("MSR added, cMsrs now %u\n", cMsrs));
2206 fAdded = true;
2207 }
2208
2209 /* Update the MSR value for the newly added or already existing MSR. */
2210 pGuestMsrLoad[i].u32Msr = idMsr;
2211 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2212
2213 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2214 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2215 {
2216 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2217 pGuestMsrStore[i].u32Msr = idMsr;
2218 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2219 }
2220
2221 /* Update the corresponding slot in the host MSR area. */
2222 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2223 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2224 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2225 pHostMsr[i].u32Msr = idMsr;
2226
2227 /*
2228 * Only if the caller requests to update the host MSR value AND we've newly added the
2229 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2230 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2231 *
2232 * We do this for performance reasons since reading MSRs may be quite expensive.
2233 */
2234 if (fAdded)
2235 {
2236 if (fUpdateHostMsr)
2237 {
2238 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2239 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2240 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2241 }
2242 else
2243 {
2244 /* Someone else can do the work. */
2245 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2246 }
2247 }
2248 return VINF_SUCCESS;
2249}
2250
2251
2252/**
2253 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2254 * auto-load/store MSR area in the VMCS.
2255 *
2256 * @returns VBox status code.
2257 * @param pVCpu The cross context virtual CPU structure.
2258 * @param pVmxTransient The VMX-transient structure.
2259 * @param idMsr The MSR.
2260 */
2261static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2262{
2263 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2264 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2265 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2266 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2267
2268 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2269
2270 for (uint32_t i = 0; i < cMsrs; i++)
2271 {
2272 /* Find the MSR. */
2273 if (pGuestMsrLoad[i].u32Msr == idMsr)
2274 {
2275 /*
2276 * If it's the last MSR, we only need to reduce the MSR count.
2277 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2278 */
2279 if (i < cMsrs - 1)
2280 {
2281 /* Remove it from the VM-entry MSR-load area. */
2282 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2283 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2284
2285 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2286 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2287 {
2288 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2289 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2290 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2291 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2292 }
2293
2294 /* Remove it from the VM-exit MSR-load area. */
2295 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2296 Assert(pHostMsr[i].u32Msr == idMsr);
2297 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2298 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2299 }
2300
2301 /* Reduce the count to reflect the removed MSR and bail. */
2302 --cMsrs;
2303 break;
2304 }
2305 }
2306
2307 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2308 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2309 {
2310 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2311 AssertRCReturn(rc, rc);
2312
2313 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2314 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2315 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2316
2317 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2318 return VINF_SUCCESS;
2319 }
2320
2321 return VERR_NOT_FOUND;
2322}
2323
2324
2325/**
2326 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2327 *
2328 * @returns @c true if found, @c false otherwise.
2329 * @param pVmcsInfo The VMCS info. object.
2330 * @param idMsr The MSR to find.
2331 */
2332static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2333{
2334 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2335 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2336 Assert(pMsrs);
2337 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2338 for (uint32_t i = 0; i < cMsrs; i++)
2339 {
2340 if (pMsrs[i].u32Msr == idMsr)
2341 return true;
2342 }
2343 return false;
2344}
2345
2346
2347/**
2348 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2349 *
2350 * @param pVCpu The cross context virtual CPU structure.
2351 * @param pVmcsInfo The VMCS info. object.
2352 *
2353 * @remarks No-long-jump zone!!!
2354 */
2355static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2356{
2357 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2358
2359 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2360 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2361 Assert(pHostMsrLoad);
2362 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2363 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2364 for (uint32_t i = 0; i < cMsrs; i++)
2365 {
2366 /*
2367 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2368 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2369 */
2370 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2371 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2372 else
2373 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2374 }
2375}
2376
2377
2378/**
2379 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2380 * perform lazy restoration of the host MSRs while leaving VT-x.
2381 *
2382 * @param pVCpu The cross context virtual CPU structure.
2383 *
2384 * @remarks No-long-jump zone!!!
2385 */
2386static void hmR0VmxLazySaveHostMsrs(PVMCPU pVCpu)
2387{
2388 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2389
2390 /*
2391 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2392 */
2393 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2394 {
2395 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2396#if HC_ARCH_BITS == 64
2397 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2398 {
2399 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2400 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2401 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2402 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2403 }
2404#endif
2405 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2406 }
2407}
2408
2409
2410/**
2411 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2412 * lazily while leaving VT-x.
2413 *
2414 * @returns true if it does, false otherwise.
2415 * @param pVCpu The cross context virtual CPU structure.
2416 * @param idMsr The MSR to check.
2417 */
2418static bool hmR0VmxIsLazyGuestMsr(PCVMCPU pVCpu, uint32_t idMsr)
2419{
2420 NOREF(pVCpu);
2421#if HC_ARCH_BITS == 64
2422 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2423 {
2424 switch (idMsr)
2425 {
2426 case MSR_K8_LSTAR:
2427 case MSR_K6_STAR:
2428 case MSR_K8_SF_MASK:
2429 case MSR_K8_KERNEL_GS_BASE:
2430 return true;
2431 }
2432 }
2433#else
2434 RT_NOREF(pVCpu, idMsr);
2435#endif
2436 return false;
2437}
2438
2439
2440/**
2441 * Loads a set of guests MSRs to allow read/passthru to the guest.
2442 *
2443 * The name of this function is slightly confusing. This function does NOT
2444 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2445 * common prefix for functions dealing with "lazy restoration" of the shared
2446 * MSRs.
2447 *
2448 * @param pVCpu The cross context virtual CPU structure.
2449 *
2450 * @remarks No-long-jump zone!!!
2451 */
2452static void hmR0VmxLazyLoadGuestMsrs(PVMCPU pVCpu)
2453{
2454 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2455 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2456
2457 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2458#if HC_ARCH_BITS == 64
2459 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2460 {
2461 /*
2462 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2463 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2464 * we can skip a few MSR writes.
2465 *
2466 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2467 * guest MSR values in the guest-CPU context might be different to what's currently
2468 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2469 * CPU, see @bugref{8728}.
2470 */
2471 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2472 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2473 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2474 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2475 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2476 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2477 {
2478#ifdef VBOX_STRICT
2479 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2480 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2481 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2482 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2483#endif
2484 }
2485 else
2486 {
2487 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2488 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2489 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2490 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2491 }
2492 }
2493#endif
2494 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2495}
2496
2497
2498/**
2499 * Performs lazy restoration of the set of host MSRs if they were previously
2500 * loaded with guest MSR values.
2501 *
2502 * @param pVCpu The cross context virtual CPU structure.
2503 *
2504 * @remarks No-long-jump zone!!!
2505 * @remarks The guest MSRs should have been saved back into the guest-CPU
2506 * context by hmR0VmxImportGuestState()!!!
2507 */
2508static void hmR0VmxLazyRestoreHostMsrs(PVMCPU pVCpu)
2509{
2510 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2511 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2512
2513 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2514 {
2515 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2516#if HC_ARCH_BITS == 64
2517 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2518 {
2519 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2520 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2521 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2522 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2523 }
2524#endif
2525 }
2526 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2527}
2528
2529
2530/**
2531 * Verifies that our cached values of the VMCS fields are all consistent with
2532 * what's actually present in the VMCS.
2533 *
2534 * @returns VBox status code.
2535 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2536 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2537 * VMCS content. HMCPU error-field is
2538 * updated, see VMX_VCI_XXX.
2539 * @param pVCpu The cross context virtual CPU structure.
2540 * @param pVmcsInfo The VMCS info. object.
2541 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2542 */
2543static int hmR0VmxCheckVmcsCtls(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2544{
2545 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2546
2547 uint32_t u32Val;
2548 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2549 AssertRCReturn(rc, rc);
2550 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2551 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2552 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2553 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2554
2555 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2556 AssertRCReturn(rc, rc);
2557 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2558 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2559 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2560 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2561
2562 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2563 AssertRCReturn(rc, rc);
2564 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2565 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2566 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2567 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2568
2569 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2570 AssertRCReturn(rc, rc);
2571 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2572 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2573 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2574 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2575
2576 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2577 {
2578 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2579 AssertRCReturn(rc, rc);
2580 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2581 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2582 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2583 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2584 }
2585
2586 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2587 AssertRCReturn(rc, rc);
2588 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2589 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2590 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2591 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2592
2593 uint64_t u64Val;
2594 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2595 AssertRCReturn(rc, rc);
2596 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2597 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2598 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2599 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2600
2601 NOREF(pcszVmcs);
2602 return VINF_SUCCESS;
2603}
2604
2605
2606#ifdef VBOX_STRICT
2607/**
2608 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2609 *
2610 * @param pVCpu The cross context virtual CPU structure.
2611 * @param pVmcsInfo The VMCS info. object.
2612 */
2613static void hmR0VmxCheckHostEferMsr(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2614{
2615 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2616
2617 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2618 {
2619 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2620 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2621 uint64_t uVmcsEferMsrVmcs;
2622 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2623 AssertRC(rc);
2624
2625 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2626 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2627 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2628 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2629 }
2630}
2631
2632
2633/**
2634 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2635 * VMCS are correct.
2636 *
2637 * @param pVCpu The cross context virtual CPU structure.
2638 * @param pVmcsInfo The VMCS info. object.
2639 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2640 */
2641static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2642{
2643 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2644
2645 /* Read the various MSR-area counts from the VMCS. */
2646 uint32_t cEntryLoadMsrs;
2647 uint32_t cExitStoreMsrs;
2648 uint32_t cExitLoadMsrs;
2649 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2650 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2651 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2652
2653 /* Verify all the MSR counts are the same. */
2654 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2655 Assert(cExitStoreMsrs == cExitLoadMsrs);
2656 uint32_t const cMsrs = cExitLoadMsrs;
2657
2658 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2659 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2660
2661 /* Verify the MSR counts are within the allocated page size. */
2662 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2663
2664 /* Verify the relevant contents of the MSR areas match. */
2665 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2666 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2667 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2668 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2669 for (uint32_t i = 0; i < cMsrs; i++)
2670 {
2671 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2672 if (fSeparateExitMsrStorePage)
2673 {
2674 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2675 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2676 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2677 }
2678
2679 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2680 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2681 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2682
2683 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2684 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2685 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2686 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2687
2688 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2689 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2690 if (fIsEferMsr)
2691 {
2692 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2693 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2694 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2695 }
2696
2697 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2698 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2699 {
2700 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2701 if (fIsEferMsr)
2702 {
2703 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2704 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2705 }
2706 else
2707 {
2708 if (!fIsNstGstVmcs)
2709 {
2710 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2711 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2712 }
2713 else
2714 {
2715 /*
2716 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2717 * execute a nested-guest with MSR passthrough.
2718 *
2719 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2720 * allow passthrough too.
2721 */
2722 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2723 Assert(pvMsrBitmapNstGst);
2724 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2725 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2726 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2727 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2728 }
2729 }
2730 }
2731
2732 /* Move to the next MSR. */
2733 pHostMsrLoad++;
2734 pGuestMsrLoad++;
2735 pGuestMsrStore++;
2736 }
2737}
2738#endif /* VBOX_STRICT */
2739
2740
2741/**
2742 * Flushes the TLB using EPT.
2743 *
2744 * @returns VBox status code.
2745 * @param pVCpu The cross context virtual CPU structure of the calling
2746 * EMT. Can be NULL depending on @a enmTlbFlush.
2747 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2748 * enmTlbFlush.
2749 * @param enmTlbFlush Type of flush.
2750 *
2751 * @remarks Caller is responsible for making sure this function is called only
2752 * when NestedPaging is supported and providing @a enmTlbFlush that is
2753 * supported by the CPU.
2754 * @remarks Can be called with interrupts disabled.
2755 */
2756static void hmR0VmxFlushEpt(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2757{
2758 uint64_t au64Descriptor[2];
2759 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2760 au64Descriptor[0] = 0;
2761 else
2762 {
2763 Assert(pVCpu);
2764 Assert(pVmcsInfo);
2765 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2766 }
2767 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2768
2769 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2770 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2771
2772 if ( RT_SUCCESS(rc)
2773 && pVCpu)
2774 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2775}
2776
2777
2778/**
2779 * Flushes the TLB using VPID.
2780 *
2781 * @returns VBox status code.
2782 * @param pVCpu The cross context virtual CPU structure of the calling
2783 * EMT. Can be NULL depending on @a enmTlbFlush.
2784 * @param enmTlbFlush Type of flush.
2785 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2786 * on @a enmTlbFlush).
2787 *
2788 * @remarks Can be called with interrupts disabled.
2789 */
2790static void hmR0VmxFlushVpid(PVMCPU pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2791{
2792 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2793
2794 uint64_t au64Descriptor[2];
2795 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2796 {
2797 au64Descriptor[0] = 0;
2798 au64Descriptor[1] = 0;
2799 }
2800 else
2801 {
2802 AssertPtr(pVCpu);
2803 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2804 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2805 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2806 au64Descriptor[1] = GCPtr;
2807 }
2808
2809 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2810 AssertMsg(rc == VINF_SUCCESS,
2811 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2812
2813 if ( RT_SUCCESS(rc)
2814 && pVCpu)
2815 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2816 NOREF(rc);
2817}
2818
2819
2820/**
2821 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2822 * otherwise there is nothing really to invalidate.
2823 *
2824 * @returns VBox status code.
2825 * @param pVCpu The cross context virtual CPU structure.
2826 * @param GCVirt Guest virtual address of the page to invalidate.
2827 */
2828VMMR0DECL(int) VMXR0InvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt)
2829{
2830 AssertPtr(pVCpu);
2831 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2832
2833 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2834 {
2835 /*
2836 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2837 * the EPT case. See @bugref{6043} and @bugref{6177}.
2838 *
2839 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2840 * as this function maybe called in a loop with individual addresses.
2841 */
2842 PVM pVM = pVCpu->CTX_SUFF(pVM);
2843 if (pVM->hm.s.vmx.fVpid)
2844 {
2845 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2846
2847#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
2848 /*
2849 * Workaround Erratum BV75, AAJ159 and others that affect several Intel CPUs
2850 * where executing INVVPID outside 64-bit mode does not flush translations of
2851 * 64-bit linear addresses, see @bugref{6208#c72}.
2852 */
2853 if (RT_HI_U32(GCVirt))
2854 fVpidFlush = false;
2855#endif
2856
2857 if (fVpidFlush)
2858 {
2859 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2860 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2861 }
2862 else
2863 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2864 }
2865 else if (pVM->hm.s.fNestedPaging)
2866 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2867 }
2868
2869 return VINF_SUCCESS;
2870}
2871
2872
2873/**
2874 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2875 * case where neither EPT nor VPID is supported by the CPU.
2876 *
2877 * @param pHostCpu The HM physical-CPU structure.
2878 * @param pVCpu The cross context virtual CPU structure.
2879 *
2880 * @remarks Called with interrupts disabled.
2881 */
2882static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
2883{
2884 AssertPtr(pVCpu);
2885 AssertPtr(pHostCpu);
2886
2887 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2888
2889 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2890 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2891 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2892 pVCpu->hm.s.fForceTLBFlush = false;
2893 return;
2894}
2895
2896
2897/**
2898 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2899 *
2900 * @param pHostCpu The HM physical-CPU structure.
2901 * @param pVCpu The cross context virtual CPU structure.
2902 * @param pVmcsInfo The VMCS info. object.
2903 *
2904 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2905 * nomenclature. The reason is, to avoid confusion in compare statements
2906 * since the host-CPU copies are named "ASID".
2907 *
2908 * @remarks Called with interrupts disabled.
2909 */
2910static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2911{
2912#ifdef VBOX_WITH_STATISTICS
2913 bool fTlbFlushed = false;
2914# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2915# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2916 if (!fTlbFlushed) \
2917 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2918 } while (0)
2919#else
2920# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2921# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2922#endif
2923
2924 AssertPtr(pVCpu);
2925 AssertPtr(pHostCpu);
2926 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2927
2928 PVM pVM = pVCpu->CTX_SUFF(pVM);
2929 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2930 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2931 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2932
2933 /*
2934 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2935 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2936 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2937 * cannot reuse the current ASID anymore.
2938 */
2939 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2940 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2941 {
2942 ++pHostCpu->uCurrentAsid;
2943 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2944 {
2945 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2946 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2947 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2948 }
2949
2950 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2951 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2952 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2953
2954 /*
2955 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2956 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2957 */
2958 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2959 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2960 HMVMX_SET_TAGGED_TLB_FLUSHED();
2961 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2962 }
2963 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2964 {
2965 /*
2966 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2967 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2968 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2969 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2970 * mappings, see @bugref{6568}.
2971 *
2972 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2973 */
2974 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2975 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2976 HMVMX_SET_TAGGED_TLB_FLUSHED();
2977 }
2978
2979 pVCpu->hm.s.fForceTLBFlush = false;
2980 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
2981
2982 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
2983 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
2984 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2985 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
2986 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
2987 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
2988 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
2989 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
2990 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
2991
2992 /* Update VMCS with the VPID. */
2993 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
2994 AssertRC(rc);
2995
2996#undef HMVMX_SET_TAGGED_TLB_FLUSHED
2997}
2998
2999
3000/**
3001 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3002 *
3003 * @param pHostCpu The HM physical-CPU structure.
3004 * @param pVCpu The cross context virtual CPU structure.
3005 * @param pVmcsInfo The VMCS info. object.
3006 *
3007 * @remarks Called with interrupts disabled.
3008 */
3009static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3010{
3011 AssertPtr(pVCpu);
3012 AssertPtr(pHostCpu);
3013 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3014 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3015 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3016
3017 /*
3018 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3019 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3020 */
3021 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3022 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3023 {
3024 pVCpu->hm.s.fForceTLBFlush = true;
3025 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3026 }
3027
3028 /* Check for explicit TLB flushes. */
3029 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3030 {
3031 pVCpu->hm.s.fForceTLBFlush = true;
3032 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3033 }
3034
3035 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3036 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3037
3038 if (pVCpu->hm.s.fForceTLBFlush)
3039 {
3040 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3041 pVCpu->hm.s.fForceTLBFlush = false;
3042 }
3043}
3044
3045
3046/**
3047 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3048 *
3049 * @param pHostCpu The HM physical-CPU structure.
3050 * @param pVCpu The cross context virtual CPU structure.
3051 *
3052 * @remarks Called with interrupts disabled.
3053 */
3054static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
3055{
3056 AssertPtr(pVCpu);
3057 AssertPtr(pHostCpu);
3058 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3059 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3060 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3061
3062 /*
3063 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3064 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3065 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3066 * cannot reuse the current ASID anymore.
3067 */
3068 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3069 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3070 {
3071 pVCpu->hm.s.fForceTLBFlush = true;
3072 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3073 }
3074
3075 /* Check for explicit TLB flushes. */
3076 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3077 {
3078 /*
3079 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3080 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3081 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3082 * include fExplicitFlush's too) - an obscure corner case.
3083 */
3084 pVCpu->hm.s.fForceTLBFlush = true;
3085 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3086 }
3087
3088 PVM pVM = pVCpu->CTX_SUFF(pVM);
3089 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3090 if (pVCpu->hm.s.fForceTLBFlush)
3091 {
3092 ++pHostCpu->uCurrentAsid;
3093 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3094 {
3095 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3096 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3097 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3098 }
3099
3100 pVCpu->hm.s.fForceTLBFlush = false;
3101 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3102 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3103 if (pHostCpu->fFlushAsidBeforeUse)
3104 {
3105 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3106 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3107 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3108 {
3109 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3110 pHostCpu->fFlushAsidBeforeUse = false;
3111 }
3112 else
3113 {
3114 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3115 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3116 }
3117 }
3118 }
3119
3120 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3121 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3122 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3123 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3124 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3125 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3126 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3127
3128 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3129 AssertRC(rc);
3130}
3131
3132
3133/**
3134 * Flushes the guest TLB entry based on CPU capabilities.
3135 *
3136 * @param pHostCpu The HM physical-CPU structure.
3137 * @param pVCpu The cross context virtual CPU structure.
3138 * @param pVmcsInfo The VMCS info. object.
3139 *
3140 * @remarks Called with interrupts disabled.
3141 */
3142static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3143{
3144#ifdef HMVMX_ALWAYS_FLUSH_TLB
3145 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3146#endif
3147 PVM pVM = pVCpu->CTX_SUFF(pVM);
3148 switch (pVM->hm.s.vmx.enmTlbFlushType)
3149 {
3150 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3151 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3152 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3153 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3154 default:
3155 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3156 break;
3157 }
3158 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3159}
3160
3161
3162/**
3163 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3164 * TLB entries from the host TLB before VM-entry.
3165 *
3166 * @returns VBox status code.
3167 * @param pVM The cross context VM structure.
3168 */
3169static int hmR0VmxSetupTaggedTlb(PVM pVM)
3170{
3171 /*
3172 * Determine optimal flush type for nested paging.
3173 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3174 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3175 */
3176 if (pVM->hm.s.fNestedPaging)
3177 {
3178 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3179 {
3180 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3181 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3182 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3183 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3184 else
3185 {
3186 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3187 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3188 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3189 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3190 }
3191
3192 /* Make sure the write-back cacheable memory type for EPT is supported. */
3193 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3194 {
3195 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3196 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3197 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3198 }
3199
3200 /* EPT requires a page-walk length of 4. */
3201 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3202 {
3203 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3204 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3205 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3206 }
3207 }
3208 else
3209 {
3210 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3211 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3212 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3213 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3214 }
3215 }
3216
3217 /*
3218 * Determine optimal flush type for VPID.
3219 */
3220 if (pVM->hm.s.vmx.fVpid)
3221 {
3222 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3223 {
3224 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3225 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3226 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3227 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3228 else
3229 {
3230 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3231 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3232 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3233 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3234 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3235 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3236 pVM->hm.s.vmx.fVpid = false;
3237 }
3238 }
3239 else
3240 {
3241 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3242 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3243 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3244 pVM->hm.s.vmx.fVpid = false;
3245 }
3246 }
3247
3248 /*
3249 * Setup the handler for flushing tagged-TLBs.
3250 */
3251 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3252 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3253 else if (pVM->hm.s.fNestedPaging)
3254 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3255 else if (pVM->hm.s.vmx.fVpid)
3256 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3257 else
3258 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3259 return VINF_SUCCESS;
3260}
3261
3262
3263#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3264/**
3265 * Sets up the shadow VMCS fields arrays.
3266 *
3267 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3268 * executing the guest.
3269 *
3270 * @returns VBox status code.
3271 * @param pVM The cross context VM structure.
3272 */
3273static int hmR0VmxSetupShadowVmcsFieldsArrays(PVM pVM)
3274{
3275 /*
3276 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3277 * when the host does not support it.
3278 */
3279 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3280 if ( !fGstVmwriteAll
3281 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3282 { /* likely. */ }
3283 else
3284 {
3285 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3286 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3287 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3288 }
3289
3290 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3291 uint32_t cRwFields = 0;
3292 uint32_t cRoFields = 0;
3293 for (uint32_t i = 0; i < cVmcsFields; i++)
3294 {
3295 VMXVMCSFIELD VmcsField;
3296 VmcsField.u = g_aVmcsFields[i];
3297
3298 /*
3299 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3300 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3301 * in the shadow VMCS fields array as they would be redundant.
3302 *
3303 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3304 * we must not include it in the shadow VMCS fields array. Guests attempting to
3305 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3306 * the required behavior.
3307 */
3308 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3309 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3310 {
3311 /*
3312 * Read-only fields are placed in a separate array so that while syncing shadow
3313 * VMCS fields later (which is more performance critical) we can avoid branches.
3314 *
3315 * However, if the guest can write to all fields (including read-only fields),
3316 * we treat it a as read/write field. Otherwise, writing to these fields would
3317 * cause a VMWRITE instruction error while syncing the shadow VMCS .
3318 */
3319 if ( fGstVmwriteAll
3320 || !HMVmxIsVmcsFieldReadOnly(VmcsField.u))
3321 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3322 else
3323 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3324 }
3325 }
3326
3327 /* Update the counts. */
3328 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3329 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3330 return VINF_SUCCESS;
3331}
3332
3333
3334/**
3335 * Sets up the VMREAD and VMWRITE bitmaps.
3336 *
3337 * @param pVM The cross context VM structure.
3338 */
3339static void hmR0VmxSetupVmreadVmwriteBitmaps(PVM pVM)
3340{
3341 /*
3342 * By default, ensure guest attempts to acceses to any VMCS fields cause VM-exits.
3343 */
3344 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3345 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3346 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3347 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3348 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3349
3350 /*
3351 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3352 * VMREAD and VMWRITE bitmaps.
3353 */
3354 {
3355 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3356 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3357 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3358 {
3359 uint32_t const uVmcsField = paShadowVmcsFields[i];
3360 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3361 Assert(uVmcsField >> 3 < cbBitmap);
3362 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3363 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3364 }
3365 }
3366
3367 /*
3368 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3369 * if the host supports VMWRITE to all supported VMCS fields.
3370 */
3371 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3372 {
3373 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3374 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3375 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3376 {
3377 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3378 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3379 Assert(uVmcsField >> 3 < cbBitmap);
3380 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3381 }
3382 }
3383}
3384#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3385
3386
3387/**
3388 * Sets up the virtual-APIC page address for the VMCS.
3389 *
3390 * @returns VBox status code.
3391 * @param pVCpu The cross context virtual CPU structure.
3392 * @param pVmcsInfo The VMCS info. object.
3393 */
3394DECLINLINE(int) hmR0VmxSetupVmcsVirtApicAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3395{
3396 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3397 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3398 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3399 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3400 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3401}
3402
3403
3404/**
3405 * Sets up the MSR-bitmap address for the VMCS.
3406 *
3407 * @returns VBox status code.
3408 * @param pVCpu The cross context virtual CPU structure.
3409 * @param pVmcsInfo The VMCS info. object.
3410 */
3411DECLINLINE(int) hmR0VmxSetupVmcsMsrBitmapAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3412{
3413 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3414 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3415 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3416 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3417 return VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3418}
3419
3420
3421/**
3422 * Sets up the APIC-access page address for the VMCS.
3423 *
3424 * @returns VBox status code.
3425 * @param pVCpu The cross context virtual CPU structure.
3426 */
3427DECLINLINE(int) hmR0VmxSetupVmcsApicAccessAddr(PVMCPU pVCpu)
3428{
3429 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3430 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3431 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3432 return VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3433}
3434
3435
3436#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3437/**
3438 * Sets up the VMREAD bitmap address for the VMCS.
3439 *
3440 * @returns VBox status code.
3441 * @param pVCpu The cross context virtual CPU structure.
3442 */
3443DECLINLINE(int) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPU pVCpu)
3444{
3445 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3446 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3447 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3448 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3449}
3450
3451
3452/**
3453 * Sets up the VMWRITE bitmap address for the VMCS.
3454 *
3455 * @returns VBox status code.
3456 * @param pVCpu The cross context virtual CPU structure.
3457 */
3458DECLINLINE(int) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPU pVCpu)
3459{
3460 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3461 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3462 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3463 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3464}
3465#endif
3466
3467
3468/**
3469 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3470 * in the VMCS.
3471 *
3472 * @returns VBox status code.
3473 * @param pVCpu The cross context virtual CPU structure.
3474 * @param pVmcsInfo The VMCS info. object.
3475 */
3476DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3477{
3478 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3479
3480 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3481 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3482 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3483
3484 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3485 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3486 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3487
3488 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3489 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3490 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3491
3492 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad);
3493 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore);
3494 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad);
3495 AssertRCReturn(rc, rc);
3496 return VINF_SUCCESS;
3497}
3498
3499
3500/**
3501 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3502 *
3503 * @param pVCpu The cross context virtual CPU structure.
3504 * @param pVmcsInfo The VMCS info. object.
3505 */
3506static void hmR0VmxSetupVmcsMsrPermissions(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3507{
3508 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3509
3510 /*
3511 * The guest can access the following MSRs (read, write) without causing
3512 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3513 */
3514 PVM pVM = pVCpu->CTX_SUFF(pVM);
3515 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3516 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3517 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3518 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3519 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3520
3521 /*
3522 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3523 * associated with then. We never need to intercept access (writes need to be
3524 * executed without causing a VM-exit, reads will #GP fault anyway).
3525 *
3526 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3527 * read/write them. We swap the the guest/host MSR value using the
3528 * auto-load/store MSR area.
3529 */
3530 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3531 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3532 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3533 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3534 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3535 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3536
3537#if HC_ARCH_BITS == 64
3538 /*
3539 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3540 * required for 64-bit guests.
3541 */
3542 if (pVM->hm.s.fAllow64BitGuests)
3543 {
3544 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3545 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3546 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3547 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3548 }
3549#endif
3550
3551 /*
3552 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3553 */
3554#ifdef VBOX_STRICT
3555 Assert(pVmcsInfo->pvMsrBitmap);
3556 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3557 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3558#endif
3559}
3560
3561
3562/**
3563 * Sets up pin-based VM-execution controls in the VMCS.
3564 *
3565 * @returns VBox status code.
3566 * @param pVCpu The cross context virtual CPU structure.
3567 * @param pVmcsInfo The VMCS info. object.
3568 */
3569static int hmR0VmxSetupVmcsPinCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3570{
3571 PVM pVM = pVCpu->CTX_SUFF(pVM);
3572 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3573 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3574
3575 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3576 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3577
3578 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3579 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3580
3581 /* Enable the VMX-preemption timer. */
3582 if (pVM->hm.s.vmx.fUsePreemptTimer)
3583 {
3584 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3585 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3586 }
3587
3588#if 0
3589 /* Enable posted-interrupt processing. */
3590 if (pVM->hm.s.fPostedIntrs)
3591 {
3592 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3593 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3594 fVal |= VMX_PIN_CTLS_POSTED_INT;
3595 }
3596#endif
3597
3598 if ((fVal & fZap) != fVal)
3599 {
3600 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3601 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3602 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3603 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3604 }
3605
3606 /* Commit it to the VMCS and update our cache. */
3607 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3608 AssertRCReturn(rc, rc);
3609 pVmcsInfo->u32PinCtls = fVal;
3610
3611 return VINF_SUCCESS;
3612}
3613
3614
3615/**
3616 * Sets up secondary processor-based VM-execution controls in the VMCS.
3617 *
3618 * @returns VBox status code.
3619 * @param pVCpu The cross context virtual CPU structure.
3620 * @param pVmcsInfo The VMCS info. object.
3621 */
3622static int hmR0VmxSetupVmcsProcCtls2(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3623{
3624 PVM pVM = pVCpu->CTX_SUFF(pVM);
3625 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3626 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3627
3628 /* WBINVD causes a VM-exit. */
3629 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3630 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3631
3632 /* Enable EPT (aka nested-paging). */
3633 if (pVM->hm.s.fNestedPaging)
3634 fVal |= VMX_PROC_CTLS2_EPT;
3635
3636 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3637 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3638 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3639 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3640 fVal |= VMX_PROC_CTLS2_INVPCID;
3641
3642 /* Enable VPID. */
3643 if (pVM->hm.s.vmx.fVpid)
3644 fVal |= VMX_PROC_CTLS2_VPID;
3645
3646 /* Enable unrestricted guest execution. */
3647 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3648 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3649
3650#if 0
3651 if (pVM->hm.s.fVirtApicRegs)
3652 {
3653 /* Enable APIC-register virtualization. */
3654 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3655 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3656
3657 /* Enable virtual-interrupt delivery. */
3658 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3659 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3660 }
3661#endif
3662
3663 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3664 where the TPR shadow resides. */
3665 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3666 * done dynamically. */
3667 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3668 {
3669 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3670 int rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3671 AssertRCReturn(rc, rc);
3672 }
3673
3674 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3675 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3676 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3677 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3678 fVal |= VMX_PROC_CTLS2_RDTSCP;
3679
3680 /* Enable Pause-Loop exiting. */
3681 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3682 && pVM->hm.s.vmx.cPleGapTicks
3683 && pVM->hm.s.vmx.cPleWindowTicks)
3684 {
3685 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3686
3687 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks);
3688 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks);
3689 AssertRCReturn(rc, rc);
3690 }
3691
3692 if ((fVal & fZap) != fVal)
3693 {
3694 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3695 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3696 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3697 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3698 }
3699
3700 /* Commit it to the VMCS and update our cache. */
3701 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3702 AssertRCReturn(rc, rc);
3703 pVmcsInfo->u32ProcCtls2 = fVal;
3704
3705 return VINF_SUCCESS;
3706}
3707
3708
3709/**
3710 * Sets up processor-based VM-execution controls in the VMCS.
3711 *
3712 * @returns VBox status code.
3713 * @param pVCpu The cross context virtual CPU structure.
3714 * @param pVmcsInfo The VMCS info. object.
3715 */
3716static int hmR0VmxSetupVmcsProcCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3717{
3718 PVM pVM = pVCpu->CTX_SUFF(pVM);
3719
3720 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3721 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3722
3723 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3724 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3725 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3726 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3727 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3728 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3729 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3730
3731 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3732 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3733 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3734 {
3735 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3736 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3737 }
3738
3739 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3740 if (!pVM->hm.s.fNestedPaging)
3741 {
3742 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3743 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3744 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3745 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3746 }
3747
3748 /* Use TPR shadowing if supported by the CPU. */
3749 if ( PDMHasApic(pVM)
3750 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3751 {
3752 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3753 /* CR8 writes cause a VM-exit based on TPR threshold. */
3754 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3755 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3756 int rc = hmR0VmxSetupVmcsVirtApicAddr(pVCpu, pVmcsInfo);
3757 AssertRCReturn(rc, rc);
3758 }
3759 else
3760 {
3761 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3762 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3763 if (pVM->hm.s.fAllow64BitGuests)
3764 {
3765 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3766 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3767 }
3768 }
3769
3770 /* Use MSR-bitmaps if supported by the CPU. */
3771 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3772 {
3773 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3774 int rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3775 AssertRCReturn(rc, rc);
3776 }
3777
3778 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3779 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3780 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3781
3782 if ((fVal & fZap) != fVal)
3783 {
3784 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3785 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3786 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3787 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3788 }
3789
3790 /* Commit it to the VMCS and update our cache. */
3791 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3792 AssertRCReturn(rc, rc);
3793 pVmcsInfo->u32ProcCtls = fVal;
3794
3795 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3796 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3797 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3798
3799 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3800 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3801 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3802
3803 /* Sanity check, should not really happen. */
3804 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3805 { /* likely */ }
3806 else
3807 {
3808 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3809 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3810 }
3811
3812 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3813 return VINF_SUCCESS;
3814}
3815
3816
3817/**
3818 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3819 * Processor-based VM-execution) control fields in the VMCS.
3820 *
3821 * @returns VBox status code.
3822 * @param pVCpu The cross context virtual CPU structure.
3823 * @param pVmcsInfo The VMCS info. object.
3824 */
3825static int hmR0VmxSetupVmcsMiscCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3826{
3827#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3828 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3829 {
3830 int rc = hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3831 rc |= hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3832 if (RT_SUCCESS(rc))
3833 { /* likely */ }
3834 else
3835 {
3836 LogRelFunc(("Failed to setup VMREAD/VMWRITE bitmap addresses. rc=%Rrc\n", rc));
3837 return rc;
3838 }
3839 }
3840#endif
3841
3842 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3843 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3844 if (RT_SUCCESS(rc))
3845 {
3846 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3847 if (RT_SUCCESS(rc))
3848 {
3849 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3850 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3851 rc = VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
3852 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
3853 if (RT_SUCCESS(rc))
3854 {
3855 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3856 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3857 return VINF_SUCCESS;
3858 }
3859 LogRelFunc(("Failed to initialize VMCS CR0/CR4 guest/host mask. rc=%Rrc\n", rc));
3860 }
3861 else
3862 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3863 }
3864 else
3865 LogRelFunc(("Failed to initialize VMCS link pointer. rc=%Rrc\n", rc));
3866 return rc;
3867}
3868
3869
3870/**
3871 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3872 *
3873 * We shall setup those exception intercepts that don't change during the
3874 * lifetime of the VM here. The rest are done dynamically while loading the
3875 * guest state.
3876 *
3877 * @returns VBox status code.
3878 * @param pVCpu The cross context virtual CPU structure.
3879 * @param pVmcsInfo The VMCS info. object.
3880 */
3881static int hmR0VmxSetupVmcsXcptBitmap(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3882{
3883 /*
3884 * The following exceptions are always intercepted:
3885 *
3886 * #AC - To prevent the guest from hanging the CPU.
3887 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3888 * recursive #DBs can cause a CPU hang.
3889 * #PF - To sync our shadow page tables when nested-paging is not used.
3890 */
3891 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3892 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3893 | RT_BIT(X86_XCPT_DB)
3894 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3895
3896 /* Commit it to the VMCS. */
3897 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3898 AssertRCReturn(rc, rc);
3899
3900 /* Update our cache of the exception bitmap. */
3901 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3902 return VINF_SUCCESS;
3903}
3904
3905
3906#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3907/**
3908 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3909 *
3910 * @returns VBox status code.
3911 * @param pVCpu The cross context virtual CPU structure.
3912 * @param pVmcsInfo The VMCS info. object.
3913 */
3914static int hmR0VmxSetupVmcsCtlsNested(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3915{
3916 PVM pVM = pVCpu->CTX_SUFF(pVM);
3917 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3918 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3919 if (RT_SUCCESS(rc))
3920 {
3921 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3922 if (RT_SUCCESS(rc))
3923 {
3924 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3925 rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3926 if (RT_SUCCESS(rc))
3927 {
3928 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3929 rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3930 if (RT_SUCCESS(rc))
3931 return VINF_SUCCESS;
3932
3933 LogRelFunc(("Failed to set up the APIC-access address in the nested-guest VMCS. rc=%Rrc\n", rc));
3934 }
3935 else
3936 LogRelFunc(("Failed to set up the MSR-bitmap address in the nested-guest VMCS. rc=%Rrc\n", rc));
3937 }
3938 else
3939 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3940 }
3941 else
3942 LogRelFunc(("Failed to set up the auto-load/store MSR addresses in the nested-guest VMCS. rc=%Rrc\n", rc));
3943
3944 return rc;
3945}
3946#endif
3947
3948
3949/**
3950 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
3951 * VMX.
3952 *
3953 * @returns VBox status code.
3954 * @param pVCpu The cross context virtual CPU structure.
3955 * @param pVmcsInfo The VMCS info. object.
3956 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
3957 */
3958static int hmR0VmxSetupVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
3959{
3960 Assert(pVmcsInfo->pvVmcs);
3961 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3962
3963 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
3964 PVM pVM = pVCpu->CTX_SUFF(pVM);
3965 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3966 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
3967
3968 LogFlowFunc(("\n"));
3969
3970 /*
3971 * Initialize the VMCS using VMCLEAR before loading the VMCS.
3972 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
3973 */
3974 int rc = hmR0VmxClearVmcs(pVmcsInfo);
3975 if (RT_SUCCESS(rc))
3976 {
3977 rc = hmR0VmxLoadVmcs(pVmcsInfo);
3978 if (RT_SUCCESS(rc))
3979 {
3980 if (!fIsNstGstVmcs)
3981 {
3982 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
3983 if (RT_SUCCESS(rc))
3984 {
3985 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
3986 if (RT_SUCCESS(rc))
3987 {
3988 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
3989 if (RT_SUCCESS(rc))
3990 {
3991 rc = hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
3992 if (RT_SUCCESS(rc))
3993 {
3994#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3995 /*
3996 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
3997 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
3998 * making it fit for use when VMCS shadowing is later enabled.
3999 */
4000 if (pVmcsInfo->pvShadowVmcs)
4001 {
4002 VMXVMCSREVID VmcsRevId;
4003 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4004 VmcsRevId.n.fIsShadowVmcs = 1;
4005 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4006 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4007 if (RT_SUCCESS(rc))
4008 { /* likely */ }
4009 else
4010 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4011 }
4012#endif
4013 }
4014 else
4015 LogRelFunc(("Failed to initialize exception bitmap. rc=%Rrc\n", rc));
4016 }
4017 else
4018 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4019 }
4020 else
4021 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4022 }
4023 else
4024 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4025 }
4026 else
4027 {
4028#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4029 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4030 if (RT_SUCCESS(rc))
4031 { /* likely */ }
4032 else
4033 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4034#else
4035 AssertFailed();
4036#endif
4037 }
4038 }
4039 else
4040 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4041 }
4042 else
4043 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4044
4045 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4046 if (RT_SUCCESS(rc))
4047 {
4048 rc = hmR0VmxClearVmcs(pVmcsInfo);
4049 if (RT_SUCCESS(rc))
4050 { /* likely */ }
4051 else
4052 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4053 }
4054
4055 /*
4056 * Update the last-error record both for failures and success, so we
4057 * can propagate the status code back to ring-3 for diagnostics.
4058 */
4059 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4060 NOREF(pszVmcs);
4061 return rc;
4062}
4063
4064
4065/**
4066 * Does global VT-x initialization (called during module initialization).
4067 *
4068 * @returns VBox status code.
4069 */
4070VMMR0DECL(int) VMXR0GlobalInit(void)
4071{
4072#ifdef HMVMX_USE_FUNCTION_TABLE
4073 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4074# ifdef VBOX_STRICT
4075 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4076 Assert(g_apfnVMExitHandlers[i]);
4077# endif
4078#endif
4079 return VINF_SUCCESS;
4080}
4081
4082
4083/**
4084 * Does global VT-x termination (called during module termination).
4085 */
4086VMMR0DECL(void) VMXR0GlobalTerm()
4087{
4088 /* Nothing to do currently. */
4089}
4090
4091
4092/**
4093 * Sets up and activates VT-x on the current CPU.
4094 *
4095 * @returns VBox status code.
4096 * @param pHostCpu The HM physical-CPU structure.
4097 * @param pVM The cross context VM structure. Can be
4098 * NULL after a host resume operation.
4099 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4100 * fEnabledByHost is @c true).
4101 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4102 * @a fEnabledByHost is @c true).
4103 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4104 * enable VT-x on the host.
4105 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4106 */
4107VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4108 PCSUPHWVIRTMSRS pHwvirtMsrs)
4109{
4110 AssertPtr(pHostCpu);
4111 AssertPtr(pHwvirtMsrs);
4112 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4113
4114 /* Enable VT-x if it's not already enabled by the host. */
4115 if (!fEnabledByHost)
4116 {
4117 int rc = hmR0VmxEnterRootMode(pVM, HCPhysCpuPage, pvCpuPage);
4118 if (RT_FAILURE(rc))
4119 return rc;
4120 }
4121
4122 /*
4123 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4124 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4125 * invalidated when flushing by VPID.
4126 */
4127 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4128 {
4129 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4130 pHostCpu->fFlushAsidBeforeUse = false;
4131 }
4132 else
4133 pHostCpu->fFlushAsidBeforeUse = true;
4134
4135 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4136 ++pHostCpu->cTlbFlushes;
4137
4138 return VINF_SUCCESS;
4139}
4140
4141
4142/**
4143 * Deactivates VT-x on the current CPU.
4144 *
4145 * @returns VBox status code.
4146 * @param pvCpuPage Pointer to the VMXON region.
4147 * @param HCPhysCpuPage Physical address of the VMXON region.
4148 *
4149 * @remarks This function should never be called when SUPR0EnableVTx() or
4150 * similar was used to enable VT-x on the host.
4151 */
4152VMMR0DECL(int) VMXR0DisableCpu(void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4153{
4154 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4155
4156 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4157 return hmR0VmxLeaveRootMode();
4158}
4159
4160
4161/**
4162 * Does per-VM VT-x initialization.
4163 *
4164 * @returns VBox status code.
4165 * @param pVM The cross context VM structure.
4166 */
4167VMMR0DECL(int) VMXR0InitVM(PVM pVM)
4168{
4169 AssertPtr(pVM);
4170 LogFlowFunc(("pVM=%p\n", pVM));
4171
4172 int rc = hmR0VmxStructsAlloc(pVM);
4173 if (RT_FAILURE(rc))
4174 {
4175 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4176 return rc;
4177 }
4178
4179 return VINF_SUCCESS;
4180}
4181
4182
4183/**
4184 * Does per-VM VT-x termination.
4185 *
4186 * @returns VBox status code.
4187 * @param pVM The cross context VM structure.
4188 */
4189VMMR0DECL(int) VMXR0TermVM(PVM pVM)
4190{
4191 AssertPtr(pVM);
4192 LogFlowFunc(("pVM=%p\n", pVM));
4193
4194#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4195 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4196 {
4197 Assert(pVM->hm.s.vmx.pvScratch);
4198 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4199 }
4200#endif
4201 hmR0VmxStructsFree(pVM);
4202 return VINF_SUCCESS;
4203}
4204
4205
4206/**
4207 * Sets up the VM for execution using hardware-assisted VMX.
4208 * This function is only called once per-VM during initialization.
4209 *
4210 * @returns VBox status code.
4211 * @param pVM The cross context VM structure.
4212 */
4213VMMR0DECL(int) VMXR0SetupVM(PVM pVM)
4214{
4215 AssertPtr(pVM);
4216 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4217
4218 LogFlowFunc(("pVM=%p\n", pVM));
4219
4220 /*
4221 * At least verify if VMX is enabled, since we can't check if we're in
4222 * VMX root mode or not without causing a #GP.
4223 */
4224 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4225 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4226 { /* likely */ }
4227 else
4228 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4229
4230 /*
4231 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4232 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4233 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4234 */
4235 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4236 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4237 || !pVM->hm.s.vmx.pRealModeTSS))
4238 {
4239 LogRelFunc(("Invalid real-on-v86 state.\n"));
4240 return VERR_INTERNAL_ERROR;
4241 }
4242
4243 /* Initialize these always, see hmR3InitFinalizeR0().*/
4244 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4245 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4246
4247 /* Setup the tagged-TLB flush handlers. */
4248 int rc = hmR0VmxSetupTaggedTlb(pVM);
4249 if (RT_FAILURE(rc))
4250 {
4251 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4252 return rc;
4253 }
4254
4255#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4256 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4257 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4258 {
4259 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4260 if (RT_SUCCESS(rc))
4261 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4262 else
4263 {
4264 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4265 return rc;
4266 }
4267 }
4268#endif
4269
4270 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4271 {
4272 PVMCPU pVCpu = &pVM->aCpus[idCpu];
4273 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4274
4275 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4276 if (RT_SUCCESS(rc))
4277 {
4278#if HC_ARCH_BITS == 32
4279 hmR0VmxInitVmcsReadCache(pVCpu);
4280#endif
4281#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4282 if (pVM->cpum.ro.GuestFeatures.fVmx)
4283 {
4284 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4285 if (RT_SUCCESS(rc))
4286 { /* likely */ }
4287 else
4288 {
4289 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4290 return rc;
4291 }
4292 }
4293#endif
4294 }
4295 else
4296 {
4297 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4298 return rc;
4299 }
4300 }
4301
4302 return VINF_SUCCESS;
4303}
4304
4305
4306#if HC_ARCH_BITS == 32
4307# ifdef VBOX_ENABLE_64_BITS_GUESTS
4308/**
4309 * Check if guest state allows safe use of 32-bit switcher again.
4310 *
4311 * Segment bases and protected mode structures must be 32-bit addressable
4312 * because the 32-bit switcher will ignore high dword when writing these VMCS
4313 * fields. See @bugref{8432} for details.
4314 *
4315 * @returns true if safe, false if must continue to use the 64-bit switcher.
4316 * @param pCtx Pointer to the guest-CPU context.
4317 *
4318 * @remarks No-long-jump zone!!!
4319 */
4320static bool hmR0VmxIs32BitSwitcherSafe(PCCPUMCTX pCtx)
4321{
4322 if (pCtx->gdtr.pGdt & UINT64_C(0xffffffff00000000)) return false;
4323 if (pCtx->idtr.pIdt & UINT64_C(0xffffffff00000000)) return false;
4324 if (pCtx->ldtr.u64Base & UINT64_C(0xffffffff00000000)) return false;
4325 if (pCtx->tr.u64Base & UINT64_C(0xffffffff00000000)) return false;
4326 if (pCtx->es.u64Base & UINT64_C(0xffffffff00000000)) return false;
4327 if (pCtx->cs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4328 if (pCtx->ss.u64Base & UINT64_C(0xffffffff00000000)) return false;
4329 if (pCtx->ds.u64Base & UINT64_C(0xffffffff00000000)) return false;
4330 if (pCtx->fs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4331 if (pCtx->gs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4332
4333 /* All good, bases are 32-bit. */
4334 return true;
4335}
4336# endif /* VBOX_ENABLE_64_BITS_GUESTS */
4337
4338# ifdef VBOX_STRICT
4339static bool hmR0VmxIsValidWriteFieldInCache(uint32_t idxField)
4340{
4341 switch (idxField)
4342 {
4343 case VMX_VMCS_GUEST_RIP:
4344 case VMX_VMCS_GUEST_RSP:
4345 case VMX_VMCS_GUEST_SYSENTER_EIP:
4346 case VMX_VMCS_GUEST_SYSENTER_ESP:
4347 case VMX_VMCS_GUEST_GDTR_BASE:
4348 case VMX_VMCS_GUEST_IDTR_BASE:
4349 case VMX_VMCS_GUEST_CS_BASE:
4350 case VMX_VMCS_GUEST_DS_BASE:
4351 case VMX_VMCS_GUEST_ES_BASE:
4352 case VMX_VMCS_GUEST_FS_BASE:
4353 case VMX_VMCS_GUEST_GS_BASE:
4354 case VMX_VMCS_GUEST_SS_BASE:
4355 case VMX_VMCS_GUEST_LDTR_BASE:
4356 case VMX_VMCS_GUEST_TR_BASE:
4357 case VMX_VMCS_GUEST_CR3:
4358 return true;
4359 }
4360 return false;
4361}
4362
4363static bool hmR0VmxIsValidReadFieldInCache(uint32_t idxField)
4364{
4365 switch (idxField)
4366 {
4367 /* Read-only fields. */
4368 case VMX_VMCS_RO_EXIT_QUALIFICATION:
4369 return true;
4370 }
4371 /* Remaining readable fields should also be writable. */
4372 return hmR0VmxIsValidWriteFieldInCache(idxField);
4373}
4374# endif /* VBOX_STRICT */
4375
4376
4377/**
4378 * Executes the specified handler in 64-bit mode.
4379 *
4380 * @returns VBox status code (no informational status codes).
4381 * @param pVCpu The cross context virtual CPU structure.
4382 * @param enmOp The operation to perform.
4383 * @param cParams Number of parameters.
4384 * @param paParam Array of 32-bit parameters.
4385 */
4386VMMR0DECL(int) VMXR0Execute64BitsHandler(PVMCPU pVCpu, HM64ON32OP enmOp, uint32_t cParams, uint32_t *paParam)
4387{
4388 AssertPtr(pVCpu);
4389 PVM pVM = pVCpu->CTX_SUFF(pVM);
4390 AssertReturn(pVM->hm.s.pfnHost32ToGuest64R0, VERR_HM_NO_32_TO_64_SWITCHER);
4391 Assert(enmOp > HM64ON32OP_INVALID && enmOp < HM64ON32OP_END);
4392 Assert(pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Write.aField));
4393 Assert(pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Read.aField));
4394
4395#ifdef VBOX_STRICT
4396 for (uint32_t i = 0; i < pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries; i++)
4397 Assert(hmR0VmxIsValidWriteFieldInCache(pVCpu->hm.s.vmx.VmcsCache.Write.aField[i]));
4398
4399 for (uint32_t i = 0; i <pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries; i++)
4400 Assert(hmR0VmxIsValidReadFieldInCache(pVCpu->hm.s.vmx.VmcsCache.Read.aField[i]));
4401#endif
4402
4403 /* Disable interrupts. */
4404 RTCCUINTREG fOldEFlags = ASMIntDisableFlags();
4405
4406#ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
4407 RTCPUID idHostCpu = RTMpCpuId();
4408 CPUMR0SetLApic(pVCpu, idHostCpu);
4409#endif
4410
4411 /** @todo replace with hmR0VmxEnterRootMode() and hmR0VmxLeaveRootMode(). */
4412
4413 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
4414 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
4415
4416 /* Clear VMCS. Marking it inactive, clearing implementation-specific data and writing VMCS data back to memory. */
4417 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
4418 hmR0VmxClearVmcs(pVmcsInfo);
4419
4420 /* Leave VMX root mode and disable VMX. */
4421 VMXDisable();
4422 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
4423
4424 CPUMSetHyperESP(pVCpu, VMMGetStackRC(pVCpu));
4425 CPUMSetHyperEIP(pVCpu, enmOp);
4426 for (int i = (int)cParams - 1; i >= 0; i--)
4427 CPUMPushHyper(pVCpu, paParam[i]);
4428
4429 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatWorldSwitch3264, z);
4430
4431 /* Call the switcher. */
4432 int rc = pVM->hm.s.pfnHost32ToGuest64R0(pVM, RT_UOFFSETOF_DYN(VM, aCpus[pVCpu->idCpu].cpum) - RT_UOFFSETOF(VM, cpum));
4433 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatWorldSwitch3264, z);
4434
4435 /* Re-enable VMX to make sure the VMX instructions don't cause #UD faults. */
4436 SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
4437
4438 /* Re-enter VMX root mode. */
4439 int rc2 = VMXEnable(HCPhysCpuPage);
4440 if (RT_FAILURE(rc2))
4441 {
4442 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
4443 ASMSetFlags(fOldEFlags);
4444 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
4445 return rc2;
4446 }
4447
4448 /* Restore the VMCS as the current VMCS. */
4449 rc2 = hmR0VmxLoadVmcs(pVmcsInfo);
4450 AssertRC(rc2);
4451 Assert(!(ASMGetFlags() & X86_EFL_IF));
4452 ASMSetFlags(fOldEFlags);
4453 return rc;
4454}
4455
4456
4457/**
4458 * Prepares for and executes VMLAUNCH (64-bit guests) for 32-bit hosts
4459 * supporting 64-bit guests.
4460 *
4461 * @returns VBox status code.
4462 * @param fResume Whether to VMLAUNCH or VMRESUME.
4463 * @param pCtx Pointer to the guest-CPU context.
4464 * @param pCache Pointer to the VMCS batch cache.
4465 * @param pVM The cross context VM structure.
4466 * @param pVCpu The cross context virtual CPU structure.
4467 */
4468DECLASM(int) VMXR0SwitcherStartVM64(RTHCUINT fResume, PCPUMCTX pCtx, PVMXVMCSCACHE pCache, PVM pVM, PVMCPU pVCpu)
4469{
4470 NOREF(fResume);
4471
4472 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
4473 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
4474 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
4475
4476#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4477 pCache->uPos = 1;
4478 pCache->interPD = PGMGetInterPaeCR3(pVM);
4479 pCache->pSwitcher = (uint64_t)pVM->hm.s.pfnHost32ToGuest64R0;
4480#endif
4481
4482#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
4483 pCache->TestIn.HCPhysCpuPage = 0;
4484 pCache->TestIn.HCPhysVmcs = 0;
4485 pCache->TestIn.pCache = 0;
4486 pCache->TestOut.HCPhysVmcs = 0;
4487 pCache->TestOut.pCache = 0;
4488 pCache->TestOut.pCtx = 0;
4489 pCache->TestOut.eflags = 0;
4490#else
4491 NOREF(pCache);
4492#endif
4493
4494 uint32_t aParam[10];
4495 aParam[0] = RT_LO_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Lo. */
4496 aParam[1] = RT_HI_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Hi. */
4497 aParam[2] = RT_LO_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Lo. */
4498 aParam[3] = RT_HI_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Hi. */
4499 aParam[4] = VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache);
4500 aParam[5] = 0;
4501 aParam[6] = VM_RC_ADDR(pVM, pVM);
4502 aParam[7] = 0;
4503 aParam[8] = VM_RC_ADDR(pVM, pVCpu);
4504 aParam[9] = 0;
4505
4506#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4507 pCtx->dr[4] = pVM->hm.s.vmx.pScratchPhys + 16 + 8;
4508 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 1;
4509#endif
4510 int rc = VMXR0Execute64BitsHandler(pVCpu, HM64ON32OP_VMXRCStartVM64, RT_ELEMENTS(aParam), &aParam[0]);
4511
4512#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4513 Assert(*(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) == 5);
4514 Assert(pCtx->dr[4] == 10);
4515 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 0xff;
4516#endif
4517
4518#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
4519 AssertMsg(pCache->TestIn.HCPhysCpuPage == HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage));
4520 AssertMsg(pCache->TestIn.HCPhysVmcs == pVmcsInfo->HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
4521 pVmcsInfo->HCPhysVmcs));
4522 AssertMsg(pCache->TestIn.HCPhysVmcs == pCache->TestOut.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
4523 pCache->TestOut.HCPhysVmcs));
4524 AssertMsg(pCache->TestIn.pCache == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache,
4525 pCache->TestOut.pCache));
4526 AssertMsg(pCache->TestIn.pCache == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache),
4527 ("%RGv vs %RGv\n", pCache->TestIn.pCache, VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache)));
4528 AssertMsg(pCache->TestIn.pCtx == pCache->TestOut.pCtx, ("%RGv vs %RGv\n", pCache->TestIn.pCtx,
4529 pCache->TestOut.pCtx));
4530 Assert(!(pCache->TestOut.eflags & X86_EFL_IF));
4531#endif
4532 NOREF(pCtx);
4533 return rc;
4534}
4535#endif
4536
4537
4538/**
4539 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4540 * the VMCS.
4541 *
4542 * @returns VBox status code.
4543 */
4544static int hmR0VmxExportHostControlRegs(void)
4545{
4546 RTCCUINTREG uReg = ASMGetCR0();
4547 int rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR0, uReg);
4548 AssertRCReturn(rc, rc);
4549
4550 uReg = ASMGetCR3();
4551 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR3, uReg);
4552 AssertRCReturn(rc, rc);
4553
4554 uReg = ASMGetCR4();
4555 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR4, uReg);
4556 AssertRCReturn(rc, rc);
4557 return rc;
4558}
4559
4560
4561/**
4562 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4563 * the host-state area in the VMCS.
4564 *
4565 * @returns VBox status code.
4566 * @param pVCpu The cross context virtual CPU structure.
4567 */
4568static int hmR0VmxExportHostSegmentRegs(PVMCPU pVCpu)
4569{
4570#if HC_ARCH_BITS == 64
4571/**
4572 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4573 * requirements. See hmR0VmxExportHostSegmentRegs().
4574 */
4575# define VMXLOCAL_ADJUST_HOST_SEG(seg, selValue) \
4576 if ((selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4577 { \
4578 bool fValidSelector = true; \
4579 if ((selValue) & X86_SEL_LDT) \
4580 { \
4581 uint32_t uAttr = ASMGetSegAttr((selValue)); \
4582 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4583 } \
4584 if (fValidSelector) \
4585 { \
4586 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##seg; \
4587 pVCpu->hm.s.vmx.RestoreHost.uHostSel##seg = (selValue); \
4588 } \
4589 (selValue) = 0; \
4590 }
4591
4592 /*
4593 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4594 * will be messed up. We should -not- save the messed up state without restoring
4595 * the original host-state, see @bugref{7240}.
4596 *
4597 * This apparently can happen (most likely the FPU changes), deal with it rather than
4598 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4599 */
4600 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4601 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4602 {
4603 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4604 pVCpu->idCpu));
4605 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4606 }
4607 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4608#else
4609 RT_NOREF(pVCpu);
4610#endif
4611
4612 /*
4613 * Host DS, ES, FS and GS segment registers.
4614 */
4615#if HC_ARCH_BITS == 64
4616 RTSEL uSelDS = ASMGetDS();
4617 RTSEL uSelES = ASMGetES();
4618 RTSEL uSelFS = ASMGetFS();
4619 RTSEL uSelGS = ASMGetGS();
4620#else
4621 RTSEL uSelDS = 0;
4622 RTSEL uSelES = 0;
4623 RTSEL uSelFS = 0;
4624 RTSEL uSelGS = 0;
4625#endif
4626
4627 /*
4628 * Host CS and SS segment registers.
4629 */
4630 RTSEL uSelCS = ASMGetCS();
4631 RTSEL uSelSS = ASMGetSS();
4632
4633 /*
4634 * Host TR segment register.
4635 */
4636 RTSEL uSelTR = ASMGetTR();
4637
4638#if HC_ARCH_BITS == 64
4639 /*
4640 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4641 * gain VM-entry and restore them before we get preempted.
4642 *
4643 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4644 */
4645 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4646 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4647 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4648 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4649# undef VMXLOCAL_ADJUST_HOST_SEG
4650#endif
4651
4652 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4653 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4654 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4655 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4656 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4657 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4658 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4659 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4660 Assert(uSelCS);
4661 Assert(uSelTR);
4662
4663 /* Write these host selector fields into the host-state area in the VMCS. */
4664 int rc = VMXWriteVmcs32(VMX_VMCS16_HOST_CS_SEL, uSelCS);
4665 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_SS_SEL, uSelSS);
4666#if HC_ARCH_BITS == 64
4667 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_DS_SEL, uSelDS);
4668 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_ES_SEL, uSelES);
4669 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_FS_SEL, uSelFS);
4670 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_GS_SEL, uSelGS);
4671#else
4672 NOREF(uSelDS);
4673 NOREF(uSelES);
4674 NOREF(uSelFS);
4675 NOREF(uSelGS);
4676#endif
4677 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_TR_SEL, uSelTR);
4678 AssertRCReturn(rc, rc);
4679
4680 /*
4681 * Host GDTR and IDTR.
4682 */
4683 RTGDTR Gdtr;
4684 RTIDTR Idtr;
4685 RT_ZERO(Gdtr);
4686 RT_ZERO(Idtr);
4687 ASMGetGDTR(&Gdtr);
4688 ASMGetIDTR(&Idtr);
4689 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt);
4690 rc |= VMXWriteVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt);
4691 AssertRCReturn(rc, rc);
4692
4693#if HC_ARCH_BITS == 64
4694 /*
4695 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4696 * them to the maximum limit (0xffff) on every VM-exit.
4697 */
4698 if (Gdtr.cbGdt != 0xffff)
4699 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4700
4701 /*
4702 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4703 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4704 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4705 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4706 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4707 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4708 * at 0xffff on hosts where we are sure it won't cause trouble.
4709 */
4710# if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4711 if (Idtr.cbIdt < 0x0fff)
4712# else
4713 if (Idtr.cbIdt != 0xffff)
4714# endif
4715 {
4716 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4717 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4718 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4719 }
4720#endif
4721
4722 /*
4723 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4724 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4725 * RPL should be too in most cases.
4726 */
4727 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4728 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4729
4730 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4731#if HC_ARCH_BITS == 64
4732 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4733
4734 /*
4735 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4736 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4737 * restoration if the host has something else. Task switching is not supported in 64-bit
4738 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4739 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4740 *
4741 * [1] See Intel spec. 3.5 "System Descriptor Types".
4742 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4743 */
4744 PVM pVM = pVCpu->CTX_SUFF(pVM);
4745 Assert(pDesc->System.u4Type == 11);
4746 if ( pDesc->System.u16LimitLow != 0x67
4747 || pDesc->System.u4LimitHigh)
4748 {
4749 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4750 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4751 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4752 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4753 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4754 }
4755
4756 /*
4757 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4758 */
4759 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4760 {
4761 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4762 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4763 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4764 {
4765 /* The GDT is read-only but the writable GDT is available. */
4766 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4767 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4768 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4769 AssertRCReturn(rc, rc);
4770 }
4771 }
4772#else
4773 uintptr_t const uTRBase = X86DESC_BASE(pDesc);
4774#endif
4775 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_TR_BASE, uTRBase);
4776 AssertRCReturn(rc, rc);
4777
4778 /*
4779 * Host FS base and GS base.
4780 */
4781#if HC_ARCH_BITS == 64
4782 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4783 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4784 rc = VMXWriteVmcs64(VMX_VMCS_HOST_FS_BASE, u64FSBase);
4785 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_GS_BASE, u64GSBase);
4786 AssertRCReturn(rc, rc);
4787
4788 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4789 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4790 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4791 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4792 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4793#endif
4794 return VINF_SUCCESS;
4795}
4796
4797
4798/**
4799 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4800 * host-state area of the VMCS.
4801 *
4802 * These MSRs will be automatically restored on the host after every successful
4803 * VM-exit.
4804 *
4805 * @returns VBox status code.
4806 * @param pVCpu The cross context virtual CPU structure.
4807 *
4808 * @remarks No-long-jump zone!!!
4809 */
4810static int hmR0VmxExportHostMsrs(PVMCPU pVCpu)
4811{
4812 AssertPtr(pVCpu);
4813
4814 /*
4815 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4816 * rather than swapping them on every VM-entry.
4817 */
4818 hmR0VmxLazySaveHostMsrs(pVCpu);
4819
4820 /*
4821 * Host Sysenter MSRs.
4822 */
4823 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS));
4824#if HC_ARCH_BITS == 32
4825 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr_Low(MSR_IA32_SYSENTER_ESP));
4826 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr_Low(MSR_IA32_SYSENTER_EIP));
4827#else
4828 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP));
4829 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP));
4830#endif
4831 AssertRCReturn(rc, rc);
4832
4833 /*
4834 * Host EFER MSR.
4835 *
4836 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4837 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4838 */
4839 PVM pVM = pVCpu->CTX_SUFF(pVM);
4840 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4841 {
4842 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4843 AssertRCReturn(rc, rc);
4844 }
4845
4846 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4847 * hmR0VmxExportGuestEntryExitCtls(). */
4848
4849 return VINF_SUCCESS;
4850}
4851
4852
4853/**
4854 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4855 *
4856 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4857 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4858 *
4859 * @returns true if we need to load guest EFER, false otherwise.
4860 * @param pVCpu The cross context virtual CPU structure.
4861 *
4862 * @remarks Requires EFER, CR4.
4863 * @remarks No-long-jump zone!!!
4864 */
4865static bool hmR0VmxShouldSwapEferMsr(PCVMCPU pVCpu)
4866{
4867#ifdef HMVMX_ALWAYS_SWAP_EFER
4868 RT_NOREF(pVCpu);
4869 return true;
4870#else
4871 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4872#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
4873 /* For 32-bit hosts running 64-bit guests, we always swap EFER MSR in the world-switcher. Nothing to do here. */
4874 if (CPUMIsGuestInLongModeEx(pCtx))
4875 return false;
4876#endif
4877
4878 PVM pVM = pVCpu->CTX_SUFF(pVM);
4879 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4880 uint64_t const u64GuestEfer = pCtx->msrEFER;
4881
4882 /*
4883 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4884 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4885 */
4886 if ( CPUMIsGuestInLongModeEx(pCtx)
4887 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4888 return true;
4889
4890 /*
4891 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4892 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4893 *
4894 * See Intel spec. 4.5 "IA-32e Paging".
4895 * See Intel spec. 4.1.1 "Three Paging Modes".
4896 *
4897 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4898 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4899 */
4900 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4901 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4902 if ( (pCtx->cr4 & X86_CR4_PAE)
4903 && (pCtx->cr0 & X86_CR0_PG)
4904 && (u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4905 {
4906 /* Assert that host is NX capable. */
4907 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4908 return true;
4909 }
4910
4911 return false;
4912#endif
4913}
4914
4915/**
4916 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4917 * VMCS.
4918 *
4919 * This is typically required when the guest changes paging mode.
4920 *
4921 * @returns VBox status code.
4922 * @param pVCpu The cross context virtual CPU structure.
4923 * @param pVmxTransient The VMX-transient structure.
4924 *
4925 * @remarks Requires EFER.
4926 * @remarks No-long-jump zone!!!
4927 */
4928static int hmR0VmxExportGuestEntryExitCtls(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4929{
4930 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4931 {
4932 PVM pVM = pVCpu->CTX_SUFF(pVM);
4933 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4934
4935 /*
4936 * VM-entry controls.
4937 */
4938 {
4939 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4940 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4941
4942 /*
4943 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4944 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4945 *
4946 * For nested-guests, this is a mandatory VM-entry control. It's also
4947 * required because we do not want to leak host bits to the nested-guest.
4948 */
4949 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4950
4951 /*
4952 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4953 *
4954 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4955 * required to get the nested-guest working with hardware-assisted VMX execution.
4956 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a guest hypervisor
4957 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4958 * here rather than while merging the guest VMCS controls.
4959 */
4960 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
4961 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4962 else
4963 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4964
4965 /*
4966 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4967 *
4968 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4969 * regardless of whether the nested-guest VMCS specifies it because we are free to
4970 * load whatever MSRs we require and we do not need to modify the guest visible copy
4971 * of the VM-entry MSR load area.
4972 */
4973 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4974 && hmR0VmxShouldSwapEferMsr(pVCpu))
4975 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4976 else
4977 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4978
4979 /*
4980 * The following should -not- be set (since we're not in SMM mode):
4981 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4982 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4983 */
4984
4985 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4986 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4987
4988 if ((fVal & fZap) == fVal)
4989 { /* likely */ }
4990 else
4991 {
4992 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4993 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4994 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4995 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4996 }
4997
4998 /* Commit it to the VMCS. */
4999 if (pVmcsInfo->u32EntryCtls != fVal)
5000 {
5001 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
5002 AssertRCReturn(rc, rc);
5003 pVmcsInfo->u32EntryCtls = fVal;
5004 }
5005 }
5006
5007 /*
5008 * VM-exit controls.
5009 */
5010 {
5011 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5012 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5013
5014 /*
5015 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
5016 * supported the 1-setting of this bit.
5017 *
5018 * For nested-guests, we set the "save debug controls" as the converse
5019 * "load debug controls" is mandatory for nested-guests anyway.
5020 */
5021 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
5022
5023 /*
5024 * Set the host long mode active (EFER.LMA) bit (which Intel calls
5025 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
5026 * host EFER.LMA and EFER.LME bit to this value. See assertion in
5027 * hmR0VmxExportHostMsrs().
5028 *
5029 * For nested-guests, we always set this bit as we do not support 32-bit
5030 * hosts.
5031 */
5032#if HC_ARCH_BITS == 64
5033 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5034#else
5035 Assert(!pVmxTransient->fIsNestedGuest);
5036 Assert( pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64
5037 || pVmcsInfo->pfnStartVM == VMXR0StartVM32);
5038 /* Set the host address-space size based on the switcher, not guest state. See @bugref{8432}. */
5039 if (pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64)
5040 {
5041 /* The switcher returns to long mode, the EFER MSR is managed by the switcher. */
5042 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5043 }
5044 else
5045 Assert(!(fVal & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE));
5046#endif
5047
5048 /*
5049 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
5050 *
5051 * For nested-guests, we should use the "save IA32_EFER" control if we also
5052 * used the "load IA32_EFER" control while exporting VM-entry controls.
5053 */
5054 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
5055 && hmR0VmxShouldSwapEferMsr(pVCpu))
5056 {
5057 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
5058 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
5059 }
5060
5061 /*
5062 * Enable saving of the VMX-preemption timer value on VM-exit.
5063 * For nested-guests, currently not exposed/used.
5064 */
5065 if ( pVM->hm.s.vmx.fUsePreemptTimer
5066 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
5067 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
5068
5069 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
5070 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
5071
5072 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5073 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5074 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5075
5076 if ((fVal & fZap) == fVal)
5077 { /* likely */ }
5078 else
5079 {
5080 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5081 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
5082 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5083 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5084 }
5085
5086 /* Commit it to the VMCS. */
5087 if (pVmcsInfo->u32ExitCtls != fVal)
5088 {
5089 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5090 AssertRCReturn(rc, rc);
5091 pVmcsInfo->u32ExitCtls = fVal;
5092 }
5093 }
5094
5095 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5096 }
5097 return VINF_SUCCESS;
5098}
5099
5100
5101/**
5102 * Sets the TPR threshold in the VMCS.
5103 *
5104 * @returns VBox status code.
5105 * @param pVCpu The cross context virtual CPU structure.
5106 * @param pVmcsInfo The VMCS info. object.
5107 * @param u32TprThreshold The TPR threshold (task-priority class only).
5108 */
5109DECLINLINE(int) hmR0VmxApicSetTprThreshold(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5110{
5111 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5112 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5113 RT_NOREF2(pVCpu, pVmcsInfo);
5114 return VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5115}
5116
5117
5118/**
5119 * Exports the guest APIC TPR state into the VMCS.
5120 *
5121 * @returns VBox status code.
5122 * @param pVCpu The cross context virtual CPU structure.
5123 * @param pVmxTransient The VMX-transient structure.
5124 *
5125 * @remarks No-long-jump zone!!!
5126 */
5127static int hmR0VmxExportGuestApicTpr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5128{
5129 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5130 {
5131 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5132
5133 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5134 if (!pVmxTransient->fIsNestedGuest)
5135 {
5136 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5137 && APICIsEnabled(pVCpu))
5138 {
5139 /*
5140 * Setup TPR shadowing.
5141 */
5142 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5143 {
5144 bool fPendingIntr = false;
5145 uint8_t u8Tpr = 0;
5146 uint8_t u8PendingIntr = 0;
5147 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5148 AssertRCReturn(rc, rc);
5149
5150 /*
5151 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5152 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5153 * priority of the pending interrupt so we can deliver the interrupt. If there
5154 * are no interrupts pending, set threshold to 0 to not cause any
5155 * TPR-below-threshold VM-exits.
5156 */
5157 Assert(pVmcsInfo->pbVirtApic);
5158 pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR] = u8Tpr;
5159 uint32_t u32TprThreshold = 0;
5160 if (fPendingIntr)
5161 {
5162 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5163 (which is the Task-Priority Class). */
5164 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5165 const uint8_t u8TprPriority = u8Tpr >> 4;
5166 if (u8PendingPriority <= u8TprPriority)
5167 u32TprThreshold = u8PendingPriority;
5168 }
5169
5170 rc = hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u32TprThreshold);
5171 AssertRCReturn(rc, rc);
5172 }
5173 }
5174 }
5175 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5176 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5177 }
5178 return VINF_SUCCESS;
5179}
5180
5181
5182/**
5183 * Gets the guest interruptibility-state.
5184 *
5185 * @returns Guest's interruptibility-state.
5186 * @param pVCpu The cross context virtual CPU structure.
5187 * @param pVmxTransient The VMX-transient structure.
5188 *
5189 * @remarks No-long-jump zone!!!
5190 */
5191static uint32_t hmR0VmxGetGuestIntrState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5192{
5193 /*
5194 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5195 */
5196 uint32_t fIntrState = 0;
5197 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5198 {
5199 /* If inhibition is active, RIP and RFLAGS should've been updated
5200 (i.e. read previously from the VMCS or from ring-3). */
5201 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5202#ifdef VBOX_STRICT
5203 uint64_t const fExtrn = ASMAtomicUoReadU64(&pCtx->fExtrn);
5204 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
5205 AssertMsg(!(fExtrn & (CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS)), ("%#x\n", fExtrn));
5206#endif
5207 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5208 {
5209 if (pCtx->eflags.Bits.u1IF)
5210 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5211 else
5212 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5213 }
5214 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5215 {
5216 /*
5217 * We can clear the inhibit force flag as even if we go back to the recompiler
5218 * without executing guest code in VT-x, the flag's condition to be cleared is
5219 * met and thus the cleared state is correct.
5220 */
5221 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5222 }
5223 }
5224
5225 /*
5226 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
5227 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
5228 * setting this would block host-NMIs and IRET will not clear the blocking.
5229 *
5230 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
5231 *
5232 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
5233 */
5234 if ( hmR0VmxIsPinCtlsSet(pVCpu, pVmxTransient, VMX_PIN_CTLS_VIRT_NMI)
5235 && CPUMIsGuestNmiBlocking(pVCpu))
5236 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5237
5238 return fIntrState;
5239}
5240
5241
5242/**
5243 * Exports the exception intercepts required for guest execution in the VMCS.
5244 *
5245 * @returns VBox status code.
5246 * @param pVCpu The cross context virtual CPU structure.
5247 * @param pVmxTransient The VMX-transient structure.
5248 *
5249 * @remarks No-long-jump zone!!!
5250 */
5251static int hmR0VmxExportGuestXcptIntercepts(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5252{
5253 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5254 {
5255 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5256 if ( !pVmxTransient->fIsNestedGuest
5257 && pVCpu->hm.s.fGIMTrapXcptUD)
5258 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5259 else
5260 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5261
5262 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5263 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5264 }
5265 return VINF_SUCCESS;
5266}
5267
5268
5269/**
5270 * Exports the guest's RIP into the guest-state area in the VMCS.
5271 *
5272 * @returns VBox status code.
5273 * @param pVCpu The cross context virtual CPU structure.
5274 *
5275 * @remarks No-long-jump zone!!!
5276 */
5277static int hmR0VmxExportGuestRip(PVMCPU pVCpu)
5278{
5279 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5280 {
5281 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5282
5283 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5284 AssertRCReturn(rc, rc);
5285
5286 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5287 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5288 }
5289 return VINF_SUCCESS;
5290}
5291
5292
5293/**
5294 * Exports the guest's RSP into the guest-state area in the VMCS.
5295 *
5296 * @returns VBox status code.
5297 * @param pVCpu The cross context virtual CPU structure.
5298 *
5299 * @remarks No-long-jump zone!!!
5300 */
5301static int hmR0VmxExportGuestRsp(PVMCPU pVCpu)
5302{
5303 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5304 {
5305 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5306
5307 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5308 AssertRCReturn(rc, rc);
5309
5310 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5311 }
5312 return VINF_SUCCESS;
5313}
5314
5315
5316/**
5317 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5318 *
5319 * @returns VBox status code.
5320 * @param pVCpu The cross context virtual CPU structure.
5321 * @param pVmxTransient The VMX-transient structure.
5322 *
5323 * @remarks No-long-jump zone!!!
5324 */
5325static int hmR0VmxExportGuestRflags(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5326{
5327 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5328 {
5329 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5330
5331 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5332 Let us assert it as such and use 32-bit VMWRITE. */
5333 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5334 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5335 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5336 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5337
5338 /*
5339 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5340 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5341 * can run the real-mode guest code under Virtual 8086 mode.
5342 */
5343 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5344 if (pVmcsInfo->RealMode.fRealOnV86Active)
5345 {
5346 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5347 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5348 Assert(!pVmxTransient->fIsNestedGuest);
5349 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5350 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5351 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5352 }
5353
5354 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5355 AssertRCReturn(rc, rc);
5356
5357 /*
5358 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
5359 *
5360 * We must avoid setting any automatic debug exceptions delivery when single-stepping
5361 * through the hypervisor debugger using EFLAGS.TF.
5362 */
5363 if ( !pVmxTransient->fIsNestedGuest
5364 && !pVCpu->hm.s.fSingleInstruction
5365 && fEFlags.Bits.u1TF)
5366 {
5367 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
5368 * premature trips to ring-3 esp since IEM does not yet handle it. */
5369 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
5370 AssertRCReturn(rc, rc);
5371 }
5372 /** @todo NSTVMX: Handling copying of VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS from
5373 * nested-guest VMCS. */
5374
5375 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5376 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5377 }
5378 return VINF_SUCCESS;
5379}
5380
5381
5382#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5383/**
5384 * Copies the nested-guest VMCS to the shadow VMCS.
5385 *
5386 * @returns VBox status code.
5387 * @param pVCpu The cross context virtual CPU structure.
5388 * @param pVmcsInfo The VMCS info. object.
5389 *
5390 * @remarks No-long-jump zone!!!
5391 */
5392static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5393{
5394 PVM pVM = pVCpu->CTX_SUFF(pVM);
5395 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5396
5397 /*
5398 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5399 * current VMCS, as we may try saving guest lazy MSRs.
5400 *
5401 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5402 * calling the import VMCS code which is currently performing the guest MSR reads
5403 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5404 * and the rest of the VMX leave session machinery.
5405 */
5406 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5407
5408 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5409 if (RT_SUCCESS(rc))
5410 {
5411 /*
5412 * Copy all guest read/write VMCS fields.
5413 *
5414 * We don't check for VMWRITE failures here for performance reasons and
5415 * because they are not expected to fail, barring irrecoverable conditions
5416 * like hardware errors.
5417 */
5418 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5419 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5420 {
5421 uint64_t u64Val;
5422 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5423 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5424 VMXWriteVmcs64(uVmcsField, u64Val);
5425 }
5426
5427 /*
5428 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5429 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5430 */
5431 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5432 {
5433 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5434 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5435 {
5436 uint64_t u64Val;
5437 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5438 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5439 VMXWriteVmcs64(uVmcsField, u64Val);
5440 }
5441 }
5442
5443 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5444 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5445 }
5446
5447 ASMSetFlags(fEFlags);
5448 return rc;
5449}
5450
5451
5452/**
5453 * Copies the shadow VMCS to the nested-guest VMCS.
5454 *
5455 * @returns VBox status code.
5456 * @param pVCpu The cross context virtual CPU structure.
5457 * @param pVmcsInfo The VMCS info. object.
5458 *
5459 * @remarks Called with interrupts disabled.
5460 */
5461static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5462{
5463 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5464 PVM pVM = pVCpu->CTX_SUFF(pVM);
5465 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5466
5467 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5468 if (RT_SUCCESS(rc))
5469 {
5470 /*
5471 * Copy guest read/write fields from the shadow VMCS.
5472 * Guest read-only fields cannot be modified, so no need to copy them.
5473 *
5474 * We don't check for VMREAD failures here for performance reasons and
5475 * because they are not expected to fail, barring irrecoverable conditions
5476 * like hardware errors.
5477 */
5478 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5479 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5480 {
5481 uint64_t u64Val;
5482 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5483 VMXReadVmcs64(uVmcsField, &u64Val);
5484 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5485 }
5486
5487 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5488 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5489 }
5490 return rc;
5491}
5492
5493
5494/**
5495 * Enables VMCS shadowing for the given VMCS info. object.
5496 *
5497 * @param pVCpu The cross context virtual CPU structure.
5498 * @param pVmcsInfo The VMCS info. object.
5499 *
5500 * @remarks No-long-jump zone!!!
5501 */
5502static void hmR0VmxEnableVmcsShadowing(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5503{
5504 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
5505
5506 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5507 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5508 {
5509 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5510 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5511 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2);
5512 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs);
5513 AssertRC(rc);
5514
5515 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5516 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5517 Log4Func(("Enabled\n"));
5518 }
5519}
5520
5521
5522/**
5523 * Disables VMCS shadowing for the given VMCS info. object.
5524 *
5525 * @param pVCpu The cross context virtual CPU structure.
5526 * @param pVmcsInfo The VMCS info. object.
5527 *
5528 * @remarks No-long-jump zone!!!
5529 */
5530static void hmR0VmxDisableVmcsShadowing(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5531{
5532 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
5533
5534 /*
5535 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5536 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5537 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5538 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5539 *
5540 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5541 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5542 */
5543 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5544 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5545 {
5546 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5547 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2);
5548 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
5549 AssertRC(rc);
5550
5551 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5552 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5553 Log4Func(("Disabled\n"));
5554 }
5555}
5556#endif
5557
5558
5559/**
5560 * Exports the guest hardware-virtualization state.
5561 *
5562 * @returns VBox status code.
5563 * @param pVCpu The cross context virtual CPU structure.
5564 * @param pVmxTransient The VMX-transient structure.
5565 *
5566 * @remarks No-long-jump zone!!!
5567 */
5568static int hmR0VmxExportGuestHwvirtState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5569{
5570 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5571 {
5572#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5573 /*
5574 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5575 * VMCS shadowing.
5576 */
5577 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5578 {
5579 /*
5580 * If the guest hypervisor has loaded a current VMCS and is in VMX root mode,
5581 * copy the guest hypervisor's current VMCS into the shadow VMCS and enable
5582 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5583 *
5584 * We check for VMX root mode here in case the guest executes VMXOFF without
5585 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5586 * not clear the current VMCS pointer.
5587 */
5588 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5589 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5590 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5591 && CPUMIsGuestVmxCurrentVmcsValid(pVCpu, &pVCpu->cpum.GstCtx))
5592 {
5593 /* Paranoia. */
5594 Assert(!pVmxTransient->fIsNestedGuest);
5595
5596 /*
5597 * For performance reasons, also check if the guest hypervisor's current VMCS
5598 * was newly loaded or modified before copying it to the shadow VMCS.
5599 */
5600 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5601 {
5602 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5603 AssertRCReturn(rc, rc);
5604 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5605 }
5606 hmR0VmxEnableVmcsShadowing(pVCpu, pVmcsInfo);
5607 }
5608 else
5609 hmR0VmxDisableVmcsShadowing(pVCpu, pVmcsInfo);
5610 }
5611#else
5612 NOREF(pVmxTransient);
5613#endif
5614 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5615 }
5616 return VINF_SUCCESS;
5617}
5618
5619
5620/**
5621 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5622 *
5623 * The guest FPU state is always pre-loaded hence we don't need to bother about
5624 * sharing FPU related CR0 bits between the guest and host.
5625 *
5626 * @returns VBox status code.
5627 * @param pVCpu The cross context virtual CPU structure.
5628 * @param pVmxTransient The VMX-transient structure.
5629 *
5630 * @remarks No-long-jump zone!!!
5631 */
5632static int hmR0VmxExportGuestCR0(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5633{
5634 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5635 {
5636 PVM pVM = pVCpu->CTX_SUFF(pVM);
5637 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5638
5639 /*
5640 * Figure out fixed CR0 bits in VMX operation.
5641 */
5642 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5643 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5644 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5645 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5646 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5647 else
5648 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5649
5650 if (!pVmxTransient->fIsNestedGuest)
5651 {
5652 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5653 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5654 uint64_t const u64ShadowCr0 = u64GuestCr0;
5655 Assert(!RT_HI_U32(u64GuestCr0));
5656
5657 /*
5658 * Setup VT-x's view of the guest CR0.
5659 */
5660 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5661 if (pVM->hm.s.fNestedPaging)
5662 {
5663 if (CPUMIsGuestPagingEnabled(pVCpu))
5664 {
5665 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5666 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5667 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5668 }
5669 else
5670 {
5671 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5672 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5673 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5674 }
5675
5676 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5677 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5678 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5679 }
5680 else
5681 {
5682 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5683 u64GuestCr0 |= X86_CR0_WP;
5684 }
5685
5686 /*
5687 * Guest FPU bits.
5688 *
5689 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5690 * using CR0.TS.
5691 *
5692 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5693 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5694 */
5695 u64GuestCr0 |= X86_CR0_NE;
5696
5697 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5698 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5699
5700 /*
5701 * Update exception intercepts.
5702 */
5703 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5704 if (pVmcsInfo->RealMode.fRealOnV86Active)
5705 {
5706 Assert(PDMVmmDevHeapIsEnabled(pVM));
5707 Assert(pVM->hm.s.vmx.pRealModeTSS);
5708 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5709 }
5710 else
5711 {
5712 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5713 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5714 if (fInterceptMF)
5715 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5716 }
5717
5718 /* Additional intercepts for debugging, define these yourself explicitly. */
5719#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5720 uXcptBitmap |= 0
5721 | RT_BIT(X86_XCPT_BP)
5722 | RT_BIT(X86_XCPT_DE)
5723 | RT_BIT(X86_XCPT_NM)
5724 | RT_BIT(X86_XCPT_TS)
5725 | RT_BIT(X86_XCPT_UD)
5726 | RT_BIT(X86_XCPT_NP)
5727 | RT_BIT(X86_XCPT_SS)
5728 | RT_BIT(X86_XCPT_GP)
5729 | RT_BIT(X86_XCPT_PF)
5730 | RT_BIT(X86_XCPT_MF)
5731 ;
5732#elif defined(HMVMX_ALWAYS_TRAP_PF)
5733 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5734#endif
5735 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5736 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5737 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5738
5739 /* Apply the hardware specified fixed CR0 bits and enable caching. */
5740 u64GuestCr0 |= fSetCr0;
5741 u64GuestCr0 &= fZapCr0;
5742 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5743
5744 /* Commit the CR0 and related fields to the guest VMCS. */
5745 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0); /** @todo Fix to 64-bit when we drop 32-bit. */
5746 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
5747 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5748 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5749 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5750 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5751 AssertRCReturn(rc, rc);
5752
5753 /* Update our caches. */
5754 pVmcsInfo->u32ProcCtls = uProcCtls;
5755 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5756
5757 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5758 }
5759 else
5760 {
5761 /*
5762 * With nested-guests, we may have extended the guest/host mask here since we
5763 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5764 * (to read from the nested-guest CR0 read-shadow) than the guest hypervisor
5765 * originally supplied. We must copy those bits from the nested-guest CR0 into
5766 * the nested-guest CR0 read-shadow.
5767 */
5768 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5769 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5770 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(pVCpu, &pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5771 Assert(!RT_HI_U32(u64GuestCr0));
5772 Assert(u64GuestCr0 & X86_CR0_NE);
5773
5774 /*
5775 * Apply the hardware specified fixed CR0 bits and enable caching.
5776 * Note! We could be altering our VMX emulation's fixed bits. We thus
5777 * need to re-apply them while importing CR0.
5778 */
5779 u64GuestCr0 |= fSetCr0;
5780 u64GuestCr0 &= fZapCr0;
5781 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5782
5783 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5784 /** @todo NSTVMX: Fix to 64-bit when we drop 32-bit. */
5785 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0);
5786 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
5787 AssertRCReturn(rc, rc);
5788
5789 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5790 }
5791
5792 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5793 }
5794
5795 return VINF_SUCCESS;
5796}
5797
5798
5799/**
5800 * Exports the guest control registers (CR3, CR4) into the guest-state area
5801 * in the VMCS.
5802 *
5803 * @returns VBox strict status code.
5804 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5805 * without unrestricted guest access and the VMMDev is not presently
5806 * mapped (e.g. EFI32).
5807 *
5808 * @param pVCpu The cross context virtual CPU structure.
5809 * @param pVmxTransient The VMX-transient structure.
5810 *
5811 * @remarks No-long-jump zone!!!
5812 */
5813static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5814{
5815 int rc = VINF_SUCCESS;
5816 PVM pVM = pVCpu->CTX_SUFF(pVM);
5817
5818 /*
5819 * Guest CR2.
5820 * It's always loaded in the assembler code. Nothing to do here.
5821 */
5822
5823 /*
5824 * Guest CR3.
5825 */
5826 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5827 {
5828 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5829
5830 RTGCPHYS GCPhysGuestCr3 = NIL_RTGCPHYS;
5831 if (pVM->hm.s.fNestedPaging)
5832 {
5833 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5834 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5835
5836 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5837 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5838 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5839 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5840
5841 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5842 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5843 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5844
5845 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5846 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5847 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5848 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5849 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5850 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5851 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5852
5853 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5854 AssertRCReturn(rc, rc);
5855
5856 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5857 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5858 || CPUMIsGuestPagingEnabledEx(pCtx))
5859 {
5860 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5861 if (CPUMIsGuestInPAEModeEx(pCtx))
5862 {
5863 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5864 AssertRCReturn(rc, rc);
5865 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u);
5866 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u);
5867 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u);
5868 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u);
5869 AssertRCReturn(rc, rc);
5870 }
5871
5872 /*
5873 * The guest's view of its CR3 is unblemished with nested paging when the
5874 * guest is using paging or we have unrestricted guest execution to handle
5875 * the guest when it's not using paging.
5876 */
5877 GCPhysGuestCr3 = pCtx->cr3;
5878 }
5879 else
5880 {
5881 /*
5882 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5883 * thinks it accesses physical memory directly, we use our identity-mapped
5884 * page table to map guest-linear to guest-physical addresses. EPT takes care
5885 * of translating it to host-physical addresses.
5886 */
5887 RTGCPHYS GCPhys;
5888 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5889
5890 /* We obtain it here every time as the guest could have relocated this PCI region. */
5891 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5892 if (RT_SUCCESS(rc))
5893 { /* likely */ }
5894 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5895 {
5896 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5897 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5898 }
5899 else
5900 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5901
5902 GCPhysGuestCr3 = GCPhys;
5903 }
5904
5905 Log4Func(("u32GuestCr3=%#RGp (GstN)\n", GCPhysGuestCr3));
5906 rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_CR3, GCPhysGuestCr3);
5907 AssertRCReturn(rc, rc);
5908 }
5909 else
5910 {
5911 /* Non-nested paging case, just use the hypervisor's CR3. */
5912 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5913
5914 Log4Func(("u32GuestCr3=%#RHv (HstN)\n", HCPhysGuestCr3));
5915 rc = VMXWriteVmcsHstN(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5916 AssertRCReturn(rc, rc);
5917 }
5918
5919 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5920 }
5921
5922 /*
5923 * Guest CR4.
5924 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5925 */
5926 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5927 {
5928 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5929 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5930
5931 /*
5932 * Figure out fixed CR4 bits in VMX operation.
5933 */
5934 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5935 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5936 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5937
5938 /*
5939 * With nested-guests, we may have extended the guest/host mask here (since we
5940 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5941 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5942 * the guest hypervisor originally supplied. Thus, we should, in essence, copy
5943 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5944 */
5945 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5946 uint64_t u64GuestCr4 = pCtx->cr4;
5947 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5948 ? pCtx->cr4
5949 : CPUMGetGuestVmxMaskedCr4(pVCpu, pCtx, pVmcsInfo->u64Cr4Mask);
5950 Assert(!RT_HI_U32(u64GuestCr4));
5951
5952 /*
5953 * Setup VT-x's view of the guest CR4.
5954 *
5955 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5956 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5957 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5958 *
5959 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5960 */
5961 if (pVmcsInfo->RealMode.fRealOnV86Active)
5962 {
5963 Assert(pVM->hm.s.vmx.pRealModeTSS);
5964 Assert(PDMVmmDevHeapIsEnabled(pVM));
5965 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5966 }
5967
5968 if (pVM->hm.s.fNestedPaging)
5969 {
5970 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5971 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5972 {
5973 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5974 u64GuestCr4 |= X86_CR4_PSE;
5975 /* Our identity mapping is a 32-bit page directory. */
5976 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5977 }
5978 /* else use guest CR4.*/
5979 }
5980 else
5981 {
5982 Assert(!pVmxTransient->fIsNestedGuest);
5983
5984 /*
5985 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5986 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5987 */
5988 switch (pVCpu->hm.s.enmShadowMode)
5989 {
5990 case PGMMODE_REAL: /* Real-mode. */
5991 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5992 case PGMMODE_32_BIT: /* 32-bit paging. */
5993 {
5994 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5995 break;
5996 }
5997
5998 case PGMMODE_PAE: /* PAE paging. */
5999 case PGMMODE_PAE_NX: /* PAE paging with NX. */
6000 {
6001 u64GuestCr4 |= X86_CR4_PAE;
6002 break;
6003 }
6004
6005 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
6006 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
6007#ifdef VBOX_ENABLE_64_BITS_GUESTS
6008 break;
6009#endif
6010 default:
6011 AssertFailed();
6012 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6013 }
6014 }
6015
6016 /*
6017 * Apply the hardware specified fixed CR4 bits (mainly CR4.VMXE).
6018 * Note! For nested-guests, we could be altering our VMX emulation's
6019 * fixed bits. We thus need to re-apply them while importing CR4.
6020 */
6021 u64GuestCr4 |= fSetCr4;
6022 u64GuestCr4 &= fZapCr4;
6023
6024 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
6025 /** @todo Fix to 64-bit when we drop 32-bit. */
6026 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR4, u64GuestCr4);
6027 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4);
6028 AssertRCReturn(rc, rc);
6029
6030 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
6031 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
6032
6033 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
6034
6035 Log4Func(("cr4=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
6036 }
6037 return rc;
6038}
6039
6040
6041/**
6042 * Exports the guest debug registers into the guest-state area in the VMCS.
6043 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
6044 *
6045 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
6046 *
6047 * @returns VBox status code.
6048 * @param pVCpu The cross context virtual CPU structure.
6049 * @param pVmxTransient The VMX-transient structure.
6050 *
6051 * @remarks No-long-jump zone!!!
6052 */
6053static int hmR0VmxExportSharedDebugState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6054{
6055 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
6056
6057 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
6058 * stepping. */
6059 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6060 if (pVmxTransient->fIsNestedGuest)
6061 {
6062 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
6063 AssertRCReturn(rc, rc);
6064 return VINF_SUCCESS;
6065 }
6066
6067#ifdef VBOX_STRICT
6068 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
6069 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
6070 {
6071 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
6072 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
6073 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
6074 }
6075#endif
6076
6077 bool fSteppingDB = false;
6078 bool fInterceptMovDRx = false;
6079 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6080 if (pVCpu->hm.s.fSingleInstruction)
6081 {
6082 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
6083 PVM pVM = pVCpu->CTX_SUFF(pVM);
6084 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
6085 {
6086 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
6087 Assert(fSteppingDB == false);
6088 }
6089 else
6090 {
6091 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
6092 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
6093 pVCpu->hm.s.fClearTrapFlag = true;
6094 fSteppingDB = true;
6095 }
6096 }
6097
6098 uint32_t u32GuestDr7;
6099 if ( fSteppingDB
6100 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
6101 {
6102 /*
6103 * Use the combined guest and host DRx values found in the hypervisor register set
6104 * because the hypervisor debugger has breakpoints active or someone is single stepping
6105 * on the host side without a monitor trap flag.
6106 *
6107 * Note! DBGF expects a clean DR6 state before executing guest code.
6108 */
6109#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6110 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6111 && !CPUMIsHyperDebugStateActivePending(pVCpu))
6112 {
6113 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6114 Assert(CPUMIsHyperDebugStateActivePending(pVCpu));
6115 Assert(!CPUMIsGuestDebugStateActivePending(pVCpu));
6116 }
6117 else
6118#endif
6119 if (!CPUMIsHyperDebugStateActive(pVCpu))
6120 {
6121 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6122 Assert(CPUMIsHyperDebugStateActive(pVCpu));
6123 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
6124 }
6125
6126 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6127 u32GuestDr7 = (uint32_t)CPUMGetHyperDR7(pVCpu);
6128 pVCpu->hm.s.fUsingHyperDR7 = true;
6129 fInterceptMovDRx = true;
6130 }
6131 else
6132 {
6133 /*
6134 * If the guest has enabled debug registers, we need to load them prior to
6135 * executing guest code so they'll trigger at the right time.
6136 */
6137 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6138 {
6139#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6140 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6141 && !CPUMIsGuestDebugStateActivePending(pVCpu))
6142 {
6143 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6144 Assert(CPUMIsGuestDebugStateActivePending(pVCpu));
6145 Assert(!CPUMIsHyperDebugStateActivePending(pVCpu));
6146 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6147 }
6148 else
6149#endif
6150 if (!CPUMIsGuestDebugStateActive(pVCpu))
6151 {
6152 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6153 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6154 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6155 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6156 }
6157 Assert(!fInterceptMovDRx);
6158 }
6159 /*
6160 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6161 * must intercept #DB in order to maintain a correct DR6 guest value, and
6162 * because we need to intercept it to prevent nested #DBs from hanging the
6163 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6164 */
6165#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6166 else if ( !CPUMIsGuestDebugStateActivePending(pVCpu)
6167 && !CPUMIsGuestDebugStateActive(pVCpu))
6168#else
6169 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6170#endif
6171 {
6172 fInterceptMovDRx = true;
6173 }
6174
6175 /* Update DR7 with the actual guest value. */
6176 u32GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6177 pVCpu->hm.s.fUsingHyperDR7 = false;
6178 }
6179
6180 if (fInterceptMovDRx)
6181 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6182 else
6183 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6184
6185 /*
6186 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6187 * monitor-trap flag and update our cache.
6188 */
6189 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6190 {
6191 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6192 AssertRCReturn(rc2, rc2);
6193 pVmcsInfo->u32ProcCtls = uProcCtls;
6194 }
6195
6196 /*
6197 * Update guest DR7.
6198 */
6199 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, u32GuestDr7);
6200 AssertRCReturn(rc, rc);
6201
6202 /*
6203 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6204 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6205 *
6206 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6207 */
6208 if (fSteppingDB)
6209 {
6210 Assert(pVCpu->hm.s.fSingleInstruction);
6211 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6212
6213 uint32_t fIntrState = 0;
6214 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6215 AssertRCReturn(rc, rc);
6216
6217 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6218 {
6219 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6220 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6221 AssertRCReturn(rc, rc);
6222 }
6223 }
6224
6225 return VINF_SUCCESS;
6226}
6227
6228
6229#ifdef VBOX_STRICT
6230/**
6231 * Strict function to validate segment registers.
6232 *
6233 * @param pVCpu The cross context virtual CPU structure.
6234 * @param pVmcsInfo The VMCS info. object.
6235 *
6236 * @remarks Will import guest CR0 on strict builds during validation of
6237 * segments.
6238 */
6239static void hmR0VmxValidateSegmentRegs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
6240{
6241 /*
6242 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6243 *
6244 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6245 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6246 * unusable bit and doesn't change the guest-context value.
6247 */
6248 PVM pVM = pVCpu->CTX_SUFF(pVM);
6249 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6250 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6251 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
6252 && ( !CPUMIsGuestInRealModeEx(pCtx)
6253 && !CPUMIsGuestInV86ModeEx(pCtx)))
6254 {
6255 /* Protected mode checks */
6256 /* CS */
6257 Assert(pCtx->cs.Attr.n.u1Present);
6258 Assert(!(pCtx->cs.Attr.u & 0xf00));
6259 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6260 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6261 || !(pCtx->cs.Attr.n.u1Granularity));
6262 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6263 || (pCtx->cs.Attr.n.u1Granularity));
6264 /* CS cannot be loaded with NULL in protected mode. */
6265 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6266 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6267 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6268 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6269 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6270 else
6271 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6272 /* SS */
6273 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6274 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6275 if ( !(pCtx->cr0 & X86_CR0_PE)
6276 || pCtx->cs.Attr.n.u4Type == 3)
6277 {
6278 Assert(!pCtx->ss.Attr.n.u2Dpl);
6279 }
6280 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6281 {
6282 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6283 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6284 Assert(pCtx->ss.Attr.n.u1Present);
6285 Assert(!(pCtx->ss.Attr.u & 0xf00));
6286 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6287 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6288 || !(pCtx->ss.Attr.n.u1Granularity));
6289 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6290 || (pCtx->ss.Attr.n.u1Granularity));
6291 }
6292 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6293 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6294 {
6295 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6296 Assert(pCtx->ds.Attr.n.u1Present);
6297 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6298 Assert(!(pCtx->ds.Attr.u & 0xf00));
6299 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6300 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6301 || !(pCtx->ds.Attr.n.u1Granularity));
6302 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6303 || (pCtx->ds.Attr.n.u1Granularity));
6304 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6305 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6306 }
6307 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6308 {
6309 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6310 Assert(pCtx->es.Attr.n.u1Present);
6311 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6312 Assert(!(pCtx->es.Attr.u & 0xf00));
6313 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6314 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6315 || !(pCtx->es.Attr.n.u1Granularity));
6316 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6317 || (pCtx->es.Attr.n.u1Granularity));
6318 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6319 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6320 }
6321 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6322 {
6323 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6324 Assert(pCtx->fs.Attr.n.u1Present);
6325 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6326 Assert(!(pCtx->fs.Attr.u & 0xf00));
6327 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6328 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6329 || !(pCtx->fs.Attr.n.u1Granularity));
6330 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6331 || (pCtx->fs.Attr.n.u1Granularity));
6332 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6333 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6334 }
6335 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6336 {
6337 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6338 Assert(pCtx->gs.Attr.n.u1Present);
6339 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6340 Assert(!(pCtx->gs.Attr.u & 0xf00));
6341 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6342 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6343 || !(pCtx->gs.Attr.n.u1Granularity));
6344 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6345 || (pCtx->gs.Attr.n.u1Granularity));
6346 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6347 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6348 }
6349 /* 64-bit capable CPUs. */
6350# if HC_ARCH_BITS == 64
6351 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6352 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6353 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6354 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6355# endif
6356 }
6357 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6358 || ( CPUMIsGuestInRealModeEx(pCtx)
6359 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6360 {
6361 /* Real and v86 mode checks. */
6362 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6363 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6364 if (pVmcsInfo->RealMode.fRealOnV86Active)
6365 {
6366 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6367 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6368 }
6369 else
6370 {
6371 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6372 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6373 }
6374
6375 /* CS */
6376 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6377 Assert(pCtx->cs.u32Limit == 0xffff);
6378 Assert(u32CSAttr == 0xf3);
6379 /* SS */
6380 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6381 Assert(pCtx->ss.u32Limit == 0xffff);
6382 Assert(u32SSAttr == 0xf3);
6383 /* DS */
6384 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6385 Assert(pCtx->ds.u32Limit == 0xffff);
6386 Assert(u32DSAttr == 0xf3);
6387 /* ES */
6388 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6389 Assert(pCtx->es.u32Limit == 0xffff);
6390 Assert(u32ESAttr == 0xf3);
6391 /* FS */
6392 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6393 Assert(pCtx->fs.u32Limit == 0xffff);
6394 Assert(u32FSAttr == 0xf3);
6395 /* GS */
6396 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6397 Assert(pCtx->gs.u32Limit == 0xffff);
6398 Assert(u32GSAttr == 0xf3);
6399 /* 64-bit capable CPUs. */
6400# if HC_ARCH_BITS == 64
6401 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6402 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6403 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6404 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6405# endif
6406 }
6407}
6408#endif /* VBOX_STRICT */
6409
6410
6411/**
6412 * Exports a guest segment register into the guest-state area in the VMCS.
6413 *
6414 * @returns VBox status code.
6415 * @param pVCpu The cross context virtual CPU structure.
6416 * @param pVmcsInfo The VMCS info. object.
6417 * @param iSegReg The segment register number (X86_SREG_XXX).
6418 * @param pSelReg Pointer to the segment selector.
6419 *
6420 * @remarks No-long-jump zone!!!
6421 */
6422static int hmR0VmxExportGuestSegReg(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6423{
6424 Assert(iSegReg < X86_SREG_COUNT);
6425 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6426 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6427 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6428 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6429
6430 uint32_t u32Access = pSelReg->Attr.u;
6431 if (pVmcsInfo->RealMode.fRealOnV86Active)
6432 {
6433 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6434 u32Access = 0xf3;
6435 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6436 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6437 RT_NOREF_PV(pVCpu);
6438 }
6439 else
6440 {
6441 /*
6442 * The way to differentiate between whether this is really a null selector or was just
6443 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6444 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6445 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6446 * NULL selectors loaded in protected-mode have their attribute as 0.
6447 */
6448 if (!u32Access)
6449 u32Access = X86DESCATTR_UNUSABLE;
6450 }
6451
6452 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6453 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6454 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6455
6456 /*
6457 * Commit it to the VMCS.
6458 */
6459 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel);
6460 rc |= VMXWriteVmcs32(idxLimit, pSelReg->u32Limit);
6461 rc |= VMXWriteVmcsGstN(idxBase, pSelReg->u64Base);
6462 rc |= VMXWriteVmcs32(idxAttr, u32Access);
6463 AssertRCReturn(rc, rc);
6464 return rc;
6465}
6466
6467
6468/**
6469 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6470 * area in the VMCS.
6471 *
6472 * @returns VBox status code.
6473 * @param pVCpu The cross context virtual CPU structure.
6474 * @param pVmxTransient The VMX-transient structure.
6475 *
6476 * @remarks Will import guest CR0 on strict builds during validation of
6477 * segments.
6478 * @remarks No-long-jump zone!!!
6479 */
6480static int hmR0VmxExportGuestSegRegsXdtr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6481{
6482 int rc = VERR_INTERNAL_ERROR_5;
6483 PVM pVM = pVCpu->CTX_SUFF(pVM);
6484 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6485 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6486
6487 /*
6488 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6489 */
6490 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6491 {
6492#ifdef VBOX_WITH_REM
6493 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6494 {
6495 Assert(!pVmxTransient->fIsNestedGuest);
6496 Assert(pVM->hm.s.vmx.pRealModeTSS);
6497 AssertCompile(PGMMODE_REAL < PGMMODE_PROTECTED);
6498 if ( pVmcsInfo->fWasInRealMode
6499 && PGMGetGuestMode(pVCpu) >= PGMMODE_PROTECTED)
6500 {
6501 /*
6502 * Notify the recompiler must flush its code-cache as the guest -may-
6503 * rewrite code it in real-mode (e.g. OpenBSD 4.0).
6504 */
6505 REMFlushTBs(pVM);
6506 Log4Func(("Switch to protected mode detected!\n"));
6507 pVmcsInfo->fWasInRealMode = false;
6508 }
6509 }
6510#endif
6511 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6512 {
6513 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6514 if (pVmcsInfo->RealMode.fRealOnV86Active)
6515 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6516 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6517 AssertRCReturn(rc, rc);
6518 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6519 }
6520
6521 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6522 {
6523 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6524 if (pVmcsInfo->RealMode.fRealOnV86Active)
6525 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6526 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6527 AssertRCReturn(rc, rc);
6528 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6529 }
6530
6531 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6532 {
6533 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6534 if (pVmcsInfo->RealMode.fRealOnV86Active)
6535 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6536 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6537 AssertRCReturn(rc, rc);
6538 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6539 }
6540
6541 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6542 {
6543 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6544 if (pVmcsInfo->RealMode.fRealOnV86Active)
6545 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6546 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6547 AssertRCReturn(rc, rc);
6548 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6549 }
6550
6551 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6552 {
6553 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6554 if (pVmcsInfo->RealMode.fRealOnV86Active)
6555 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6556 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6557 AssertRCReturn(rc, rc);
6558 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6559 }
6560
6561 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6562 {
6563 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6564 if (pVmcsInfo->RealMode.fRealOnV86Active)
6565 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6566 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6567 AssertRCReturn(rc, rc);
6568 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6569 }
6570
6571#ifdef VBOX_STRICT
6572 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6573#endif
6574 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6575 pCtx->cs.Attr.u));
6576 }
6577
6578 /*
6579 * Guest TR.
6580 */
6581 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6582 {
6583 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6584
6585 /*
6586 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6587 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6588 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6589 */
6590 uint16_t u16Sel;
6591 uint32_t u32Limit;
6592 uint64_t u64Base;
6593 uint32_t u32AccessRights;
6594 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6595 {
6596 u16Sel = pCtx->tr.Sel;
6597 u32Limit = pCtx->tr.u32Limit;
6598 u64Base = pCtx->tr.u64Base;
6599 u32AccessRights = pCtx->tr.Attr.u;
6600 }
6601 else
6602 {
6603 Assert(!pVmxTransient->fIsNestedGuest);
6604 Assert(pVM->hm.s.vmx.pRealModeTSS);
6605 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6606
6607 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6608 RTGCPHYS GCPhys;
6609 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6610 AssertRCReturn(rc, rc);
6611
6612 X86DESCATTR DescAttr;
6613 DescAttr.u = 0;
6614 DescAttr.n.u1Present = 1;
6615 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6616
6617 u16Sel = 0;
6618 u32Limit = HM_VTX_TSS_SIZE;
6619 u64Base = GCPhys;
6620 u32AccessRights = DescAttr.u;
6621 }
6622
6623 /* Validate. */
6624 Assert(!(u16Sel & RT_BIT(2)));
6625 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6626 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6627 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6628 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6629 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6630 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6631 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6632 Assert( (u32Limit & 0xfff) == 0xfff
6633 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6634 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6635 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6636
6637 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_TR_SEL, u16Sel);
6638 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit);
6639 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights);
6640 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_TR_BASE, u64Base);
6641 AssertRCReturn(rc, rc);
6642
6643 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6644 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6645 }
6646
6647 /*
6648 * Guest GDTR.
6649 */
6650 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6651 {
6652 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6653
6654 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt);
6655 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt);
6656 AssertRCReturn(rc, rc);
6657
6658 /* Validate. */
6659 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6660
6661 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6662 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6663 }
6664
6665 /*
6666 * Guest LDTR.
6667 */
6668 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6669 {
6670 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6671
6672 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6673 uint32_t u32Access;
6674 if ( !pVmxTransient->fIsNestedGuest
6675 && !pCtx->ldtr.Attr.u)
6676 u32Access = X86DESCATTR_UNUSABLE;
6677 else
6678 u32Access = pCtx->ldtr.Attr.u;
6679
6680 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel);
6681 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit);
6682 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access);
6683 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base);
6684 AssertRCReturn(rc, rc);
6685
6686 /* Validate. */
6687 if (!(u32Access & X86DESCATTR_UNUSABLE))
6688 {
6689 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6690 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6691 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6692 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6693 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6694 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6695 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6696 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6697 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6698 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6699 }
6700
6701 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6702 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6703 }
6704
6705 /*
6706 * Guest IDTR.
6707 */
6708 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6709 {
6710 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6711
6712 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt);
6713 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt);
6714 AssertRCReturn(rc, rc);
6715
6716 /* Validate. */
6717 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6718
6719 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6720 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6721 }
6722
6723 return VINF_SUCCESS;
6724}
6725
6726
6727/**
6728 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6729 * areas.
6730 *
6731 * These MSRs will automatically be loaded to the host CPU on every successful
6732 * VM-entry and stored from the host CPU on every successful VM-exit.
6733 *
6734 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6735 * actual host MSR values are not- updated here for performance reasons. See
6736 * hmR0VmxExportHostMsrs().
6737 *
6738 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6739 *
6740 * @returns VBox status code.
6741 * @param pVCpu The cross context virtual CPU structure.
6742 * @param pVmxTransient The VMX-transient structure.
6743 *
6744 * @remarks No-long-jump zone!!!
6745 */
6746static int hmR0VmxExportGuestMsrs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6747{
6748 AssertPtr(pVCpu);
6749 AssertPtr(pVmxTransient);
6750
6751 PVM pVM = pVCpu->CTX_SUFF(pVM);
6752 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6753
6754 /*
6755 * MSRs that we use the auto-load/store MSR area in the VMCS.
6756 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs().
6757 * The host MSR values are updated when it's safe in hmR0VmxLazySaveHostMsrs().
6758 *
6759 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6760 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6761 * emulation, nothing to do here.
6762 */
6763 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6764 {
6765 if ( !pVmxTransient->fIsNestedGuest
6766 && pVM->hm.s.fAllow64BitGuests)
6767 {
6768#if HC_ARCH_BITS == 32
6769 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSCALL_MSRS | CPUMCTX_EXTRN_KERNEL_GS_BASE);
6770 Assert(!pVmxTransient->fIsNestedGuest);
6771
6772 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_LSTAR, pCtx->msrLSTAR, true, false);
6773 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_STAR, pCtx->msrSTAR, true, false);
6774 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_SF_MASK, pCtx->msrSFMASK, true, false);
6775 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE, true, false);
6776 AssertRCReturn(rc, rc);
6777#endif
6778 }
6779 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6780 }
6781
6782 /*
6783 * Guest Sysenter MSRs.
6784 */
6785 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6786 {
6787 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6788
6789 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6790 {
6791 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6792 AssertRCReturn(rc, rc);
6793 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6794 }
6795
6796 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6797 {
6798 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6799 AssertRCReturn(rc, rc);
6800 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6801 }
6802
6803 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6804 {
6805 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6806 AssertRCReturn(rc, rc);
6807 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6808 }
6809 }
6810
6811 /*
6812 * Guest/host EFER MSR.
6813 */
6814 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6815 {
6816 /* Whether we are using the VMCS to swap the EFER MSR must have been
6817 determined earlier while exporting VM-entry/VM-exit controls. */
6818 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6819 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6820
6821 if (hmR0VmxShouldSwapEferMsr(pVCpu))
6822 {
6823 /*
6824 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6825 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6826 */
6827 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6828 {
6829 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, pCtx->msrEFER);
6830 AssertRCReturn(rc, rc);
6831 }
6832 else
6833 {
6834 /*
6835 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6836 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6837 */
6838 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, pCtx->msrEFER,
6839 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6840 AssertRCReturn(rc, rc);
6841 }
6842 }
6843 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6844 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6845
6846 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6847 }
6848
6849 /*
6850 * Other MSRs.
6851 * Speculation Control (R/W).
6852 */
6853 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6854 {
6855 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6856 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6857 {
6858 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6859 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6860 AssertRCReturn(rc, rc);
6861 }
6862 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6863 }
6864
6865 return VINF_SUCCESS;
6866}
6867
6868
6869/**
6870 * Selects up the appropriate function to run guest code.
6871 *
6872 * @returns VBox status code.
6873 * @param pVCpu The cross context virtual CPU structure.
6874 * @param pVmxTransient The VMX-transient structure.
6875 *
6876 * @remarks No-long-jump zone!!!
6877 */
6878static int hmR0VmxSelectVMRunHandler(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6879{
6880 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6881 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6882
6883 if (CPUMIsGuestInLongModeEx(pCtx))
6884 {
6885#ifndef VBOX_ENABLE_64_BITS_GUESTS
6886 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6887#endif
6888 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
6889#if HC_ARCH_BITS == 32
6890 /* 32-bit host. We need to switch to 64-bit before running the 64-bit guest. */
6891 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
6892 {
6893#ifdef VBOX_STRICT
6894 if (pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
6895 {
6896 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
6897 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
6898 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
6899 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
6900 ("fCtxChanged=%#RX64\n", fCtxChanged));
6901 }
6902#endif
6903 pVmcsInfo->pfnStartVM = VMXR0SwitcherStartVM64;
6904
6905 /* Mark that we've switched to 64-bit handler, we can't safely switch back to 32-bit for
6906 the rest of the VM run (until VM reset). See @bugref{8432#c7}. */
6907 pVmcsInfo->fSwitchedTo64on32 = true;
6908 Log4Func(("Selected 64-bit switcher\n"));
6909 }
6910#else
6911 /* 64-bit host. */
6912 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
6913#endif
6914 }
6915 else
6916 {
6917 /* Guest is not in long mode, use the 32-bit handler. */
6918#if HC_ARCH_BITS == 32
6919 if ( pVmcsInfo->pfnStartVM != VMXR0StartVM32
6920 && !pVmcsInfo->fSwitchedTo64on32 /* If set, guest mode change does not imply switcher change. */
6921 && pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
6922 {
6923# ifdef VBOX_STRICT
6924 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
6925 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
6926 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
6927 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
6928 ("fCtxChanged=%#RX64\n", fCtxChanged));
6929# endif
6930 }
6931# ifdef VBOX_ENABLE_64_BITS_GUESTS
6932 /*
6933 * Keep using the 64-bit switcher even though we're in 32-bit because of bad Intel
6934 * design, see @bugref{8432#c7}. If real-on-v86 mode is active, clear the 64-bit
6935 * switcher flag now because we know the guest is in a sane state where it's safe
6936 * to use the 32-bit switcher. Otherwise, check the guest state if it's safe to use
6937 * the much faster 32-bit switcher again.
6938 */
6939 if (!pVmcsInfo->fSwitchedTo64on32)
6940 {
6941 if (pVmcsInfo->pfnStartVM != VMXR0StartVM32)
6942 Log4Func(("Selected 32-bit switcher\n"));
6943 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6944 }
6945 else
6946 {
6947 Assert(pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64);
6948 if ( pVmcsInfo->RealMode.fRealOnV86Active
6949 || hmR0VmxIs32BitSwitcherSafe(pCtx))
6950 {
6951 pVmcsInfo->fSwitchedTo64on32 = false;
6952 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6953 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR
6954 | HM_CHANGED_VMX_ENTRY_EXIT_CTLS
6955 | HM_CHANGED_HOST_CONTEXT);
6956 Log4Func(("Selected 32-bit switcher (safe)\n"));
6957 }
6958 }
6959# else
6960 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6961# endif
6962#else
6963 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6964#endif
6965 }
6966 Assert(pVmcsInfo->pfnStartVM);
6967 return VINF_SUCCESS;
6968}
6969
6970
6971/**
6972 * Wrapper for running the guest code in VT-x.
6973 *
6974 * @returns VBox status code, no informational status codes.
6975 * @param pVCpu The cross context virtual CPU structure.
6976 * @param pVmxTransient The VMX-transient structure.
6977 *
6978 * @remarks No-long-jump zone!!!
6979 */
6980DECLINLINE(int) hmR0VmxRunGuest(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient)
6981{
6982 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6983 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6984 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6985
6986 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6987
6988 /*
6989 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6990 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6991 * callee-saved and thus the need for this XMM wrapper.
6992 *
6993 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6994 */
6995 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6996 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6997 PVM pVM = pVCpu->CTX_SUFF(pVM);
6998#ifdef VBOX_WITH_KERNEL_USING_XMM
6999 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu, pVmcsInfo->pfnStartVM);
7000#else
7001 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu);
7002#endif
7003 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
7004 return rc;
7005}
7006
7007
7008/**
7009 * Reports world-switch error and dumps some useful debug info.
7010 *
7011 * @param pVCpu The cross context virtual CPU structure.
7012 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
7013 * @param pVmxTransient The VMX-transient structure (only
7014 * exitReason updated).
7015 */
7016static void hmR0VmxReportWorldSwitchError(PVMCPU pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
7017{
7018 Assert(pVCpu);
7019 Assert(pVmxTransient);
7020 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
7021
7022 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
7023 switch (rcVMRun)
7024 {
7025 case VERR_VMX_INVALID_VMXON_PTR:
7026 AssertFailed();
7027 break;
7028 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
7029 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
7030 {
7031 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
7032 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
7033 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
7034 AssertRC(rc);
7035
7036 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
7037 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
7038 Cannot do it here as we may have been long preempted. */
7039
7040#ifdef VBOX_STRICT
7041 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7042 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
7043 pVmxTransient->uExitReason));
7044 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
7045 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
7046 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
7047 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
7048 else
7049 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
7050 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
7051 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
7052
7053 /* VMX control bits. */
7054 uint32_t u32Val;
7055 uint64_t u64Val;
7056 RTHCUINTREG uHCReg;
7057 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val); AssertRC(rc);
7058 Log4(("VMX_VMCS32_CTRL_PIN_EXEC %#RX32\n", u32Val));
7059 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val); AssertRC(rc);
7060 Log4(("VMX_VMCS32_CTRL_PROC_EXEC %#RX32\n", u32Val));
7061 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
7062 {
7063 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val); AssertRC(rc);
7064 Log4(("VMX_VMCS32_CTRL_PROC_EXEC2 %#RX32\n", u32Val));
7065 }
7066 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val); AssertRC(rc);
7067 Log4(("VMX_VMCS32_CTRL_ENTRY %#RX32\n", u32Val));
7068 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val); AssertRC(rc);
7069 Log4(("VMX_VMCS32_CTRL_EXIT %#RX32\n", u32Val));
7070 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_CR3_TARGET_COUNT, &u32Val); AssertRC(rc);
7071 Log4(("VMX_VMCS32_CTRL_CR3_TARGET_COUNT %#RX32\n", u32Val));
7072 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32Val); AssertRC(rc);
7073 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", u32Val));
7074 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &u32Val); AssertRC(rc);
7075 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", u32Val));
7076 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &u32Val); AssertRC(rc);
7077 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %u\n", u32Val));
7078 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, &u32Val); AssertRC(rc);
7079 Log4(("VMX_VMCS32_CTRL_TPR_THRESHOLD %u\n", u32Val));
7080 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &u32Val); AssertRC(rc);
7081 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT %u (guest MSRs)\n", u32Val));
7082 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
7083 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT %u (host MSRs)\n", u32Val));
7084 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
7085 Log4(("VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT %u (guest MSRs)\n", u32Val));
7086 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val); AssertRC(rc);
7087 Log4(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP %#RX32\n", u32Val));
7088 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, &u32Val); AssertRC(rc);
7089 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK %#RX32\n", u32Val));
7090 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, &u32Val); AssertRC(rc);
7091 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH %#RX32\n", u32Val));
7092 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
7093 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
7094 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
7095 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
7096 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
7097 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
7098 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
7099 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
7100 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
7101 {
7102 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
7103 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
7104 }
7105
7106 /* Guest bits. */
7107 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val); AssertRC(rc);
7108 Log4(("Old Guest Rip %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rip, u64Val));
7109 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val); AssertRC(rc);
7110 Log4(("Old Guest Rsp %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rsp, u64Val));
7111 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val); AssertRC(rc);
7112 Log4(("Old Guest Rflags %#RX32 New %#RX32\n", pVCpu->cpum.GstCtx.eflags.u32, u32Val));
7113 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid)
7114 {
7115 rc = VMXReadVmcs32(VMX_VMCS16_VPID, &u32Val); AssertRC(rc);
7116 Log4(("VMX_VMCS16_VPID %u\n", u32Val));
7117 }
7118
7119 /* Host bits. */
7120 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR0, &uHCReg); AssertRC(rc);
7121 Log4(("Host CR0 %#RHr\n", uHCReg));
7122 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR3, &uHCReg); AssertRC(rc);
7123 Log4(("Host CR3 %#RHr\n", uHCReg));
7124 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR4, &uHCReg); AssertRC(rc);
7125 Log4(("Host CR4 %#RHr\n", uHCReg));
7126
7127 RTGDTR HostGdtr;
7128 PCX86DESCHC pDesc;
7129 ASMGetGDTR(&HostGdtr);
7130 rc = VMXReadVmcs32(VMX_VMCS16_HOST_CS_SEL, &u32Val); AssertRC(rc);
7131 Log4(("Host CS %#08x\n", u32Val));
7132 if (u32Val < HostGdtr.cbGdt)
7133 {
7134 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7135 hmR0DumpDescriptor(pDesc, u32Val, "CS: ");
7136 }
7137
7138 rc = VMXReadVmcs32(VMX_VMCS16_HOST_DS_SEL, &u32Val); AssertRC(rc);
7139 Log4(("Host DS %#08x\n", u32Val));
7140 if (u32Val < HostGdtr.cbGdt)
7141 {
7142 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7143 hmR0DumpDescriptor(pDesc, u32Val, "DS: ");
7144 }
7145
7146 rc = VMXReadVmcs32(VMX_VMCS16_HOST_ES_SEL, &u32Val); AssertRC(rc);
7147 Log4(("Host ES %#08x\n", u32Val));
7148 if (u32Val < HostGdtr.cbGdt)
7149 {
7150 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7151 hmR0DumpDescriptor(pDesc, u32Val, "ES: ");
7152 }
7153
7154 rc = VMXReadVmcs32(VMX_VMCS16_HOST_FS_SEL, &u32Val); AssertRC(rc);
7155 Log4(("Host FS %#08x\n", u32Val));
7156 if (u32Val < HostGdtr.cbGdt)
7157 {
7158 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7159 hmR0DumpDescriptor(pDesc, u32Val, "FS: ");
7160 }
7161
7162 rc = VMXReadVmcs32(VMX_VMCS16_HOST_GS_SEL, &u32Val); AssertRC(rc);
7163 Log4(("Host GS %#08x\n", u32Val));
7164 if (u32Val < HostGdtr.cbGdt)
7165 {
7166 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7167 hmR0DumpDescriptor(pDesc, u32Val, "GS: ");
7168 }
7169
7170 rc = VMXReadVmcs32(VMX_VMCS16_HOST_SS_SEL, &u32Val); AssertRC(rc);
7171 Log4(("Host SS %#08x\n", u32Val));
7172 if (u32Val < HostGdtr.cbGdt)
7173 {
7174 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7175 hmR0DumpDescriptor(pDesc, u32Val, "SS: ");
7176 }
7177
7178 rc = VMXReadVmcs32(VMX_VMCS16_HOST_TR_SEL, &u32Val); AssertRC(rc);
7179 Log4(("Host TR %#08x\n", u32Val));
7180 if (u32Val < HostGdtr.cbGdt)
7181 {
7182 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7183 hmR0DumpDescriptor(pDesc, u32Val, "TR: ");
7184 }
7185
7186 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_TR_BASE, &uHCReg); AssertRC(rc);
7187 Log4(("Host TR Base %#RHv\n", uHCReg));
7188 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, &uHCReg); AssertRC(rc);
7189 Log4(("Host GDTR Base %#RHv\n", uHCReg));
7190 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, &uHCReg); AssertRC(rc);
7191 Log4(("Host IDTR Base %#RHv\n", uHCReg));
7192 rc = VMXReadVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, &u32Val); AssertRC(rc);
7193 Log4(("Host SYSENTER CS %#08x\n", u32Val));
7194 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_EIP, &uHCReg); AssertRC(rc);
7195 Log4(("Host SYSENTER EIP %#RHv\n", uHCReg));
7196 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_ESP, &uHCReg); AssertRC(rc);
7197 Log4(("Host SYSENTER ESP %#RHv\n", uHCReg));
7198 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RSP, &uHCReg); AssertRC(rc);
7199 Log4(("Host RSP %#RHv\n", uHCReg));
7200 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RIP, &uHCReg); AssertRC(rc);
7201 Log4(("Host RIP %#RHv\n", uHCReg));
7202# if HC_ARCH_BITS == 64
7203 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
7204 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
7205 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
7206 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
7207 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
7208 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
7209# endif
7210#endif /* VBOX_STRICT */
7211 break;
7212 }
7213
7214 default:
7215 /* Impossible */
7216 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
7217 break;
7218 }
7219}
7220
7221
7222#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
7223# ifndef VMX_USE_CACHED_VMCS_ACCESSES
7224# error "VMX_USE_CACHED_VMCS_ACCESSES not defined when it should be!"
7225# endif
7226
7227/**
7228 * Initialize the VMCS-Read cache.
7229 *
7230 * The VMCS cache is used for 32-bit hosts running 64-bit guests (except 32-bit
7231 * Darwin which runs with 64-bit paging in 32-bit mode) for 64-bit fields that
7232 * cannot be accessed in 32-bit mode. Some 64-bit fields -can- be accessed
7233 * (those that have a 32-bit FULL & HIGH part).
7234 *
7235 * @param pVCpu The cross context virtual CPU structure.
7236 */
7237static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu)
7238{
7239#define VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, idxField) \
7240 do { \
7241 Assert(pCache->Read.aField[idxField##_CACHE_IDX] == 0); \
7242 pCache->Read.aField[idxField##_CACHE_IDX] = idxField; \
7243 pCache->Read.aFieldVal[idxField##_CACHE_IDX] = 0; \
7244 ++cReadFields; \
7245 } while (0)
7246
7247 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
7248 uint32_t cReadFields = 0;
7249
7250 /*
7251 * Don't remove the #if 0'd fields in this code. They're listed here for consistency
7252 * and serve to indicate exceptions to the rules.
7253 */
7254
7255 /* Guest-natural selector base fields. */
7256#if 0
7257 /* These are 32-bit in practice. See Intel spec. 2.5 "Control Registers". */
7258 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR0);
7259 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR4);
7260#endif
7261 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_ES_BASE);
7262 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CS_BASE);
7263 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SS_BASE);
7264 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_DS_BASE);
7265 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_FS_BASE);
7266 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GS_BASE);
7267 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_LDTR_BASE);
7268 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_TR_BASE);
7269 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GDTR_BASE);
7270 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_IDTR_BASE);
7271 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RSP);
7272 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RIP);
7273#if 0
7274 /* Unused natural width guest-state fields. */
7275 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS);
7276 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3); /* Handled in nested paging case */
7277#endif
7278 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_ESP);
7279 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_EIP);
7280
7281 /* 64-bit guest-state fields; unused as we use two 32-bit VMREADs for
7282 these 64-bit fields (using "FULL" and "HIGH" fields). */
7283#if 0
7284 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL);
7285 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_DEBUGCTL_FULL);
7286 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PAT_FULL);
7287 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_EFER_FULL);
7288 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL);
7289 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE0_FULL);
7290 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE1_FULL);
7291 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE2_FULL);
7292 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE3_FULL);
7293#endif
7294
7295 /* Natural width guest-state fields. */
7296 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_EXIT_QUALIFICATION);
7297 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_GUEST_LINEAR_ADDR);
7298
7299 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
7300 {
7301 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3);
7302 AssertMsg(cReadFields == VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields,
7303 VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX));
7304 pCache->Read.cValidEntries = VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX;
7305 }
7306 else
7307 {
7308 AssertMsg(cReadFields == VMX_VMCS_MAX_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields, VMX_VMCS_MAX_CACHE_IDX));
7309 pCache->Read.cValidEntries = VMX_VMCS_MAX_CACHE_IDX;
7310 }
7311
7312#undef VMXLOCAL_INIT_READ_CACHE_FIELD
7313}
7314
7315
7316/**
7317 * Writes a field into the VMCS. This can either directly invoke a VMWRITE or
7318 * queue up the VMWRITE by using the VMCS write cache (on 32-bit hosts, except
7319 * darwin, running 64-bit guests).
7320 *
7321 * @returns VBox status code.
7322 * @param pVCpu The cross context virtual CPU structure.
7323 * @param idxField The VMCS field encoding.
7324 * @param u64Val 16, 32 or 64-bit value.
7325 */
7326VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
7327{
7328 AssertPtr(pVCpu);
7329 int rc;
7330 switch (idxField)
7331 {
7332 /*
7333 * These fields consists of a "FULL" and a "HIGH" part which can be written to individually.
7334 */
7335 /* 64-bit Control fields. */
7336 case VMX_VMCS64_CTRL_IO_BITMAP_A_FULL:
7337 case VMX_VMCS64_CTRL_IO_BITMAP_B_FULL:
7338 case VMX_VMCS64_CTRL_MSR_BITMAP_FULL:
7339 case VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL:
7340 case VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL:
7341 case VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL:
7342 case VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL:
7343 case VMX_VMCS64_CTRL_TSC_OFFSET_FULL:
7344 case VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL:
7345 case VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL:
7346 case VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL:
7347 case VMX_VMCS64_CTRL_EPTP_FULL:
7348 case VMX_VMCS64_CTRL_EPTP_LIST_FULL:
7349 /* 64-bit Guest-state fields. */
7350 case VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL:
7351 case VMX_VMCS64_GUEST_DEBUGCTL_FULL:
7352 case VMX_VMCS64_GUEST_PAT_FULL:
7353 case VMX_VMCS64_GUEST_EFER_FULL:
7354 case VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL:
7355 case VMX_VMCS64_GUEST_PDPTE0_FULL:
7356 case VMX_VMCS64_GUEST_PDPTE1_FULL:
7357 case VMX_VMCS64_GUEST_PDPTE2_FULL:
7358 case VMX_VMCS64_GUEST_PDPTE3_FULL:
7359 /* 64-bit Host-state fields. */
7360 case VMX_VMCS64_HOST_PAT_FULL:
7361 case VMX_VMCS64_HOST_EFER_FULL:
7362 case VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL:
7363 {
7364 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
7365 rc |= VMXWriteVmcs32(idxField + 1, RT_HI_U32(u64Val));
7366 break;
7367 }
7368
7369 /*
7370 * These fields do not have high and low parts. Queue up the VMWRITE by using the VMCS write-cache (for 64-bit
7371 * values). When we switch the host to 64-bit mode for running 64-bit guests, these VMWRITEs get executed then.
7372 */
7373 /* Natural-width Guest-state fields. */
7374 case VMX_VMCS_GUEST_CR3:
7375 case VMX_VMCS_GUEST_ES_BASE:
7376 case VMX_VMCS_GUEST_CS_BASE:
7377 case VMX_VMCS_GUEST_SS_BASE:
7378 case VMX_VMCS_GUEST_DS_BASE:
7379 case VMX_VMCS_GUEST_FS_BASE:
7380 case VMX_VMCS_GUEST_GS_BASE:
7381 case VMX_VMCS_GUEST_LDTR_BASE:
7382 case VMX_VMCS_GUEST_TR_BASE:
7383 case VMX_VMCS_GUEST_GDTR_BASE:
7384 case VMX_VMCS_GUEST_IDTR_BASE:
7385 case VMX_VMCS_GUEST_RSP:
7386 case VMX_VMCS_GUEST_RIP:
7387 case VMX_VMCS_GUEST_SYSENTER_ESP:
7388 case VMX_VMCS_GUEST_SYSENTER_EIP:
7389 {
7390 if (!(RT_HI_U32(u64Val)))
7391 {
7392 /* If this field is 64-bit, VT-x will zero out the top bits. */
7393 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
7394 }
7395 else
7396 {
7397 /* Assert that only the 32->64 switcher case should ever come here. */
7398 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests);
7399 rc = VMXWriteCachedVmcsEx(pVCpu, idxField, u64Val);
7400 }
7401 break;
7402 }
7403
7404 default:
7405 {
7406 AssertMsgFailed(("VMXWriteVmcs64Ex: Invalid field %#RX32 (pVCpu=%p u64Val=%#RX64)\n", idxField, pVCpu, u64Val));
7407 pVCpu->hm.s.u32HMError = idxField;
7408 rc = VERR_INVALID_PARAMETER;
7409 break;
7410 }
7411 }
7412 AssertRCReturn(rc, rc);
7413 return rc;
7414}
7415
7416
7417/**
7418 * Queue up a VMWRITE by using the VMCS write cache.
7419 * This is only used on 32-bit hosts (except darwin) for 64-bit guests.
7420 *
7421 * @param pVCpu The cross context virtual CPU structure.
7422 * @param idxField The VMCS field encoding.
7423 * @param u64Val 16, 32 or 64-bit value.
7424 */
7425VMMR0DECL(int) VMXWriteCachedVmcsEx(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
7426{
7427 AssertPtr(pVCpu);
7428 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
7429
7430 AssertMsgReturn(pCache->Write.cValidEntries < VMX_VMCS_CACHE_MAX_ENTRY - 1,
7431 ("entries=%u\n", pCache->Write.cValidEntries), VERR_ACCESS_DENIED);
7432
7433 /* Make sure there are no duplicates. */
7434 for (uint32_t i = 0; i < pCache->Write.cValidEntries; i++)
7435 {
7436 if (pCache->Write.aField[i] == idxField)
7437 {
7438 pCache->Write.aFieldVal[i] = u64Val;
7439 return VINF_SUCCESS;
7440 }
7441 }
7442
7443 pCache->Write.aField[pCache->Write.cValidEntries] = idxField;
7444 pCache->Write.aFieldVal[pCache->Write.cValidEntries] = u64Val;
7445 pCache->Write.cValidEntries++;
7446 return VINF_SUCCESS;
7447}
7448#endif /* HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) */
7449
7450
7451/**
7452 * Sets up the usage of TSC-offsetting and updates the VMCS.
7453 *
7454 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
7455 * VMX-preemption timer.
7456 *
7457 * @returns VBox status code.
7458 * @param pVCpu The cross context virtual CPU structure.
7459 * @param pVmxTransient The VMX-transient structure.
7460 *
7461 * @remarks No-long-jump zone!!!
7462 */
7463static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
7464{
7465 bool fOffsettedTsc;
7466 bool fParavirtTsc;
7467 uint64_t uTscOffset;
7468 PVM pVM = pVCpu->CTX_SUFF(pVM);
7469 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7470
7471 if (pVM->hm.s.vmx.fUsePreemptTimer)
7472 {
7473 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
7474
7475 /* Make sure the returned values have sane upper and lower boundaries. */
7476 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7477 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
7478 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
7479 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7480
7481 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7482 * preemption timers here. We probably need to clamp the preemption timer,
7483 * after converting the timer value to the host. */
7484 uint32_t cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7485 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7486 AssertRC(rc);
7487 }
7488 else
7489 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7490
7491 if (fParavirtTsc)
7492 {
7493 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7494 information before every VM-entry, hence disable it for performance sake. */
7495#if 0
7496 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7497 AssertRC(rc);
7498#endif
7499 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7500 }
7501
7502 if ( fOffsettedTsc
7503 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
7504 {
7505 if (pVmxTransient->fIsNestedGuest)
7506 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7507 hmR0VmxSetTscOffsetVmcs(pVCpu, pVmcsInfo, uTscOffset);
7508 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7509 }
7510 else
7511 {
7512 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7513 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7514 }
7515}
7516
7517
7518/**
7519 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7520 * VM-exit interruption info type.
7521 *
7522 * @returns The IEM exception flags.
7523 * @param uVector The event vector.
7524 * @param uVmxEventType The VMX event type.
7525 *
7526 * @remarks This function currently only constructs flags required for
7527 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7528 * and CR2 aspects of an exception are not included).
7529 */
7530static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7531{
7532 uint32_t fIemXcptFlags;
7533 switch (uVmxEventType)
7534 {
7535 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7536 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7537 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7538 break;
7539
7540 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7541 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7542 break;
7543
7544 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7545 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7546 break;
7547
7548 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7549 {
7550 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7551 if (uVector == X86_XCPT_BP)
7552 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7553 else if (uVector == X86_XCPT_OF)
7554 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7555 else
7556 {
7557 fIemXcptFlags = 0;
7558 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7559 }
7560 break;
7561 }
7562
7563 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7564 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7565 break;
7566
7567 default:
7568 fIemXcptFlags = 0;
7569 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7570 break;
7571 }
7572 return fIemXcptFlags;
7573}
7574
7575
7576/**
7577 * Sets an event as a pending event to be injected into the guest.
7578 *
7579 * @param pVCpu The cross context virtual CPU structure.
7580 * @param u32IntInfo The VM-entry interruption-information field.
7581 * @param cbInstr The VM-entry instruction length in bytes (for software
7582 * interrupts, exceptions and privileged software
7583 * exceptions).
7584 * @param u32ErrCode The VM-entry exception error code.
7585 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7586 * page-fault.
7587 */
7588DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7589 RTGCUINTPTR GCPtrFaultAddress)
7590{
7591 Assert(!pVCpu->hm.s.Event.fPending);
7592 pVCpu->hm.s.Event.fPending = true;
7593 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7594 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7595 pVCpu->hm.s.Event.cbInstr = cbInstr;
7596 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7597}
7598
7599
7600/**
7601 * Sets an external interrupt as pending-for-injection into the VM.
7602 *
7603 * @param pVCpu The cross context virtual CPU structure.
7604 * @param u8Interrupt The external interrupt vector.
7605 */
7606DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPU pVCpu, uint8_t u8Interrupt)
7607{
7608 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7609 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7610 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7611 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7612 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7613}
7614
7615
7616/**
7617 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7618 *
7619 * @param pVCpu The cross context virtual CPU structure.
7620 */
7621DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPU pVCpu)
7622{
7623 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7624 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7625 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7626 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7627 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7628}
7629
7630
7631/**
7632 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7633 *
7634 * @param pVCpu The cross context virtual CPU structure.
7635 */
7636DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu)
7637{
7638 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7639 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7640 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7641 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7642 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7643}
7644
7645
7646/**
7647 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7648 *
7649 * @param pVCpu The cross context virtual CPU structure.
7650 */
7651DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu)
7652{
7653 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7654 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7655 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7656 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7657 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7658}
7659
7660
7661/**
7662 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7663 *
7664 * @param pVCpu The cross context virtual CPU structure.
7665 */
7666DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu)
7667{
7668 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7669 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7670 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7671 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7672 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7673}
7674
7675
7676#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7677/**
7678 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7679 *
7680 * @param pVCpu The cross context virtual CPU structure.
7681 * @param u32ErrCode The error code for the general-protection exception.
7682 */
7683DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPU pVCpu, uint32_t u32ErrCode)
7684{
7685 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7686 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7687 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7688 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7689 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7690}
7691
7692
7693/**
7694 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7695 *
7696 * @param pVCpu The cross context virtual CPU structure.
7697 * @param u32ErrCode The error code for the stack exception.
7698 */
7699DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPU pVCpu, uint32_t u32ErrCode)
7700{
7701 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7702 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7703 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7704 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7705 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7706}
7707#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7708
7709
7710static void hmR0VmxFixUnusableSegRegAttr(PVMCPU pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7711{
7712 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7713
7714 /*
7715 * If VT-x marks the segment as unusable, most other bits remain undefined:
7716 * - For CS the L, D and G bits have meaning.
7717 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7718 * - For the remaining data segments no bits are defined.
7719 *
7720 * The present bit and the unusable bit has been observed to be set at the
7721 * same time (the selector was supposed to be invalid as we started executing
7722 * a V8086 interrupt in ring-0).
7723 *
7724 * What should be important for the rest of the VBox code, is that the P bit is
7725 * cleared. Some of the other VBox code recognizes the unusable bit, but
7726 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7727 * safe side here, we'll strip off P and other bits we don't care about. If
7728 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7729 *
7730 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7731 */
7732#ifdef VBOX_STRICT
7733 uint32_t const uAttr = pSelReg->Attr.u;
7734#endif
7735
7736 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7737 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7738 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7739
7740#ifdef VBOX_STRICT
7741 VMMRZCallRing3Disable(pVCpu);
7742 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7743# ifdef DEBUG_bird
7744 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7745 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7746 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7747# endif
7748 VMMRZCallRing3Enable(pVCpu);
7749 NOREF(uAttr);
7750#endif
7751 RT_NOREF2(pVCpu, idxSel);
7752}
7753
7754
7755/**
7756 * Imports a guest segment register from the current VMCS into the guest-CPU
7757 * context.
7758 *
7759 * @returns VBox status code.
7760 * @param pVCpu The cross context virtual CPU structure.
7761 * @param iSegReg The segment register number (X86_SREG_XXX).
7762 *
7763 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7764 * do not log!
7765 */
7766static int hmR0VmxImportGuestSegReg(PVMCPU pVCpu, uint8_t iSegReg)
7767{
7768 Assert(iSegReg < X86_SREG_COUNT);
7769
7770 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7771 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7772 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7773#ifdef VMX_USE_CACHED_VMCS_ACCESSES
7774 uint32_t const idxBase = g_aVmcsCacheSegBase[iSegReg];
7775#else
7776 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7777#endif
7778 uint64_t u64Base;
7779 uint32_t u32Sel, u32Limit, u32Attr;
7780 int rc = VMXReadVmcs32(idxSel, &u32Sel);
7781 rc |= VMXReadVmcs32(idxLimit, &u32Limit);
7782 rc |= VMXReadVmcs32(idxAttr, &u32Attr);
7783 rc |= VMXReadVmcsGstNByIdxVal(idxBase, &u64Base);
7784 if (RT_SUCCESS(rc))
7785 {
7786 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7787 pSelReg->Sel = u32Sel;
7788 pSelReg->ValidSel = u32Sel;
7789 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7790 pSelReg->u32Limit = u32Limit;
7791 pSelReg->u64Base = u64Base;
7792 pSelReg->Attr.u = u32Attr;
7793 if (u32Attr & X86DESCATTR_UNUSABLE)
7794 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7795 }
7796 return rc;
7797}
7798
7799
7800/**
7801 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7802 *
7803 * @returns VBox status code.
7804 * @param pVCpu The cross context virtual CPU structure.
7805 *
7806 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7807 * do not log!
7808 */
7809static int hmR0VmxImportGuestLdtr(PVMCPU pVCpu)
7810{
7811 uint64_t u64Base;
7812 uint32_t u32Sel, u32Limit, u32Attr;
7813 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, &u32Sel);
7814 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit);
7815 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr);
7816 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, &u64Base);
7817 if (RT_SUCCESS(rc))
7818 {
7819 pVCpu->cpum.GstCtx.ldtr.Sel = u32Sel;
7820 pVCpu->cpum.GstCtx.ldtr.ValidSel = u32Sel;
7821 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7822 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7823 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7824 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7825 if (u32Attr & X86DESCATTR_UNUSABLE)
7826 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7827 }
7828 return rc;
7829}
7830
7831
7832/**
7833 * Imports the guest TR from the current VMCS into the guest-CPU context.
7834 *
7835 * @returns VBox status code.
7836 * @param pVCpu The cross context virtual CPU structure.
7837 *
7838 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7839 * do not log!
7840 */
7841static int hmR0VmxImportGuestTr(PVMCPU pVCpu)
7842{
7843 uint32_t u32Sel, u32Limit, u32Attr;
7844 uint64_t u64Base;
7845 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_TR_SEL, &u32Sel);
7846 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit);
7847 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr);
7848 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_TR_BASE, &u64Base);
7849 AssertRCReturn(rc, rc);
7850
7851 pVCpu->cpum.GstCtx.tr.Sel = u32Sel;
7852 pVCpu->cpum.GstCtx.tr.ValidSel = u32Sel;
7853 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7854 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7855 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7856 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7857 /* TR is the only selector that can never be unusable. */
7858 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7859 return VINF_SUCCESS;
7860}
7861
7862
7863/**
7864 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7865 *
7866 * @returns VBox status code.
7867 * @param pVCpu The cross context virtual CPU structure.
7868 *
7869 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7870 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7871 * instead!!!
7872 */
7873static int hmR0VmxImportGuestRip(PVMCPU pVCpu)
7874{
7875 uint64_t u64Val;
7876 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7877 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7878 {
7879 int rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val);
7880 if (RT_SUCCESS(rc))
7881 {
7882 pCtx->rip = u64Val;
7883 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7884 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7885 }
7886 return rc;
7887 }
7888 return VINF_SUCCESS;
7889}
7890
7891
7892/**
7893 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7894 *
7895 * @returns VBox status code.
7896 * @param pVCpu The cross context virtual CPU structure.
7897 * @param pVmcsInfo The VMCS info. object.
7898 *
7899 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7900 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7901 * instead!!!
7902 */
7903static int hmR0VmxImportGuestRFlags(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7904{
7905 uint32_t u32Val;
7906 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7907 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7908 {
7909 int rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val);
7910 if (RT_SUCCESS(rc))
7911 {
7912 pCtx->eflags.u32 = u32Val;
7913
7914 /* Restore eflags for real-on-v86-mode hack. */
7915 if (pVmcsInfo->RealMode.fRealOnV86Active)
7916 {
7917 pCtx->eflags.Bits.u1VM = 0;
7918 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7919 }
7920 }
7921 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7922 return rc;
7923 }
7924 return VINF_SUCCESS;
7925}
7926
7927
7928/**
7929 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7930 * context.
7931 *
7932 * @returns VBox status code.
7933 * @param pVCpu The cross context virtual CPU structure.
7934 * @param pVmcsInfo The VMCS info. object.
7935 *
7936 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7937 * do not log!
7938 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7939 * instead!!!
7940 */
7941static int hmR0VmxImportGuestIntrState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7942{
7943 uint32_t u32Val;
7944 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val);
7945 if (RT_SUCCESS(rc))
7946 {
7947 if (!u32Val)
7948 {
7949 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7950 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7951
7952 CPUMSetGuestNmiBlocking(pVCpu, false);
7953 }
7954 else
7955 {
7956 /*
7957 * We must import RIP here to set our EM interrupt-inhibited state.
7958 * We also import RFLAGS as our code that evaluates pending interrupts
7959 * before VM-entry requires it.
7960 */
7961 rc = hmR0VmxImportGuestRip(pVCpu);
7962 rc |= hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7963 if (RT_SUCCESS(rc))
7964 {
7965 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7966 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7967 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7968 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7969
7970 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7971 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7972 }
7973 }
7974 }
7975 return rc;
7976}
7977
7978
7979/**
7980 * Worker for VMXR0ImportStateOnDemand.
7981 *
7982 * @returns VBox status code.
7983 * @param pVCpu The cross context virtual CPU structure.
7984 * @param pVmcsInfo The VMCS info. object.
7985 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7986 */
7987static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7988{
7989#define VMXLOCAL_BREAK_RC(a_rc) \
7990 if (RT_SUCCESS(a_rc)) \
7991 { } \
7992 else \
7993 break
7994
7995 int rc = VINF_SUCCESS;
7996 PVM pVM = pVCpu->CTX_SUFF(pVM);
7997 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7998 uint64_t u64Val;
7999 uint32_t u32Val;
8000
8001 /*
8002 * Note! This is hack to workaround a mysterious BSOD observed with release builds
8003 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
8004 * neither are other host platforms.
8005 *
8006 * Committing this temporarily as it prevents BSOD.
8007 *
8008 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
8009 */
8010#ifdef RT_OS_WINDOWS
8011 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
8012 return VERR_HM_IPE_1;
8013#endif
8014
8015 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
8016
8017 /*
8018 * We disable interrupts to make the updating of the state and in particular
8019 * the fExtrn modification atomic wrt to preemption hooks.
8020 */
8021 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
8022
8023 fWhat &= pCtx->fExtrn;
8024 if (fWhat)
8025 {
8026 do
8027 {
8028 if (fWhat & CPUMCTX_EXTRN_RIP)
8029 {
8030 rc = hmR0VmxImportGuestRip(pVCpu);
8031 VMXLOCAL_BREAK_RC(rc);
8032 }
8033
8034 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
8035 {
8036 rc = hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
8037 VMXLOCAL_BREAK_RC(rc);
8038 }
8039
8040 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
8041 {
8042 rc = hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
8043 VMXLOCAL_BREAK_RC(rc);
8044 }
8045
8046 if (fWhat & CPUMCTX_EXTRN_RSP)
8047 {
8048 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val);
8049 VMXLOCAL_BREAK_RC(rc);
8050 pCtx->rsp = u64Val;
8051 }
8052
8053 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
8054 {
8055 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
8056 if (fWhat & CPUMCTX_EXTRN_CS)
8057 {
8058 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
8059 rc |= hmR0VmxImportGuestRip(pVCpu);
8060 if (fRealOnV86Active)
8061 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
8062 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
8063 }
8064 if (fWhat & CPUMCTX_EXTRN_SS)
8065 {
8066 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
8067 if (fRealOnV86Active)
8068 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
8069 }
8070 if (fWhat & CPUMCTX_EXTRN_DS)
8071 {
8072 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
8073 if (fRealOnV86Active)
8074 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
8075 }
8076 if (fWhat & CPUMCTX_EXTRN_ES)
8077 {
8078 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
8079 if (fRealOnV86Active)
8080 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
8081 }
8082 if (fWhat & CPUMCTX_EXTRN_FS)
8083 {
8084 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
8085 if (fRealOnV86Active)
8086 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
8087 }
8088 if (fWhat & CPUMCTX_EXTRN_GS)
8089 {
8090 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
8091 if (fRealOnV86Active)
8092 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
8093 }
8094 VMXLOCAL_BREAK_RC(rc);
8095 }
8096
8097 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
8098 {
8099 if (fWhat & CPUMCTX_EXTRN_LDTR)
8100 rc |= hmR0VmxImportGuestLdtr(pVCpu);
8101
8102 if (fWhat & CPUMCTX_EXTRN_GDTR)
8103 {
8104 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
8105 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
8106 pCtx->gdtr.pGdt = u64Val;
8107 pCtx->gdtr.cbGdt = u32Val;
8108 }
8109
8110 /* Guest IDTR. */
8111 if (fWhat & CPUMCTX_EXTRN_IDTR)
8112 {
8113 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
8114 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
8115 pCtx->idtr.pIdt = u64Val;
8116 pCtx->idtr.cbIdt = u32Val;
8117 }
8118
8119 /* Guest TR. */
8120 if (fWhat & CPUMCTX_EXTRN_TR)
8121 {
8122 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
8123 don't need to import that one. */
8124 if (!pVmcsInfo->RealMode.fRealOnV86Active)
8125 rc |= hmR0VmxImportGuestTr(pVCpu);
8126 }
8127 VMXLOCAL_BREAK_RC(rc);
8128 }
8129
8130 if (fWhat & CPUMCTX_EXTRN_DR7)
8131 {
8132 if (!pVCpu->hm.s.fUsingHyperDR7)
8133 {
8134 /* Upper 32-bits are always zero. See Intel spec. 2.7.3 "Loading and Storing Debug Registers". */
8135 rc = VMXReadVmcs32(VMX_VMCS_GUEST_DR7, &u32Val);
8136 VMXLOCAL_BREAK_RC(rc);
8137 pCtx->dr[7] = u32Val;
8138 }
8139 }
8140
8141 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
8142 {
8143 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip);
8144 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp);
8145 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val);
8146 pCtx->SysEnter.cs = u32Val;
8147 VMXLOCAL_BREAK_RC(rc);
8148 }
8149
8150#if HC_ARCH_BITS == 64
8151 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
8152 {
8153 if ( pVM->hm.s.fAllow64BitGuests
8154 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
8155 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
8156 }
8157
8158 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
8159 {
8160 if ( pVM->hm.s.fAllow64BitGuests
8161 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
8162 {
8163 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
8164 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
8165 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
8166 }
8167 }
8168#endif
8169
8170 if ( (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
8171#if HC_ARCH_BITS == 32
8172 || (fWhat & (CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS))
8173#endif
8174 )
8175 {
8176 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
8177 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
8178 Assert(pMsrs);
8179 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
8180 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
8181 for (uint32_t i = 0; i < cMsrs; i++)
8182 {
8183 uint32_t const idMsr = pMsrs[i].u32Msr;
8184 switch (idMsr)
8185 {
8186 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
8187 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
8188 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
8189#if HC_ARCH_BITS == 32
8190 case MSR_K8_LSTAR: pCtx->msrLSTAR = pMsrs[i].u64Value; break;
8191 case MSR_K6_STAR: pCtx->msrSTAR = pMsrs[i].u64Value; break;
8192 case MSR_K8_SF_MASK: pCtx->msrSFMASK = pMsrs[i].u64Value; break;
8193 case MSR_K8_KERNEL_GS_BASE: pCtx->msrKERNELGSBASE = pMsrs[i].u64Value; break;
8194#endif
8195 default:
8196 {
8197 pCtx->fExtrn = 0;
8198 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
8199 ASMSetFlags(fEFlags);
8200 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
8201 return VERR_HM_UNEXPECTED_LD_ST_MSR;
8202 }
8203 }
8204 }
8205 }
8206
8207 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
8208 {
8209 uint64_t u64Shadow;
8210 if (fWhat & CPUMCTX_EXTRN_CR0)
8211 {
8212 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
8213 * remove when we drop 32-bit host w/ 64-bit host support, see
8214 * @bugref{9180#c39}. */
8215 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val);
8216#if HC_ARCH_BITS == 32
8217 uint32_t u32Shadow;
8218 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u32Shadow);
8219 u64Shadow = u32Shadow;
8220#else
8221 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow);
8222#endif
8223 VMXLOCAL_BREAK_RC(rc);
8224 u64Val = u32Val;
8225 u64Val = (u64Val & ~pVmcsInfo->u64Cr0Mask)
8226 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
8227#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8228 /*
8229 * Reapply the nested-guest's CR0 fixed bits that might have been altered while
8230 * exporting the nested-guest CR0 for executing using hardware-assisted VMX.
8231 */
8232 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8233 {
8234 u64Val |= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed0;
8235 u64Val &= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed1;
8236 }
8237#endif
8238 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
8239 CPUMSetGuestCR0(pVCpu, u64Val);
8240 VMMRZCallRing3Enable(pVCpu);
8241 }
8242
8243 if (fWhat & CPUMCTX_EXTRN_CR4)
8244 {
8245 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
8246 * remove when we drop 32-bit host w/ 64-bit host support, see
8247 * @bugref{9180#c39}. */
8248 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32Val);
8249#if HC_ARCH_BITS == 32
8250 uint32_t u32Shadow;
8251 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u32Shadow);
8252 u64Shadow = u32Shadow;
8253#else
8254 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow);
8255#endif
8256 VMXLOCAL_BREAK_RC(rc);
8257 u64Val = u32Val;
8258 u64Val = (u64Val & ~pVmcsInfo->u64Cr4Mask)
8259 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
8260#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8261 /*
8262 * Reapply the nested-guest's CR4 fixed bits that might have been altered while
8263 * exporting the nested-guest CR4 for executing using hardware-assisted VMX.
8264 */
8265 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8266 {
8267 u64Val |= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed0;
8268 u64Val &= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed1;
8269 }
8270#endif
8271 pCtx->cr4 = u64Val;
8272 }
8273
8274 if (fWhat & CPUMCTX_EXTRN_CR3)
8275 {
8276 /* CR0.PG bit changes are always intercepted, so it's up to date. */
8277 if ( pVM->hm.s.vmx.fUnrestrictedGuest
8278 || ( pVM->hm.s.fNestedPaging
8279 && CPUMIsGuestPagingEnabledEx(pCtx)))
8280 {
8281 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_CR3, &u64Val);
8282 VMXLOCAL_BREAK_RC(rc);
8283 if (pCtx->cr3 != u64Val)
8284 {
8285 pCtx->cr3 = u64Val;
8286 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
8287 }
8288
8289 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
8290 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
8291 if (CPUMIsGuestInPAEModeEx(pCtx))
8292 {
8293 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u);
8294 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u);
8295 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u);
8296 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u);
8297 VMXLOCAL_BREAK_RC(rc);
8298 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
8299 }
8300 }
8301 }
8302 }
8303
8304#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8305 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
8306 {
8307 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
8308 && !CPUMIsGuestInVmxNonRootMode(pCtx))
8309 {
8310 Assert(CPUMIsGuestInVmxRootMode(pCtx));
8311 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
8312 VMXLOCAL_BREAK_RC(rc);
8313 }
8314
8315# if 0
8316 /** @todo NSTVMX: We handle most of these fields individually by passing it to IEM
8317 * VM-exit handlers as parameters. We would handle it differently when using
8318 * the fast path. */
8319 /*
8320 * The hardware virtualization state currently consists of VMCS fields that may be
8321 * modified by execution of the nested-guest (that are not part of the general
8322 * guest state) and is visible to guest software. Hence, it is technically part of
8323 * the guest-CPU state when executing a nested-guest.
8324 */
8325 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8326 {
8327 PVMXVVMCS pGstVmcs = pCtx->hwvirt.vmx.CTX_SUFF(pVmcs);
8328 rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pGstVmcs->u32RoExitReason);
8329 rc |= VMXReadVmcsGstN(VMX_VMCS_RO_EXIT_QUALIFICATION, &pGstVmcs->u64RoExitQual.u);
8330 VMXLOCAL_BREAK_RC(rc);
8331
8332 /*
8333 * VM-entry can fail due to invalid-guest state, machine-check events and
8334 * MSR loading failures. Other than VM-exit reason and Exit qualification
8335 * all other VMCS fields are left unmodified on VM-entry failure.
8336 *
8337 * See Intel spec. 26.7 "VM-entry Failures During Or After Loading Guest State".
8338 */
8339 bool const fEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(pGstVmcs->u32RoExitReason);
8340 if (!fEntryFailed)
8341 {
8342 /*
8343 * Some notes on VMCS fields that may need importing when the fast path
8344 * is implemented. Currently we fully emulate VMLAUNCH/VMRESUME in IEM.
8345 *
8346 * Requires fixing up when using hardware-assisted VMX:
8347 * - VM-exit interruption info: Shouldn't reflect host interrupts/NMIs.
8348 * - VM-exit interruption error code: Cleared to 0 when not appropriate.
8349 * - IDT-vectoring info: Think about this.
8350 * - IDT-vectoring error code: Think about this.
8351 *
8352 * Emulated:
8353 * - Guest-interruptiblity state: Derived from FFs and RIP.
8354 * - Guest pending debug exceptions: Derived from DR6.
8355 * - Guest activity state: Emulated from EM state.
8356 * - Guest PDPTEs: Currently all 0s since we don't support nested EPT.
8357 * - Entry-interrupt info: Emulated, cleared to 0.
8358 */
8359 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pGstVmcs->u32RoExitIntInfo);
8360 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pGstVmcs->u32RoExitIntErrCode);
8361 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pGstVmcs->u32RoIdtVectoringInfo);
8362 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pGstVmcs->u32RoIdtVectoringErrCode);
8363 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pGstVmcs->u32RoExitInstrLen);
8364 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pGstVmcs->u32RoExitIntInfo);
8365 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pGstVmcs->u64RoGuestPhysAddr.u);
8366 rc |= VMXReadVmcsGstN(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pGstVmcs->u64RoGuestLinearAddr.u);
8367 /** @todo NSTVMX: Save and adjust preemption timer value. */
8368 }
8369
8370 VMXLOCAL_BREAK_RC(rc);
8371 }
8372# endif
8373 }
8374#endif
8375 } while (0);
8376
8377 if (RT_SUCCESS(rc))
8378 {
8379 /* Update fExtrn. */
8380 pCtx->fExtrn &= ~fWhat;
8381
8382 /* If everything has been imported, clear the HM keeper bit. */
8383 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
8384 {
8385 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
8386 Assert(!pCtx->fExtrn);
8387 }
8388 }
8389 }
8390 else
8391 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
8392
8393 ASMSetFlags(fEFlags);
8394
8395 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
8396
8397 if (RT_SUCCESS(rc))
8398 { /* likely */ }
8399 else
8400 return rc;
8401
8402 /*
8403 * Honor any pending CR3 updates.
8404 *
8405 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> hmR0VmxCallRing3Callback()
8406 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
8407 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
8408 *
8409 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
8410 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
8411 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
8412 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
8413 *
8414 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
8415 */
8416 if (VMMRZCallRing3IsEnabled(pVCpu))
8417 {
8418 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
8419 {
8420 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
8421 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
8422 }
8423
8424 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
8425 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
8426
8427 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
8428 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
8429 }
8430
8431 return VINF_SUCCESS;
8432#undef VMXLOCAL_BREAK_RC
8433}
8434
8435
8436/**
8437 * Saves the guest state from the VMCS into the guest-CPU context.
8438 *
8439 * @returns VBox status code.
8440 * @param pVCpu The cross context virtual CPU structure.
8441 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
8442 */
8443VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPU pVCpu, uint64_t fWhat)
8444{
8445 AssertPtr(pVCpu);
8446 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8447 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
8448}
8449
8450
8451/**
8452 * Check per-VM and per-VCPU force flag actions that require us to go back to
8453 * ring-3 for one reason or another.
8454 *
8455 * @returns Strict VBox status code (i.e. informational status codes too)
8456 * @retval VINF_SUCCESS if we don't have any actions that require going back to
8457 * ring-3.
8458 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
8459 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
8460 * interrupts)
8461 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
8462 * all EMTs to be in ring-3.
8463 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
8464 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
8465 * to the EM loop.
8466 *
8467 * @param pVCpu The cross context virtual CPU structure.
8468 * @param fStepping Whether we are single-stepping the guest using the
8469 * hypervisor debugger.
8470 */
8471static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPU pVCpu, bool fStepping)
8472{
8473 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8474
8475 /*
8476 * Update pending interrupts into the APIC's IRR.
8477 */
8478 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
8479 APICUpdatePendingInterrupts(pVCpu);
8480
8481 /*
8482 * Anything pending? Should be more likely than not if we're doing a good job.
8483 */
8484 PVM pVM = pVCpu->CTX_SUFF(pVM);
8485 if ( !fStepping
8486 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
8487 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
8488 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
8489 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
8490 return VINF_SUCCESS;
8491
8492 /* Pending PGM C3 sync. */
8493 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
8494 {
8495 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8496 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
8497 VBOXSTRICTRC rcStrict2 = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
8498 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
8499 if (rcStrict2 != VINF_SUCCESS)
8500 {
8501 AssertRC(VBOXSTRICTRC_VAL(rcStrict2));
8502 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict2)));
8503 return rcStrict2;
8504 }
8505 }
8506
8507 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
8508 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
8509 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
8510 {
8511 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
8512 int rc2 = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
8513 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc2));
8514 return rc2;
8515 }
8516
8517 /* Pending VM request packets, such as hardware interrupts. */
8518 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
8519 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
8520 {
8521 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
8522 Log4Func(("Pending VM request forcing us back to ring-3\n"));
8523 return VINF_EM_PENDING_REQUEST;
8524 }
8525
8526 /* Pending PGM pool flushes. */
8527 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
8528 {
8529 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
8530 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
8531 return VINF_PGM_POOL_FLUSH_PENDING;
8532 }
8533
8534 /* Pending DMA requests. */
8535 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
8536 {
8537 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
8538 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
8539 return VINF_EM_RAW_TO_R3;
8540 }
8541
8542 return VINF_SUCCESS;
8543}
8544
8545
8546/**
8547 * Converts any TRPM trap into a pending HM event. This is typically used when
8548 * entering from ring-3 (not longjmp returns).
8549 *
8550 * @param pVCpu The cross context virtual CPU structure.
8551 */
8552static void hmR0VmxTrpmTrapToPendingEvent(PVMCPU pVCpu)
8553{
8554 Assert(TRPMHasTrap(pVCpu));
8555 Assert(!pVCpu->hm.s.Event.fPending);
8556
8557 uint8_t uVector;
8558 TRPMEVENT enmTrpmEvent;
8559 RTGCUINT uErrCode;
8560 RTGCUINTPTR GCPtrFaultAddress;
8561 uint8_t cbInstr;
8562
8563 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr);
8564 AssertRC(rc);
8565
8566 uint32_t u32IntInfo;
8567 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8568 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent);
8569
8570 rc = TRPMResetTrap(pVCpu);
8571 AssertRC(rc);
8572 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8573 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8574
8575 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8576}
8577
8578
8579/**
8580 * Converts the pending HM event into a TRPM trap.
8581 *
8582 * @param pVCpu The cross context virtual CPU structure.
8583 */
8584static void hmR0VmxPendingEventToTrpmTrap(PVMCPU pVCpu)
8585{
8586 Assert(pVCpu->hm.s.Event.fPending);
8587
8588 /* If a trap was already pending, we did something wrong! */
8589 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8590
8591 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8592 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8593 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8594
8595 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8596
8597 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8598 AssertRC(rc);
8599
8600 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8601 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8602
8603 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8604 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8605 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
8606 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8607
8608 /* We're now done converting the pending event. */
8609 pVCpu->hm.s.Event.fPending = false;
8610}
8611
8612
8613/**
8614 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8615 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8616 *
8617 * @param pVCpu The cross context virtual CPU structure.
8618 * @param pVmcsInfo The VMCS info. object.
8619 */
8620static void hmR0VmxSetIntWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
8621{
8622 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8623 {
8624 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8625 {
8626 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8627 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8628 AssertRC(rc);
8629 }
8630 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8631}
8632
8633
8634/**
8635 * Clears the interrupt-window exiting control in the VMCS.
8636 *
8637 * @param pVmcsInfo The VMCS info. object.
8638 */
8639DECLINLINE(int) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8640{
8641 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8642 {
8643 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8644 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8645 }
8646 return VINF_SUCCESS;
8647}
8648
8649
8650/**
8651 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8652 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8653 *
8654 * @param pVCpu The cross context virtual CPU structure.
8655 * @param pVmcsInfo The VMCS info. object.
8656 */
8657static void hmR0VmxSetNmiWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
8658{
8659 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8660 {
8661 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8662 {
8663 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8664 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8665 AssertRC(rc);
8666 Log4Func(("Setup NMI-window exiting\n"));
8667 }
8668 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8669}
8670
8671
8672/**
8673 * Clears the NMI-window exiting control in the VMCS.
8674 *
8675 * @param pVmcsInfo The VMCS info. object.
8676 */
8677DECLINLINE(int) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8678{
8679 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8680 {
8681 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8682 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8683 }
8684 return VINF_SUCCESS;
8685}
8686
8687
8688/**
8689 * Does the necessary state syncing before returning to ring-3 for any reason
8690 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8691 *
8692 * @returns VBox status code.
8693 * @param pVCpu The cross context virtual CPU structure.
8694 * @param fImportState Whether to import the guest state from the VMCS back
8695 * to the guest-CPU context.
8696 *
8697 * @remarks No-long-jmp zone!!!
8698 */
8699static int hmR0VmxLeave(PVMCPU pVCpu, bool fImportState)
8700{
8701 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8702 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8703
8704 RTCPUID const idCpu = RTMpCpuId();
8705 Log4Func(("HostCpuId=%u\n", idCpu));
8706
8707 /*
8708 * !!! IMPORTANT !!!
8709 * If you modify code here, check whether hmR0VmxCallRing3Callback() needs to be updated too.
8710 */
8711
8712 /* Save the guest state if necessary. */
8713 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8714 if (fImportState)
8715 {
8716 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8717 AssertRCReturn(rc, rc);
8718 }
8719
8720 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8721 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8722 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8723
8724 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8725#ifdef VBOX_STRICT
8726 if (CPUMIsHyperDebugStateActive(pVCpu))
8727 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8728#endif
8729 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8730 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
8731 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
8732
8733#if HC_ARCH_BITS == 64
8734 /* Restore host-state bits that VT-x only restores partially. */
8735 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8736 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8737 {
8738 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
8739 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8740 }
8741 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8742#endif
8743
8744 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8745 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8746 {
8747 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8748 if (!fImportState)
8749 {
8750 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8751 AssertRCReturn(rc, rc);
8752 }
8753 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8754 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
8755 }
8756 else
8757 pVCpu->hm.s.vmx.fLazyMsrs = 0;
8758
8759 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8760 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8761
8762 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8763 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8764 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8765 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8766 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8767 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8768 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8769 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8770 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8771 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8772
8773 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8774
8775 /** @todo This partially defeats the purpose of having preemption hooks.
8776 * The problem is, deregistering the hooks should be moved to a place that
8777 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8778 * context.
8779 */
8780 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8781 AssertRCReturn(rc, rc);
8782
8783#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8784 /*
8785 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8786 * clear a shadow VMCS before allowing that VMCS to become active on another
8787 * logical processor. We may or may not be importing guest state which clears
8788 * it, so cover for it here.
8789 *
8790 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8791 */
8792 if ( pVmcsInfo->pvShadowVmcs
8793 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8794 {
8795 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8796 AssertRCReturn(rc, rc);
8797 }
8798
8799 /*
8800 * Flag that we need to re-import the host state if we switch to this VMCS before
8801 * executing guest or nested-guest code.
8802 */
8803 pVmcsInfo->idHostCpu = NIL_RTCPUID;
8804#endif
8805
8806 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8807 NOREF(idCpu);
8808 return VINF_SUCCESS;
8809}
8810
8811
8812/**
8813 * Leaves the VT-x session.
8814 *
8815 * @returns VBox status code.
8816 * @param pVCpu The cross context virtual CPU structure.
8817 *
8818 * @remarks No-long-jmp zone!!!
8819 */
8820static int hmR0VmxLeaveSession(PVMCPU pVCpu)
8821{
8822 HM_DISABLE_PREEMPT(pVCpu);
8823 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8824 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8825 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8826
8827 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8828 and done this from the VMXR0ThreadCtxCallback(). */
8829 if (!pVCpu->hm.s.fLeaveDone)
8830 {
8831 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8832 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8833 pVCpu->hm.s.fLeaveDone = true;
8834 }
8835 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8836
8837 /*
8838 * !!! IMPORTANT !!!
8839 * If you modify code here, make sure to check whether hmR0VmxCallRing3Callback() needs to be updated too.
8840 */
8841
8842 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8843 /** @todo Deregistering here means we need to VMCLEAR always
8844 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8845 * for calling VMMR0ThreadCtxHookDisable here! */
8846 VMMR0ThreadCtxHookDisable(pVCpu);
8847
8848 /* Leave HM context. This takes care of local init (term). */
8849 int rc = HMR0LeaveCpu(pVCpu);
8850
8851 HM_RESTORE_PREEMPT();
8852 return rc;
8853}
8854
8855
8856/**
8857 * Does the necessary state syncing before doing a longjmp to ring-3.
8858 *
8859 * @returns VBox status code.
8860 * @param pVCpu The cross context virtual CPU structure.
8861 *
8862 * @remarks No-long-jmp zone!!!
8863 */
8864DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPU pVCpu)
8865{
8866 return hmR0VmxLeaveSession(pVCpu);
8867}
8868
8869
8870/**
8871 * Take necessary actions before going back to ring-3.
8872 *
8873 * An action requires us to go back to ring-3. This function does the necessary
8874 * steps before we can safely return to ring-3. This is not the same as longjmps
8875 * to ring-3, this is voluntary and prepares the guest so it may continue
8876 * executing outside HM (recompiler/IEM).
8877 *
8878 * @returns VBox status code.
8879 * @param pVCpu The cross context virtual CPU structure.
8880 * @param rcExit The reason for exiting to ring-3. Can be
8881 * VINF_VMM_UNKNOWN_RING3_CALL.
8882 */
8883static int hmR0VmxExitToRing3(PVMCPU pVCpu, VBOXSTRICTRC rcExit)
8884{
8885 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8886
8887 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8888 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8889 {
8890 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8891 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8892 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8893 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8894 }
8895
8896 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8897 VMMRZCallRing3Disable(pVCpu);
8898 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8899
8900 /*
8901 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8902 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8903 *
8904 * This is because execution may continue from ring-3 and we would need to inject
8905 * the event from there (hence place it back in TRPM).
8906 */
8907 if (pVCpu->hm.s.Event.fPending)
8908 {
8909 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8910 Assert(!pVCpu->hm.s.Event.fPending);
8911
8912 /* Clear the events from the VMCS. */
8913 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8914 AssertRCReturn(rc, rc);
8915 }
8916#ifdef VBOX_STRICT
8917 else
8918 {
8919 /*
8920 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8921 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8922 * occasionally, see @bugref{9180#c42}.
8923 *
8924 * However, if the VM-entry failed, any VM entry-interruption info. field would
8925 * be left unmodified as the event would not have been injected to the guest. In
8926 * such cases, don't assert, we're not going to continue guest execution anyway.
8927 */
8928 uint32_t uExitReason;
8929 uint32_t uEntryIntInfo;
8930 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8931 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8932 AssertRC(rc);
8933 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8934 }
8935#endif
8936
8937 /*
8938 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8939 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8940 * (e.g. TPR below threshold).
8941 */
8942 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8943 {
8944 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8945 rc |= hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8946 AssertRCReturn(rc, rc);
8947 }
8948
8949 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8950 and if we're injecting an event we should have a TRPM trap pending. */
8951 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8952#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8953 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8954#endif
8955
8956 /* Save guest state and restore host state bits. */
8957 int rc = hmR0VmxLeaveSession(pVCpu);
8958 AssertRCReturn(rc, rc);
8959 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8960
8961 /* Thread-context hooks are unregistered at this point!!! */
8962
8963 /* Sync recompiler state. */
8964 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8965 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8966 | CPUM_CHANGED_LDTR
8967 | CPUM_CHANGED_GDTR
8968 | CPUM_CHANGED_IDTR
8969 | CPUM_CHANGED_TR
8970 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8971 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8972 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8973 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8974
8975 Assert(!pVCpu->hm.s.fClearTrapFlag);
8976
8977 /* Update the exit-to-ring 3 reason. */
8978 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8979
8980 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8981 if ( rcExit != VINF_EM_RAW_INTERRUPT
8982 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8983 {
8984 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8985 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8986 }
8987
8988 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8989
8990 /* We do -not- want any longjmp notifications after this! We must return to ring-3 ASAP. */
8991 VMMRZCallRing3RemoveNotification(pVCpu);
8992 VMMRZCallRing3Enable(pVCpu);
8993
8994 return rc;
8995}
8996
8997
8998/**
8999 * VMMRZCallRing3() callback wrapper which saves the guest state before we
9000 * longjump to ring-3 and possibly get preempted.
9001 *
9002 * @returns VBox status code.
9003 * @param pVCpu The cross context virtual CPU structure.
9004 * @param enmOperation The operation causing the ring-3 longjump.
9005 * @param pvUser User argument, currently unused, NULL.
9006 */
9007static DECLCALLBACK(int) hmR0VmxCallRing3Callback(PVMCPU pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
9008{
9009 RT_NOREF(pvUser);
9010 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
9011 {
9012 /*
9013 * !!! IMPORTANT !!!
9014 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
9015 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
9016 */
9017 VMMRZCallRing3RemoveNotification(pVCpu);
9018 VMMRZCallRing3Disable(pVCpu);
9019 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
9020 RTThreadPreemptDisable(&PreemptState);
9021
9022 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9023 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
9024 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
9025 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
9026
9027#if HC_ARCH_BITS == 64
9028 /* Restore host-state bits that VT-x only restores partially. */
9029 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
9030 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
9031 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
9032 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
9033#endif
9034
9035 /* Restore the lazy host MSRs as we're leaving VT-x context. */
9036 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
9037 hmR0VmxLazyRestoreHostMsrs(pVCpu);
9038
9039 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
9040 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
9041 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
9042
9043 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
9044 cleared as part of importing the guest state above. */
9045 hmR0VmxClearVmcs(pVmcsInfo);
9046
9047 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
9048 VMMR0ThreadCtxHookDisable(pVCpu);
9049 HMR0LeaveCpu(pVCpu);
9050 RTThreadPreemptRestore(&PreemptState);
9051 return VINF_SUCCESS;
9052 }
9053
9054 Assert(pVCpu);
9055 Assert(pvUser);
9056 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9057 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9058
9059 VMMRZCallRing3Disable(pVCpu);
9060 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9061
9062 Log4Func((" -> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
9063
9064 int rc = hmR0VmxLongJmpToRing3(pVCpu);
9065 AssertRCReturn(rc, rc);
9066
9067 VMMRZCallRing3Enable(pVCpu);
9068 return VINF_SUCCESS;
9069}
9070
9071
9072/**
9073 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
9074 * stack.
9075 *
9076 * @returns Strict VBox status code (i.e. informational status codes too).
9077 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
9078 * @param pVCpu The cross context virtual CPU structure.
9079 * @param uValue The value to push to the guest stack.
9080 */
9081static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPU pVCpu, uint16_t uValue)
9082{
9083 /*
9084 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
9085 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
9086 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
9087 */
9088 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9089 if (pCtx->sp == 1)
9090 return VINF_EM_RESET;
9091 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
9092 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
9093 AssertRC(rc);
9094 return rc;
9095}
9096
9097
9098/**
9099 * Injects an event into the guest upon VM-entry by updating the relevant fields
9100 * in the VM-entry area in the VMCS.
9101 *
9102 * @returns Strict VBox status code (i.e. informational status codes too).
9103 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
9104 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
9105 *
9106 * @param pVCpu The cross context virtual CPU structure.
9107 * @param pVmxTransient The VMX-transient structure.
9108 * @param pEvent The event being injected.
9109 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
9110 * will be updated if necessary. This cannot not be NULL.
9111 * @param fStepping Whether we're single-stepping guest execution and should
9112 * return VINF_EM_DBG_STEPPED if the event is injected
9113 * directly (registers modified by us, not by hardware on
9114 * VM-entry).
9115 */
9116static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
9117 uint32_t *pfIntrState)
9118{
9119 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
9120 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
9121 Assert(pfIntrState);
9122
9123 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9124 uint32_t u32IntInfo = pEvent->u64IntInfo;
9125 uint32_t const u32ErrCode = pEvent->u32ErrCode;
9126 uint32_t const cbInstr = pEvent->cbInstr;
9127 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
9128 uint32_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
9129 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
9130
9131#ifdef VBOX_STRICT
9132 /*
9133 * Validate the error-code-valid bit for hardware exceptions.
9134 * No error codes for exceptions in real-mode.
9135 *
9136 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
9137 */
9138 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
9139 && !CPUMIsGuestInRealModeEx(pCtx))
9140 {
9141 switch (uVector)
9142 {
9143 case X86_XCPT_PF:
9144 case X86_XCPT_DF:
9145 case X86_XCPT_TS:
9146 case X86_XCPT_NP:
9147 case X86_XCPT_SS:
9148 case X86_XCPT_GP:
9149 case X86_XCPT_AC:
9150 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
9151 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
9152 RT_FALL_THRU();
9153 default:
9154 break;
9155 }
9156 }
9157
9158 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
9159 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
9160 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9161#endif
9162
9163 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
9164
9165 /*
9166 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
9167 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
9168 * interrupt handler in the (real-mode) guest.
9169 *
9170 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
9171 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
9172 */
9173 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
9174 {
9175 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
9176 {
9177 /*
9178 * For CPUs with unrestricted guest execution enabled and with the guest
9179 * in real-mode, we must not set the deliver-error-code bit.
9180 *
9181 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
9182 */
9183 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
9184 }
9185 else
9186 {
9187 PVM pVM = pVCpu->CTX_SUFF(pVM);
9188 Assert(PDMVmmDevHeapIsEnabled(pVM));
9189 Assert(pVM->hm.s.vmx.pRealModeTSS);
9190 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
9191
9192 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
9193 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9194 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
9195 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
9196 AssertRCReturn(rc2, rc2);
9197
9198 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
9199 size_t const cbIdtEntry = sizeof(X86IDTR16);
9200 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
9201 {
9202 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
9203 if (uVector == X86_XCPT_DF)
9204 return VINF_EM_RESET;
9205
9206 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
9207 No error codes for exceptions in real-mode. */
9208 if (uVector == X86_XCPT_GP)
9209 {
9210 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
9211 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
9212 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
9213 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
9214 HMEVENT EventXcptDf;
9215 RT_ZERO(EventXcptDf);
9216 EventXcptDf.u64IntInfo = uXcptDfInfo;
9217 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
9218 }
9219
9220 /*
9221 * If we're injecting an event with no valid IDT entry, inject a #GP.
9222 * No error codes for exceptions in real-mode.
9223 *
9224 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
9225 */
9226 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
9227 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
9228 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
9229 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
9230 HMEVENT EventXcptGp;
9231 RT_ZERO(EventXcptGp);
9232 EventXcptGp.u64IntInfo = uXcptGpInfo;
9233 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
9234 }
9235
9236 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
9237 uint16_t uGuestIp = pCtx->ip;
9238 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
9239 {
9240 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
9241 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
9242 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
9243 }
9244 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
9245 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
9246
9247 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
9248 X86IDTR16 IdtEntry;
9249 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
9250 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
9251 AssertRCReturn(rc2, rc2);
9252
9253 /* Construct the stack frame for the interrupt/exception handler. */
9254 VBOXSTRICTRC rcStrict;
9255 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
9256 if (rcStrict == VINF_SUCCESS)
9257 {
9258 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
9259 if (rcStrict == VINF_SUCCESS)
9260 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
9261 }
9262
9263 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
9264 if (rcStrict == VINF_SUCCESS)
9265 {
9266 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
9267 pCtx->rip = IdtEntry.offSel;
9268 pCtx->cs.Sel = IdtEntry.uSel;
9269 pCtx->cs.ValidSel = IdtEntry.uSel;
9270 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
9271 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
9272 && uVector == X86_XCPT_PF)
9273 pCtx->cr2 = GCPtrFault;
9274
9275 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
9276 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
9277 | HM_CHANGED_GUEST_RSP);
9278
9279 /*
9280 * If we delivered a hardware exception (other than an NMI) and if there was
9281 * block-by-STI in effect, we should clear it.
9282 */
9283 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9284 {
9285 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
9286 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
9287 Log4Func(("Clearing inhibition due to STI\n"));
9288 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
9289 }
9290
9291 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
9292 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
9293
9294 /*
9295 * The event has been truly dispatched to the guest. Mark it as no longer pending so
9296 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
9297 */
9298 pVCpu->hm.s.Event.fPending = false;
9299
9300 /*
9301 * If we eventually support nested-guest execution without unrestricted guest execution,
9302 * we should set fInterceptEvents here.
9303 */
9304 Assert(!pVmxTransient->fIsNestedGuest);
9305
9306 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
9307 if (fStepping)
9308 rcStrict = VINF_EM_DBG_STEPPED;
9309 }
9310 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
9311 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
9312 return rcStrict;
9313 }
9314 }
9315
9316 /*
9317 * Validate.
9318 */
9319 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
9320 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
9321
9322 /*
9323 * Inject the event into the VMCS.
9324 */
9325 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
9326 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
9327 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
9328 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
9329 AssertRCReturn(rc, rc);
9330
9331 /*
9332 * Update guest CR2 if this is a page-fault.
9333 */
9334 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
9335 pCtx->cr2 = GCPtrFault;
9336
9337 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
9338 return VINF_SUCCESS;
9339}
9340
9341
9342/**
9343 * Evaluates the event to be delivered to the guest and sets it as the pending
9344 * event.
9345 *
9346 * @returns Strict VBox status code (i.e. informational status codes too).
9347 * @param pVCpu The cross context virtual CPU structure.
9348 * @param pVmxTransient The VMX-transient structure.
9349 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
9350 */
9351static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
9352{
9353 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9354 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9355 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
9356
9357 /* Get the current interruptibility-state of the guest and then figure out what can be injected. */
9358 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
9359 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9360 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9361 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9362
9363 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9364 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9365 Assert(!fBlockSti || pCtx->eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9366 Assert(!TRPMHasTrap(pVCpu));
9367 Assert(pfIntrState);
9368
9369 *pfIntrState = fIntrState;
9370
9371 /*
9372 * Toggling of interrupt force-flags here is safe since we update TRPM on premature exits
9373 * to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must NOT restore these force-flags.
9374 */
9375 /** @todo SMI. SMIs take priority over NMIs. */
9376 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI)) /* NMI. NMIs take priority over regular interrupts. */
9377 {
9378 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
9379 if ( !pVCpu->hm.s.Event.fPending
9380 && !fBlockNmi
9381 && !fBlockSti
9382 && !fBlockMovSS)
9383 {
9384#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9385 if ( fIsNestedGuest
9386 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
9387 return IEMExecVmxVmexitXcptNmi(pVCpu);
9388#endif
9389 hmR0VmxSetPendingXcptNmi(pVCpu);
9390 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
9391 Log4Func(("Pending NMI\n"));
9392 }
9393 else if (!fIsNestedGuest)
9394 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
9395 }
9396 /*
9397 * Check if the guest can receive external interrupts (PIC/APIC). Once PDMGetInterrupt() returns
9398 * a valid interrupt we -must- deliver the interrupt. We can no longer re-request it from the APIC.
9399 */
9400 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9401 && !pVCpu->hm.s.fSingleInstruction)
9402 {
9403 Assert(!DBGFIsStepping(pVCpu));
9404 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
9405 AssertRCReturn(rc, rc);
9406 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
9407 if ( !pVCpu->hm.s.Event.fPending
9408 && !fBlockInt
9409 && !fBlockSti
9410 && !fBlockMovSS)
9411 {
9412#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9413 if ( fIsNestedGuest
9414 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9415 {
9416 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0/* uVector */, true /* fIntPending */);
9417 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9418 return rcStrict;
9419 }
9420#endif
9421 uint8_t u8Interrupt;
9422 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9423 if (RT_SUCCESS(rc))
9424 {
9425#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9426 if ( fIsNestedGuest
9427 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
9428 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
9429 {
9430 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9431 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9432 return rcStrict;
9433 }
9434#endif
9435 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9436 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
9437 }
9438 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9439 {
9440 if ( !fIsNestedGuest
9441 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9442 hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u8Interrupt >> 4);
9443 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9444
9445 /*
9446 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9447 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9448 * need to re-set this force-flag here.
9449 */
9450 }
9451 else
9452 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9453 }
9454 else if (!fIsNestedGuest)
9455 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
9456 }
9457
9458 return VINF_SUCCESS;
9459}
9460
9461
9462/**
9463 * Injects any pending events into the guest if the guest is in a state to
9464 * receive them.
9465 *
9466 * @returns Strict VBox status code (i.e. informational status codes too).
9467 * @param pVCpu The cross context virtual CPU structure.
9468 * @param pVmxTransient The VMX-transient structure.
9469 * @param fIntrState The VT-x guest-interruptibility state.
9470 * @param fStepping Whether we are single-stepping the guest using the
9471 * hypervisor debugger and should return
9472 * VINF_EM_DBG_STEPPED if the event was dispatched
9473 * directly.
9474 */
9475static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9476{
9477 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9478 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9479
9480 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9481 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9482
9483 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9484 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9485 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9486 Assert(!TRPMHasTrap(pVCpu));
9487
9488 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9489 if (pVCpu->hm.s.Event.fPending)
9490 {
9491 /*
9492 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9493 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9494 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9495 *
9496 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9497 */
9498 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9499#ifdef VBOX_STRICT
9500 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9501 {
9502 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9503 Assert(!fBlockInt);
9504 Assert(!fBlockSti);
9505 Assert(!fBlockMovSS);
9506 }
9507 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9508 {
9509 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9510 Assert(!fBlockSti);
9511 Assert(!fBlockMovSS);
9512 Assert(!fBlockNmi);
9513 }
9514#endif
9515 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9516 uIntType));
9517
9518 /*
9519 * Inject the event and get any changes to the guest-interruptibility state.
9520 *
9521 * The guest-interruptibility state may need to be updated if we inject the event
9522 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9523 */
9524 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9525 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9526
9527 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9528 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9529 else
9530 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9531 }
9532
9533 /*
9534 * Update the guest-interruptibility state.
9535 *
9536 * This is required for the real-on-v86 software interrupt injection case above, as well as
9537 * updates to the guest state from ring-3 or IEM/REM.
9538 */
9539 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9540 AssertRCReturn(rc, rc);
9541
9542 /*
9543 * There's no need to clear the VM-entry interruption-information field here if we're not
9544 * injecting anything. VT-x clears the valid bit on every VM-exit.
9545 *
9546 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9547 */
9548
9549 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9550 NOREF(fBlockMovSS); NOREF(fBlockSti);
9551 return rcStrict;
9552}
9553
9554
9555/**
9556 * Enters the VT-x session.
9557 *
9558 * @returns VBox status code.
9559 * @param pVCpu The cross context virtual CPU structure.
9560 */
9561VMMR0DECL(int) VMXR0Enter(PVMCPU pVCpu)
9562{
9563 AssertPtr(pVCpu);
9564 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9565 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9566
9567 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9568 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9569 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9570
9571#ifdef VBOX_STRICT
9572 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9573 RTCCUINTREG uHostCr4 = ASMGetCR4();
9574 if (!(uHostCr4 & X86_CR4_VMXE))
9575 {
9576 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9577 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9578 }
9579#endif
9580
9581 /*
9582 * Load the appropriate VMCS as the current and active one.
9583 */
9584 PVMXVMCSINFO pVmcsInfo;
9585 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9586 if (!fInNestedGuestMode)
9587 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
9588 else
9589 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
9590 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9591 if (RT_SUCCESS(rc))
9592 {
9593 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9594 pVCpu->hm.s.fLeaveDone = false;
9595 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9596
9597 /*
9598 * Do the EMT scheduled L1D flush here if needed.
9599 */
9600 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9601 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9602 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9603 hmR0MdsClear();
9604 }
9605 return rc;
9606}
9607
9608
9609/**
9610 * The thread-context callback (only on platforms which support it).
9611 *
9612 * @param enmEvent The thread-context event.
9613 * @param pVCpu The cross context virtual CPU structure.
9614 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9615 * @thread EMT(pVCpu)
9616 */
9617VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit)
9618{
9619 AssertPtr(pVCpu);
9620 RT_NOREF1(fGlobalInit);
9621
9622 switch (enmEvent)
9623 {
9624 case RTTHREADCTXEVENT_OUT:
9625 {
9626 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9627 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9628 VMCPU_ASSERT_EMT(pVCpu);
9629
9630 /* No longjmps (logger flushes, locks) in this fragile context. */
9631 VMMRZCallRing3Disable(pVCpu);
9632 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9633
9634 /* Restore host-state (FPU, debug etc.) */
9635 if (!pVCpu->hm.s.fLeaveDone)
9636 {
9637 /*
9638 * Do -not- import the guest-state here as we might already be in the middle of importing
9639 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9640 */
9641 hmR0VmxLeave(pVCpu, false /* fImportState */);
9642 pVCpu->hm.s.fLeaveDone = true;
9643 }
9644
9645 /* Leave HM context, takes care of local init (term). */
9646 int rc = HMR0LeaveCpu(pVCpu);
9647 AssertRC(rc);
9648
9649 /* Restore longjmp state. */
9650 VMMRZCallRing3Enable(pVCpu);
9651 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9652 break;
9653 }
9654
9655 case RTTHREADCTXEVENT_IN:
9656 {
9657 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9658 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9659 VMCPU_ASSERT_EMT(pVCpu);
9660
9661 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9662 VMMRZCallRing3Disable(pVCpu);
9663 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9664
9665 /* Initialize the bare minimum state required for HM. This takes care of
9666 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9667 int rc = hmR0EnterCpu(pVCpu);
9668 AssertRC(rc);
9669 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9670 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9671
9672 /* Load the active VMCS as the current one. */
9673 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9674 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9675 AssertRC(rc);
9676 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9677 pVCpu->hm.s.fLeaveDone = false;
9678
9679 /* Do the EMT scheduled L1D flush if needed. */
9680 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9681 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9682
9683 /* Restore longjmp state. */
9684 VMMRZCallRing3Enable(pVCpu);
9685 break;
9686 }
9687
9688 default:
9689 break;
9690 }
9691}
9692
9693
9694/**
9695 * Exports the host state into the VMCS host-state area.
9696 * Sets up the VM-exit MSR-load area.
9697 *
9698 * The CPU state will be loaded from these fields on every successful VM-exit.
9699 *
9700 * @returns VBox status code.
9701 * @param pVCpu The cross context virtual CPU structure.
9702 *
9703 * @remarks No-long-jump zone!!!
9704 */
9705static int hmR0VmxExportHostState(PVMCPU pVCpu)
9706{
9707 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9708
9709 int rc = VINF_SUCCESS;
9710 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9711 {
9712 rc = hmR0VmxExportHostControlRegs();
9713 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9714
9715 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
9716 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9717
9718 rc = hmR0VmxExportHostMsrs(pVCpu);
9719 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9720
9721 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9722 }
9723 return rc;
9724}
9725
9726
9727/**
9728 * Saves the host state in the VMCS host-state.
9729 *
9730 * @returns VBox status code.
9731 * @param pVCpu The cross context virtual CPU structure.
9732 *
9733 * @remarks No-long-jump zone!!!
9734 */
9735VMMR0DECL(int) VMXR0ExportHostState(PVMCPU pVCpu)
9736{
9737 AssertPtr(pVCpu);
9738 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9739
9740 /*
9741 * Export the host state here while entering HM context.
9742 * When thread-context hooks are used, we might get preempted and have to re-save the host
9743 * state but most of the time we won't be, so do it here before we disable interrupts.
9744 */
9745 return hmR0VmxExportHostState(pVCpu);
9746}
9747
9748
9749/**
9750 * Exports the guest state into the VMCS guest-state area.
9751 *
9752 * The will typically be done before VM-entry when the guest-CPU state and the
9753 * VMCS state may potentially be out of sync.
9754 *
9755 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9756 * VM-entry controls.
9757 * Sets up the appropriate VMX non-root function to execute guest code based on
9758 * the guest CPU mode.
9759 *
9760 * @returns VBox strict status code.
9761 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9762 * without unrestricted guest execution and the VMMDev is not presently
9763 * mapped (e.g. EFI32).
9764 *
9765 * @param pVCpu The cross context virtual CPU structure.
9766 * @param pVmxTransient The VMX-transient structure.
9767 *
9768 * @remarks No-long-jump zone!!!
9769 */
9770static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9771{
9772 AssertPtr(pVCpu);
9773 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9774 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9775
9776 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9777
9778 /*
9779 * Determine real-on-v86 mode.
9780 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9781 */
9782 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9783 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9784 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9785 pVmcsInfo->RealMode. fRealOnV86Active = false;
9786 else
9787 {
9788 Assert(!pVmxTransient->fIsNestedGuest);
9789 pVmcsInfo->RealMode.fRealOnV86Active = true;
9790 }
9791
9792 /*
9793 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9794 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9795 */
9796 /** @todo r=ramshankar: Move hmR0VmxSelectVMRunHandler inside
9797 * hmR0VmxExportGuestEntryExitCtls and do it conditionally. There shouldn't
9798 * be a need to evaluate this everytime since I'm pretty sure we intercept
9799 * all guest paging mode changes. */
9800 int rc = hmR0VmxSelectVMRunHandler(pVCpu, pVmxTransient);
9801 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9802
9803 rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9804 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9805
9806 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9807 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9808
9809 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9810 if (rcStrict == VINF_SUCCESS)
9811 { /* likely */ }
9812 else
9813 {
9814 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9815 return rcStrict;
9816 }
9817
9818 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9819 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9820
9821 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9822 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9823
9824 rc = hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9825 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9826
9827 rc = hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9828 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9829
9830 rc = hmR0VmxExportGuestRip(pVCpu);
9831 rc |= hmR0VmxExportGuestRsp(pVCpu);
9832 rc |= hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9833 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9834
9835 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9836 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9837
9838 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9839 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9840 | HM_CHANGED_GUEST_CR2
9841 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9842 | HM_CHANGED_GUEST_X87
9843 | HM_CHANGED_GUEST_SSE_AVX
9844 | HM_CHANGED_GUEST_OTHER_XSAVE
9845 | HM_CHANGED_GUEST_XCRx
9846 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9847 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9848 | HM_CHANGED_GUEST_TSC_AUX
9849 | HM_CHANGED_GUEST_OTHER_MSRS
9850 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9851
9852 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9853 return rc;
9854}
9855
9856
9857/**
9858 * Exports the state shared between the host and guest into the VMCS.
9859 *
9860 * @param pVCpu The cross context virtual CPU structure.
9861 * @param pVmxTransient The VMX-transient structure.
9862 *
9863 * @remarks No-long-jump zone!!!
9864 */
9865static void hmR0VmxExportSharedState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9866{
9867 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9868 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9869
9870 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9871 {
9872 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9873 AssertRC(rc);
9874 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9875
9876 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9877 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9878 {
9879 rc = hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9880 AssertRC(rc);
9881 }
9882 }
9883
9884 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9885 {
9886 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9887 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9888 }
9889
9890 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9891 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9892}
9893
9894
9895/**
9896 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9897 *
9898 * @returns Strict VBox status code (i.e. informational status codes too).
9899 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9900 * without unrestricted guest execution and the VMMDev is not presently
9901 * mapped (e.g. EFI32).
9902 *
9903 * @param pVCpu The cross context virtual CPU structure.
9904 * @param pVmxTransient The VMX-transient structure.
9905 *
9906 * @remarks No-long-jump zone!!!
9907 */
9908static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9909{
9910 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9911 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9912 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9913
9914#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9915 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9916#endif
9917
9918 /*
9919 * For many exits it's only RIP that changes and hence try to export it first
9920 * without going through a lot of change flag checks.
9921 */
9922 VBOXSTRICTRC rcStrict;
9923 uint64_t fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9924 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9925 if ((fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)) == HM_CHANGED_GUEST_RIP)
9926 {
9927 rcStrict = hmR0VmxExportGuestRip(pVCpu);
9928 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9929 { /* likely */}
9930 else
9931 AssertMsgFailedReturn(("Failed to export guest RIP! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
9932 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9933 }
9934 else if (fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9935 {
9936 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9937 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9938 { /* likely */}
9939 else
9940 {
9941 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9942 VBOXSTRICTRC_VAL(rcStrict)));
9943 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9944 return rcStrict;
9945 }
9946 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9947 }
9948 else
9949 rcStrict = VINF_SUCCESS;
9950
9951#ifdef VBOX_STRICT
9952 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9953 fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9954 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9955 AssertMsg(!(fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)),
9956 ("fCtxChanged=%#RX64\n", fCtxChanged));
9957#endif
9958 return rcStrict;
9959}
9960
9961
9962/**
9963 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9964 * and update error record fields accordingly.
9965 *
9966 * @returns VMX_IGS_* error codes.
9967 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9968 * wrong with the guest state.
9969 *
9970 * @param pVCpu The cross context virtual CPU structure.
9971 * @param pVmcsInfo The VMCS info. object.
9972 *
9973 * @remarks This function assumes our cache of the VMCS controls
9974 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9975 */
9976static uint32_t hmR0VmxCheckGuestState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
9977{
9978#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9979#define HMVMX_CHECK_BREAK(expr, err) do { \
9980 if (!(expr)) { uError = (err); break; } \
9981 } while (0)
9982
9983 int rc;
9984 PVM pVM = pVCpu->CTX_SUFF(pVM);
9985 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9986 uint32_t uError = VMX_IGS_ERROR;
9987 uint32_t u32Val;
9988 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9989
9990 do
9991 {
9992 /*
9993 * CR0.
9994 */
9995 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9996 uint32_t fSetCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9997 uint32_t const fZapCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9998 /* Exceptions for unrestricted guest execution for fixed CR0 bits (PE, PG).
9999 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
10000 if (fUnrestrictedGuest)
10001 fSetCr0 &= ~(X86_CR0_PE | X86_CR0_PG);
10002
10003 uint32_t u32GuestCr0;
10004 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32GuestCr0);
10005 AssertRCBreak(rc);
10006 HMVMX_CHECK_BREAK((u32GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
10007 HMVMX_CHECK_BREAK(!(u32GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
10008 if ( !fUnrestrictedGuest
10009 && (u32GuestCr0 & X86_CR0_PG)
10010 && !(u32GuestCr0 & X86_CR0_PE))
10011 {
10012 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
10013 }
10014
10015 /*
10016 * CR4.
10017 */
10018 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
10019 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
10020 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
10021
10022 uint32_t u32GuestCr4;
10023 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32GuestCr4);
10024 AssertRCBreak(rc);
10025 HMVMX_CHECK_BREAK((u32GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
10026 HMVMX_CHECK_BREAK(!(u32GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
10027
10028 /*
10029 * IA32_DEBUGCTL MSR.
10030 */
10031 uint64_t u64Val;
10032 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
10033 AssertRCBreak(rc);
10034 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
10035 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
10036 {
10037 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
10038 }
10039 uint64_t u64DebugCtlMsr = u64Val;
10040
10041#ifdef VBOX_STRICT
10042 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
10043 AssertRCBreak(rc);
10044 Assert(u32Val == pVmcsInfo->u32EntryCtls);
10045#endif
10046 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
10047
10048 /*
10049 * RIP and RFLAGS.
10050 */
10051 uint32_t u32Eflags;
10052#if HC_ARCH_BITS == 64
10053 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RIP, &u64Val);
10054 AssertRCBreak(rc);
10055 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
10056 if ( !fLongModeGuest
10057 || !pCtx->cs.Attr.n.u1Long)
10058 {
10059 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
10060 }
10061 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
10062 * must be identical if the "IA-32e mode guest" VM-entry
10063 * control is 1 and CS.L is 1. No check applies if the
10064 * CPU supports 64 linear-address bits. */
10065
10066 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
10067 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RFLAGS, &u64Val);
10068 AssertRCBreak(rc);
10069 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
10070 VMX_IGS_RFLAGS_RESERVED);
10071 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10072 u32Eflags = u64Val;
10073#else
10074 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Eflags);
10075 AssertRCBreak(rc);
10076 HMVMX_CHECK_BREAK(!(u32Eflags & 0xffc08028), VMX_IGS_RFLAGS_RESERVED); /* Bit 31:22, Bit 15, 5, 3 MBZ. */
10077 HMVMX_CHECK_BREAK((u32Eflags & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10078#endif
10079
10080 if ( fLongModeGuest
10081 || ( fUnrestrictedGuest
10082 && !(u32GuestCr0 & X86_CR0_PE)))
10083 {
10084 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
10085 }
10086
10087 uint32_t u32EntryInfo;
10088 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
10089 AssertRCBreak(rc);
10090 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10091 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
10092
10093 /*
10094 * 64-bit checks.
10095 */
10096#if HC_ARCH_BITS == 64
10097 if (fLongModeGuest)
10098 {
10099 HMVMX_CHECK_BREAK(u32GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
10100 HMVMX_CHECK_BREAK(u32GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
10101 }
10102
10103 if ( !fLongModeGuest
10104 && (u32GuestCr4 & X86_CR4_PCIDE))
10105 {
10106 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
10107 }
10108
10109 /** @todo CR3 field must be such that bits 63:52 and bits in the range
10110 * 51:32 beyond the processor's physical-address width are 0. */
10111
10112 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
10113 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
10114 {
10115 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
10116 }
10117
10118 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
10119 AssertRCBreak(rc);
10120 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
10121
10122 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
10123 AssertRCBreak(rc);
10124 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
10125#endif
10126
10127 /*
10128 * PERF_GLOBAL MSR.
10129 */
10130 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
10131 {
10132 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
10133 AssertRCBreak(rc);
10134 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
10135 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
10136 }
10137
10138 /*
10139 * PAT MSR.
10140 */
10141 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
10142 {
10143 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
10144 AssertRCBreak(rc);
10145 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
10146 for (unsigned i = 0; i < 8; i++)
10147 {
10148 uint8_t u8Val = (u64Val & 0xff);
10149 if ( u8Val != 0 /* UC */
10150 && u8Val != 1 /* WC */
10151 && u8Val != 4 /* WT */
10152 && u8Val != 5 /* WP */
10153 && u8Val != 6 /* WB */
10154 && u8Val != 7 /* UC- */)
10155 {
10156 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
10157 }
10158 u64Val >>= 8;
10159 }
10160 }
10161
10162 /*
10163 * EFER MSR.
10164 */
10165 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
10166 {
10167 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
10168 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
10169 AssertRCBreak(rc);
10170 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
10171 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
10172 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
10173 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
10174 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
10175 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
10176 * iemVmxVmentryCheckGuestState(). */
10177 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10178 || !(u32GuestCr0 & X86_CR0_PG)
10179 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
10180 VMX_IGS_EFER_LMA_LME_MISMATCH);
10181 }
10182
10183 /*
10184 * Segment registers.
10185 */
10186 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10187 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
10188 if (!(u32Eflags & X86_EFL_VM))
10189 {
10190 /* CS */
10191 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
10192 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
10193 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
10194 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
10195 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10196 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
10197 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10198 /* CS cannot be loaded with NULL in protected mode. */
10199 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
10200 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
10201 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
10202 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
10203 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
10204 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
10205 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
10206 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
10207 else
10208 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
10209
10210 /* SS */
10211 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10212 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
10213 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
10214 if ( !(pCtx->cr0 & X86_CR0_PE)
10215 || pCtx->cs.Attr.n.u4Type == 3)
10216 {
10217 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
10218 }
10219 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
10220 {
10221 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
10222 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
10223 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
10224 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
10225 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
10226 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10227 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
10228 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10229 }
10230
10231 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
10232 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
10233 {
10234 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
10235 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
10236 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10237 || pCtx->ds.Attr.n.u4Type > 11
10238 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10239 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
10240 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
10241 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
10242 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10243 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
10244 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10245 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10246 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
10247 }
10248 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
10249 {
10250 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
10251 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
10252 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10253 || pCtx->es.Attr.n.u4Type > 11
10254 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10255 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
10256 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
10257 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
10258 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10259 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
10260 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10261 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10262 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
10263 }
10264 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
10265 {
10266 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
10267 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
10268 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10269 || pCtx->fs.Attr.n.u4Type > 11
10270 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
10271 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
10272 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
10273 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
10274 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10275 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
10276 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10277 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10278 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
10279 }
10280 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
10281 {
10282 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
10283 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
10284 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10285 || pCtx->gs.Attr.n.u4Type > 11
10286 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
10287 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
10288 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
10289 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
10290 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10291 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
10292 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10293 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10294 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
10295 }
10296 /* 64-bit capable CPUs. */
10297#if HC_ARCH_BITS == 64
10298 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10299 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10300 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10301 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10302 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10303 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10304 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10305 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10306 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10307 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10308 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10309#endif
10310 }
10311 else
10312 {
10313 /* V86 mode checks. */
10314 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
10315 if (pVmcsInfo->RealMode.fRealOnV86Active)
10316 {
10317 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
10318 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
10319 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
10320 }
10321 else
10322 {
10323 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
10324 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
10325 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
10326 }
10327
10328 /* CS */
10329 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10330 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10331 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10332 /* SS */
10333 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10334 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10335 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10336 /* DS */
10337 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10338 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10339 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10340 /* ES */
10341 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10342 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10343 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10344 /* FS */
10345 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10346 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10347 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10348 /* GS */
10349 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10350 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10351 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10352 /* 64-bit capable CPUs. */
10353#if HC_ARCH_BITS == 64
10354 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10355 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10356 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10357 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10358 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10359 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10360 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10361 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10362 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10363 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10364 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10365#endif
10366 }
10367
10368 /*
10369 * TR.
10370 */
10371 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10372 /* 64-bit capable CPUs. */
10373#if HC_ARCH_BITS == 64
10374 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10375#endif
10376 if (fLongModeGuest)
10377 {
10378 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10379 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10380 }
10381 else
10382 {
10383 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10384 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10385 VMX_IGS_TR_ATTR_TYPE_INVALID);
10386 }
10387 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10388 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10389 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10390 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10391 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10392 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10393 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10394 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10395
10396 /*
10397 * GDTR and IDTR.
10398 */
10399#if HC_ARCH_BITS == 64
10400 rc = VMXReadVmcs64(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10401 AssertRCBreak(rc);
10402 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10403
10404 rc = VMXReadVmcs64(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10405 AssertRCBreak(rc);
10406 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10407#endif
10408
10409 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10410 AssertRCBreak(rc);
10411 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10412
10413 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10414 AssertRCBreak(rc);
10415 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10416
10417 /*
10418 * Guest Non-Register State.
10419 */
10420 /* Activity State. */
10421 uint32_t u32ActivityState;
10422 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10423 AssertRCBreak(rc);
10424 HMVMX_CHECK_BREAK( !u32ActivityState
10425 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10426 VMX_IGS_ACTIVITY_STATE_INVALID);
10427 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10428 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10429 uint32_t u32IntrState;
10430 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
10431 AssertRCBreak(rc);
10432 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10433 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10434 {
10435 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10436 }
10437
10438 /** @todo Activity state and injecting interrupts. Left as a todo since we
10439 * currently don't use activity states but ACTIVE. */
10440
10441 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10442 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10443
10444 /* Guest interruptibility-state. */
10445 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10446 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10447 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10448 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10449 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10450 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10451 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10452 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10453 {
10454 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10455 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10456 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10457 }
10458 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10459 {
10460 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10461 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10462 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10463 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10464 }
10465 /** @todo Assumes the processor is not in SMM. */
10466 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10467 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10468 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10469 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10470 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10471 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10472 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10473 {
10474 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI),
10475 VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10476 }
10477
10478 /* Pending debug exceptions. */
10479#if HC_ARCH_BITS == 64
10480 rc = VMXReadVmcs64(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10481 AssertRCBreak(rc);
10482 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10483 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10484 u32Val = u64Val; /* For pending debug exceptions checks below. */
10485#else
10486 rc = VMXReadVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u32Val);
10487 AssertRCBreak(rc);
10488 /* Bits 31:15, Bit 13, Bits 11:4 MBZ. */
10489 HMVMX_CHECK_BREAK(!(u32Val & 0xffffaff0), VMX_IGS_PENDING_DEBUG_RESERVED);
10490#endif
10491
10492 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10493 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10494 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10495 {
10496 if ( (u32Eflags & X86_EFL_TF)
10497 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10498 {
10499 /* Bit 14 is PendingDebug.BS. */
10500 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10501 }
10502 if ( !(u32Eflags & X86_EFL_TF)
10503 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10504 {
10505 /* Bit 14 is PendingDebug.BS. */
10506 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10507 }
10508 }
10509
10510 /* VMCS link pointer. */
10511 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10512 AssertRCBreak(rc);
10513 if (u64Val != UINT64_C(0xffffffffffffffff))
10514 {
10515 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10516 /** @todo Bits beyond the processor's physical-address width MBZ. */
10517 /** @todo SMM checks. */
10518 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10519 Assert(pVmcsInfo->pvShadowVmcs);
10520 VMXVMCSREVID VmcsRevId;
10521 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10522 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
10523 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10524 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10525 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10526 }
10527
10528 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10529 * not using nested paging? */
10530 if ( pVM->hm.s.fNestedPaging
10531 && !fLongModeGuest
10532 && CPUMIsGuestInPAEModeEx(pCtx))
10533 {
10534 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10535 AssertRCBreak(rc);
10536 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10537
10538 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10539 AssertRCBreak(rc);
10540 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10541
10542 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10543 AssertRCBreak(rc);
10544 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10545
10546 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10547 AssertRCBreak(rc);
10548 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10549 }
10550
10551 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10552 if (uError == VMX_IGS_ERROR)
10553 uError = VMX_IGS_REASON_NOT_FOUND;
10554 } while (0);
10555
10556 pVCpu->hm.s.u32HMError = uError;
10557 return uError;
10558
10559#undef HMVMX_ERROR_BREAK
10560#undef HMVMX_CHECK_BREAK
10561}
10562
10563
10564/**
10565 * Map the APIC-access page for virtualizing APIC accesses.
10566 *
10567 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10568 * this not done as part of exporting guest state, see @bugref{8721}.
10569 *
10570 * @returns VBox status code.
10571 * @param pVCpu The cross context virtual CPU structure.
10572 */
10573static int hmR0VmxMapHCApicAccessPage(PVMCPU pVCpu)
10574{
10575 PVM pVM = pVCpu->CTX_SUFF(pVM);
10576 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10577
10578 Assert(PDMHasApic(pVM));
10579 Assert(u64MsrApicBase);
10580
10581 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10582 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10583
10584 /* Unalias the existing mapping. */
10585 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10586 AssertRCReturn(rc, rc);
10587
10588 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10589 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10590 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10591 AssertRCReturn(rc, rc);
10592
10593 /* Update the per-VCPU cache of the APIC base MSR. */
10594 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10595 return VINF_SUCCESS;
10596}
10597
10598
10599/**
10600 * Wrapper for dispatching host NMIs.
10601 *
10602 * @returns VBox status code.
10603 * @param pVCpu The cross context virtual CPU structure.
10604 */
10605static int hmR0VmxExitHostNmi(PVMCPU pVCpu)
10606{
10607 VMXDispatchHostNmi();
10608 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10609 return VINF_SUCCESS;
10610}
10611
10612
10613#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10614/**
10615 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10616 * nested-guest using hardware-assisted VMX.
10617 *
10618 * @param pVCpu The cross context virtual CPU structure.
10619 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10620 * @param pVmcsInfoGst The guest VMCS info. object.
10621 */
10622static void hmR0VmxMergeMsrBitmapNested(PCVMCPU pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10623{
10624 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10625 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10626 Assert(pu64MsrBitmap);
10627
10628 /*
10629 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10630 * MSR that is intercepted by the guest is also intercepted while executing the
10631 * nested-guest using hardware-assisted VMX.
10632 *
10633 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
10634 * nested-guest VM-exit even if the outer guest is not intercepting some
10635 * MSRs. We cannot assume the caller has initialized the nested-guest
10636 * MSR bitmap in this case.
10637 *
10638 * The guest hypervisor may also switch whether it uses MSR bitmaps for
10639 * each VM-entry, hence initializing it once per-VM while setting up the
10640 * nested-guest VMCS is not sufficient.
10641 */
10642 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10643 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10644 {
10645 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10646 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10647 Assert(pu64MsrBitmapNstGst);
10648 Assert(pu64MsrBitmapGst);
10649
10650 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10651 for (uint32_t i = 0; i < cFrags; i++)
10652 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10653 }
10654 else
10655 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10656}
10657
10658
10659/**
10660 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10661 * hardware-assisted VMX execution of the nested-guest.
10662 *
10663 * For a guest, we don't modify these controls once we set up the VMCS and hence
10664 * this function is never called.
10665 *
10666 * For nested-guests since the guest hypervisor provides these controls on every
10667 * nested-guest VM-entry and could potentially change them everytime we need to
10668 * merge them before every nested-guest VM-entry.
10669 *
10670 * @returns VBox status code.
10671 * @param pVCpu The cross context virtual CPU structure.
10672 */
10673static int hmR0VmxMergeVmcsNested(PVMCPU pVCpu)
10674{
10675 PVM pVM = pVCpu->CTX_SUFF(pVM);
10676 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
10677 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10678 Assert(pVmcsNstGst);
10679
10680 /*
10681 * Merge the controls with the requirements of the guest VMCS.
10682 *
10683 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10684 * VMCS with the features supported by the physical CPU as it's already done by the
10685 * VMLAUNCH/VMRESUME instruction emulation.
10686 *
10687 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10688 * derived from the VMX features supported by the physical CPU.
10689 */
10690
10691 /* Pin-based VM-execution controls. */
10692 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10693
10694 /* Processor-based VM-execution controls. */
10695 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10696 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10697 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10698 | VMX_PROC_CTLS_USE_TPR_SHADOW
10699 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10700
10701 /* Secondary processor-based VM-execution controls. */
10702 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10703 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10704 | VMX_PROC_CTLS2_INVPCID
10705 | VMX_PROC_CTLS2_VMCS_SHADOWING
10706 | VMX_PROC_CTLS2_RDTSCP
10707 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10708 | VMX_PROC_CTLS2_APIC_REG_VIRT
10709 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10710 | VMX_PROC_CTLS2_VMFUNC));
10711
10712 /*
10713 * VM-entry controls:
10714 * These controls contains state that depends on the nested-guest state (primarily
10715 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10716 * VM-exit. Although the guest hypervisor cannot change it, we need to in order to
10717 * properly continue executing the nested-guest if the EFER MSR changes but does not
10718 * cause a nested-guest VM-exits.
10719 *
10720 * VM-exit controls:
10721 * These controls specify the host state on return. We cannot use the controls from
10722 * the guest hypervisor state as is as it would contain the guest state rather than
10723 * the host state. Since the host state is subject to change (e.g. preemption, trips
10724 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10725 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10726 *
10727 * VM-entry MSR-load:
10728 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10729 * context by the VMLAUNCH/VMRESUME instruction emulation.
10730 *
10731 * VM-exit MSR-store:
10732 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10733 * back into the VM-exit MSR-store area.
10734 *
10735 * VM-exit MSR-load areas:
10736 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10737 * can entirely ignore what the guest hypervisor wants to load here.
10738 */
10739
10740 /*
10741 * Exception bitmap.
10742 *
10743 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10744 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10745 * code more flexible if intercepting exceptions become more dynamic in the future we do
10746 * it as part of exporting the nested-guest state.
10747 */
10748 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10749
10750 /*
10751 * CR0/CR4 guest/host mask.
10752 *
10753 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10754 * cause VM-exits, so we need to merge them here.
10755 */
10756 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10757 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10758
10759 /*
10760 * Page-fault error-code mask and match.
10761 *
10762 * Although we require unrestricted guest execution (and thereby nested-paging) for
10763 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10764 * normally intercept #PFs, it might intercept them for debugging purposes.
10765 *
10766 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10767 * If the outer guest is intercepting #PFs we must intercept all #PFs.
10768 */
10769 uint32_t u32XcptPFMask;
10770 uint32_t u32XcptPFMatch;
10771 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10772 {
10773 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10774 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10775 }
10776 else
10777 {
10778 u32XcptPFMask = 0;
10779 u32XcptPFMatch = 0;
10780 }
10781
10782 /*
10783 * Pause-Loop exiting.
10784 */
10785 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10786 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10787
10788 /*
10789 * I/O Bitmap.
10790 *
10791 * We do not use the I/O bitmap that may be provided by the guest hypervisor as we always
10792 * intercept all I/O port accesses.
10793 */
10794 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10795
10796 /*
10797 * VMCS shadowing.
10798 *
10799 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10800 * enabled while executing the nested-guest.
10801 */
10802 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10803
10804 /*
10805 * APIC-access page.
10806 *
10807 * The APIC-access page address has already been initialized while setting up the
10808 * nested-guest VMCS. In theory, even if the guest-physical address is invalid, it should
10809 * not be of any consequence to the host or to the guest for that matter, but we only
10810 * accept valid addresses verified by the VMLAUNCH/VMRESUME instruction emulation to keep
10811 * it simple.
10812 */
10813
10814 /*
10815 * Virtual-APIC page and TPR threshold.
10816 *
10817 * The virtual-APIC page has already been allocated (by CPUM during VM startup) and cached
10818 * from guest memory as part of VMLAUNCH/VMRESUME instruction emulation. The host physical
10819 * address has also been updated in the nested-guest VMCS.
10820 */
10821 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10822 RTHCPHYS HCPhysVirtApic;
10823 uint32_t u32TprThreshold;
10824 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10825 {
10826 HCPhysVirtApic = pVmcsInfoNstGst->HCPhysVirtApic;
10827 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10828 }
10829 else
10830 {
10831 HCPhysVirtApic = 0;
10832 u32TprThreshold = 0;
10833
10834 /*
10835 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10836 * used by the guest hypervisor. Preventing MMIO accesses to the physical APIC will
10837 * be taken care of by EPT/shadow paging.
10838 */
10839 if (pVM->hm.s.fAllow64BitGuests)
10840 {
10841 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10842 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10843 }
10844 }
10845
10846 /*
10847 * Validate basic assumptions.
10848 */
10849 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10850 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10851 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10852
10853 /*
10854 * Commit it to the nested-guest VMCS.
10855 */
10856 int rc = VINF_SUCCESS;
10857 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10858 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10859 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10860 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10861 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10862 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10863 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10864 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10865 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10866 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10867 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10868 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10869 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10870 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10871 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10872 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10873 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10874 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10875 {
10876 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10877 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10878 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10879 }
10880 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10881 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, pVmcsInfoNstGst->HCPhysVirtApic);
10882 AssertRCReturn(rc, rc);
10883
10884 /*
10885 * Update the nested-guest VMCS cache.
10886 */
10887 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10888 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10889 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10890 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10891 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10892 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10893 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10894 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10895 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10896
10897 /*
10898 * MSR bitmap.
10899 *
10900 * The MSR bitmap address has already been initialized while setting up the nested-guest
10901 * VMCS, here we need to merge the MSR bitmaps.
10902 */
10903 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10904 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10905
10906 return VINF_SUCCESS;
10907}
10908#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10909
10910
10911/**
10912 * Does the preparations before executing guest code in VT-x.
10913 *
10914 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10915 * recompiler/IEM. We must be cautious what we do here regarding committing
10916 * guest-state information into the VMCS assuming we assuredly execute the
10917 * guest in VT-x mode.
10918 *
10919 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10920 * the common-state (TRPM/forceflags), we must undo those changes so that the
10921 * recompiler/IEM can (and should) use them when it resumes guest execution.
10922 * Otherwise such operations must be done when we can no longer exit to ring-3.
10923 *
10924 * @returns Strict VBox status code (i.e. informational status codes too).
10925 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10926 * have been disabled.
10927 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10928 * pending events).
10929 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10930 * double-fault into the guest.
10931 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10932 * dispatched directly.
10933 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10934 *
10935 * @param pVCpu The cross context virtual CPU structure.
10936 * @param pVmxTransient The VMX-transient structure.
10937 * @param fStepping Whether we are single-stepping the guest in the
10938 * hypervisor debugger. Makes us ignore some of the reasons
10939 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10940 * if event dispatching took place.
10941 */
10942static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10943{
10944 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10945
10946#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10947 if (pVmxTransient->fIsNestedGuest)
10948 {
10949 RT_NOREF2(pVCpu, fStepping);
10950 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10951 return VINF_EM_RESCHEDULE_REM;
10952 }
10953#endif
10954
10955#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10956 PGMRZDynMapFlushAutoSet(pVCpu);
10957#endif
10958
10959 /*
10960 * Check and process force flag actions, some of which might require us to go back to ring-3.
10961 */
10962 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
10963 if (rcStrict == VINF_SUCCESS)
10964 { /* FFs don't get set all the time. */ }
10965 else
10966 return rcStrict;
10967
10968 /*
10969 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10970 */
10971 /** @todo Doing this from ring-3 after VM setup phase causes a
10972 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
10973 * idea why atm. */
10974 PVM pVM = pVCpu->CTX_SUFF(pVM);
10975 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10976 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10977 && PDMHasApic(pVM))
10978 {
10979 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10980 AssertRCReturn(rc, rc);
10981 }
10982
10983#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10984 /*
10985 * Merge guest VMCS controls with the nested-guest VMCS controls.
10986 *
10987 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10988 * saved state), we should be okay with merging controls as we initialize the
10989 * guest VMCS controls as part of VM setup phase.
10990 */
10991 if ( pVmxTransient->fIsNestedGuest
10992 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10993 {
10994 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10995 AssertRCReturn(rc, rc);
10996 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10997 }
10998#endif
10999
11000 /*
11001 * Evaluate events to be injected into the guest.
11002 *
11003 * Events in TRPM can be injected without inspecting the guest state.
11004 * If any new events (interrupts/NMI) are pending currently, we try to set up the
11005 * guest to cause a VM-exit the next time they are ready to receive the event.
11006 *
11007 * With nested-guests, evaluating pending events may cause VM-exits.
11008 */
11009 if (TRPMHasTrap(pVCpu))
11010 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
11011
11012 uint32_t fIntrState;
11013 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
11014
11015#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11016 /*
11017 * While evaluating pending events if something failed (unlikely) or if we were
11018 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
11019 */
11020 if (rcStrict != VINF_SUCCESS)
11021 return rcStrict;
11022 if ( pVmxTransient->fIsNestedGuest
11023 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11024 {
11025 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11026 return VINF_VMX_VMEXIT;
11027 }
11028#else
11029 Assert(rcStrict == VINF_SUCCESS);
11030#endif
11031
11032 /*
11033 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
11034 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
11035 * also result in triple-faulting the VM.
11036 *
11037 * With nested-guests, the above does not apply since unrestricted guest execution is a
11038 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
11039 */
11040 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
11041 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11042 { /* likely */ }
11043 else
11044 {
11045 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
11046 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
11047 return rcStrict;
11048 }
11049
11050 /*
11051 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
11052 * import CR3 themselves. We will need to update them here, as even as late as the above
11053 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
11054 * the below force flags to be set.
11055 */
11056 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
11057 {
11058 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
11059 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
11060 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
11061 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
11062 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11063 }
11064 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
11065 {
11066 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
11067 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11068 }
11069
11070#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11071 /* Paranoia. */
11072 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11073#endif
11074
11075 /*
11076 * No longjmps to ring-3 from this point on!!!
11077 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
11078 * This also disables flushing of the R0-logger instance (if any).
11079 */
11080 VMMRZCallRing3Disable(pVCpu);
11081
11082 /*
11083 * Export the guest state bits.
11084 *
11085 * We cannot perform longjmps while loading the guest state because we do not preserve the
11086 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
11087 * CPU migration.
11088 *
11089 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
11090 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
11091 */
11092 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
11093 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11094 { /* likely */ }
11095 else
11096 {
11097 VMMRZCallRing3Enable(pVCpu);
11098 return rcStrict;
11099 }
11100
11101 /*
11102 * We disable interrupts so that we don't miss any interrupts that would flag preemption
11103 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
11104 * preemption disabled for a while. Since this is purely to aid the
11105 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
11106 * disable interrupt on NT.
11107 *
11108 * We need to check for force-flags that could've possible been altered since we last
11109 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
11110 * see @bugref{6398}).
11111 *
11112 * We also check a couple of other force-flags as a last opportunity to get the EMT back
11113 * to ring-3 before executing guest code.
11114 */
11115 pVmxTransient->fEFlags = ASMIntDisableFlags();
11116
11117 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
11118 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
11119 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
11120 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
11121 {
11122 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
11123 {
11124 pVCpu->hm.s.Event.fPending = false;
11125
11126#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11127 /*
11128 * If we are executing a nested-guest make sure that we should intercept subsequent
11129 * events. The one we are injecting might be part of VM-entry.
11130 */
11131 if (pVmxTransient->fIsNestedGuest)
11132 pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = true;
11133#endif
11134
11135 /*
11136 * We've injected any pending events. This is really the point of no return (to ring-3).
11137 *
11138 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
11139 * returns from this function, so don't enable them here.
11140 */
11141 return VINF_SUCCESS;
11142 }
11143
11144 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
11145 rcStrict = VINF_EM_RAW_INTERRUPT;
11146 }
11147 else
11148 {
11149 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
11150 rcStrict = VINF_EM_RAW_TO_R3;
11151 }
11152
11153 ASMSetFlags(pVmxTransient->fEFlags);
11154 VMMRZCallRing3Enable(pVCpu);
11155
11156 return rcStrict;
11157}
11158
11159
11160/**
11161 * Final preparations before executing guest code using hardware-assisted VMX.
11162 *
11163 * We can no longer get preempted to a different host CPU and there are no returns
11164 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
11165 * failures), this function is not intended to fail sans unrecoverable hardware
11166 * errors.
11167 *
11168 * @param pVCpu The cross context virtual CPU structure.
11169 * @param pVmxTransient The VMX-transient structure.
11170 *
11171 * @remarks Called with preemption disabled.
11172 * @remarks No-long-jump zone!!!
11173 */
11174static void hmR0VmxPreRunGuestCommitted(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
11175{
11176 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11177 Assert(VMMR0IsLogFlushDisabled(pVCpu));
11178 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
11179 Assert(!pVCpu->hm.s.Event.fPending);
11180
11181 /*
11182 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
11183 */
11184 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11185 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
11186
11187 PVM pVM = pVCpu->CTX_SUFF(pVM);
11188 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11189 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
11190 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
11191
11192 if (!CPUMIsGuestFPUStateActive(pVCpu))
11193 {
11194 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11195 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
11196 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
11197 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11198 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
11199 }
11200
11201 /*
11202 * Re-export the host state bits as we may've been preempted (only happens when
11203 * thread-context hooks are used or when the VM start function changes) or if
11204 * the host CR0 is modified while loading the guest FPU state above.
11205 *
11206 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
11207 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
11208 * see @bugref{8432}.
11209 *
11210 * This may also happen when switching to/from a nested-guest VMCS without leaving
11211 * ring-0.
11212 */
11213 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
11214 {
11215 hmR0VmxExportHostState(pVCpu);
11216 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
11217 }
11218 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
11219
11220 /*
11221 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
11222 */
11223 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
11224 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
11225 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
11226
11227 /*
11228 * Store status of the shared guest/host debug state at the time of VM-entry.
11229 */
11230#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
11231 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
11232 {
11233 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActivePending(pVCpu);
11234 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActivePending(pVCpu);
11235 }
11236 else
11237#endif
11238 {
11239 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
11240 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11241 }
11242
11243 /*
11244 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11245 * more than one conditional check. The post-run side of our code shall determine
11246 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11247 */
11248 if (pVmcsInfo->pbVirtApic)
11249 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11250
11251 /*
11252 * Update the host MSRs values in the VM-exit MSR-load area.
11253 */
11254 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
11255 {
11256 if (pVmcsInfo->cExitMsrLoad > 0)
11257 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11258 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
11259 }
11260
11261 /*
11262 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11263 * VMX-preemption timer based on the next virtual sync clock deadline.
11264 */
11265 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11266 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
11267 {
11268 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
11269 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11270 }
11271
11272 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11273 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11274 if (!fIsRdtscIntercepted)
11275 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11276 else
11277 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11278
11279 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11280 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11281 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
11282 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Update the error reporting info. with the current host CPU. */
11283 pVmcsInfo->idHostCpu = idCurrentCpu; /* Update the CPU for which we updated host-state in this VMCS. */
11284
11285 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11286
11287 TMNotifyStartOfExecution(pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11288 as we're about to start executing the guest . */
11289
11290 /*
11291 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11292 *
11293 * This is done this late as updating the TSC offsetting/preemption timer above
11294 * figures out if we can skip intercepting RDTSCP by calculating the number of
11295 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11296 */
11297 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11298 && !fIsRdtscIntercepted)
11299 {
11300 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11301
11302 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11303 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11304 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11305 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11306 AssertRC(rc);
11307 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11308 pVmxTransient->fRemoveTscAuxMsr = true;
11309 }
11310
11311#ifdef VBOX_STRICT
11312 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
11313 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11314 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
11315 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11316#endif
11317
11318#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11319 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11320 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11321 * see @bugref{9180#c54}. */
11322 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11323 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11324 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11325#endif
11326}
11327
11328
11329/**
11330 * First C routine invoked after running guest code using hardware-assisted VMX.
11331 *
11332 * @param pVCpu The cross context virtual CPU structure.
11333 * @param pVmxTransient The VMX-transient structure.
11334 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11335 *
11336 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11337 *
11338 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11339 * unconditionally when it is safe to do so.
11340 */
11341static void hmR0VmxPostRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11342{
11343 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
11344
11345 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11346 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11347 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11348 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11349 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11350 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11351
11352 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11353 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11354 {
11355 uint64_t uGstTsc;
11356 if (!pVmxTransient->fIsNestedGuest)
11357 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11358 else
11359 {
11360 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11361 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11362 }
11363 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11364 }
11365
11366 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11367 TMNotifyEndOfExecution(pVCpu); /* Notify TM that the guest is no longer running. */
11368 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11369
11370#if HC_ARCH_BITS == 64
11371 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11372#endif
11373#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
11374 /* The 64-on-32 switcher maintains VMCS-launch state on its own
11375 and we need to leave it alone here. */
11376 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
11377 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11378#else
11379 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11380#endif
11381#ifdef VBOX_STRICT
11382 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11383#endif
11384 Assert(!ASMIntAreEnabled());
11385 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11386 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11387
11388 /*
11389 * Save the basic VM-exit reason and check if the VM-entry failed.
11390 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11391 */
11392 uint32_t uExitReason;
11393 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11394 AssertRC(rc);
11395 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11396 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11397
11398 /*
11399 * Log the VM-exit before logging anything else as otherwise it might be a
11400 * tad confusing what happens before and after the world-switch.
11401 */
11402 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11403
11404 /*
11405 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11406 * bitmap permissions, if it was added before VM-entry.
11407 */
11408 if (pVmxTransient->fRemoveTscAuxMsr)
11409 {
11410 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11411 pVmxTransient->fRemoveTscAuxMsr = false;
11412 }
11413
11414 /*
11415 * Check if VMLAUNCH/VMRESUME succeeded.
11416 * If this failed, we cause a guru meditation and cease further execution.
11417 *
11418 * However, if we are executing a nested-guest we might fail if we use the
11419 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11420 */
11421 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11422 {
11423 /*
11424 * Update the VM-exit history array here even if the VM-entry failed due to:
11425 * - Invalid guest state.
11426 * - MSR loading.
11427 * - Machine-check event.
11428 *
11429 * In any of the above cases we will still have a "valid" VM-exit reason
11430 * despite @a fVMEntryFailed being false.
11431 *
11432 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11433 *
11434 * Note! We don't have CS or RIP at this point. Will probably address that later
11435 * by amending the history entry added here.
11436 */
11437 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11438 UINT64_MAX, uHostTsc);
11439
11440 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11441 {
11442 VMMRZCallRing3Enable(pVCpu);
11443
11444 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11445 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11446
11447#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11448 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11449 AssertRC(rc);
11450#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11451 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
11452 AssertRC(rc);
11453#else
11454 /*
11455 * Import the guest-interruptibility state always as we need it while evaluating
11456 * injecting events on re-entry.
11457 *
11458 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11459 * checking for real-mode while exporting the state because all bits that cause
11460 * mode changes wrt CR0 are intercepted.
11461 */
11462 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
11463 AssertRC(rc);
11464#endif
11465
11466 /*
11467 * Sync the TPR shadow with our APIC state.
11468 *
11469 * With nested-guests, mark the virtual-APIC page as dirty so it can be synced
11470 * when performing the nested-guest VM-exit.
11471 */
11472 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
11473 {
11474 if (!pVmxTransient->fIsNestedGuest)
11475 {
11476 Assert(pVmcsInfo->pbVirtApic);
11477 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11478 {
11479 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11480 AssertRC(rc);
11481 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11482 }
11483 }
11484 else
11485 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = true;
11486 }
11487
11488 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11489 return;
11490 }
11491 }
11492#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11493 else if (pVmxTransient->fIsNestedGuest)
11494 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11495#endif
11496 else
11497 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11498
11499 VMMRZCallRing3Enable(pVCpu);
11500}
11501
11502
11503/**
11504 * Runs the guest code using hardware-assisted VMX the normal way.
11505 *
11506 * @returns VBox status code.
11507 * @param pVCpu The cross context virtual CPU structure.
11508 * @param pcLoops Pointer to the number of executed loops.
11509 */
11510static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPU pVCpu, uint32_t *pcLoops)
11511{
11512 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11513 Assert(pcLoops);
11514 Assert(*pcLoops <= cMaxResumeLoops);
11515 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11516
11517#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11518 /*
11519 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11520 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11521 * guest VMCS while entering the VMX ring-0 session.
11522 */
11523 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11524 {
11525 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11526 if (RT_SUCCESS(rc))
11527 { /* likely */ }
11528 else
11529 {
11530 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11531 return rc;
11532 }
11533 }
11534#endif
11535
11536 VMXTRANSIENT VmxTransient;
11537 RT_ZERO(VmxTransient);
11538 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11539
11540 /* Paranoia. */
11541 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
11542
11543 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11544 for (;;)
11545 {
11546 Assert(!HMR0SuspendPending());
11547 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11548 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11549
11550 /*
11551 * Preparatory work for running nested-guest code, this may force us to
11552 * return to ring-3.
11553 *
11554 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11555 */
11556 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11557 if (rcStrict != VINF_SUCCESS)
11558 break;
11559
11560 /* Interrupts are disabled at this point! */
11561 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11562 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11563 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11564 /* Interrupts are re-enabled at this point! */
11565
11566 /*
11567 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11568 */
11569 if (RT_SUCCESS(rcRun))
11570 { /* very likely */ }
11571 else
11572 {
11573 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11574 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11575 return rcRun;
11576 }
11577
11578 /*
11579 * Profile the VM-exit.
11580 */
11581 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11582 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11583 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11584 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11585 HMVMX_START_EXIT_DISPATCH_PROF();
11586
11587 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11588
11589 /*
11590 * Handle the VM-exit.
11591 */
11592#ifdef HMVMX_USE_FUNCTION_TABLE
11593 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
11594#else
11595 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11596#endif
11597 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11598 if (rcStrict == VINF_SUCCESS)
11599 {
11600 if (++(*pcLoops) <= cMaxResumeLoops)
11601 continue;
11602 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11603 rcStrict = VINF_EM_RAW_INTERRUPT;
11604 }
11605 break;
11606 }
11607
11608 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11609 return rcStrict;
11610}
11611
11612
11613#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11614/**
11615 * Runs the nested-guest code using hardware-assisted VMX.
11616 *
11617 * @returns VBox status code.
11618 * @param pVCpu The cross context virtual CPU structure.
11619 * @param pcLoops Pointer to the number of executed loops.
11620 *
11621 * @sa hmR0VmxRunGuestCodeNormal.
11622 */
11623static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPU pVCpu, uint32_t *pcLoops)
11624{
11625 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11626 Assert(pcLoops);
11627 Assert(*pcLoops <= cMaxResumeLoops);
11628 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11629
11630 /*
11631 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11632 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11633 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11634 */
11635 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11636 {
11637 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11638 if (RT_SUCCESS(rc))
11639 { /* likely */ }
11640 else
11641 {
11642 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11643 return rc;
11644 }
11645 }
11646
11647 VMXTRANSIENT VmxTransient;
11648 RT_ZERO(VmxTransient);
11649 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11650 VmxTransient.fIsNestedGuest = true;
11651
11652 /* Paranoia. */
11653 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11654
11655 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11656 for (;;)
11657 {
11658 Assert(!HMR0SuspendPending());
11659 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11660 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11661
11662 /*
11663 * Preparatory work for running guest code, this may force us to
11664 * return to ring-3.
11665 *
11666 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11667 */
11668 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11669 if (rcStrict != VINF_SUCCESS)
11670 break;
11671
11672 /* Interrupts are disabled at this point! */
11673 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11674 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11675 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11676 /* Interrupts are re-enabled at this point! */
11677
11678 /*
11679 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11680 */
11681 if (RT_SUCCESS(rcRun))
11682 { /* very likely */ }
11683 else
11684 {
11685 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11686 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11687 return rcRun;
11688 }
11689
11690 /*
11691 * Profile the VM-exit.
11692 */
11693 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11694 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11695 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11696 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11697 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11698 HMVMX_START_EXIT_DISPATCH_PROF();
11699
11700 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11701
11702 /*
11703 * Handle the VM-exit.
11704 */
11705 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11706 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11707 if (rcStrict == VINF_SUCCESS)
11708 {
11709 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11710 {
11711 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11712 rcStrict = VINF_VMX_VMEXIT;
11713 }
11714 else
11715 {
11716 if (++(*pcLoops) <= cMaxResumeLoops)
11717 continue;
11718 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11719 rcStrict = VINF_EM_RAW_INTERRUPT;
11720 }
11721 }
11722 else
11723 Assert(rcStrict != VINF_VMX_VMEXIT);
11724 break;
11725 }
11726
11727 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11728 return rcStrict;
11729}
11730#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11731
11732
11733/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11734 * probes.
11735 *
11736 * The following few functions and associated structure contains the bloat
11737 * necessary for providing detailed debug events and dtrace probes as well as
11738 * reliable host side single stepping. This works on the principle of
11739 * "subclassing" the normal execution loop and workers. We replace the loop
11740 * method completely and override selected helpers to add necessary adjustments
11741 * to their core operation.
11742 *
11743 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11744 * any performance for debug and analysis features.
11745 *
11746 * @{
11747 */
11748
11749/**
11750 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11751 * the debug run loop.
11752 */
11753typedef struct VMXRUNDBGSTATE
11754{
11755 /** The RIP we started executing at. This is for detecting that we stepped. */
11756 uint64_t uRipStart;
11757 /** The CS we started executing with. */
11758 uint16_t uCsStart;
11759
11760 /** Whether we've actually modified the 1st execution control field. */
11761 bool fModifiedProcCtls : 1;
11762 /** Whether we've actually modified the 2nd execution control field. */
11763 bool fModifiedProcCtls2 : 1;
11764 /** Whether we've actually modified the exception bitmap. */
11765 bool fModifiedXcptBitmap : 1;
11766
11767 /** We desire the modified the CR0 mask to be cleared. */
11768 bool fClearCr0Mask : 1;
11769 /** We desire the modified the CR4 mask to be cleared. */
11770 bool fClearCr4Mask : 1;
11771 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11772 uint32_t fCpe1Extra;
11773 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11774 uint32_t fCpe1Unwanted;
11775 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11776 uint32_t fCpe2Extra;
11777 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11778 uint32_t bmXcptExtra;
11779 /** The sequence number of the Dtrace provider settings the state was
11780 * configured against. */
11781 uint32_t uDtraceSettingsSeqNo;
11782 /** VM-exits to check (one bit per VM-exit). */
11783 uint32_t bmExitsToCheck[3];
11784
11785 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11786 uint32_t fProcCtlsInitial;
11787 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11788 uint32_t fProcCtls2Initial;
11789 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11790 uint32_t bmXcptInitial;
11791} VMXRUNDBGSTATE;
11792AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11793typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11794
11795
11796/**
11797 * Initializes the VMXRUNDBGSTATE structure.
11798 *
11799 * @param pVCpu The cross context virtual CPU structure of the
11800 * calling EMT.
11801 * @param pVmxTransient The VMX-transient structure.
11802 * @param pDbgState The debug state to initialize.
11803 */
11804static void hmR0VmxRunDebugStateInit(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11805{
11806 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11807 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11808
11809 pDbgState->fModifiedProcCtls = false;
11810 pDbgState->fModifiedProcCtls2 = false;
11811 pDbgState->fModifiedXcptBitmap = false;
11812 pDbgState->fClearCr0Mask = false;
11813 pDbgState->fClearCr4Mask = false;
11814 pDbgState->fCpe1Extra = 0;
11815 pDbgState->fCpe1Unwanted = 0;
11816 pDbgState->fCpe2Extra = 0;
11817 pDbgState->bmXcptExtra = 0;
11818 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11819 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11820 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11821}
11822
11823
11824/**
11825 * Updates the VMSC fields with changes requested by @a pDbgState.
11826 *
11827 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11828 * immediately before executing guest code, i.e. when interrupts are disabled.
11829 * We don't check status codes here as we cannot easily assert or return in the
11830 * latter case.
11831 *
11832 * @param pVCpu The cross context virtual CPU structure.
11833 * @param pVmxTransient The VMX-transient structure.
11834 * @param pDbgState The debug state.
11835 */
11836static void hmR0VmxPreRunGuestDebugStateApply(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11837{
11838 /*
11839 * Ensure desired flags in VMCS control fields are set.
11840 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11841 *
11842 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11843 * there should be no stale data in pCtx at this point.
11844 */
11845 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11846 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11847 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11848 {
11849 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11850 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11851 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11852 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11853 pDbgState->fModifiedProcCtls = true;
11854 }
11855
11856 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11857 {
11858 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11859 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11860 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11861 pDbgState->fModifiedProcCtls2 = true;
11862 }
11863
11864 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11865 {
11866 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11867 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11868 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11869 pDbgState->fModifiedXcptBitmap = true;
11870 }
11871
11872 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11873 {
11874 pVmcsInfo->u64Cr0Mask = 0;
11875 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, 0);
11876 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11877 }
11878
11879 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11880 {
11881 pVmcsInfo->u64Cr4Mask = 0;
11882 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, 0);
11883 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11884 }
11885
11886 NOREF(pVCpu);
11887}
11888
11889
11890/**
11891 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11892 * re-entry next time around.
11893 *
11894 * @returns Strict VBox status code (i.e. informational status codes too).
11895 * @param pVCpu The cross context virtual CPU structure.
11896 * @param pVmxTransient The VMX-transient structure.
11897 * @param pDbgState The debug state.
11898 * @param rcStrict The return code from executing the guest using single
11899 * stepping.
11900 */
11901static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11902 VBOXSTRICTRC rcStrict)
11903{
11904 /*
11905 * Restore VM-exit control settings as we may not reenter this function the
11906 * next time around.
11907 */
11908 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11909
11910 /* We reload the initial value, trigger what we can of recalculations the
11911 next time around. From the looks of things, that's all that's required atm. */
11912 if (pDbgState->fModifiedProcCtls)
11913 {
11914 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11915 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11916 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11917 AssertRCReturn(rc2, rc2);
11918 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11919 }
11920
11921 /* We're currently the only ones messing with this one, so just restore the
11922 cached value and reload the field. */
11923 if ( pDbgState->fModifiedProcCtls2
11924 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11925 {
11926 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11927 AssertRCReturn(rc2, rc2);
11928 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11929 }
11930
11931 /* If we've modified the exception bitmap, we restore it and trigger
11932 reloading and partial recalculation the next time around. */
11933 if (pDbgState->fModifiedXcptBitmap)
11934 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11935
11936 return rcStrict;
11937}
11938
11939
11940/**
11941 * Configures VM-exit controls for current DBGF and DTrace settings.
11942 *
11943 * This updates @a pDbgState and the VMCS execution control fields to reflect
11944 * the necessary VM-exits demanded by DBGF and DTrace.
11945 *
11946 * @param pVCpu The cross context virtual CPU structure.
11947 * @param pVmxTransient The VMX-transient structure. May update
11948 * fUpdatedTscOffsettingAndPreemptTimer.
11949 * @param pDbgState The debug state.
11950 */
11951static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11952{
11953 /*
11954 * Take down the dtrace serial number so we can spot changes.
11955 */
11956 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11957 ASMCompilerBarrier();
11958
11959 /*
11960 * We'll rebuild most of the middle block of data members (holding the
11961 * current settings) as we go along here, so start by clearing it all.
11962 */
11963 pDbgState->bmXcptExtra = 0;
11964 pDbgState->fCpe1Extra = 0;
11965 pDbgState->fCpe1Unwanted = 0;
11966 pDbgState->fCpe2Extra = 0;
11967 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11968 pDbgState->bmExitsToCheck[i] = 0;
11969
11970 /*
11971 * Software interrupts (INT XXh) - no idea how to trigger these...
11972 */
11973 PVM pVM = pVCpu->CTX_SUFF(pVM);
11974 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11975 || VBOXVMM_INT_SOFTWARE_ENABLED())
11976 {
11977 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11978 }
11979
11980 /*
11981 * INT3 breakpoints - triggered by #BP exceptions.
11982 */
11983 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11984 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11985
11986 /*
11987 * Exception bitmap and XCPT events+probes.
11988 */
11989 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11990 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11991 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11992
11993 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11994 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11995 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11996 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11997 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11998 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11999 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
12000 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
12001 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
12002 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
12003 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
12004 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
12005 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
12006 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
12007 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
12008 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
12009 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
12010 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
12011
12012 if (pDbgState->bmXcptExtra)
12013 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12014
12015 /*
12016 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
12017 *
12018 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
12019 * So, when adding/changing/removing please don't forget to update it.
12020 *
12021 * Some of the macros are picking up local variables to save horizontal space,
12022 * (being able to see it in a table is the lesser evil here).
12023 */
12024#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
12025 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
12026 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
12027#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
12028 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12029 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12030 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12031 } else do { } while (0)
12032#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
12033 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12034 { \
12035 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
12036 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12037 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12038 } else do { } while (0)
12039#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
12040 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12041 { \
12042 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
12043 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12044 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12045 } else do { } while (0)
12046#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
12047 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12048 { \
12049 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
12050 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12051 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12052 } else do { } while (0)
12053
12054 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
12055 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
12056 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
12057 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
12058 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
12059
12060 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
12061 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
12062 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
12063 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
12064 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
12065 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
12066 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
12067 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
12068 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
12069 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
12070 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
12071 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
12072 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
12073 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
12074 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
12075 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
12076 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
12077 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
12078 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
12079 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
12080 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
12081 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
12082 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
12083 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
12084 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
12085 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
12086 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
12087 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
12088 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
12089 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
12090 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
12091 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
12092 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
12093 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
12094 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
12095 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
12096
12097 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
12098 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12099 {
12100 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
12101 | CPUMCTX_EXTRN_APIC_TPR);
12102 AssertRC(rc);
12103
12104#if 0 /** @todo fix me */
12105 pDbgState->fClearCr0Mask = true;
12106 pDbgState->fClearCr4Mask = true;
12107#endif
12108 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
12109 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
12110 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12111 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
12112 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
12113 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
12114 require clearing here and in the loop if we start using it. */
12115 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
12116 }
12117 else
12118 {
12119 if (pDbgState->fClearCr0Mask)
12120 {
12121 pDbgState->fClearCr0Mask = false;
12122 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
12123 }
12124 if (pDbgState->fClearCr4Mask)
12125 {
12126 pDbgState->fClearCr4Mask = false;
12127 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
12128 }
12129 }
12130 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
12131 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
12132
12133 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
12134 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
12135 {
12136 /** @todo later, need to fix handler as it assumes this won't usually happen. */
12137 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
12138 }
12139 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
12140 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
12141
12142 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
12143 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
12144 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
12145 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
12146 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
12147 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
12148 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
12149 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
12150#if 0 /** @todo too slow, fix handler. */
12151 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
12152#endif
12153 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
12154
12155 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
12156 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
12157 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
12158 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
12159 {
12160 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12161 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
12162 }
12163 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12164 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12165 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12166 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12167
12168 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
12169 || IS_EITHER_ENABLED(pVM, INSTR_STR)
12170 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
12171 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
12172 {
12173 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12174 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
12175 }
12176 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
12177 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
12178 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
12179 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
12180
12181 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
12182 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
12183 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
12184 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
12185 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
12186 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
12187 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
12188 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
12189 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
12190 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
12191 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
12192 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
12193 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
12194 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
12195 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
12196 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
12197 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
12198 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
12199 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
12200 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
12201 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
12202 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
12203
12204#undef IS_EITHER_ENABLED
12205#undef SET_ONLY_XBM_IF_EITHER_EN
12206#undef SET_CPE1_XBM_IF_EITHER_EN
12207#undef SET_CPEU_XBM_IF_EITHER_EN
12208#undef SET_CPE2_XBM_IF_EITHER_EN
12209
12210 /*
12211 * Sanitize the control stuff.
12212 */
12213 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
12214 if (pDbgState->fCpe2Extra)
12215 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
12216 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
12217 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
12218 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
12219 {
12220 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
12221 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
12222 }
12223
12224 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
12225 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
12226 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
12227 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
12228}
12229
12230
12231/**
12232 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
12233 * appropriate.
12234 *
12235 * The caller has checked the VM-exit against the
12236 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12237 * already, so we don't have to do that either.
12238 *
12239 * @returns Strict VBox status code (i.e. informational status codes too).
12240 * @param pVCpu The cross context virtual CPU structure.
12241 * @param pVmxTransient The VMX-transient structure.
12242 * @param uExitReason The VM-exit reason.
12243 *
12244 * @remarks The name of this function is displayed by dtrace, so keep it short
12245 * and to the point. No longer than 33 chars long, please.
12246 */
12247static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12248{
12249 /*
12250 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12251 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12252 *
12253 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12254 * does. Must add/change/remove both places. Same ordering, please.
12255 *
12256 * Added/removed events must also be reflected in the next section
12257 * where we dispatch dtrace events.
12258 */
12259 bool fDtrace1 = false;
12260 bool fDtrace2 = false;
12261 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12262 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12263 uint32_t uEventArg = 0;
12264#define SET_EXIT(a_EventSubName) \
12265 do { \
12266 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12267 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12268 } while (0)
12269#define SET_BOTH(a_EventSubName) \
12270 do { \
12271 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12272 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12273 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12274 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12275 } while (0)
12276 switch (uExitReason)
12277 {
12278 case VMX_EXIT_MTF:
12279 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12280
12281 case VMX_EXIT_XCPT_OR_NMI:
12282 {
12283 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12284 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12285 {
12286 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12287 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12288 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12289 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12290 {
12291 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12292 {
12293 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12294 uEventArg = pVmxTransient->uExitIntErrorCode;
12295 }
12296 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12297 switch (enmEvent1)
12298 {
12299 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12300 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12301 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12302 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12303 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12304 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12305 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12306 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12307 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12308 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12309 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12310 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12311 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12312 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12313 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12314 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12315 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12316 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12317 default: break;
12318 }
12319 }
12320 else
12321 AssertFailed();
12322 break;
12323
12324 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12325 uEventArg = idxVector;
12326 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12327 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12328 break;
12329 }
12330 break;
12331 }
12332
12333 case VMX_EXIT_TRIPLE_FAULT:
12334 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12335 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12336 break;
12337 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12338 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12339 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12340 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12341 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12342
12343 /* Instruction specific VM-exits: */
12344 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12345 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12346 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12347 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12348 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12349 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12350 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12351 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12352 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12353 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12354 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12355 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12356 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12357 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12358 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12359 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12360 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12361 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12362 case VMX_EXIT_MOV_CRX:
12363 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12364 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12365 SET_BOTH(CRX_READ);
12366 else
12367 SET_BOTH(CRX_WRITE);
12368 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12369 break;
12370 case VMX_EXIT_MOV_DRX:
12371 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12372 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12373 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12374 SET_BOTH(DRX_READ);
12375 else
12376 SET_BOTH(DRX_WRITE);
12377 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12378 break;
12379 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12380 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12381 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12382 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12383 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12384 case VMX_EXIT_GDTR_IDTR_ACCESS:
12385 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12386 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12387 {
12388 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12389 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12390 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12391 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12392 }
12393 break;
12394
12395 case VMX_EXIT_LDTR_TR_ACCESS:
12396 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12397 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12398 {
12399 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12400 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12401 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12402 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12403 }
12404 break;
12405
12406 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12407 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12408 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12409 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12410 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12411 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12412 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12413 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12414 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12415 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12416 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12417
12418 /* Events that aren't relevant at this point. */
12419 case VMX_EXIT_EXT_INT:
12420 case VMX_EXIT_INT_WINDOW:
12421 case VMX_EXIT_NMI_WINDOW:
12422 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12423 case VMX_EXIT_PREEMPT_TIMER:
12424 case VMX_EXIT_IO_INSTR:
12425 break;
12426
12427 /* Errors and unexpected events. */
12428 case VMX_EXIT_INIT_SIGNAL:
12429 case VMX_EXIT_SIPI:
12430 case VMX_EXIT_IO_SMI:
12431 case VMX_EXIT_SMI:
12432 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12433 case VMX_EXIT_ERR_MSR_LOAD:
12434 case VMX_EXIT_ERR_MACHINE_CHECK:
12435 case VMX_EXIT_PML_FULL:
12436 case VMX_EXIT_VIRTUALIZED_EOI:
12437 break;
12438
12439 default:
12440 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12441 break;
12442 }
12443#undef SET_BOTH
12444#undef SET_EXIT
12445
12446 /*
12447 * Dtrace tracepoints go first. We do them here at once so we don't
12448 * have to copy the guest state saving and stuff a few dozen times.
12449 * Down side is that we've got to repeat the switch, though this time
12450 * we use enmEvent since the probes are a subset of what DBGF does.
12451 */
12452 if (fDtrace1 || fDtrace2)
12453 {
12454 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12455 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12456 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12457 switch (enmEvent1)
12458 {
12459 /** @todo consider which extra parameters would be helpful for each probe. */
12460 case DBGFEVENT_END: break;
12461 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12462 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12463 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12464 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12465 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12466 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12467 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12468 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12469 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12470 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12471 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12472 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12473 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12474 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12475 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12476 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12477 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12478 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12479 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12480 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12481 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12482 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12483 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12484 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12485 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12486 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12487 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12488 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12489 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12490 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12491 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12492 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12493 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12494 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12495 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12496 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12497 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12498 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12499 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12500 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12501 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12502 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12503 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12504 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12505 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12506 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12507 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12508 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12509 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12510 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12511 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12512 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12513 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12514 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12515 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12516 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12517 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12518 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12519 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12520 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12521 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12522 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12523 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12524 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12525 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12526 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12527 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12528 }
12529 switch (enmEvent2)
12530 {
12531 /** @todo consider which extra parameters would be helpful for each probe. */
12532 case DBGFEVENT_END: break;
12533 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12534 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12535 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12536 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12537 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12538 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12539 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12540 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12541 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12542 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12543 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12544 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12545 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12546 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12547 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12548 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12549 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12550 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12551 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12552 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12553 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12554 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12555 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12556 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12557 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12558 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12559 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12560 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12561 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12562 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12563 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12564 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12565 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12566 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12567 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12568 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12569 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12570 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12571 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12572 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12573 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12574 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12575 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12576 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12577 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12578 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12579 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12580 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12581 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12582 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12583 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12584 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12585 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12586 }
12587 }
12588
12589 /*
12590 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12591 * the DBGF call will do a full check).
12592 *
12593 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12594 * Note! If we have to events, we prioritize the first, i.e. the instruction
12595 * one, in order to avoid event nesting.
12596 */
12597 PVM pVM = pVCpu->CTX_SUFF(pVM);
12598 if ( enmEvent1 != DBGFEVENT_END
12599 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12600 {
12601 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12602 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12603 if (rcStrict != VINF_SUCCESS)
12604 return rcStrict;
12605 }
12606 else if ( enmEvent2 != DBGFEVENT_END
12607 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12608 {
12609 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12610 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12611 if (rcStrict != VINF_SUCCESS)
12612 return rcStrict;
12613 }
12614
12615 return VINF_SUCCESS;
12616}
12617
12618
12619/**
12620 * Single-stepping VM-exit filtering.
12621 *
12622 * This is preprocessing the VM-exits and deciding whether we've gotten far
12623 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12624 * handling is performed.
12625 *
12626 * @returns Strict VBox status code (i.e. informational status codes too).
12627 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12628 * @param pVmxTransient The VMX-transient structure.
12629 * @param pDbgState The debug state.
12630 */
12631DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12632{
12633 /*
12634 * Expensive (saves context) generic dtrace VM-exit probe.
12635 */
12636 uint32_t const uExitReason = pVmxTransient->uExitReason;
12637 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12638 { /* more likely */ }
12639 else
12640 {
12641 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12642 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12643 AssertRC(rc);
12644 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12645 }
12646
12647 /*
12648 * Check for host NMI, just to get that out of the way.
12649 */
12650 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12651 { /* normally likely */ }
12652 else
12653 {
12654 int rc2 = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12655 AssertRCReturn(rc2, rc2);
12656 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12657 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12658 return hmR0VmxExitHostNmi(pVCpu);
12659 }
12660
12661 /*
12662 * Check for single stepping event if we're stepping.
12663 */
12664 if (pVCpu->hm.s.fSingleInstruction)
12665 {
12666 switch (uExitReason)
12667 {
12668 case VMX_EXIT_MTF:
12669 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12670
12671 /* Various events: */
12672 case VMX_EXIT_XCPT_OR_NMI:
12673 case VMX_EXIT_EXT_INT:
12674 case VMX_EXIT_TRIPLE_FAULT:
12675 case VMX_EXIT_INT_WINDOW:
12676 case VMX_EXIT_NMI_WINDOW:
12677 case VMX_EXIT_TASK_SWITCH:
12678 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12679 case VMX_EXIT_APIC_ACCESS:
12680 case VMX_EXIT_EPT_VIOLATION:
12681 case VMX_EXIT_EPT_MISCONFIG:
12682 case VMX_EXIT_PREEMPT_TIMER:
12683
12684 /* Instruction specific VM-exits: */
12685 case VMX_EXIT_CPUID:
12686 case VMX_EXIT_GETSEC:
12687 case VMX_EXIT_HLT:
12688 case VMX_EXIT_INVD:
12689 case VMX_EXIT_INVLPG:
12690 case VMX_EXIT_RDPMC:
12691 case VMX_EXIT_RDTSC:
12692 case VMX_EXIT_RSM:
12693 case VMX_EXIT_VMCALL:
12694 case VMX_EXIT_VMCLEAR:
12695 case VMX_EXIT_VMLAUNCH:
12696 case VMX_EXIT_VMPTRLD:
12697 case VMX_EXIT_VMPTRST:
12698 case VMX_EXIT_VMREAD:
12699 case VMX_EXIT_VMRESUME:
12700 case VMX_EXIT_VMWRITE:
12701 case VMX_EXIT_VMXOFF:
12702 case VMX_EXIT_VMXON:
12703 case VMX_EXIT_MOV_CRX:
12704 case VMX_EXIT_MOV_DRX:
12705 case VMX_EXIT_IO_INSTR:
12706 case VMX_EXIT_RDMSR:
12707 case VMX_EXIT_WRMSR:
12708 case VMX_EXIT_MWAIT:
12709 case VMX_EXIT_MONITOR:
12710 case VMX_EXIT_PAUSE:
12711 case VMX_EXIT_GDTR_IDTR_ACCESS:
12712 case VMX_EXIT_LDTR_TR_ACCESS:
12713 case VMX_EXIT_INVEPT:
12714 case VMX_EXIT_RDTSCP:
12715 case VMX_EXIT_INVVPID:
12716 case VMX_EXIT_WBINVD:
12717 case VMX_EXIT_XSETBV:
12718 case VMX_EXIT_RDRAND:
12719 case VMX_EXIT_INVPCID:
12720 case VMX_EXIT_VMFUNC:
12721 case VMX_EXIT_RDSEED:
12722 case VMX_EXIT_XSAVES:
12723 case VMX_EXIT_XRSTORS:
12724 {
12725 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12726 AssertRCReturn(rc, rc);
12727 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12728 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12729 return VINF_EM_DBG_STEPPED;
12730 break;
12731 }
12732
12733 /* Errors and unexpected events: */
12734 case VMX_EXIT_INIT_SIGNAL:
12735 case VMX_EXIT_SIPI:
12736 case VMX_EXIT_IO_SMI:
12737 case VMX_EXIT_SMI:
12738 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12739 case VMX_EXIT_ERR_MSR_LOAD:
12740 case VMX_EXIT_ERR_MACHINE_CHECK:
12741 case VMX_EXIT_PML_FULL:
12742 case VMX_EXIT_VIRTUALIZED_EOI:
12743 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12744 break;
12745
12746 default:
12747 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12748 break;
12749 }
12750 }
12751
12752 /*
12753 * Check for debugger event breakpoints and dtrace probes.
12754 */
12755 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12756 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12757 {
12758 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12759 if (rcStrict != VINF_SUCCESS)
12760 return rcStrict;
12761 }
12762
12763 /*
12764 * Normal processing.
12765 */
12766#ifdef HMVMX_USE_FUNCTION_TABLE
12767 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12768#else
12769 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12770#endif
12771}
12772
12773
12774/**
12775 * Single steps guest code using hardware-assisted VMX.
12776 *
12777 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12778 * but single-stepping through the hypervisor debugger.
12779 *
12780 * @returns Strict VBox status code (i.e. informational status codes too).
12781 * @param pVCpu The cross context virtual CPU structure.
12782 * @param pcLoops Pointer to the number of executed loops.
12783 *
12784 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12785 */
12786static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPU pVCpu, uint32_t *pcLoops)
12787{
12788 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12789 Assert(pcLoops);
12790 Assert(*pcLoops <= cMaxResumeLoops);
12791
12792 VMXTRANSIENT VmxTransient;
12793 RT_ZERO(VmxTransient);
12794 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12795
12796 /* Set HMCPU indicators. */
12797 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12798 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12799 pVCpu->hm.s.fDebugWantRdTscExit = false;
12800 pVCpu->hm.s.fUsingDebugLoop = true;
12801
12802 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12803 VMXRUNDBGSTATE DbgState;
12804 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12805 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12806
12807 /*
12808 * The loop.
12809 */
12810 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12811 for (;;)
12812 {
12813 Assert(!HMR0SuspendPending());
12814 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12815 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12816 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12817
12818 /* Set up VM-execution controls the next two can respond to. */
12819 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12820
12821 /*
12822 * Preparatory work for running guest code, this may force us to
12823 * return to ring-3.
12824 *
12825 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12826 */
12827 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12828 if (rcStrict != VINF_SUCCESS)
12829 break;
12830
12831 /* Interrupts are disabled at this point! */
12832 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12833
12834 /* Override any obnoxious code in the above two calls. */
12835 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12836
12837 /*
12838 * Finally execute the guest.
12839 */
12840 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12841
12842 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12843 /* Interrupts are re-enabled at this point! */
12844
12845 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12846 if (RT_SUCCESS(rcRun))
12847 { /* very likely */ }
12848 else
12849 {
12850 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12851 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12852 return rcRun;
12853 }
12854
12855 /* Profile the VM-exit. */
12856 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12857 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12858 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12859 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12860 HMVMX_START_EXIT_DISPATCH_PROF();
12861
12862 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12863
12864 /*
12865 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12866 */
12867 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12868 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12869 if (rcStrict != VINF_SUCCESS)
12870 break;
12871 if (++(*pcLoops) > cMaxResumeLoops)
12872 {
12873 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12874 rcStrict = VINF_EM_RAW_INTERRUPT;
12875 break;
12876 }
12877
12878 /*
12879 * Stepping: Did the RIP change, if so, consider it a single step.
12880 * Otherwise, make sure one of the TFs gets set.
12881 */
12882 if (fStepping)
12883 {
12884 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12885 AssertRC(rc);
12886 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12887 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12888 {
12889 rcStrict = VINF_EM_DBG_STEPPED;
12890 break;
12891 }
12892 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12893 }
12894
12895 /*
12896 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12897 */
12898 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12899 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12900 }
12901
12902 /*
12903 * Clear the X86_EFL_TF if necessary.
12904 */
12905 if (pVCpu->hm.s.fClearTrapFlag)
12906 {
12907 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12908 AssertRC(rc);
12909 pVCpu->hm.s.fClearTrapFlag = false;
12910 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12911 }
12912 /** @todo there seems to be issues with the resume flag when the monitor trap
12913 * flag is pending without being used. Seen early in bios init when
12914 * accessing APIC page in protected mode. */
12915
12916 /*
12917 * Restore VM-exit control settings as we may not re-enter this function the
12918 * next time around.
12919 */
12920 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12921
12922 /* Restore HMCPU indicators. */
12923 pVCpu->hm.s.fUsingDebugLoop = false;
12924 pVCpu->hm.s.fDebugWantRdTscExit = false;
12925 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12926
12927 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12928 return rcStrict;
12929}
12930
12931
12932/** @} */
12933
12934
12935/**
12936 * Checks if any expensive dtrace probes are enabled and we should go to the
12937 * debug loop.
12938 *
12939 * @returns true if we should use debug loop, false if not.
12940 */
12941static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12942{
12943 /* It's probably faster to OR the raw 32-bit counter variables together.
12944 Since the variables are in an array and the probes are next to one
12945 another (more or less), we have good locality. So, better read
12946 eight-nine cache lines ever time and only have one conditional, than
12947 128+ conditionals, right? */
12948 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12949 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12950 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12951 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12952 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12953 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12954 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12955 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12956 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12957 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12958 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12959 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12960 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12961 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12962 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12963 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12964 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12965 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12966 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12967 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12968 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12969 ) != 0
12970 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12971 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12972 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12973 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12974 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12975 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12976 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12977 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12978 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12979 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12980 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12981 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12982 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12983 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12984 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12985 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12986 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12987 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12988 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12989 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12990 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12991 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12992 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12993 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12994 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12995 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12996 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12997 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12998 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12999 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
13000 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
13001 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
13002 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
13003 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
13004 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
13005 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
13006 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
13007 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
13008 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
13009 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
13010 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
13011 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
13012 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
13013 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
13014 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
13015 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
13016 ) != 0
13017 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
13018 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
13019 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
13020 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
13021 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
13022 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
13023 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
13024 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
13025 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
13026 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
13027 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
13028 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
13029 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
13030 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
13031 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
13032 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
13033 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
13034 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
13035 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
13036 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
13037 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
13038 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
13039 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
13040 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
13041 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
13042 | VBOXVMM_EXIT_STR_ENABLED_RAW()
13043 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
13044 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
13045 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
13046 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
13047 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
13048 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
13049 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
13050 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
13051 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
13052 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
13053 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
13054 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
13055 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
13056 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
13057 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
13058 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
13059 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
13060 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
13061 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
13062 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
13063 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
13064 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
13065 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
13066 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
13067 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
13068 ) != 0;
13069}
13070
13071
13072/**
13073 * Runs the guest using hardware-assisted VMX.
13074 *
13075 * @returns Strict VBox status code (i.e. informational status codes too).
13076 * @param pVCpu The cross context virtual CPU structure.
13077 */
13078VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPU pVCpu)
13079{
13080 AssertPtr(pVCpu);
13081 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13082 Assert(VMMRZCallRing3IsEnabled(pVCpu));
13083 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13084 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
13085
13086 VMMRZCallRing3SetNotification(pVCpu, hmR0VmxCallRing3Callback, pCtx);
13087
13088 VBOXSTRICTRC rcStrict;
13089 uint32_t cLoops = 0;
13090 for (;;)
13091 {
13092#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13093 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
13094#else
13095 bool const fInNestedGuestMode = false;
13096#endif
13097 if (!fInNestedGuestMode)
13098 {
13099 if ( !pVCpu->hm.s.fUseDebugLoop
13100 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
13101 && !DBGFIsStepping(pVCpu)
13102 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
13103 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
13104 else
13105 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
13106 }
13107#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13108 else
13109 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
13110
13111 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
13112 {
13113 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
13114 continue;
13115 }
13116 if (rcStrict == VINF_VMX_VMEXIT)
13117 {
13118 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
13119 continue;
13120 }
13121#endif
13122 break;
13123 }
13124
13125 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
13126 switch (rcLoop)
13127 {
13128 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
13129 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
13130 }
13131
13132 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
13133 if (RT_FAILURE(rc2))
13134 {
13135 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
13136 rcStrict = rc2;
13137 }
13138 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13139 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
13140 return rcStrict;
13141}
13142
13143
13144#ifndef HMVMX_USE_FUNCTION_TABLE
13145/**
13146 * Handles a guest VM-exit from hardware-assisted VMX execution.
13147 *
13148 * @returns Strict VBox status code (i.e. informational status codes too).
13149 * @param pVCpu The cross context virtual CPU structure.
13150 * @param pVmxTransient The VMX-transient structure.
13151 */
13152DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13153{
13154#ifdef DEBUG_ramshankar
13155#define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
13156 do { \
13157 if (a_fSave != 0) \
13158 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
13159 VBOXSTRICTRC rcStrict = a_CallExpr; \
13160 if (a_fSave != 0) \
13161 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
13162 return rcStrict; \
13163 } while (0)
13164#else
13165# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
13166#endif
13167 uint32_t const uExitReason = pVmxTransient->uExitReason;
13168 switch (uExitReason)
13169 {
13170 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
13171 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
13172 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
13173 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
13174 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
13175 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
13176 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
13177 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
13178 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
13179 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
13180 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
13181 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
13182 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
13183 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
13184 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
13185 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
13186 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
13187 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
13188 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
13189 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
13190 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
13191 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
13192 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
13193 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
13194 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
13195 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
13196 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
13197 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
13198 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
13199 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
13200#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13201 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
13202 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
13203 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
13204 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
13205 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
13206 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
13207 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
13208 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
13209 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
13210 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
13211 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
13212#else
13213 case VMX_EXIT_VMCLEAR:
13214 case VMX_EXIT_VMLAUNCH:
13215 case VMX_EXIT_VMPTRLD:
13216 case VMX_EXIT_VMPTRST:
13217 case VMX_EXIT_VMREAD:
13218 case VMX_EXIT_VMRESUME:
13219 case VMX_EXIT_VMWRITE:
13220 case VMX_EXIT_VMXOFF:
13221 case VMX_EXIT_VMXON:
13222 case VMX_EXIT_INVVPID:
13223 case VMX_EXIT_INVEPT:
13224 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
13225#endif
13226
13227 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
13228 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
13229 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
13230
13231 case VMX_EXIT_INIT_SIGNAL:
13232 case VMX_EXIT_SIPI:
13233 case VMX_EXIT_IO_SMI:
13234 case VMX_EXIT_SMI:
13235 case VMX_EXIT_ERR_MSR_LOAD:
13236 case VMX_EXIT_ERR_MACHINE_CHECK:
13237 case VMX_EXIT_PML_FULL:
13238 case VMX_EXIT_VIRTUALIZED_EOI:
13239 case VMX_EXIT_GDTR_IDTR_ACCESS:
13240 case VMX_EXIT_LDTR_TR_ACCESS:
13241 case VMX_EXIT_APIC_WRITE:
13242 case VMX_EXIT_RDRAND:
13243 case VMX_EXIT_RSM:
13244 case VMX_EXIT_VMFUNC:
13245 case VMX_EXIT_ENCLS:
13246 case VMX_EXIT_RDSEED:
13247 case VMX_EXIT_XSAVES:
13248 case VMX_EXIT_XRSTORS:
13249 case VMX_EXIT_UMWAIT:
13250 case VMX_EXIT_TPAUSE:
13251 default:
13252 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13253 }
13254#undef VMEXIT_CALL_RET
13255}
13256#endif /* !HMVMX_USE_FUNCTION_TABLE */
13257
13258
13259#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13260/**
13261 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13262 *
13263 * @returns Strict VBox status code (i.e. informational status codes too).
13264 * @param pVCpu The cross context virtual CPU structure.
13265 * @param pVmxTransient The VMX-transient structure.
13266 */
13267DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13268{
13269 uint32_t const uExitReason = pVmxTransient->uExitReason;
13270 switch (uExitReason)
13271 {
13272 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13273 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13274 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13275 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13276 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13277
13278 /*
13279 * We shouldn't direct host physical interrupts to the nested-guest.
13280 */
13281 case VMX_EXIT_EXT_INT:
13282 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13283
13284 /*
13285 * Instructions that cause VM-exits unconditionally or the condition is
13286 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13287 * happens, it's guaranteed to be a nested-guest VM-exit).
13288 *
13289 * - Provides VM-exit instruction length ONLY.
13290 */
13291 case VMX_EXIT_CPUID: /* Unconditional. */
13292 case VMX_EXIT_VMCALL:
13293 case VMX_EXIT_GETSEC:
13294 case VMX_EXIT_INVD:
13295 case VMX_EXIT_XSETBV:
13296 case VMX_EXIT_VMLAUNCH:
13297 case VMX_EXIT_VMRESUME:
13298 case VMX_EXIT_VMXOFF:
13299 case VMX_EXIT_ENCLS: /* Condition specified solely by guest hypervisor. */
13300 case VMX_EXIT_VMFUNC:
13301 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13302
13303 /*
13304 * Instructions that cause VM-exits unconditionally or the condition is
13305 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13306 * happens, it's guaranteed to be a nested-guest VM-exit).
13307 *
13308 * - Provides VM-exit instruction length.
13309 * - Provides VM-exit information.
13310 * - Optionally provides Exit qualification.
13311 *
13312 * Since Exit qualification is 0 for all VM-exits where it is not
13313 * applicable, reading and passing it to the guest should produce
13314 * defined behavior.
13315 *
13316 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13317 */
13318 case VMX_EXIT_INVEPT: /* Unconditional. */
13319 case VMX_EXIT_INVVPID:
13320 case VMX_EXIT_VMCLEAR:
13321 case VMX_EXIT_VMPTRLD:
13322 case VMX_EXIT_VMPTRST:
13323 case VMX_EXIT_VMXON:
13324 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by guest hypervisor. */
13325 case VMX_EXIT_LDTR_TR_ACCESS:
13326 case VMX_EXIT_RDRAND:
13327 case VMX_EXIT_RDSEED:
13328 case VMX_EXIT_XSAVES:
13329 case VMX_EXIT_XRSTORS:
13330 case VMX_EXIT_UMWAIT:
13331 case VMX_EXIT_TPAUSE:
13332 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13333
13334 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13335 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13336 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13337 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13338 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13339 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13340 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13341 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13342 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13343 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13344 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13345 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13346 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13347 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13348 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13349 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13350 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13351 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13352 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13353
13354 case VMX_EXIT_PREEMPT_TIMER:
13355 {
13356 /** @todo NSTVMX: Preempt timer. */
13357 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13358 }
13359
13360 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13361 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13362
13363 case VMX_EXIT_VMREAD:
13364 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13365
13366 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13367 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13368
13369 case VMX_EXIT_INIT_SIGNAL:
13370 case VMX_EXIT_SIPI:
13371 case VMX_EXIT_IO_SMI:
13372 case VMX_EXIT_SMI:
13373 case VMX_EXIT_ERR_MSR_LOAD:
13374 case VMX_EXIT_ERR_MACHINE_CHECK:
13375 case VMX_EXIT_PML_FULL:
13376 case VMX_EXIT_RSM:
13377 default:
13378 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13379 }
13380}
13381#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13382
13383
13384/** @name VM-exit helpers.
13385 * @{
13386 */
13387/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13388/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13389/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13390
13391/** Macro for VM-exits called unexpectedly. */
13392#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13393 do { \
13394 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13395 return VERR_VMX_UNEXPECTED_EXIT; \
13396 } while (0)
13397
13398#ifdef VBOX_STRICT
13399/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13400# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13401 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13402
13403# define HMVMX_ASSERT_PREEMPT_CPUID() \
13404 do { \
13405 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13406 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13407 } while (0)
13408
13409# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13410 do { \
13411 AssertPtr((a_pVCpu)); \
13412 AssertPtr((a_pVmxTransient)); \
13413 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13414 Assert((a_pVmxTransient)->pVmcsInfo); \
13415 Assert(ASMIntAreEnabled()); \
13416 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13417 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13418 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13419 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13420 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13421 HMVMX_ASSERT_PREEMPT_CPUID(); \
13422 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13423 } while (0)
13424
13425# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13426 do { \
13427 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13428 Assert((a_pVmxTransient)->fIsNestedGuest); \
13429 } while (0)
13430
13431# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13432 do { \
13433 Log4Func(("\n")); \
13434 } while (0)
13435#else
13436# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13437 do { \
13438 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13439 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13440 } while (0)
13441
13442# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13443 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13444
13445# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13446#endif
13447
13448#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13449/** Macro that does the necessary privilege checks and intercepted VM-exits for
13450 * guests that attempted to execute a VMX instruction. */
13451# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13452 do \
13453 { \
13454 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13455 if (rcStrictTmp == VINF_SUCCESS) \
13456 { /* likely */ } \
13457 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13458 { \
13459 Assert((a_pVCpu)->hm.s.Event.fPending); \
13460 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13461 return VINF_SUCCESS; \
13462 } \
13463 else \
13464 { \
13465 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13466 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13467 } \
13468 } while (0)
13469
13470/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13471# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13472 do \
13473 { \
13474 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13475 (a_pGCPtrEffAddr)); \
13476 if (rcStrictTmp == VINF_SUCCESS) \
13477 { /* likely */ } \
13478 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13479 { \
13480 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13481 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13482 NOREF(uXcptTmp); \
13483 return VINF_SUCCESS; \
13484 } \
13485 else \
13486 { \
13487 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13488 return rcStrictTmp; \
13489 } \
13490 } while (0)
13491#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13492
13493
13494/**
13495 * Advances the guest RIP by the specified number of bytes.
13496 *
13497 * @param pVCpu The cross context virtual CPU structure.
13498 * @param cbInstr Number of bytes to advance the RIP by.
13499 *
13500 * @remarks No-long-jump zone!!!
13501 */
13502DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPU pVCpu, uint32_t cbInstr)
13503{
13504 /* Advance the RIP. */
13505 pVCpu->cpum.GstCtx.rip += cbInstr;
13506 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13507
13508 /* Update interrupt inhibition. */
13509 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13510 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13511 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13512}
13513
13514
13515/**
13516 * Advances the guest RIP after reading it from the VMCS.
13517 *
13518 * @returns VBox status code, no informational status codes.
13519 * @param pVCpu The cross context virtual CPU structure.
13520 * @param pVmxTransient The VMX-transient structure.
13521 *
13522 * @remarks No-long-jump zone!!!
13523 */
13524static int hmR0VmxAdvanceGuestRip(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13525{
13526 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13527 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13528 AssertRCReturn(rc, rc);
13529
13530 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbInstr);
13531 return VINF_SUCCESS;
13532}
13533
13534
13535/**
13536 * Handle a condition that occurred while delivering an event through the guest
13537 * IDT.
13538 *
13539 * @returns Strict VBox status code (i.e. informational status codes too).
13540 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13541 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13542 * to continue execution of the guest which will delivery the \#DF.
13543 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13544 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13545 *
13546 * @param pVCpu The cross context virtual CPU structure.
13547 * @param pVmxTransient The VMX-transient structure.
13548 *
13549 * @remarks No-long-jump zone!!!
13550 */
13551static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13552{
13553 /* Read the IDT vectoring info. and VM-exit interruption info. */
13554 {
13555 int rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
13556 rc |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
13557 AssertRCReturn(rc, rc);
13558 }
13559
13560 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13561 uint32_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13562 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
13563 {
13564 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo);
13565 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo);
13566
13567 /*
13568 * If the event was a software interrupt (generated with INT n) or a software exception
13569 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13570 * can handle the VM-exit and continue guest execution which will re-execute the
13571 * instruction rather than re-injecting the exception, as that can cause premature
13572 * trips to ring-3 before injection and involve TRPM which currently has no way of
13573 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13574 * the problem).
13575 */
13576 IEMXCPTRAISE enmRaise;
13577 IEMXCPTRAISEINFO fRaiseInfo;
13578 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13579 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13580 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13581 {
13582 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13583 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13584 }
13585 else if (VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo))
13586 {
13587 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
13588 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13589 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13590
13591 /** @todo Make AssertMsgReturn as just AssertMsg later. */
13592 AssertMsgReturn(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT,
13593 ("Unexpected VM-exit interruption vector type %#x!\n", uExitVectorType), VERR_VMX_IPE_5);
13594
13595 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13596
13597 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13598 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13599 {
13600 pVmxTransient->fVectoringPF = true;
13601 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13602 }
13603 }
13604 else
13605 {
13606 /*
13607 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13608 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13609 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13610 */
13611 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13612 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13613 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13614 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13615 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13616 }
13617
13618 /*
13619 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13620 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13621 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13622 * subsequent VM-entry would fail, see @bugref{7445}.
13623 *
13624 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13625 */
13626 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13627 && ( enmRaise == IEMXCPTRAISE_PREV_EVENT
13628 || (fRaiseInfo & IEMXCPTRAISEINFO_NMI_PF))
13629 && hmR0VmxIsPinCtlsSet(pVCpu, pVmxTransient, VMX_PIN_CTLS_VIRT_NMI)
13630 && CPUMIsGuestNmiBlocking(pVCpu))
13631 {
13632 CPUMSetGuestNmiBlocking(pVCpu, false);
13633 }
13634
13635 switch (enmRaise)
13636 {
13637 case IEMXCPTRAISE_CURRENT_XCPT:
13638 {
13639 Log4Func(("IDT: Pending secondary Xcpt: uIdtVectoringInfo=%#RX64 uExitIntInfo=%#RX64\n",
13640 pVmxTransient->uIdtVectoringInfo, pVmxTransient->uExitIntInfo));
13641 Assert(rcStrict == VINF_SUCCESS);
13642 break;
13643 }
13644
13645 case IEMXCPTRAISE_PREV_EVENT:
13646 {
13647 uint32_t u32ErrCode;
13648 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
13649 {
13650 int rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
13651 AssertRCReturn(rc, rc);
13652 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13653 }
13654 else
13655 u32ErrCode = 0;
13656
13657 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13658 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13659 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
13660 0 /* cbInstr */, u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13661
13662 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13663 pVCpu->hm.s.Event.u32ErrCode));
13664 Assert(rcStrict == VINF_SUCCESS);
13665 break;
13666 }
13667
13668 case IEMXCPTRAISE_REEXEC_INSTR:
13669 Assert(rcStrict == VINF_SUCCESS);
13670 break;
13671
13672 case IEMXCPTRAISE_DOUBLE_FAULT:
13673 {
13674 /*
13675 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13676 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13677 */
13678 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13679 {
13680 pVmxTransient->fVectoringDoublePF = true;
13681 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13682 pVCpu->cpum.GstCtx.cr2));
13683 rcStrict = VINF_SUCCESS;
13684 }
13685 else
13686 {
13687 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13688 hmR0VmxSetPendingXcptDF(pVCpu);
13689 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13690 uIdtVector, uExitVector));
13691 rcStrict = VINF_HM_DOUBLE_FAULT;
13692 }
13693 break;
13694 }
13695
13696 case IEMXCPTRAISE_TRIPLE_FAULT:
13697 {
13698 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector, uExitVector));
13699 rcStrict = VINF_EM_RESET;
13700 break;
13701 }
13702
13703 case IEMXCPTRAISE_CPU_HANG:
13704 {
13705 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13706 rcStrict = VERR_EM_GUEST_CPU_HANG;
13707 break;
13708 }
13709
13710 default:
13711 {
13712 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13713 rcStrict = VERR_VMX_IPE_2;
13714 break;
13715 }
13716 }
13717 }
13718 else if ( VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo)
13719 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitIntInfo)
13720 && uExitVector != X86_XCPT_DF
13721 && hmR0VmxIsPinCtlsSet(pVCpu, pVmxTransient, VMX_PIN_CTLS_VIRT_NMI))
13722 {
13723 /*
13724 * Execution of IRET caused this fault when NMI blocking was in effect (i.e we're in the guest NMI handler).
13725 * We need to set the block-by-NMI field so that NMIs remain blocked until the IRET execution is restarted.
13726 * See Intel spec. 30.7.1.2 "Resuming guest software after handling an exception".
13727 */
13728 CPUMSetGuestNmiBlocking(pVCpu, true);
13729 Log4Func(("Set NMI blocking. fValid=%RTbool uExitReason=%u\n", VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo),
13730 pVmxTransient->uExitReason));
13731 }
13732
13733 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13734 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13735 return rcStrict;
13736}
13737
13738
13739#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13740/**
13741 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13742 * guest attempting to execute a VMX instruction.
13743 *
13744 * @returns Strict VBox status code (i.e. informational status codes too).
13745 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13746 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13747 *
13748 * @param pVCpu The cross context virtual CPU structure.
13749 * @param uExitReason The VM-exit reason.
13750 *
13751 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13752 * @remarks No-long-jump zone!!!
13753 */
13754static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPU pVCpu, uint32_t uExitReason)
13755{
13756 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13757 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13758
13759 /*
13760 * The physical CPU would have already checked the CPU mode/code segment.
13761 * We shall just assert here for paranoia.
13762 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13763 */
13764 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13765 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13766 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13767
13768 if (uExitReason == VMX_EXIT_VMXON)
13769 {
13770 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13771
13772 /*
13773 * We check CR4.VMXE because it is required to be always set while in VMX operation
13774 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13775 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13776 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13777 */
13778 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13779 {
13780 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13781 hmR0VmxSetPendingXcptUD(pVCpu);
13782 return VINF_HM_PENDING_XCPT;
13783 }
13784 }
13785 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13786 {
13787 /*
13788 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13789 * (other than VMXON), we need to raise a #UD.
13790 */
13791 Log4Func(("Not in VMX root mode -> #UD\n"));
13792 hmR0VmxSetPendingXcptUD(pVCpu);
13793 return VINF_HM_PENDING_XCPT;
13794 }
13795
13796 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13797 return VINF_SUCCESS;
13798}
13799
13800/**
13801 * Decodes the memory operand of an instruction that caused a VM-exit.
13802 *
13803 * The Exit qualification field provides the displacement field for memory
13804 * operand instructions, if any.
13805 *
13806 * @returns Strict VBox status code (i.e. informational status codes too).
13807 * @retval VINF_SUCCESS if the operand was successfully decoded.
13808 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13809 * operand.
13810 * @param pVCpu The cross context virtual CPU structure.
13811 * @param uExitInstrInfo The VM-exit instruction information field.
13812 * @param enmMemAccess The memory operand's access type (read or write).
13813 * @param GCPtrDisp The instruction displacement field, if any. For
13814 * RIP-relative addressing pass RIP + displacement here.
13815 * @param pGCPtrMem Where to store the effective destination memory address.
13816 *
13817 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13818 * virtual-8086 mode hence skips those checks while verifying if the
13819 * segment is valid.
13820 */
13821static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13822 PRTGCPTR pGCPtrMem)
13823{
13824 Assert(pGCPtrMem);
13825 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13826 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13827 | CPUMCTX_EXTRN_CR0);
13828
13829 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13830 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13831 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13832
13833 VMXEXITINSTRINFO ExitInstrInfo;
13834 ExitInstrInfo.u = uExitInstrInfo;
13835 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13836 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13837 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13838 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13839 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13840 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13841 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13842 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13843 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13844
13845 /*
13846 * Validate instruction information.
13847 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13848 */
13849 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13850 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13851 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13852 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13853 AssertLogRelMsgReturn(fIsMemOperand,
13854 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13855
13856 /*
13857 * Compute the complete effective address.
13858 *
13859 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13860 * See AMD spec. 4.5.2 "Segment Registers".
13861 */
13862 RTGCPTR GCPtrMem = GCPtrDisp;
13863 if (fBaseRegValid)
13864 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13865 if (fIdxRegValid)
13866 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13867
13868 RTGCPTR const GCPtrOff = GCPtrMem;
13869 if ( !fIsLongMode
13870 || iSegReg >= X86_SREG_FS)
13871 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13872 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13873
13874 /*
13875 * Validate effective address.
13876 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13877 */
13878 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13879 Assert(cbAccess > 0);
13880 if (fIsLongMode)
13881 {
13882 if (X86_IS_CANONICAL(GCPtrMem))
13883 {
13884 *pGCPtrMem = GCPtrMem;
13885 return VINF_SUCCESS;
13886 }
13887
13888 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13889 * "Data Limit Checks in 64-bit Mode". */
13890 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13891 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13892 return VINF_HM_PENDING_XCPT;
13893 }
13894
13895 /*
13896 * This is a watered down version of iemMemApplySegment().
13897 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13898 * and segment CPL/DPL checks are skipped.
13899 */
13900 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13901 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13902 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13903
13904 /* Check if the segment is present and usable. */
13905 if ( pSel->Attr.n.u1Present
13906 && !pSel->Attr.n.u1Unusable)
13907 {
13908 Assert(pSel->Attr.n.u1DescType);
13909 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13910 {
13911 /* Check permissions for the data segment. */
13912 if ( enmMemAccess == VMXMEMACCESS_WRITE
13913 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13914 {
13915 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13916 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13917 return VINF_HM_PENDING_XCPT;
13918 }
13919
13920 /* Check limits if it's a normal data segment. */
13921 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13922 {
13923 if ( GCPtrFirst32 > pSel->u32Limit
13924 || GCPtrLast32 > pSel->u32Limit)
13925 {
13926 Log4Func(("Data segment limit exceeded. "
13927 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13928 GCPtrLast32, pSel->u32Limit));
13929 if (iSegReg == X86_SREG_SS)
13930 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13931 else
13932 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13933 return VINF_HM_PENDING_XCPT;
13934 }
13935 }
13936 else
13937 {
13938 /* Check limits if it's an expand-down data segment.
13939 Note! The upper boundary is defined by the B bit, not the G bit! */
13940 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13941 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13942 {
13943 Log4Func(("Expand-down data segment limit exceeded. "
13944 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13945 GCPtrLast32, pSel->u32Limit));
13946 if (iSegReg == X86_SREG_SS)
13947 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13948 else
13949 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13950 return VINF_HM_PENDING_XCPT;
13951 }
13952 }
13953 }
13954 else
13955 {
13956 /* Check permissions for the code segment. */
13957 if ( enmMemAccess == VMXMEMACCESS_WRITE
13958 || ( enmMemAccess == VMXMEMACCESS_READ
13959 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13960 {
13961 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13962 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13963 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13964 return VINF_HM_PENDING_XCPT;
13965 }
13966
13967 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13968 if ( GCPtrFirst32 > pSel->u32Limit
13969 || GCPtrLast32 > pSel->u32Limit)
13970 {
13971 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13972 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13973 if (iSegReg == X86_SREG_SS)
13974 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13975 else
13976 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13977 return VINF_HM_PENDING_XCPT;
13978 }
13979 }
13980 }
13981 else
13982 {
13983 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13984 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13985 return VINF_HM_PENDING_XCPT;
13986 }
13987
13988 *pGCPtrMem = GCPtrMem;
13989 return VINF_SUCCESS;
13990}
13991#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13992
13993
13994/**
13995 * VM-exit helper for LMSW.
13996 */
13997static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13998{
13999 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14000 AssertRCReturn(rc, rc);
14001
14002 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
14003 AssertMsg( rcStrict == VINF_SUCCESS
14004 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14005
14006 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14007 if (rcStrict == VINF_IEM_RAISED_XCPT)
14008 {
14009 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14010 rcStrict = VINF_SUCCESS;
14011 }
14012
14013 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
14014 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14015 return rcStrict;
14016}
14017
14018
14019/**
14020 * VM-exit helper for CLTS.
14021 */
14022static VBOXSTRICTRC hmR0VmxExitClts(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
14023{
14024 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14025 AssertRCReturn(rc, rc);
14026
14027 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
14028 AssertMsg( rcStrict == VINF_SUCCESS
14029 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14030
14031 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14032 if (rcStrict == VINF_IEM_RAISED_XCPT)
14033 {
14034 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14035 rcStrict = VINF_SUCCESS;
14036 }
14037
14038 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
14039 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14040 return rcStrict;
14041}
14042
14043
14044/**
14045 * VM-exit helper for MOV from CRx (CRx read).
14046 */
14047static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14048{
14049 Assert(iCrReg < 16);
14050 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14051
14052 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14053 AssertRCReturn(rc, rc);
14054
14055 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
14056 AssertMsg( rcStrict == VINF_SUCCESS
14057 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14058
14059 if (iGReg == X86_GREG_xSP)
14060 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
14061 else
14062 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14063#ifdef VBOX_WITH_STATISTICS
14064 switch (iCrReg)
14065 {
14066 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
14067 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
14068 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
14069 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
14070 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
14071 }
14072#endif
14073 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
14074 return rcStrict;
14075}
14076
14077
14078/**
14079 * VM-exit helper for MOV to CRx (CRx write).
14080 */
14081static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14082{
14083 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14084 AssertRCReturn(rc, rc);
14085
14086 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
14087 AssertMsg( rcStrict == VINF_SUCCESS
14088 || rcStrict == VINF_IEM_RAISED_XCPT
14089 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14090
14091 switch (iCrReg)
14092 {
14093 case 0:
14094 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14095 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
14096 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
14097 break;
14098
14099 case 2:
14100 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
14101 /* Nothing to do here, CR2 it's not part of the VMCS. */
14102 break;
14103
14104 case 3:
14105 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
14106 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
14107 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
14108 break;
14109
14110 case 4:
14111 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
14112 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
14113 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
14114 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
14115 break;
14116
14117 case 8:
14118 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
14119 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
14120 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
14121 break;
14122
14123 default:
14124 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
14125 break;
14126 }
14127
14128 if (rcStrict == VINF_IEM_RAISED_XCPT)
14129 {
14130 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14131 rcStrict = VINF_SUCCESS;
14132 }
14133 return rcStrict;
14134}
14135
14136
14137/**
14138 * VM-exit exception handler for \#PF (Page-fault exception).
14139 */
14140static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14141{
14142 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14143 PVM pVM = pVCpu->CTX_SUFF(pVM);
14144 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14145 rc |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14146 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14147 AssertRCReturn(rc, rc);
14148
14149 if (!pVM->hm.s.fNestedPaging)
14150 { /* likely */ }
14151 else
14152 {
14153#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
14154 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
14155#endif
14156 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
14157 if (RT_LIKELY(!pVmxTransient->fVectoringDoublePF))
14158 {
14159 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14160 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
14161 }
14162 else
14163 {
14164 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14165 hmR0VmxSetPendingXcptDF(pVCpu);
14166 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
14167 }
14168 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14169 return rc;
14170 }
14171
14172 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
14173 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
14174 if (pVmxTransient->fVectoringPF)
14175 {
14176 Assert(pVCpu->hm.s.Event.fPending);
14177 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14178 }
14179
14180 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14181 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14182 AssertRCReturn(rc, rc);
14183
14184 Log4Func(("#PF: cr2=%#RX64 cs:rip=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", pVmxTransient->uExitQual, pCtx->cs.Sel,
14185 pCtx->rip, pVmxTransient->uExitIntErrorCode, pCtx->cr3));
14186
14187 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
14188 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
14189
14190 Log4Func(("#PF: rc=%Rrc\n", rc));
14191 if (rc == VINF_SUCCESS)
14192 {
14193 /*
14194 * This is typically a shadow page table sync or a MMIO instruction. But we may have
14195 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
14196 */
14197 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14198 TRPMResetTrap(pVCpu);
14199 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
14200 return rc;
14201 }
14202
14203 if (rc == VINF_EM_RAW_GUEST_TRAP)
14204 {
14205 if (!pVmxTransient->fVectoringDoublePF)
14206 {
14207 /* It's a guest page fault and needs to be reflected to the guest. */
14208 uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
14209 TRPMResetTrap(pVCpu);
14210 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
14211 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14212 uGstErrorCode, pVmxTransient->uExitQual);
14213 }
14214 else
14215 {
14216 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14217 TRPMResetTrap(pVCpu);
14218 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14219 hmR0VmxSetPendingXcptDF(pVCpu);
14220 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14221 }
14222
14223 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14224 return VINF_SUCCESS;
14225 }
14226
14227 TRPMResetTrap(pVCpu);
14228 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14229 return rc;
14230}
14231
14232
14233/**
14234 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14235 */
14236static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14237{
14238 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14239 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14240
14241 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14242 AssertRCReturn(rc, rc);
14243
14244 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14245 {
14246 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14247 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14248
14249 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14250 * provides VM-exit instruction length. If this causes problem later,
14251 * disassemble the instruction like it's done on AMD-V. */
14252 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14253 AssertRCReturn(rc2, rc2);
14254 return rc;
14255 }
14256
14257 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14258 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14259 return rc;
14260}
14261
14262
14263/**
14264 * VM-exit exception handler for \#BP (Breakpoint exception).
14265 */
14266static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14267{
14268 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14269 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14270
14271 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14272 AssertRCReturn(rc, rc);
14273
14274 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14275 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14276 if (rc == VINF_EM_RAW_GUEST_TRAP)
14277 {
14278 rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14279 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14280 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14281 AssertRCReturn(rc, rc);
14282
14283 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14284 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14285 }
14286
14287 Assert(rc == VINF_SUCCESS || rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_EM_DBG_BREAKPOINT);
14288 return rc;
14289}
14290
14291
14292/**
14293 * VM-exit exception handler for \#AC (alignment check exception).
14294 */
14295static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14296{
14297 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14298 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14299
14300 /*
14301 * Re-inject it. We'll detect any nesting before getting here.
14302 */
14303 int rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14304 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14305 AssertRCReturn(rc, rc);
14306 Assert(ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead) & HMVMX_READ_EXIT_INTERRUPTION_INFO);
14307
14308 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14309 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14310 return VINF_SUCCESS;
14311}
14312
14313
14314/**
14315 * VM-exit exception handler for \#DB (Debug exception).
14316 */
14317static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14318{
14319 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14320 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14321
14322 /*
14323 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14324 */
14325 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14326
14327 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14328 uint64_t const uDR6 = X86_DR6_INIT_VAL
14329 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14330 | X86_DR6_BD | X86_DR6_BS));
14331
14332 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14333 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14334 Log6Func(("rc=%Rrc\n", rc));
14335 if (rc == VINF_EM_RAW_GUEST_TRAP)
14336 {
14337 /*
14338 * The exception was for the guest. Update DR6, DR7.GD and
14339 * IA32_DEBUGCTL.LBR before forwarding it.
14340 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14341 */
14342 VMMRZCallRing3Disable(pVCpu);
14343 HM_DISABLE_PREEMPT(pVCpu);
14344
14345 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14346 pCtx->dr[6] |= uDR6;
14347 if (CPUMIsGuestDebugStateActive(pVCpu))
14348 ASMSetDR6(pCtx->dr[6]);
14349
14350 HM_RESTORE_PREEMPT();
14351 VMMRZCallRing3Enable(pVCpu);
14352
14353 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14354 AssertRCReturn(rc, rc);
14355
14356 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14357 pCtx->dr[7] &= ~X86_DR7_GD;
14358
14359 /* Paranoia. */
14360 pCtx->dr[7] &= ~X86_DR7_RAZ_MASK;
14361 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14362
14363 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, (uint32_t)pCtx->dr[7]);
14364 AssertRCReturn(rc, rc);
14365
14366 /*
14367 * Raise #DB in the guest.
14368 *
14369 * It is important to reflect exactly what the VM-exit gave us (preserving the
14370 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14371 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14372 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14373 *
14374 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14375 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14376 */
14377 rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14378 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14379 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14380 AssertRCReturn(rc, rc);
14381 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14382 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14383 return VINF_SUCCESS;
14384 }
14385
14386 /*
14387 * Not a guest trap, must be a hypervisor related debug event then.
14388 * Update DR6 in case someone is interested in it.
14389 */
14390 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14391 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14392 CPUMSetHyperDR6(pVCpu, uDR6);
14393
14394 return rc;
14395}
14396
14397
14398/**
14399 * Hacks its way around the lovely mesa driver's backdoor accesses.
14400 *
14401 * @sa hmR0SvmHandleMesaDrvGp.
14402 */
14403static int hmR0VmxHandleMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14404{
14405 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14406 RT_NOREF(pCtx);
14407
14408 /* For now we'll just skip the instruction. */
14409 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14410}
14411
14412
14413/**
14414 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14415 * backdoor logging w/o checking what it is running inside.
14416 *
14417 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14418 * backdoor port and magic numbers loaded in registers.
14419 *
14420 * @returns true if it is, false if it isn't.
14421 * @sa hmR0SvmIsMesaDrvGp.
14422 */
14423DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14424{
14425 /* 0xed: IN eAX,dx */
14426 uint8_t abInstr[1];
14427 if (pVmxTransient->cbInstr != sizeof(abInstr))
14428 return false;
14429
14430 /* Check that it is #GP(0). */
14431 if (pVmxTransient->uExitIntErrorCode != 0)
14432 return false;
14433
14434 /* Check magic and port. */
14435 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14436 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14437 if (pCtx->rax != UINT32_C(0x564d5868))
14438 return false;
14439 if (pCtx->dx != UINT32_C(0x5658))
14440 return false;
14441
14442 /* Flat ring-3 CS. */
14443 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14444 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14445 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14446 if (pCtx->cs.Attr.n.u2Dpl != 3)
14447 return false;
14448 if (pCtx->cs.u64Base != 0)
14449 return false;
14450
14451 /* Check opcode. */
14452 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14453 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14454 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14455 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14456 if (RT_FAILURE(rc))
14457 return false;
14458 if (abInstr[0] != 0xed)
14459 return false;
14460
14461 return true;
14462}
14463
14464/**
14465 * VM-exit exception handler for \#GP (General-protection exception).
14466 *
14467 * @remarks Requires pVmxTransient->uExitIntInfo to be up-to-date.
14468 */
14469static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14470{
14471 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14472 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14473
14474 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14475 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14476 if (pVmcsInfo->RealMode.fRealOnV86Active)
14477 { /* likely */ }
14478 else
14479 {
14480#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14481 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14482#endif
14483 /* If the guest is not in real-mode or we have unrestricted guest execution support, reflect #GP to the guest. */
14484 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14485 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14486 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14487 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14488 AssertRCReturn(rc, rc);
14489 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14490 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14491
14492 if ( pVmxTransient->fIsNestedGuest
14493 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14494 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14495 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14496 pVmxTransient->cbInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14497 else
14498 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14499 return rc;
14500 }
14501
14502 Assert(CPUMIsGuestInRealModeEx(pCtx));
14503 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14504 Assert(!pVmxTransient->fIsNestedGuest);
14505
14506 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14507 AssertRCReturn(rc, rc);
14508
14509 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14510 if (rcStrict == VINF_SUCCESS)
14511 {
14512 if (!CPUMIsGuestInRealModeEx(pCtx))
14513 {
14514 /*
14515 * The guest is no longer in real-mode, check if we can continue executing the
14516 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14517 */
14518 pVmcsInfo->RealMode.fRealOnV86Active = false;
14519 if (HMCanExecuteVmxGuest(pVCpu, pCtx))
14520 {
14521 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14522 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14523 }
14524 else
14525 {
14526 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14527 rcStrict = VINF_EM_RESCHEDULE;
14528 }
14529 }
14530 else
14531 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14532 }
14533 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14534 {
14535 rcStrict = VINF_SUCCESS;
14536 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14537 }
14538 return VBOXSTRICTRC_VAL(rcStrict);
14539}
14540
14541
14542/**
14543 * VM-exit exception handler wrapper for generic exceptions.
14544 *
14545 * This simply re-injects the exception back into the VM without any special
14546 * processing.
14547 */
14548static VBOXSTRICTRC hmR0VmxExitXcptGeneric(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14549{
14550 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14551
14552#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14553 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14554 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14555 ("uVector=%#x u32XcptBitmap=%#X32\n",
14556 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14557 NOREF(pVmcsInfo);
14558#endif
14559
14560 /*
14561 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14562 * would have been handled while checking exits due to event delivery.
14563 */
14564 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14565 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14566 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14567 AssertRCReturn(rc, rc);
14568
14569 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14570
14571#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14572 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14573 AssertRCReturn(rc, rc);
14574 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14575#endif
14576
14577#ifdef VBOX_WITH_STATISTICS
14578 switch (uVector)
14579 {
14580 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14581 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14582 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14583 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14584 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14585 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14586 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14587 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14588 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14589 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14590 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14591 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14592 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14593 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14594 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14595 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14596 default:
14597 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14598 break;
14599 }
14600#endif
14601
14602 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14603 Assert( uVector != X86_XCPT_PF
14604 || VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo) != VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
14605 NOREF(uVector);
14606
14607 /* Re-inject the original exception into the guest. */
14608 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14609 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14610 return VINF_SUCCESS;
14611}
14612/** @} */
14613
14614
14615/** @name VM-exit handlers.
14616 * @{
14617 */
14618/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14619/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14620/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14621
14622/**
14623 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14624 */
14625HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14626{
14627 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14628 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14629 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14630 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14631 return VINF_SUCCESS;
14632 return VINF_EM_RAW_INTERRUPT;
14633}
14634
14635
14636/**
14637 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14638 * VM-exit.
14639 */
14640HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14641{
14642 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14643 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14644
14645 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14646 AssertRCReturn(rc, rc);
14647
14648 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14649 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14650
14651 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14652 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14653 && uIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14654 NOREF(pVmcsInfo);
14655
14656 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
14657 {
14658 /*
14659 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14660 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14661 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14662 *
14663 * [1] -- See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14664 * [2] -- See Intel spec. 27.5.5 "Updating Non-Register State".
14665 */
14666 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14667 return hmR0VmxExitHostNmi(pVCpu);
14668 }
14669
14670 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
14671 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14672 if (RT_UNLIKELY(rcStrict == VINF_SUCCESS))
14673 { /* likely */ }
14674 else
14675 {
14676 if (rcStrict == VINF_HM_DOUBLE_FAULT)
14677 {
14678 Assert(pVCpu->hm.s.Event.fPending);
14679 rcStrict = VINF_SUCCESS;
14680 }
14681 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14682 return rcStrict;
14683 }
14684
14685 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
14686 uint32_t const uVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
14687 switch (uIntType)
14688 {
14689 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT: /* Privileged software exception. (#DB from ICEBP) */
14690 Assert(uVector == X86_XCPT_DB);
14691 RT_FALL_THRU();
14692 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT: /* Software exception. (#BP or #OF) */
14693 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14694 RT_FALL_THRU();
14695 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14696 {
14697 /*
14698 * If there's any exception caused as a result of event injection, the resulting
14699 * secondary/final execption will be pending, we shall continue guest execution
14700 * after injecting the event. The page-fault case is complicated and we manually
14701 * handle any currently pending event in hmR0VmxExitXcptPF.
14702 */
14703 if (!pVCpu->hm.s.Event.fPending)
14704 { /* likely */ }
14705 else if (uVector != X86_XCPT_PF)
14706 {
14707 rcStrict = VINF_SUCCESS;
14708 break;
14709 }
14710
14711 switch (uVector)
14712 {
14713 case X86_XCPT_PF: rcStrict = hmR0VmxExitXcptPF(pVCpu, pVmxTransient); break;
14714 case X86_XCPT_GP: rcStrict = hmR0VmxExitXcptGP(pVCpu, pVmxTransient); break;
14715 case X86_XCPT_MF: rcStrict = hmR0VmxExitXcptMF(pVCpu, pVmxTransient); break;
14716 case X86_XCPT_DB: rcStrict = hmR0VmxExitXcptDB(pVCpu, pVmxTransient); break;
14717 case X86_XCPT_BP: rcStrict = hmR0VmxExitXcptBP(pVCpu, pVmxTransient); break;
14718 case X86_XCPT_AC: rcStrict = hmR0VmxExitXcptAC(pVCpu, pVmxTransient); break;
14719 default:
14720 rcStrict = hmR0VmxExitXcptGeneric(pVCpu, pVmxTransient);
14721 break;
14722 }
14723 break;
14724 }
14725
14726 default:
14727 {
14728 pVCpu->hm.s.u32HMError = uExitIntInfo;
14729 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14730 AssertMsgFailed(("Unexpected interruption info %#x\n", VMX_EXIT_INT_INFO_TYPE(uExitIntInfo)));
14731 break;
14732 }
14733 }
14734 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14735 return rcStrict;
14736}
14737
14738
14739/**
14740 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14741 */
14742HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14743{
14744 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14745
14746 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14747 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14748 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14749 AssertRCReturn(rc, rc);
14750
14751 /* Evaluate and deliver pending events and resume guest execution. */
14752 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14753 return VINF_SUCCESS;
14754}
14755
14756
14757/**
14758 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14759 */
14760HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14761{
14762 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14763
14764 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14765 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14766 {
14767 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14768 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14769 }
14770
14771 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14772
14773 /*
14774 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14775 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14776 */
14777 uint32_t fIntrState;
14778 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14779 AssertRCReturn(rc, rc);
14780 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14781 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14782 {
14783 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14784 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14785
14786 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14787 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14788 AssertRCReturn(rc, rc);
14789 }
14790
14791 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14792 rc = hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14793 AssertRCReturn(rc, rc);
14794
14795 /* Evaluate and deliver pending events and resume guest execution. */
14796 return VINF_SUCCESS;
14797}
14798
14799
14800/**
14801 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14802 */
14803HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14804{
14805 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14806 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14807}
14808
14809
14810/**
14811 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14812 */
14813HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14814{
14815 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14816 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14817}
14818
14819
14820/**
14821 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14822 */
14823HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14824{
14825 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14826
14827 /*
14828 * Get the state we need and update the exit history entry.
14829 */
14830 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14831 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14832 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14833 AssertRCReturn(rc, rc);
14834
14835 VBOXSTRICTRC rcStrict;
14836 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14837 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14838 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14839 if (!pExitRec)
14840 {
14841 /*
14842 * Regular CPUID instruction execution.
14843 */
14844 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbInstr);
14845 if (rcStrict == VINF_SUCCESS)
14846 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14847 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14848 {
14849 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14850 rcStrict = VINF_SUCCESS;
14851 }
14852 }
14853 else
14854 {
14855 /*
14856 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14857 */
14858 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14859 AssertRCReturn(rc2, rc2);
14860
14861 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14862 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14863
14864 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14865 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14866
14867 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14868 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14869 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14870 }
14871 return rcStrict;
14872}
14873
14874
14875/**
14876 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14877 */
14878HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14879{
14880 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14881
14882 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14883 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14884 AssertRCReturn(rc, rc);
14885
14886 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14887 return VINF_EM_RAW_EMULATE_INSTR;
14888
14889 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14890 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14891}
14892
14893
14894/**
14895 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14896 */
14897HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14898{
14899 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14900
14901 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14902 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14903 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14904 AssertRCReturn(rc, rc);
14905
14906 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbInstr);
14907 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14908 {
14909 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14910 we must reset offsetting on VM-entry. See @bugref{6634}. */
14911 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14912 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14913 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14914 }
14915 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14916 {
14917 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14918 rcStrict = VINF_SUCCESS;
14919 }
14920 return rcStrict;
14921}
14922
14923
14924/**
14925 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14926 */
14927HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14928{
14929 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14930
14931 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14932 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14933 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14934 AssertRCReturn(rc, rc);
14935
14936 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbInstr);
14937 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14938 {
14939 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14940 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14941 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14942 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14943 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14944 }
14945 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14946 {
14947 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14948 rcStrict = VINF_SUCCESS;
14949 }
14950 return rcStrict;
14951}
14952
14953
14954/**
14955 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14956 */
14957HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14958{
14959 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14960
14961 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14962 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14963 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14964 AssertRCReturn(rc, rc);
14965
14966 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14967 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14968 if (RT_LIKELY(rc == VINF_SUCCESS))
14969 {
14970 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14971 Assert(pVmxTransient->cbInstr == 2);
14972 }
14973 else
14974 {
14975 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14976 rc = VERR_EM_INTERPRETER;
14977 }
14978 return rc;
14979}
14980
14981
14982/**
14983 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14984 */
14985HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14986{
14987 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14988
14989 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14990 if (EMAreHypercallInstructionsEnabled(pVCpu))
14991 {
14992 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14993 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14994 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14995 AssertRCReturn(rc, rc);
14996
14997 /* Perform the hypercall. */
14998 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14999 if (rcStrict == VINF_SUCCESS)
15000 {
15001 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15002 AssertRCReturn(rc, rc);
15003 }
15004 else
15005 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
15006 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
15007 || RT_FAILURE(rcStrict));
15008
15009 /* If the hypercall changes anything other than guest's general-purpose registers,
15010 we would need to reload the guest changed bits here before VM-entry. */
15011 }
15012 else
15013 Log4Func(("Hypercalls not enabled\n"));
15014
15015 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
15016 if (RT_FAILURE(rcStrict))
15017 {
15018 hmR0VmxSetPendingXcptUD(pVCpu);
15019 rcStrict = VINF_SUCCESS;
15020 }
15021
15022 return rcStrict;
15023}
15024
15025
15026/**
15027 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
15028 */
15029HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15030{
15031 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15032 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
15033
15034 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15035 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15036 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15037 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15038 AssertRCReturn(rc, rc);
15039
15040 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbInstr, pVmxTransient->uExitQual);
15041
15042 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
15043 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15044 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15045 {
15046 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15047 rcStrict = VINF_SUCCESS;
15048 }
15049 else
15050 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
15051 VBOXSTRICTRC_VAL(rcStrict)));
15052 return rcStrict;
15053}
15054
15055
15056/**
15057 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
15058 */
15059HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15060{
15061 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15062
15063 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15064 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
15065 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15066 AssertRCReturn(rc, rc);
15067
15068 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbInstr);
15069 if (rcStrict == VINF_SUCCESS)
15070 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15071 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15072 {
15073 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15074 rcStrict = VINF_SUCCESS;
15075 }
15076
15077 return rcStrict;
15078}
15079
15080
15081/**
15082 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
15083 */
15084HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15085{
15086 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15087
15088 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15089 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15090 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15091 AssertRCReturn(rc, rc);
15092
15093 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbInstr);
15094 if (RT_SUCCESS(rcStrict))
15095 {
15096 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15097 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
15098 rcStrict = VINF_SUCCESS;
15099 }
15100
15101 return rcStrict;
15102}
15103
15104
15105/**
15106 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
15107 * VM-exit.
15108 */
15109HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15110{
15111 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15112 return VINF_EM_RESET;
15113}
15114
15115
15116/**
15117 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
15118 */
15119HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15120{
15121 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15122
15123 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15124 AssertRCReturn(rc, rc);
15125
15126 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
15127 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
15128 rc = VINF_SUCCESS;
15129 else
15130 rc = VINF_EM_HALT;
15131
15132 if (rc != VINF_SUCCESS)
15133 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
15134 return rc;
15135}
15136
15137
15138/**
15139 * VM-exit handler for instructions that result in a \#UD exception delivered to
15140 * the guest.
15141 */
15142HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15143{
15144 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15145 hmR0VmxSetPendingXcptUD(pVCpu);
15146 return VINF_SUCCESS;
15147}
15148
15149
15150/**
15151 * VM-exit handler for expiry of the VMX-preemption timer.
15152 */
15153HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15154{
15155 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15156
15157 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
15158 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15159
15160 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
15161 PVM pVM = pVCpu->CTX_SUFF(pVM);
15162 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
15163 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
15164 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
15165}
15166
15167
15168/**
15169 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
15170 */
15171HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15172{
15173 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15174
15175 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15176 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15177 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15178 AssertRCReturn(rc, rc);
15179
15180 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbInstr);
15181 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15182 : HM_CHANGED_RAISED_XCPT_MASK);
15183
15184 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15185 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15186
15187 return rcStrict;
15188}
15189
15190
15191/**
15192 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15193 */
15194HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15195{
15196 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15197 /** @todo Use VM-exit instruction information. */
15198 return VERR_EM_INTERPRETER;
15199}
15200
15201
15202/**
15203 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15204 * VM-exit.
15205 */
15206HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15207{
15208 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15209 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15210 AssertRCReturn(rc, rc);
15211
15212 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15213 if (RT_FAILURE(rc))
15214 return rc;
15215
15216 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15217 NOREF(uInvalidReason);
15218
15219#ifdef VBOX_STRICT
15220 uint32_t fIntrState;
15221 RTHCUINTREG uHCReg;
15222 uint64_t u64Val;
15223 uint32_t u32Val;
15224 rc = hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15225 rc |= hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15226 rc |= hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15227 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
15228 AssertRCReturn(rc, rc);
15229
15230 Log4(("uInvalidReason %u\n", uInvalidReason));
15231 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15232 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15233 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15234 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15235
15236 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val); AssertRC(rc);
15237 Log4(("VMX_VMCS_GUEST_CR0 %#RX32\n", u32Val));
15238 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
15239 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
15240 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
15241 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15242 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
15243 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
15244 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
15245 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15246 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15247 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15248
15249 hmR0DumpRegs(pVCpu);
15250#endif
15251
15252 return VERR_VMX_INVALID_GUEST_STATE;
15253}
15254
15255/**
15256 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15257 */
15258HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15259{
15260 /*
15261 * Cummulative notes of all recognized but unexpected VM-exits.
15262 *
15263 * 1. This does -not- cover scenarios like like a page-fault VM-exit occurring when
15264 * nested-paging is used.
15265 *
15266 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15267 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15268 * this function (and thereby stop VM execution) for handling such instructions.
15269 *
15270 *
15271 * VMX_EXIT_INIT_SIGNAL:
15272 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15273 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15274 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15275 *
15276 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15277 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15278 * See Intel spec. "23.8 Restrictions on VMX operation".
15279 *
15280 * VMX_EXIT_SIPI:
15281 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15282 * activity state is used. We don't make use of it as our guests don't have direct
15283 * access to the host local APIC.
15284 *
15285 * See Intel spec. 25.3 "Other Causes of VM-exits".
15286 *
15287 * VMX_EXIT_IO_SMI:
15288 * VMX_EXIT_SMI:
15289 * This can only happen if we support dual-monitor treatment of SMI, which can be
15290 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15291 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15292 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15293 *
15294 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15295 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15296 *
15297 * VMX_EXIT_ERR_MSR_LOAD:
15298 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15299 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15300 * execution.
15301 *
15302 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15303 *
15304 * VMX_EXIT_ERR_MACHINE_CHECK:
15305 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15306 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15307 * #MC exception abort class exception is raised. We thus cannot assume a
15308 * reasonable chance of continuing any sort of execution and we bail.
15309 *
15310 * See Intel spec. 15.1 "Machine-check Architecture".
15311 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15312 *
15313 * VMX_EXIT_PML_FULL:
15314 * VMX_EXIT_VIRTUALIZED_EOI:
15315 * VMX_EXIT_APIC_WRITE:
15316 * We do not currently support any of these features and thus they are all unexpected
15317 * VM-exits.
15318 *
15319 * VMX_EXIT_GDTR_IDTR_ACCESS:
15320 * VMX_EXIT_LDTR_TR_ACCESS:
15321 * VMX_EXIT_RDRAND:
15322 * VMX_EXIT_RSM:
15323 * VMX_EXIT_VMFUNC:
15324 * VMX_EXIT_ENCLS:
15325 * VMX_EXIT_RDSEED:
15326 * VMX_EXIT_XSAVES:
15327 * VMX_EXIT_XRSTORS:
15328 * VMX_EXIT_UMWAIT:
15329 * VMX_EXIT_TPAUSE:
15330 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15331 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15332 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15333 *
15334 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15335 */
15336 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15337 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15338 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15339}
15340
15341
15342/**
15343 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15344 */
15345HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15346{
15347 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15348
15349 /** @todo Optimize this: We currently drag in in the whole MSR state
15350 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15351 * MSRs required. That would require changes to IEM and possibly CPUM too.
15352 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15353 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15354 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15355 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15356 switch (idMsr)
15357 {
15358 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15359 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15360 }
15361
15362 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15363 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15364 AssertRCReturn(rc, rc);
15365
15366 Log4Func(("ecx=%#RX32\n", idMsr));
15367
15368#ifdef VBOX_STRICT
15369 Assert(!pVmxTransient->fIsNestedGuest);
15370 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15371 {
15372 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15373 && idMsr != MSR_K6_EFER)
15374 {
15375 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15376 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15377 }
15378 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15379 {
15380 Assert(pVmcsInfo->pvMsrBitmap);
15381 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15382 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15383 {
15384 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15385 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15386 }
15387 }
15388 }
15389#endif
15390
15391 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbInstr);
15392 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15393 if (rcStrict == VINF_SUCCESS)
15394 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15395 | HM_CHANGED_GUEST_RAX | HM_CHANGED_GUEST_RDX);
15396 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15397 {
15398 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15399 rcStrict = VINF_SUCCESS;
15400 }
15401 else
15402 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15403
15404 return rcStrict;
15405}
15406
15407
15408/**
15409 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15410 */
15411HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15412{
15413 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15414
15415 /** @todo Optimize this: We currently drag in in the whole MSR state
15416 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15417 * MSRs required. That would require changes to IEM and possibly CPUM too.
15418 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15419 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15420 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15421
15422 /*
15423 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15424 * Although we don't need to fetch the base as it will be overwritten shortly, while
15425 * loading guest-state we would also load the entire segment register including limit
15426 * and attributes and thus we need to load them here.
15427 */
15428 switch (idMsr)
15429 {
15430 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15431 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15432 }
15433
15434 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15435 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15436 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15437 AssertRCReturn(rc, rc);
15438
15439 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15440
15441 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbInstr);
15442 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15443
15444 if (rcStrict == VINF_SUCCESS)
15445 {
15446 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15447
15448 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15449 if ( idMsr == MSR_IA32_APICBASE
15450 || ( idMsr >= MSR_IA32_X2APIC_START
15451 && idMsr <= MSR_IA32_X2APIC_END))
15452 {
15453 /*
15454 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15455 * When full APIC register virtualization is implemented we'll have to make
15456 * sure APIC state is saved from the VMCS before IEM changes it.
15457 */
15458 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15459 }
15460 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15461 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15462 else if (idMsr == MSR_K6_EFER)
15463 {
15464 /*
15465 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15466 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15467 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15468 */
15469 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15470 }
15471
15472 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15473 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15474 {
15475 switch (idMsr)
15476 {
15477 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15478 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15479 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15480 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15481 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15482 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15483 default:
15484 {
15485 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15486 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15487 else if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15488 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15489 break;
15490 }
15491 }
15492 }
15493#ifdef VBOX_STRICT
15494 else
15495 {
15496 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15497 switch (idMsr)
15498 {
15499 case MSR_IA32_SYSENTER_CS:
15500 case MSR_IA32_SYSENTER_EIP:
15501 case MSR_IA32_SYSENTER_ESP:
15502 case MSR_K8_FS_BASE:
15503 case MSR_K8_GS_BASE:
15504 {
15505 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15506 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15507 }
15508
15509 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15510 default:
15511 {
15512 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15513 {
15514 /* EFER MSR writes are always intercepted. */
15515 if (idMsr != MSR_K6_EFER)
15516 {
15517 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15518 idMsr));
15519 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15520 }
15521 }
15522
15523 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15524 {
15525 Assert(pVmcsInfo->pvMsrBitmap);
15526 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15527 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15528 {
15529 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15530 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15531 }
15532 }
15533 break;
15534 }
15535 }
15536 }
15537#endif /* VBOX_STRICT */
15538 }
15539 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15540 {
15541 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15542 rcStrict = VINF_SUCCESS;
15543 }
15544 else
15545 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15546
15547 return rcStrict;
15548}
15549
15550
15551/**
15552 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15553 */
15554HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15555{
15556 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15557
15558 /** @todo The guest has likely hit a contended spinlock. We might want to
15559 * poke a schedule different guest VCPU. */
15560 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15561 if (RT_SUCCESS(rc))
15562 return VINF_EM_RAW_INTERRUPT;
15563
15564 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15565 return rc;
15566}
15567
15568
15569/**
15570 * VM-exit handler for when the TPR value is lowered below the specified
15571 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15572 */
15573HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15574{
15575 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15576 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15577
15578 /*
15579 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15580 * We'll re-evaluate pending interrupts and inject them before the next VM
15581 * entry so we can just continue execution here.
15582 */
15583 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15584 return VINF_SUCCESS;
15585}
15586
15587
15588/**
15589 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15590 * VM-exit.
15591 *
15592 * @retval VINF_SUCCESS when guest execution can continue.
15593 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15594 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15595 * incompatible guest state for VMX execution (real-on-v86 case).
15596 */
15597HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15598{
15599 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15600 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15601
15602 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15603 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15604 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15605 AssertRCReturn(rc, rc);
15606
15607 VBOXSTRICTRC rcStrict;
15608 PVM pVM = pVCpu->CTX_SUFF(pVM);
15609 uint64_t const uExitQual = pVmxTransient->uExitQual;
15610 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15611 switch (uAccessType)
15612 {
15613 /*
15614 * MOV to CRx.
15615 */
15616 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15617 {
15618 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15619 AssertRCReturn(rc, rc);
15620
15621 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15622 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15623 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15624 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15625
15626 /*
15627 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15628 * - When nested paging isn't used.
15629 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15630 * - We are executing in the VM debug loop.
15631 */
15632 Assert( iCrReg != 3
15633 || !pVM->hm.s.fNestedPaging
15634 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15635 || pVCpu->hm.s.fUsingDebugLoop);
15636
15637 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15638 Assert( iCrReg != 8
15639 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15640
15641 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15642 AssertMsg( rcStrict == VINF_SUCCESS
15643 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15644
15645 /*
15646 * This is a kludge for handling switches back to real mode when we try to use
15647 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15648 * deal with special selector values, so we have to return to ring-3 and run
15649 * there till the selector values are V86 mode compatible.
15650 *
15651 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15652 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15653 * this function.
15654 */
15655 if ( iCrReg == 0
15656 && rcStrict == VINF_SUCCESS
15657 && !pVM->hm.s.vmx.fUnrestrictedGuest
15658 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15659 && (uOldCr0 & X86_CR0_PE)
15660 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15661 {
15662 /** @todo Check selectors rather than returning all the time. */
15663 Assert(!pVmxTransient->fIsNestedGuest);
15664 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15665 rcStrict = VINF_EM_RESCHEDULE_REM;
15666 }
15667 break;
15668 }
15669
15670 /*
15671 * MOV from CRx.
15672 */
15673 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15674 {
15675 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15676 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15677
15678 /*
15679 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15680 * - When nested paging isn't used.
15681 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15682 * - We are executing in the VM debug loop.
15683 */
15684 Assert( iCrReg != 3
15685 || !pVM->hm.s.fNestedPaging
15686 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15687 || pVCpu->hm.s.fUsingDebugLoop);
15688
15689 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15690 Assert( iCrReg != 8
15691 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15692
15693 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15694 break;
15695 }
15696
15697 /*
15698 * CLTS (Clear Task-Switch Flag in CR0).
15699 */
15700 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15701 {
15702 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbInstr);
15703 break;
15704 }
15705
15706 /*
15707 * LMSW (Load Machine-Status Word into CR0).
15708 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15709 */
15710 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15711 {
15712 RTGCPTR GCPtrEffDst;
15713 uint8_t const cbInstr = pVmxTransient->cbInstr;
15714 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15715 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15716 if (fMemOperand)
15717 {
15718 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
15719 AssertRCReturn(rc, rc);
15720 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15721 }
15722 else
15723 GCPtrEffDst = NIL_RTGCPTR;
15724 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15725 break;
15726 }
15727
15728 default:
15729 {
15730 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15731 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15732 }
15733 }
15734
15735 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15736 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15737 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15738
15739 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15740 NOREF(pVM);
15741 return rcStrict;
15742}
15743
15744
15745/**
15746 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15747 * VM-exit.
15748 */
15749HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15750{
15751 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15752 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15753
15754 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15755 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15756 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15757 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15758 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15759 | CPUMCTX_EXTRN_EFER);
15760 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15761 AssertRCReturn(rc, rc);
15762
15763 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15764 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15765 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15766 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15767 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15768 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15769 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15770 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15771
15772 /*
15773 * Update exit history to see if this exit can be optimized.
15774 */
15775 VBOXSTRICTRC rcStrict;
15776 PCEMEXITREC pExitRec = NULL;
15777 if ( !fGstStepping
15778 && !fDbgStepping)
15779 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15780 !fIOString
15781 ? !fIOWrite
15782 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15783 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15784 : !fIOWrite
15785 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15786 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15787 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15788 if (!pExitRec)
15789 {
15790 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15791 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15792
15793 uint32_t const cbValue = s_aIOSizes[uIOSize];
15794 uint32_t const cbInstr = pVmxTransient->cbInstr;
15795 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15796 PVM pVM = pVCpu->CTX_SUFF(pVM);
15797 if (fIOString)
15798 {
15799 /*
15800 * INS/OUTS - I/O String instruction.
15801 *
15802 * Use instruction-information if available, otherwise fall back on
15803 * interpreting the instruction.
15804 */
15805 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15806 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15807 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15808 if (fInsOutsInfo)
15809 {
15810 int rc2 = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15811 AssertRCReturn(rc2, rc2);
15812 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15813 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15814 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15815 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15816 if (fIOWrite)
15817 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15818 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15819 else
15820 {
15821 /*
15822 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15823 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15824 * See Intel Instruction spec. for "INS".
15825 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15826 */
15827 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15828 }
15829 }
15830 else
15831 rcStrict = IEMExecOne(pVCpu);
15832
15833 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15834 fUpdateRipAlready = true;
15835 }
15836 else
15837 {
15838 /*
15839 * IN/OUT - I/O instruction.
15840 */
15841 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15842 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15843 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15844 if (fIOWrite)
15845 {
15846 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15847 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15848 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15849 && !pCtx->eflags.Bits.u1TF)
15850 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15851 }
15852 else
15853 {
15854 uint32_t u32Result = 0;
15855 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15856 if (IOM_SUCCESS(rcStrict))
15857 {
15858 /* Save result of I/O IN instr. in AL/AX/EAX. */
15859 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15860 }
15861 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15862 && !pCtx->eflags.Bits.u1TF)
15863 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15864 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15865 }
15866 }
15867
15868 if (IOM_SUCCESS(rcStrict))
15869 {
15870 if (!fUpdateRipAlready)
15871 {
15872 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15873 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15874 }
15875
15876 /*
15877 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15878 * while booting Fedora 17 64-bit guest.
15879 *
15880 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15881 */
15882 if (fIOString)
15883 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15884
15885 /*
15886 * If any I/O breakpoints are armed, we need to check if one triggered
15887 * and take appropriate action.
15888 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15889 */
15890 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15891 AssertRCReturn(rc, rc);
15892
15893 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15894 * execution engines about whether hyper BPs and such are pending. */
15895 uint32_t const uDr7 = pCtx->dr[7];
15896 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15897 && X86_DR7_ANY_RW_IO(uDr7)
15898 && (pCtx->cr4 & X86_CR4_DE))
15899 || DBGFBpIsHwIoArmed(pVM)))
15900 {
15901 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15902
15903 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15904 VMMRZCallRing3Disable(pVCpu);
15905 HM_DISABLE_PREEMPT(pVCpu);
15906
15907 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15908
15909 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15910 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15911 {
15912 /* Raise #DB. */
15913 if (fIsGuestDbgActive)
15914 ASMSetDR6(pCtx->dr[6]);
15915 if (pCtx->dr[7] != uDr7)
15916 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15917
15918 hmR0VmxSetPendingXcptDB(pVCpu);
15919 }
15920 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15921 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15922 else if ( rcStrict2 != VINF_SUCCESS
15923 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15924 rcStrict = rcStrict2;
15925 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15926
15927 HM_RESTORE_PREEMPT();
15928 VMMRZCallRing3Enable(pVCpu);
15929 }
15930 }
15931
15932#ifdef VBOX_STRICT
15933 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15934 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15935 Assert(!fIOWrite);
15936 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15937 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15938 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15939 Assert(fIOWrite);
15940 else
15941 {
15942# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15943 * statuses, that the VMM device and some others may return. See
15944 * IOM_SUCCESS() for guidance. */
15945 AssertMsg( RT_FAILURE(rcStrict)
15946 || rcStrict == VINF_SUCCESS
15947 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15948 || rcStrict == VINF_EM_DBG_BREAKPOINT
15949 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15950 || rcStrict == VINF_EM_RAW_TO_R3
15951 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15952# endif
15953 }
15954#endif
15955 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15956 }
15957 else
15958 {
15959 /*
15960 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15961 */
15962 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15963 AssertRCReturn(rc2, rc2);
15964 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15965 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15966 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15967 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15968 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15969 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15970
15971 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15972 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15973
15974 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15975 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15976 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15977 }
15978 return rcStrict;
15979}
15980
15981
15982/**
15983 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15984 * VM-exit.
15985 */
15986HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15987{
15988 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15989
15990 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15991 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15992 AssertRCReturn(rc, rc);
15993 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15994 {
15995 rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15996 AssertRCReturn(rc, rc);
15997 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15998 {
15999 uint32_t uErrCode;
16000 RTGCUINTPTR GCPtrFaultAddress;
16001 uint32_t const uIntType = VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo);
16002 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo);
16003 bool const fErrorCodeValid = VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo);
16004 if (fErrorCodeValid)
16005 {
16006 rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16007 AssertRCReturn(rc, rc);
16008 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
16009 }
16010 else
16011 uErrCode = 0;
16012
16013 if ( uIntType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
16014 && uVector == X86_XCPT_PF)
16015 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
16016 else
16017 GCPtrFaultAddress = 0;
16018
16019 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16020 AssertRCReturn(rc, rc);
16021
16022 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
16023 pVmxTransient->cbInstr, uErrCode, GCPtrFaultAddress);
16024
16025 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", uIntType, uVector));
16026 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16027 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16028 }
16029 }
16030
16031 /* Fall back to the interpreter to emulate the task-switch. */
16032 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16033 return VERR_EM_INTERPRETER;
16034}
16035
16036
16037/**
16038 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
16039 */
16040HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16041{
16042 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16043
16044 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16045 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
16046 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16047 AssertRCReturn(rc, rc);
16048 return VINF_EM_DBG_STEPPED;
16049}
16050
16051
16052/**
16053 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
16054 */
16055HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16056{
16057 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16058 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
16059
16060 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
16061 VBOXSTRICTRC rcStrict1 = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16062 if (RT_LIKELY(rcStrict1 == VINF_SUCCESS))
16063 {
16064 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
16065 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
16066 {
16067 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16068 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16069 }
16070 }
16071 else
16072 {
16073 if (rcStrict1 == VINF_HM_DOUBLE_FAULT)
16074 {
16075 Assert(pVCpu->hm.s.Event.fPending);
16076 rcStrict1 = VINF_SUCCESS;
16077 }
16078 return rcStrict1;
16079 }
16080
16081 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
16082 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16083 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16084 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16085 AssertRCReturn(rc, rc);
16086
16087 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
16088 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
16089 VBOXSTRICTRC rcStrict2;
16090 switch (uAccessType)
16091 {
16092 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
16093 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
16094 {
16095 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
16096 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
16097 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
16098
16099 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
16100 GCPhys &= PAGE_BASE_GC_MASK;
16101 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
16102 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
16103 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
16104
16105 PVM pVM = pVCpu->CTX_SUFF(pVM);
16106 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16107 rcStrict2 = IOMMMIOPhysHandler(pVM, pVCpu,
16108 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
16109 CPUMCTX2CORE(pCtx), GCPhys);
16110 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict2)));
16111 if ( rcStrict2 == VINF_SUCCESS
16112 || rcStrict2 == VERR_PAGE_TABLE_NOT_PRESENT
16113 || rcStrict2 == VERR_PAGE_NOT_PRESENT)
16114 {
16115 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16116 | HM_CHANGED_GUEST_APIC_TPR);
16117 rcStrict2 = VINF_SUCCESS;
16118 }
16119 break;
16120 }
16121
16122 default:
16123 {
16124 Log4Func(("uAccessType=%#x\n", uAccessType));
16125 rcStrict2 = VINF_EM_RAW_EMULATE_INSTR;
16126 break;
16127 }
16128 }
16129
16130 if (rcStrict2 != VINF_SUCCESS)
16131 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
16132 return rcStrict2;
16133}
16134
16135
16136/**
16137 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
16138 * VM-exit.
16139 */
16140HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16141{
16142 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16143
16144 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16145 if (pVmxTransient->fWasGuestDebugStateActive)
16146 {
16147 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16148 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16149 }
16150
16151 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16152 if ( !pVCpu->hm.s.fSingleInstruction
16153 && !pVmxTransient->fWasHyperDebugStateActive)
16154 {
16155 Assert(!DBGFIsStepping(pVCpu));
16156 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16157
16158 /* Don't intercept MOV DRx any more. */
16159 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16160 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16161 AssertRCReturn(rc, rc);
16162
16163 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16164 VMMRZCallRing3Disable(pVCpu);
16165 HM_DISABLE_PREEMPT(pVCpu);
16166
16167 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16168 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16169 Assert(CPUMIsGuestDebugStateActive(pVCpu) || HC_ARCH_BITS == 32);
16170
16171 HM_RESTORE_PREEMPT();
16172 VMMRZCallRing3Enable(pVCpu);
16173
16174#ifdef VBOX_WITH_STATISTICS
16175 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16176 AssertRCReturn(rc, rc);
16177 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16178 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16179 else
16180 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16181#endif
16182 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16183 return VINF_SUCCESS;
16184 }
16185
16186 /*
16187 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16188 * The EFER MSR is always up-to-date.
16189 * Update the segment registers and DR7 from the CPU.
16190 */
16191 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16192 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16193 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16194 AssertRCReturn(rc, rc);
16195 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16196
16197 PVM pVM = pVCpu->CTX_SUFF(pVM);
16198 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16199 {
16200 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16201 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16202 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16203 if (RT_SUCCESS(rc))
16204 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16205 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16206 }
16207 else
16208 {
16209 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16210 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16211 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16212 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16213 }
16214
16215 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16216 if (RT_SUCCESS(rc))
16217 {
16218 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16219 AssertRCReturn(rc2, rc2);
16220 return VINF_SUCCESS;
16221 }
16222 return rc;
16223}
16224
16225
16226/**
16227 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16228 * Conditional VM-exit.
16229 */
16230HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16231{
16232 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16233 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16234
16235 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
16236 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16237 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16238 {
16239 /*
16240 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16241 * instruction emulation to inject the original event. Otherwise, injecting the original event
16242 * using hardware-assisted VMX would would trigger the same EPT misconfig VM-exit again.
16243 */
16244 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
16245 {
16246 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16247 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16248 }
16249 }
16250 else
16251 {
16252 if (rcStrict == VINF_HM_DOUBLE_FAULT)
16253 rcStrict = VINF_SUCCESS;
16254 return rcStrict;
16255 }
16256
16257 /*
16258 * Get sufficent state and update the exit history entry.
16259 */
16260 RTGCPHYS GCPhys;
16261 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16262 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
16263 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16264 AssertRCReturn(rc, rc);
16265
16266 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16267 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16268 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16269 if (!pExitRec)
16270 {
16271 /*
16272 * If we succeed, resume guest execution.
16273 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16274 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16275 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16276 * weird case. See @bugref{6043}.
16277 */
16278 PVM pVM = pVCpu->CTX_SUFF(pVM);
16279 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16280 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16281 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16282 if ( rcStrict == VINF_SUCCESS
16283 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16284 || rcStrict == VERR_PAGE_NOT_PRESENT)
16285 {
16286 /* Successfully handled MMIO operation. */
16287 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16288 | HM_CHANGED_GUEST_APIC_TPR);
16289 rcStrict = VINF_SUCCESS;
16290 }
16291 }
16292 else
16293 {
16294 /*
16295 * Frequent exit or something needing probing. Call EMHistoryExec.
16296 */
16297 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16298 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16299
16300 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16301 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16302
16303 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16304 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16305 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16306 }
16307 return rcStrict;
16308}
16309
16310
16311/**
16312 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16313 * VM-exit.
16314 */
16315HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16316{
16317 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16318 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16319
16320 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
16321 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16322 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16323 {
16324 /*
16325 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16326 * we shall resolve the nested #PF and re-inject the original event.
16327 */
16328 if (pVCpu->hm.s.Event.fPending)
16329 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16330 }
16331 else
16332 {
16333 if (rcStrict == VINF_HM_DOUBLE_FAULT)
16334 {
16335 Assert(pVCpu->hm.s.Event.fPending);
16336 rcStrict = VINF_SUCCESS;
16337 }
16338 return rcStrict;
16339 }
16340
16341 RTGCPHYS GCPhys;
16342 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16343 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
16344 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16345 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16346 AssertRCReturn(rc, rc);
16347
16348 /* Intel spec. Table 27-7 "Exit Qualifications for EPT violations". */
16349 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", pVmxTransient->uExitQual));
16350
16351 RTGCUINT uErrorCode = 0;
16352 if (pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16353 uErrorCode |= X86_TRAP_PF_ID;
16354 if (pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16355 uErrorCode |= X86_TRAP_PF_RW;
16356 if (pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16357 uErrorCode |= X86_TRAP_PF_P;
16358
16359 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16360
16361
16362 /* Handle the pagefault trap for the nested shadow table. */
16363 PVM pVM = pVCpu->CTX_SUFF(pVM);
16364 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16365
16366 Log4Func(("EPT violation %#x at %#RX64 ErrorCode %#x cs:rip=%#04x:%#RX64\n", pVmxTransient->uExitQual, GCPhys, uErrorCode,
16367 pCtx->cs.Sel, pCtx->rip));
16368
16369 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16370 TRPMResetTrap(pVCpu);
16371
16372 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16373 if ( rcStrict == VINF_SUCCESS
16374 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16375 || rcStrict == VERR_PAGE_NOT_PRESENT)
16376 {
16377 /* Successfully synced our nested page tables. */
16378 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16379 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16380 return VINF_SUCCESS;
16381 }
16382
16383 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16384 return rcStrict;
16385}
16386
16387
16388#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16389/**
16390 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16391 */
16392HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16393{
16394 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16395
16396 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16397 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16398 | CPUMCTX_EXTRN_HWVIRT
16399 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16400 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16401 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16402 AssertRCReturn(rc, rc);
16403
16404 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16405
16406 VMXVEXITINFO ExitInfo;
16407 RT_ZERO(ExitInfo);
16408 ExitInfo.uReason = pVmxTransient->uExitReason;
16409 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16410 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16411 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16412 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16413
16414 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16415 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16416 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16417 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16418 {
16419 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16420 rcStrict = VINF_SUCCESS;
16421 }
16422 return rcStrict;
16423}
16424
16425
16426/**
16427 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16428 */
16429HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16430{
16431 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16432
16433 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16434 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16435 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16436 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16437 AssertRCReturn(rc, rc);
16438
16439 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16440
16441 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16442 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMLAUNCH);
16443 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16444 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16445 {
16446 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16447 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16448 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16449 }
16450 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16451 return rcStrict;
16452}
16453
16454
16455/**
16456 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16457 */
16458HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16459{
16460 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16461
16462 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16463 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16464 | CPUMCTX_EXTRN_HWVIRT
16465 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16466 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16467 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16468 AssertRCReturn(rc, rc);
16469
16470 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16471
16472 VMXVEXITINFO ExitInfo;
16473 RT_ZERO(ExitInfo);
16474 ExitInfo.uReason = pVmxTransient->uExitReason;
16475 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16476 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16477 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16478 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16479
16480 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16481 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16482 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16483 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16484 {
16485 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16486 rcStrict = VINF_SUCCESS;
16487 }
16488 return rcStrict;
16489}
16490
16491
16492/**
16493 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16494 */
16495HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16496{
16497 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16498
16499 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16500 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16501 | CPUMCTX_EXTRN_HWVIRT
16502 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16503 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16504 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16505 AssertRCReturn(rc, rc);
16506
16507 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16508
16509 VMXVEXITINFO ExitInfo;
16510 RT_ZERO(ExitInfo);
16511 ExitInfo.uReason = pVmxTransient->uExitReason;
16512 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16513 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16514 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16515 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16516
16517 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16518 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16519 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16520 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16521 {
16522 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16523 rcStrict = VINF_SUCCESS;
16524 }
16525 return rcStrict;
16526}
16527
16528
16529/**
16530 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16531 */
16532HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16533{
16534 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16535
16536 /*
16537 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16538 * thus might not need to import the shadow VMCS state, it's safer just in case
16539 * code elsewhere dares look at unsynced VMCS fields.
16540 */
16541 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16542 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16543 | CPUMCTX_EXTRN_HWVIRT
16544 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16545 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16546 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16547 AssertRCReturn(rc, rc);
16548
16549 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16550
16551 VMXVEXITINFO ExitInfo;
16552 RT_ZERO(ExitInfo);
16553 ExitInfo.uReason = pVmxTransient->uExitReason;
16554 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16555 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16556 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16557 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16558 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16559
16560 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16561 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16562 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16563 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16564 {
16565 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16566 rcStrict = VINF_SUCCESS;
16567 }
16568 return rcStrict;
16569}
16570
16571
16572/**
16573 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16574 */
16575HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16576{
16577 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16578
16579 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16580 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16581 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16582 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16583 AssertRCReturn(rc, rc);
16584
16585 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16586
16587 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16588 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMRESUME);
16589 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16590 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16591 {
16592 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16593 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16594 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16595 }
16596 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16597 return rcStrict;
16598}
16599
16600
16601/**
16602 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16603 */
16604HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16605{
16606 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16607
16608 /*
16609 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16610 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16611 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16612 */
16613 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16614 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16615 | CPUMCTX_EXTRN_HWVIRT
16616 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16617 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16618 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16619 AssertRCReturn(rc, rc);
16620
16621 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16622
16623 VMXVEXITINFO ExitInfo;
16624 RT_ZERO(ExitInfo);
16625 ExitInfo.uReason = pVmxTransient->uExitReason;
16626 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16627 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16628 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16629 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16630 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16631
16632 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16633 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16634 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16635 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16636 {
16637 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16638 rcStrict = VINF_SUCCESS;
16639 }
16640 return rcStrict;
16641}
16642
16643
16644/**
16645 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16646 */
16647HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16648{
16649 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16650
16651 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16652 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16653 | CPUMCTX_EXTRN_HWVIRT
16654 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16655 AssertRCReturn(rc, rc);
16656
16657 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16658
16659 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbInstr);
16660 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16661 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16662 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16663 {
16664 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16665 rcStrict = VINF_SUCCESS;
16666 }
16667 return rcStrict;
16668}
16669
16670
16671/**
16672 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16673 */
16674HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16675{
16676 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16677
16678 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16679 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16680 | CPUMCTX_EXTRN_HWVIRT
16681 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16682 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16683 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16684 AssertRCReturn(rc, rc);
16685
16686 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16687
16688 VMXVEXITINFO ExitInfo;
16689 RT_ZERO(ExitInfo);
16690 ExitInfo.uReason = pVmxTransient->uExitReason;
16691 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16692 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16693 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16694 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16695
16696 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16697 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16698 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16699 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16700 {
16701 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16702 rcStrict = VINF_SUCCESS;
16703 }
16704 return rcStrict;
16705}
16706
16707
16708/**
16709 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16710 */
16711HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16712{
16713 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16714
16715 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16716 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16717 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16718 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16719 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16720 AssertRCReturn(rc, rc);
16721
16722 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16723
16724 VMXVEXITINFO ExitInfo;
16725 RT_ZERO(ExitInfo);
16726 ExitInfo.uReason = pVmxTransient->uExitReason;
16727 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16728 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16729 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16730 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16731
16732 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16733 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16734 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16735 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16736 {
16737 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16738 rcStrict = VINF_SUCCESS;
16739 }
16740 return rcStrict;
16741}
16742#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16743/** @} */
16744
16745
16746#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16747/** @name Nested-guest VM-exit handlers.
16748 * @{
16749 */
16750/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16751/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16752/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16753
16754/**
16755 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16756 * Conditional VM-exit.
16757 */
16758HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16759{
16760 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16761
16762 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16763 AssertRCReturn(rc, rc);
16764
16765 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16766 uint32_t const uExtIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16767 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16768
16769 /*
16770 * Make sure not to use stale/previous VM-exit instruction length since we read the
16771 * instruction length from the VMCS below only for software exceptions and privileged
16772 * software exceptions but we pass it for all exception VM-exits below.
16773 */
16774 pVmxTransient->cbInstr = 0;
16775
16776 switch (uExtIntType)
16777 {
16778 /*
16779 * Physical NMIs:
16780 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16781 */
16782 case VMX_EXIT_INT_INFO_TYPE_NMI:
16783 return hmR0VmxExitHostNmi(pVCpu);
16784
16785 /*
16786 * Hardware exceptions,
16787 * Software exceptions,
16788 * Privileged software exceptions:
16789 * Figure out if the exception must be delivered to the guest or the nested-guest.
16790 *
16791 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16792 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16793 * length.
16794 */
16795 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16796 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16797 {
16798 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16799 AssertRCReturn(rc, rc);
16800 RT_FALL_THRU();
16801 }
16802 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16803 {
16804 rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16805 AssertRCReturn(rc, rc);
16806
16807 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
16808 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uVector,
16809 pVmxTransient->uExitIntErrorCode);
16810 if (fIntercept)
16811 {
16812 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16813 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16814 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16815 AssertRCReturn(rc, rc);
16816
16817 VMXVEXITINFO ExitInfo;
16818 RT_ZERO(ExitInfo);
16819 ExitInfo.uReason = pVmxTransient->uExitReason;
16820 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16821 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16822
16823 VMXVEXITEVENTINFO ExitEventInfo;
16824 RT_ZERO(ExitEventInfo);
16825 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16826 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16827 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16828 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16829
16830 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16831 }
16832
16833 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs. */
16834 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16835
16836 /* If the guest hypervisor is not intercepting the exception, forward it to the guest. */
16837 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(uExitIntInfo), pVmxTransient->cbInstr,
16838 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
16839 return VINF_SUCCESS;
16840 }
16841
16842 /*
16843 * Software interrupts:
16844 * VM-exits cannot be caused by software interrupts.
16845 *
16846 * External interrupts:
16847 * This should only happen when "acknowledge external interrupts on VM-exit"
16848 * control is set. However, we never set this when executing a guest or
16849 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16850 * the guest.
16851 */
16852 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16853 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16854 default:
16855 {
16856 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16857 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16858 }
16859 }
16860}
16861
16862
16863/**
16864 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16865 * Unconditional VM-exit.
16866 */
16867HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16868{
16869 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16870 return IEMExecVmxVmexitTripleFault(pVCpu);
16871}
16872
16873
16874/**
16875 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16876 */
16877HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16878{
16879 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16880
16881 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16882 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16883 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16884}
16885
16886
16887/**
16888 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16889 */
16890HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16891{
16892 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16893
16894 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16895 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16896 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16897}
16898
16899
16900/**
16901 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16902 * Unconditional VM-exit.
16903 */
16904HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16905{
16906 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16907
16908 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16909 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16910 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16911 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16912 AssertRCReturn(rc, rc);
16913
16914 VMXVEXITINFO ExitInfo;
16915 RT_ZERO(ExitInfo);
16916 ExitInfo.uReason = pVmxTransient->uExitReason;
16917 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16918 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16919
16920 VMXVEXITEVENTINFO ExitEventInfo;
16921 RT_ZERO(ExitEventInfo);
16922 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16923 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16924 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16925}
16926
16927
16928/**
16929 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16930 */
16931HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16932{
16933 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16934
16935 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16936 {
16937 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16938 AssertRCReturn(rc, rc);
16939 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16940 }
16941 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16942}
16943
16944
16945/**
16946 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16947 */
16948HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16949{
16950 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16951
16952 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16953 {
16954 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16955 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16956 AssertRCReturn(rc, rc);
16957
16958 VMXVEXITINFO ExitInfo;
16959 RT_ZERO(ExitInfo);
16960 ExitInfo.uReason = pVmxTransient->uExitReason;
16961 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16962 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16963 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16964 }
16965 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16966}
16967
16968
16969/**
16970 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16971 */
16972HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16973{
16974 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16975
16976 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16977 {
16978 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16979 AssertRCReturn(rc, rc);
16980 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16981 }
16982 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16983}
16984
16985
16986/**
16987 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16988 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16989 */
16990HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16991{
16992 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16993
16994 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16995 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16996
16997 int rc = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16998 AssertRCReturn(rc, rc);
16999
17000 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
17001 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17002 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17003
17004 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
17005 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
17006 u64VmcsField &= UINT64_C(0xffffffff);
17007
17008 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
17009 {
17010 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17011 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17012 AssertRCReturn(rc, rc);
17013
17014 VMXVEXITINFO ExitInfo;
17015 RT_ZERO(ExitInfo);
17016 ExitInfo.uReason = pVmxTransient->uExitReason;
17017 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17018 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17019 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17020 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17021 }
17022
17023 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
17024 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
17025 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
17026}
17027
17028
17029/**
17030 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
17031 */
17032HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17033{
17034 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17035
17036 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17037 {
17038 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17039 AssertRCReturn(rc, rc);
17040 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17041 }
17042
17043 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
17044}
17045
17046
17047/**
17048 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
17049 * Conditional VM-exit.
17050 */
17051HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17052{
17053 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17054
17055 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17056 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17057 AssertRCReturn(rc, rc);
17058
17059 VBOXSTRICTRC rcStrict;
17060 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
17061 switch (uAccessType)
17062 {
17063 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
17064 {
17065 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17066 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17067 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17068 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17069
17070 bool fIntercept;
17071 switch (iCrReg)
17072 {
17073 case 0:
17074 case 4:
17075 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
17076 break;
17077
17078 case 3:
17079 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
17080 break;
17081
17082 case 8:
17083 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
17084 break;
17085
17086 default:
17087 fIntercept = false;
17088 break;
17089 }
17090 if (fIntercept)
17091 {
17092 VMXVEXITINFO ExitInfo;
17093 RT_ZERO(ExitInfo);
17094 ExitInfo.uReason = pVmxTransient->uExitReason;
17095 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17096 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17097 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17098 }
17099 else
17100 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17101 break;
17102 }
17103
17104 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
17105 {
17106 /*
17107 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
17108 * CR2 reads do not cause a VM-exit.
17109 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
17110 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
17111 */
17112 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17113 if ( iCrReg == 3
17114 || iCrReg == 8)
17115 {
17116 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
17117 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
17118 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
17119 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
17120 {
17121 VMXVEXITINFO ExitInfo;
17122 RT_ZERO(ExitInfo);
17123 ExitInfo.uReason = pVmxTransient->uExitReason;
17124 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17125 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17126 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17127 }
17128 else
17129 {
17130 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17131 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17132 }
17133 }
17134 else
17135 {
17136 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17137 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17138 }
17139 break;
17140 }
17141
17142 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17143 {
17144 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17145 Assert(pVmcsNstGst);
17146 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17147 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17148 if ( (uGstHostMask & X86_CR0_TS)
17149 && (uReadShadow & X86_CR0_TS))
17150 {
17151 VMXVEXITINFO ExitInfo;
17152 RT_ZERO(ExitInfo);
17153 ExitInfo.uReason = pVmxTransient->uExitReason;
17154 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17155 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17156 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17157 }
17158 else
17159 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr);
17160 break;
17161 }
17162
17163 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17164 {
17165 RTGCPTR GCPtrEffDst;
17166 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17167 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17168 if (fMemOperand)
17169 {
17170 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17171 AssertRCReturn(rc, rc);
17172 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17173 }
17174 else
17175 GCPtrEffDst = NIL_RTGCPTR;
17176
17177 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
17178 {
17179 VMXVEXITINFO ExitInfo;
17180 RT_ZERO(ExitInfo);
17181 ExitInfo.uReason = pVmxTransient->uExitReason;
17182 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17183 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17184 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17185 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17186 }
17187 else
17188 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, uNewMsw, GCPtrEffDst);
17189 break;
17190 }
17191
17192 default:
17193 {
17194 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17195 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17196 }
17197 }
17198
17199 if (rcStrict == VINF_IEM_RAISED_XCPT)
17200 {
17201 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17202 rcStrict = VINF_SUCCESS;
17203 }
17204 return rcStrict;
17205}
17206
17207
17208/**
17209 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17210 * Conditional VM-exit.
17211 */
17212HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17213{
17214 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17215
17216 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17217 {
17218 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17219 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17220 AssertRCReturn(rc, rc);
17221
17222 VMXVEXITINFO ExitInfo;
17223 RT_ZERO(ExitInfo);
17224 ExitInfo.uReason = pVmxTransient->uExitReason;
17225 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17226 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17227 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17228 }
17229 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17230}
17231
17232
17233/**
17234 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17235 * Conditional VM-exit.
17236 */
17237HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17238{
17239 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17240
17241 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17242 AssertRCReturn(rc, rc);
17243
17244 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17245 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17246 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17247
17248 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17249 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17250 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17251 {
17252 /*
17253 * IN/OUT instruction:
17254 * - Provides VM-exit instruction length.
17255 *
17256 * INS/OUTS instruction:
17257 * - Provides VM-exit instruction length.
17258 * - Provides Guest-linear address.
17259 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17260 */
17261 PVM pVM = pVCpu->CTX_SUFF(pVM);
17262 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17263 AssertRCReturn(rc, rc);
17264
17265 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17266 pVmxTransient->ExitInstrInfo.u = 0;
17267 pVmxTransient->uGuestLinearAddr = 0;
17268
17269 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17270 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17271 if (fIOString)
17272 {
17273 rc |= hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17274 if (fVmxInsOutsInfo)
17275 {
17276 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17277 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17278 }
17279 }
17280 AssertRCReturn(rc, rc);
17281
17282 VMXVEXITINFO ExitInfo;
17283 RT_ZERO(ExitInfo);
17284 ExitInfo.uReason = pVmxTransient->uExitReason;
17285 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17286 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17287 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17288 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17289 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17290 }
17291 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17292}
17293
17294
17295/**
17296 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17297 */
17298HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17299{
17300 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17301
17302 uint32_t fMsrpm;
17303 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17304 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17305 else
17306 fMsrpm = VMXMSRPM_EXIT_RD;
17307
17308 if (fMsrpm & VMXMSRPM_EXIT_RD)
17309 {
17310 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17311 AssertRCReturn(rc, rc);
17312 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17313 }
17314 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17315}
17316
17317
17318/**
17319 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17320 */
17321HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17322{
17323 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17324
17325 uint32_t fMsrpm;
17326 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17327 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17328 else
17329 fMsrpm = VMXMSRPM_EXIT_WR;
17330
17331 if (fMsrpm & VMXMSRPM_EXIT_WR)
17332 {
17333 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17334 AssertRCReturn(rc, rc);
17335 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17336 }
17337 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17338}
17339
17340
17341/**
17342 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17343 */
17344HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17345{
17346 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17347
17348 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17349 {
17350 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17351 AssertRCReturn(rc, rc);
17352 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17353 }
17354 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17355}
17356
17357
17358/**
17359 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17360 * VM-exit.
17361 */
17362HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17363{
17364 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17365
17366 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17367 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17368}
17369
17370
17371/**
17372 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17373 */
17374HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17375{
17376 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17377
17378 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17379 {
17380 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17381 AssertRCReturn(rc, rc);
17382 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17383 }
17384 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17385}
17386
17387
17388/**
17389 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17390 */
17391HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17392{
17393 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17394
17395 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17396 * PAUSE when executing a nested-guest? If it does not, we would not need
17397 * to check for the intercepts here. Just call VM-exit... */
17398
17399 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17400 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17401 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17402 {
17403 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17404 AssertRCReturn(rc, rc);
17405 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17406 }
17407 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17408}
17409
17410
17411/**
17412 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17413 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17414 */
17415HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17416{
17417 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17418
17419 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17420 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17421 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17422}
17423
17424
17425/**
17426 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17427 * VM-exit.
17428 */
17429HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17430{
17431 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17432
17433 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17434 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17435 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17436 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17437 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17438 AssertRCReturn(rc, rc);
17439
17440 VMXVEXITINFO ExitInfo;
17441 RT_ZERO(ExitInfo);
17442 ExitInfo.uReason = pVmxTransient->uExitReason;
17443 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17444 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17445
17446 VMXVEXITEVENTINFO ExitEventInfo;
17447 RT_ZERO(ExitEventInfo);
17448 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17449 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17450 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17451}
17452
17453
17454/**
17455 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17456 * Conditional VM-exit.
17457 */
17458HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17459{
17460 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17461
17462 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17463 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17464 AssertRCReturn(rc, rc);
17465
17466 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17467}
17468
17469
17470/**
17471 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17472 * Conditional VM-exit.
17473 */
17474HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17475{
17476 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17477
17478 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17479 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17480 AssertRCReturn(rc, rc);
17481
17482 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17483}
17484
17485
17486/**
17487 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17488 */
17489HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17490{
17491 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17492
17493 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17494 {
17495 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17496 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17497 AssertRCReturn(rc, rc);
17498 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17499 }
17500 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17501}
17502
17503
17504/**
17505 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17506 */
17507HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17508{
17509 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17510
17511 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17512 {
17513 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17514 AssertRCReturn(rc, rc);
17515 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17516 }
17517 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17518}
17519
17520
17521/**
17522 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17523 */
17524HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17525{
17526 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17527
17528 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17529 {
17530 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17531 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17532 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17533 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17534 AssertRCReturn(rc, rc);
17535
17536 VMXVEXITINFO ExitInfo;
17537 RT_ZERO(ExitInfo);
17538 ExitInfo.uReason = pVmxTransient->uExitReason;
17539 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17540 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17541 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17542 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17543 }
17544 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17545}
17546
17547
17548/**
17549 * Nested-guest VM-exit handler for invalid-guest state
17550 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17551 */
17552HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17553{
17554 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17555
17556 /*
17557 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17558 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17559 * Handle it like it's in an invalid guest state of the outer guest.
17560 *
17561 * When the fast path is implemented, this should be changed to cause the corresponding
17562 * nested-guest VM-exit.
17563 */
17564 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17565}
17566
17567
17568/**
17569 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17570 * and only provide the instruction length.
17571 *
17572 * Unconditional VM-exit.
17573 */
17574HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17575{
17576 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17577
17578#ifdef VBOX_STRICT
17579 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17580 switch (pVmxTransient->uExitReason)
17581 {
17582 case VMX_EXIT_ENCLS:
17583 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17584 break;
17585
17586 case VMX_EXIT_VMFUNC:
17587 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
17588 break;
17589 }
17590#endif
17591
17592 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17593 AssertRCReturn(rc, rc);
17594 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17595}
17596
17597
17598/**
17599 * Nested-guest VM-exit handler for instructions that provide instruction length as
17600 * well as more information.
17601 *
17602 * Unconditional VM-exit.
17603 */
17604HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17605{
17606 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17607
17608#ifdef VBOX_STRICT
17609 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17610 switch (pVmxTransient->uExitReason)
17611 {
17612 case VMX_EXIT_GDTR_IDTR_ACCESS:
17613 case VMX_EXIT_LDTR_TR_ACCESS:
17614 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17615 break;
17616
17617 case VMX_EXIT_RDRAND:
17618 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17619 break;
17620
17621 case VMX_EXIT_RDSEED:
17622 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17623 break;
17624
17625 case VMX_EXIT_XSAVES:
17626 case VMX_EXIT_XRSTORS:
17627 /** @todo NSTVMX: Verify XSS-bitmap. */
17628 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17629 break;
17630
17631 case VMX_EXIT_UMWAIT:
17632 case VMX_EXIT_TPAUSE:
17633 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17634 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17635 break;
17636 }
17637#endif
17638
17639 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17640 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17641 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17642 AssertRCReturn(rc, rc);
17643
17644 VMXVEXITINFO ExitInfo;
17645 RT_ZERO(ExitInfo);
17646 ExitInfo.uReason = pVmxTransient->uExitReason;
17647 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17648 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17649 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17650 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17651}
17652
17653/** @} */
17654#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17655
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette