VirtualBox

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

Last change on this file since 82531 was 82531, checked in by vboxsync, 5 years ago

VMM/HMVMXR0: Move validation of guest-interruptibility state inside hmR0VmxGetGuestIntrState, some const nits.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 710.4 KB
Line 
1/* $Id: HMVMXR0.cpp 82531 2019-12-10 04:32:55Z 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#include <iprt/mp.h>
29
30#include <VBox/vmm/pdmapi.h>
31#include <VBox/vmm/dbgf.h>
32#include <VBox/vmm/iem.h>
33#include <VBox/vmm/iom.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#include "HMInternal.h"
39#include <VBox/vmm/vmcc.h>
40#include <VBox/vmm/hmvmxinline.h>
41#include "HMVMXR0.h"
42#include "dtrace/VBoxVMM.h"
43
44#ifdef DEBUG_ramshankar
45# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
46# define HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
47# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
48# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
49# define HMVMX_ALWAYS_CLEAN_TRANSIENT
50# define HMVMX_ALWAYS_CHECK_GUEST_STATE
51# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
52# define HMVMX_ALWAYS_TRAP_PF
53# define HMVMX_ALWAYS_FLUSH_TLB
54# define HMVMX_ALWAYS_SWAP_EFER
55#endif
56
57
58/*********************************************************************************************************************************
59* Defined Constants And Macros *
60*********************************************************************************************************************************/
61/** Use the function table. */
62#define HMVMX_USE_FUNCTION_TABLE
63
64/** Determine which tagged-TLB flush handler to use. */
65#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
66#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
67#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
68#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
69
70/**
71 * Flags to skip redundant reads of some common VMCS fields that are not part of
72 * the guest-CPU or VCPU state but are needed while handling VM-exits.
73 */
74#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
75#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
76#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
77#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
78#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
79#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
80#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
81#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
82#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
83#define HMVMX_READ_GUEST_PENDING_DBG_XCPTS RT_BIT_32(9)
84
85/** All the VMCS fields required for processing of exception/NMI VM-exits. */
86#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
87 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
88 | HMVMX_READ_EXIT_INSTR_LEN \
89 | HMVMX_READ_IDT_VECTORING_INFO \
90 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
91
92/** Assert that all the given fields have been read from the VMCS. */
93#ifdef VBOX_STRICT
94# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
95 do { \
96 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
97 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
98 } while (0)
99#else
100# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
101#endif
102
103/**
104 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
105 * guest using hardware-assisted VMX.
106 *
107 * This excludes state like GPRs (other than RSP) which are always are
108 * swapped and restored across the world-switch and also registers like EFER,
109 * MSR which cannot be modified by the guest without causing a VM-exit.
110 */
111#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
112 | CPUMCTX_EXTRN_RFLAGS \
113 | CPUMCTX_EXTRN_RSP \
114 | CPUMCTX_EXTRN_SREG_MASK \
115 | CPUMCTX_EXTRN_TABLE_MASK \
116 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
117 | CPUMCTX_EXTRN_SYSCALL_MSRS \
118 | CPUMCTX_EXTRN_SYSENTER_MSRS \
119 | CPUMCTX_EXTRN_TSC_AUX \
120 | CPUMCTX_EXTRN_OTHER_MSRS \
121 | CPUMCTX_EXTRN_CR0 \
122 | CPUMCTX_EXTRN_CR3 \
123 | CPUMCTX_EXTRN_CR4 \
124 | CPUMCTX_EXTRN_DR7 \
125 | CPUMCTX_EXTRN_HWVIRT \
126 | CPUMCTX_EXTRN_HM_VMX_MASK)
127
128/**
129 * Exception bitmap mask for real-mode guests (real-on-v86).
130 *
131 * We need to intercept all exceptions manually except:
132 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
133 * due to bugs in Intel CPUs.
134 * - \#PF need not be intercepted even in real-mode if we have nested paging
135 * support.
136 */
137#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
138 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
139 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
140 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
141 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
142 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
143 | RT_BIT(X86_XCPT_XF))
144
145/** Maximum VM-instruction error number. */
146#define HMVMX_INSTR_ERROR_MAX 28
147
148/** Profiling macro. */
149#ifdef HM_PROFILE_EXIT_DISPATCH
150# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
151# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
152#else
153# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
154# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
155#endif
156
157/** Assert that preemption is disabled or covered by thread-context hooks. */
158#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
159 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
160
161/** Assert that we haven't migrated CPUs when thread-context hooks are not
162 * used. */
163#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
164 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
165 ("Illegal migration! Entered on CPU %u Current %u\n", \
166 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
167
168/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
169 * context. */
170#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
171 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
172 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
173
174/** Log the VM-exit reason with an easily visible marker to identify it in a
175 * potential sea of logging data. */
176#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
177 do { \
178 Log4(("VM-exit: vcpu[%RU32] %85s -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-\n", (a_pVCpu)->idCpu, \
179 HMGetVmxExitName(a_uExitReason))); \
180 } while (0) \
181
182
183/*********************************************************************************************************************************
184* Structures and Typedefs *
185*********************************************************************************************************************************/
186/**
187 * VMX per-VCPU transient state.
188 *
189 * A state structure for holding miscellaneous information across
190 * VMX non-root operation and restored after the transition.
191 *
192 * Note: The members are ordered and aligned such that the most
193 * frequently used ones (in the guest execution loop) fall within
194 * the first cache line.
195 */
196typedef struct VMXTRANSIENT
197{
198 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
199 uint32_t fVmcsFieldsRead;
200 /** The guest's TPR value used for TPR shadowing. */
201 uint8_t u8GuestTpr;
202 uint8_t abAlignment0[3];
203
204 /** Whether the VM-exit was caused by a page-fault during delivery of an
205 * external interrupt or NMI. */
206 bool fVectoringPF;
207 /** Whether the VM-exit was caused by a page-fault during delivery of a
208 * contributory exception or a page-fault. */
209 bool fVectoringDoublePF;
210 /** Whether the VM-entry failed or not. */
211 bool fVMEntryFailed;
212 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
213 * area after VM-exit. */
214 bool fRemoveTscAuxMsr;
215 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
216 bool fUpdatedTscOffsettingAndPreemptTimer;
217 /** Whether we are currently executing a nested-guest. */
218 bool fIsNestedGuest;
219 /** Whether the guest debug state was active at the time of VM-exit. */
220 bool fWasGuestDebugStateActive;
221 /** Whether the hyper debug state was active at the time of VM-exit. */
222 bool fWasHyperDebugStateActive;
223
224 /** The basic VM-exit reason. */
225 uint32_t uExitReason;
226 /** The VM-exit interruption error code. */
227 uint32_t uExitIntErrorCode;
228
229 /** The host's rflags/eflags. */
230 RTCCUINTREG fEFlags;
231
232 /** The VM-exit exit code qualification. */
233 uint64_t uExitQual;
234
235 /** The VMCS info. object. */
236 PVMXVMCSINFO pVmcsInfo;
237
238 /** The VM-exit interruption-information field. */
239 uint32_t uExitIntInfo;
240 /** The VM-exit instruction-length field. */
241 uint32_t cbExitInstr;
242
243 /** The VM-exit instruction-information field. */
244 VMXEXITINSTRINFO ExitInstrInfo;
245 /** IDT-vectoring information field. */
246 uint32_t uIdtVectoringInfo;
247
248 /** IDT-vectoring error code. */
249 uint32_t uIdtVectoringErrorCode;
250 uint32_t u32Alignment0;
251
252 /** The Guest-linear address. */
253 uint64_t uGuestLinearAddr;
254
255 /** The Guest-physical address. */
256 uint64_t uGuestPhysicalAddr;
257
258 /** The Guest pending-debug exceptions. */
259 uint64_t uGuestPendingDbgXcpts;
260
261 /** The VM-entry interruption-information field. */
262 uint32_t uEntryIntInfo;
263 /** The VM-entry exception error code field. */
264 uint32_t uEntryXcptErrorCode;
265
266 /** The VM-entry instruction length field. */
267 uint32_t cbEntryInstr;
268} VMXTRANSIENT;
269AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, fVmcsFieldsRead, 8);
271AssertCompileMemberAlignment(VMXTRANSIENT, fVectoringPF, 8);
272AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, 8);
273AssertCompileMemberAlignment(VMXTRANSIENT, fEFlags, 8);
274AssertCompileMemberAlignment(VMXTRANSIENT, uExitQual, 8);
275AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, 8);
276AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, 8);
277AssertCompileMemberAlignment(VMXTRANSIENT, ExitInstrInfo, 8);
278AssertCompileMemberAlignment(VMXTRANSIENT, uIdtVectoringErrorCode, 8);
279AssertCompileMemberAlignment(VMXTRANSIENT, uGuestLinearAddr, 8);
280AssertCompileMemberAlignment(VMXTRANSIENT, uGuestPhysicalAddr, 8);
281AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, 8);
282AssertCompileMemberAlignment(VMXTRANSIENT, cbEntryInstr, 8);
283/** Pointer to VMX transient state. */
284typedef VMXTRANSIENT *PVMXTRANSIENT;
285/** Pointer to a const VMX transient state. */
286typedef const VMXTRANSIENT *PCVMXTRANSIENT;
287
288/**
289 * VMX page allocation information.
290 */
291typedef struct
292{
293 uint32_t fValid; /**< Whether to allocate this page (e.g, based on a CPU feature). */
294 uint32_t uPadding0; /**< Padding to ensure array of these structs are aligned to a multiple of 8. */
295 PRTHCPHYS pHCPhys; /**< Where to store the host-physical address of the allocation. */
296 PRTR0PTR ppVirt; /**< Where to store the host-virtual address of the allocation. */
297} VMXPAGEALLOCINFO;
298/** Pointer to VMX page-allocation info. */
299typedef VMXPAGEALLOCINFO *PVMXPAGEALLOCINFO;
300/** Pointer to a const VMX page-allocation info. */
301typedef const VMXPAGEALLOCINFO *PCVMXPAGEALLOCINFO;
302AssertCompileSizeAlignment(VMXPAGEALLOCINFO, 8);
303
304/**
305 * Memory operand read or write access.
306 */
307typedef enum VMXMEMACCESS
308{
309 VMXMEMACCESS_READ = 0,
310 VMXMEMACCESS_WRITE = 1
311} VMXMEMACCESS;
312
313/**
314 * VMX VM-exit handler.
315 *
316 * @returns Strict VBox status code (i.e. informational status codes too).
317 * @param pVCpu The cross context virtual CPU structure.
318 * @param pVmxTransient The VMX-transient structure.
319 */
320#ifndef HMVMX_USE_FUNCTION_TABLE
321typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
322#else
323typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
324/** Pointer to VM-exit handler. */
325typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
326#endif
327
328/**
329 * VMX VM-exit handler, non-strict status code.
330 *
331 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
332 *
333 * @returns VBox status code, no informational status code returned.
334 * @param pVCpu The cross context virtual CPU structure.
335 * @param pVmxTransient The VMX-transient structure.
336 *
337 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
338 * use of that status code will be replaced with VINF_EM_SOMETHING
339 * later when switching over to IEM.
340 */
341#ifndef HMVMX_USE_FUNCTION_TABLE
342typedef int FNVMXEXITHANDLERNSRC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
343#else
344typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
345#endif
346
347
348/*********************************************************************************************************************************
349* Internal Functions *
350*********************************************************************************************************************************/
351#ifndef HMVMX_USE_FUNCTION_TABLE
352DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
353# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
354# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
355#else
356# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
357# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
358#endif
359#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
360DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
361#endif
362
363static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
364
365/** @name VM-exit handler prototypes.
366 * @{
367 */
368static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
369static FNVMXEXITHANDLER hmR0VmxExitExtInt;
370static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
371static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
372static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
373static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
374static FNVMXEXITHANDLER hmR0VmxExitCpuid;
375static FNVMXEXITHANDLER hmR0VmxExitGetsec;
376static FNVMXEXITHANDLER hmR0VmxExitHlt;
377static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
378static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
379static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
380static FNVMXEXITHANDLER hmR0VmxExitVmcall;
381#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
382static FNVMXEXITHANDLER hmR0VmxExitVmclear;
383static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
384static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
385static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
386static FNVMXEXITHANDLER hmR0VmxExitVmread;
387static FNVMXEXITHANDLER hmR0VmxExitVmresume;
388static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
389static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
390static FNVMXEXITHANDLER hmR0VmxExitVmxon;
391static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
392#endif
393static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
394static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
395static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
396static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
397static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
398static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
399static FNVMXEXITHANDLER hmR0VmxExitMwait;
400static FNVMXEXITHANDLER hmR0VmxExitMtf;
401static FNVMXEXITHANDLER hmR0VmxExitMonitor;
402static FNVMXEXITHANDLER hmR0VmxExitPause;
403static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
404static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
405static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
406static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
407static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
408static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
409static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
410static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
411static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
412static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
413static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
414static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
415/** @} */
416
417#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
418/** @name Nested-guest VM-exit handler prototypes.
419 * @{
420 */
421static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
422static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
423static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
424static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
425static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
426static FNVMXEXITHANDLER hmR0VmxExitHltNested;
427static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
428static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
429static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
430static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
431static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
432static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
433static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
434static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
435static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
436static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
437static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
438static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
439static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
440static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
441static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
442static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
443static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
444static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
445static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
446static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
447static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
448static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
449static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
450/** @} */
451#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
452
453
454/*********************************************************************************************************************************
455* Global Variables *
456*********************************************************************************************************************************/
457#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
458/**
459 * Array of all VMCS fields.
460 * Any fields added to the VT-x spec. should be added here.
461 *
462 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
463 * of nested-guests.
464 */
465static const uint32_t g_aVmcsFields[] =
466{
467 /* 16-bit control fields. */
468 VMX_VMCS16_VPID,
469 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
470 VMX_VMCS16_EPTP_INDEX,
471
472 /* 16-bit guest-state fields. */
473 VMX_VMCS16_GUEST_ES_SEL,
474 VMX_VMCS16_GUEST_CS_SEL,
475 VMX_VMCS16_GUEST_SS_SEL,
476 VMX_VMCS16_GUEST_DS_SEL,
477 VMX_VMCS16_GUEST_FS_SEL,
478 VMX_VMCS16_GUEST_GS_SEL,
479 VMX_VMCS16_GUEST_LDTR_SEL,
480 VMX_VMCS16_GUEST_TR_SEL,
481 VMX_VMCS16_GUEST_INTR_STATUS,
482 VMX_VMCS16_GUEST_PML_INDEX,
483
484 /* 16-bits host-state fields. */
485 VMX_VMCS16_HOST_ES_SEL,
486 VMX_VMCS16_HOST_CS_SEL,
487 VMX_VMCS16_HOST_SS_SEL,
488 VMX_VMCS16_HOST_DS_SEL,
489 VMX_VMCS16_HOST_FS_SEL,
490 VMX_VMCS16_HOST_GS_SEL,
491 VMX_VMCS16_HOST_TR_SEL,
492
493 /* 64-bit control fields. */
494 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
495 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
496 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
497 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
498 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
499 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
500 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
501 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
502 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
503 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
504 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
505 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
506 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
507 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
508 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
509 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
510 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
511 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
512 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
513 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
514 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
515 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
516 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
517 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
518 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
519 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
520 VMX_VMCS64_CTRL_EPTP_FULL,
521 VMX_VMCS64_CTRL_EPTP_HIGH,
522 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
523 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
524 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
525 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
526 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
527 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
528 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
529 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
530 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
531 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
532 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
533 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
534 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
535 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
536 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
537 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
538 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
539 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
540 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
541 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
542 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
543 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
544
545 /* 64-bit read-only data fields. */
546 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
547 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
548
549 /* 64-bit guest-state fields. */
550 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
551 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
552 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
553 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
554 VMX_VMCS64_GUEST_PAT_FULL,
555 VMX_VMCS64_GUEST_PAT_HIGH,
556 VMX_VMCS64_GUEST_EFER_FULL,
557 VMX_VMCS64_GUEST_EFER_HIGH,
558 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
559 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
560 VMX_VMCS64_GUEST_PDPTE0_FULL,
561 VMX_VMCS64_GUEST_PDPTE0_HIGH,
562 VMX_VMCS64_GUEST_PDPTE1_FULL,
563 VMX_VMCS64_GUEST_PDPTE1_HIGH,
564 VMX_VMCS64_GUEST_PDPTE2_FULL,
565 VMX_VMCS64_GUEST_PDPTE2_HIGH,
566 VMX_VMCS64_GUEST_PDPTE3_FULL,
567 VMX_VMCS64_GUEST_PDPTE3_HIGH,
568 VMX_VMCS64_GUEST_BNDCFGS_FULL,
569 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
570
571 /* 64-bit host-state fields. */
572 VMX_VMCS64_HOST_PAT_FULL,
573 VMX_VMCS64_HOST_PAT_HIGH,
574 VMX_VMCS64_HOST_EFER_FULL,
575 VMX_VMCS64_HOST_EFER_HIGH,
576 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
577 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
578
579 /* 32-bit control fields. */
580 VMX_VMCS32_CTRL_PIN_EXEC,
581 VMX_VMCS32_CTRL_PROC_EXEC,
582 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
583 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
584 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
585 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
586 VMX_VMCS32_CTRL_EXIT,
587 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
588 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
589 VMX_VMCS32_CTRL_ENTRY,
590 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
591 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
592 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
593 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
594 VMX_VMCS32_CTRL_TPR_THRESHOLD,
595 VMX_VMCS32_CTRL_PROC_EXEC2,
596 VMX_VMCS32_CTRL_PLE_GAP,
597 VMX_VMCS32_CTRL_PLE_WINDOW,
598
599 /* 32-bits read-only fields. */
600 VMX_VMCS32_RO_VM_INSTR_ERROR,
601 VMX_VMCS32_RO_EXIT_REASON,
602 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
603 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
604 VMX_VMCS32_RO_IDT_VECTORING_INFO,
605 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
606 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
607 VMX_VMCS32_RO_EXIT_INSTR_INFO,
608
609 /* 32-bit guest-state fields. */
610 VMX_VMCS32_GUEST_ES_LIMIT,
611 VMX_VMCS32_GUEST_CS_LIMIT,
612 VMX_VMCS32_GUEST_SS_LIMIT,
613 VMX_VMCS32_GUEST_DS_LIMIT,
614 VMX_VMCS32_GUEST_FS_LIMIT,
615 VMX_VMCS32_GUEST_GS_LIMIT,
616 VMX_VMCS32_GUEST_LDTR_LIMIT,
617 VMX_VMCS32_GUEST_TR_LIMIT,
618 VMX_VMCS32_GUEST_GDTR_LIMIT,
619 VMX_VMCS32_GUEST_IDTR_LIMIT,
620 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
621 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
622 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
623 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
624 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
625 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
626 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
627 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
628 VMX_VMCS32_GUEST_INT_STATE,
629 VMX_VMCS32_GUEST_ACTIVITY_STATE,
630 VMX_VMCS32_GUEST_SMBASE,
631 VMX_VMCS32_GUEST_SYSENTER_CS,
632 VMX_VMCS32_PREEMPT_TIMER_VALUE,
633
634 /* 32-bit host-state fields. */
635 VMX_VMCS32_HOST_SYSENTER_CS,
636
637 /* Natural-width control fields. */
638 VMX_VMCS_CTRL_CR0_MASK,
639 VMX_VMCS_CTRL_CR4_MASK,
640 VMX_VMCS_CTRL_CR0_READ_SHADOW,
641 VMX_VMCS_CTRL_CR4_READ_SHADOW,
642 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
643 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
644 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
645 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
646
647 /* Natural-width read-only data fields. */
648 VMX_VMCS_RO_EXIT_QUALIFICATION,
649 VMX_VMCS_RO_IO_RCX,
650 VMX_VMCS_RO_IO_RSI,
651 VMX_VMCS_RO_IO_RDI,
652 VMX_VMCS_RO_IO_RIP,
653 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
654
655 /* Natural-width guest-state field */
656 VMX_VMCS_GUEST_CR0,
657 VMX_VMCS_GUEST_CR3,
658 VMX_VMCS_GUEST_CR4,
659 VMX_VMCS_GUEST_ES_BASE,
660 VMX_VMCS_GUEST_CS_BASE,
661 VMX_VMCS_GUEST_SS_BASE,
662 VMX_VMCS_GUEST_DS_BASE,
663 VMX_VMCS_GUEST_FS_BASE,
664 VMX_VMCS_GUEST_GS_BASE,
665 VMX_VMCS_GUEST_LDTR_BASE,
666 VMX_VMCS_GUEST_TR_BASE,
667 VMX_VMCS_GUEST_GDTR_BASE,
668 VMX_VMCS_GUEST_IDTR_BASE,
669 VMX_VMCS_GUEST_DR7,
670 VMX_VMCS_GUEST_RSP,
671 VMX_VMCS_GUEST_RIP,
672 VMX_VMCS_GUEST_RFLAGS,
673 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
674 VMX_VMCS_GUEST_SYSENTER_ESP,
675 VMX_VMCS_GUEST_SYSENTER_EIP,
676
677 /* Natural-width host-state fields */
678 VMX_VMCS_HOST_CR0,
679 VMX_VMCS_HOST_CR3,
680 VMX_VMCS_HOST_CR4,
681 VMX_VMCS_HOST_FS_BASE,
682 VMX_VMCS_HOST_GS_BASE,
683 VMX_VMCS_HOST_TR_BASE,
684 VMX_VMCS_HOST_GDTR_BASE,
685 VMX_VMCS_HOST_IDTR_BASE,
686 VMX_VMCS_HOST_SYSENTER_ESP,
687 VMX_VMCS_HOST_SYSENTER_EIP,
688 VMX_VMCS_HOST_RSP,
689 VMX_VMCS_HOST_RIP
690};
691#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
692
693static const uint32_t g_aVmcsSegBase[] =
694{
695 VMX_VMCS_GUEST_ES_BASE,
696 VMX_VMCS_GUEST_CS_BASE,
697 VMX_VMCS_GUEST_SS_BASE,
698 VMX_VMCS_GUEST_DS_BASE,
699 VMX_VMCS_GUEST_FS_BASE,
700 VMX_VMCS_GUEST_GS_BASE
701};
702static const uint32_t g_aVmcsSegSel[] =
703{
704 VMX_VMCS16_GUEST_ES_SEL,
705 VMX_VMCS16_GUEST_CS_SEL,
706 VMX_VMCS16_GUEST_SS_SEL,
707 VMX_VMCS16_GUEST_DS_SEL,
708 VMX_VMCS16_GUEST_FS_SEL,
709 VMX_VMCS16_GUEST_GS_SEL
710};
711static const uint32_t g_aVmcsSegLimit[] =
712{
713 VMX_VMCS32_GUEST_ES_LIMIT,
714 VMX_VMCS32_GUEST_CS_LIMIT,
715 VMX_VMCS32_GUEST_SS_LIMIT,
716 VMX_VMCS32_GUEST_DS_LIMIT,
717 VMX_VMCS32_GUEST_FS_LIMIT,
718 VMX_VMCS32_GUEST_GS_LIMIT
719};
720static const uint32_t g_aVmcsSegAttr[] =
721{
722 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
723 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
724 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
725 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
726 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
727 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
728};
729AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
730AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
731AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
732AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
733
734#ifdef HMVMX_USE_FUNCTION_TABLE
735/**
736 * VMX_EXIT dispatch table.
737 */
738static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
739{
740 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
741 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
742 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
743 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
744 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
745 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
746 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
747 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
748 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
749 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
750 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
751 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
752 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
753 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
754 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
755 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
756 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
757 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
758 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
759#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
760 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
761 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
762 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
763 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
764 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
765 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
766 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
767 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
768 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
769#else
770 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
771 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
772 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
773 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
774 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
775 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
776 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
777 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
778 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
779#endif
780 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
781 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
782 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
783 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
784 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
785 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
786 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
787 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
788 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
789 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
790 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
791 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
792 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
793 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
794 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
795 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
796 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
797 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
798 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
799 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
800 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
801 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
802 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
803 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
804 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
805#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
806 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
807#else
808 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
809#endif
810 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
811 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
812 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
813 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
814 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
815 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
816 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
817 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
818 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
819 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
820 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
821 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
822 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
823 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
824 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
825};
826#endif /* HMVMX_USE_FUNCTION_TABLE */
827
828#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
829static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
830{
831 /* 0 */ "(Not Used)",
832 /* 1 */ "VMCALL executed in VMX root operation.",
833 /* 2 */ "VMCLEAR with invalid physical address.",
834 /* 3 */ "VMCLEAR with VMXON pointer.",
835 /* 4 */ "VMLAUNCH with non-clear VMCS.",
836 /* 5 */ "VMRESUME with non-launched VMCS.",
837 /* 6 */ "VMRESUME after VMXOFF",
838 /* 7 */ "VM-entry with invalid control fields.",
839 /* 8 */ "VM-entry with invalid host state fields.",
840 /* 9 */ "VMPTRLD with invalid physical address.",
841 /* 10 */ "VMPTRLD with VMXON pointer.",
842 /* 11 */ "VMPTRLD with incorrect revision identifier.",
843 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
844 /* 13 */ "VMWRITE to read-only VMCS component.",
845 /* 14 */ "(Not Used)",
846 /* 15 */ "VMXON executed in VMX root operation.",
847 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
848 /* 17 */ "VM-entry with non-launched executing VMCS.",
849 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
850 /* 19 */ "VMCALL with non-clear VMCS.",
851 /* 20 */ "VMCALL with invalid VM-exit control fields.",
852 /* 21 */ "(Not Used)",
853 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
854 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
855 /* 24 */ "VMCALL with invalid SMM-monitor features.",
856 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
857 /* 26 */ "VM-entry with events blocked by MOV SS.",
858 /* 27 */ "(Not Used)",
859 /* 28 */ "Invalid operand to INVEPT/INVVPID."
860};
861#endif /* VBOX_STRICT && LOG_ENABLED */
862
863
864/**
865 * Gets the CR0 guest/host mask.
866 *
867 * These bits typically does not change through the lifetime of a VM. Any bit set in
868 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
869 * by the guest.
870 *
871 * @returns The CR0 guest/host mask.
872 * @param pVCpu The cross context virtual CPU structure.
873 */
874static uint64_t hmR0VmxGetFixedCr0Mask(PCVMCPUCC pVCpu)
875{
876 /*
877 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
878 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
879 *
880 * Furthermore, modifications to any bits that are reserved/unspecified currently
881 * by the Intel spec. must also cause a VM-exit. This prevents unpredictable behavior
882 * when future CPUs specify and use currently reserved/unspecified bits.
883 */
884 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
885 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
886 * and @bugref{6944}. */
887 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
888 return ( X86_CR0_PE
889 | X86_CR0_NE
890 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
891 | X86_CR0_PG
892 | VMX_EXIT_HOST_CR0_IGNORE_MASK);
893}
894
895
896/**
897 * Gets the CR4 guest/host mask.
898 *
899 * These bits typically does not change through the lifetime of a VM. Any bit set in
900 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
901 * by the guest.
902 *
903 * @returns The CR4 guest/host mask.
904 * @param pVCpu The cross context virtual CPU structure.
905 */
906static uint64_t hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
907{
908 /*
909 * We construct a mask of all CR4 bits that the guest can modify without causing
910 * a VM-exit. Then invert this mask to obtain all CR4 bits that should cause
911 * a VM-exit when the guest attempts to modify them when executing using
912 * hardware-assisted VMX.
913 *
914 * When a feature is not exposed to the guest (and may be present on the host),
915 * we want to intercept guest modifications to the bit so we can emulate proper
916 * behavior (e.g., #GP).
917 *
918 * Furthermore, only modifications to those bits that don't require immediate
919 * emulation is allowed. For e.g., PCIDE is excluded because the behavior
920 * depends on CR3 which might not always be the guest value while executing
921 * using hardware-assisted VMX.
922 */
923 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
924 bool const fFsGsBase = pVM->cpum.ro.GuestFeatures.fFsGsBase;
925 bool const fXSaveRstor = pVM->cpum.ro.GuestFeatures.fXSaveRstor;
926 bool const fFxSaveRstor = pVM->cpum.ro.GuestFeatures.fFxSaveRstor;
927
928 /*
929 * Paranoia.
930 * Ensure features exposed to the guest are present on the host.
931 */
932 Assert(!fFsGsBase || pVM->cpum.ro.HostFeatures.fFsGsBase);
933 Assert(!fXSaveRstor || pVM->cpum.ro.HostFeatures.fXSaveRstor);
934 Assert(!fFxSaveRstor || pVM->cpum.ro.HostFeatures.fFxSaveRstor);
935
936 uint64_t const fGstMask = ( X86_CR4_PVI
937 | X86_CR4_TSD
938 | X86_CR4_DE
939 | X86_CR4_MCE
940 | X86_CR4_PCE
941 | X86_CR4_OSXMMEEXCPT
942 | (fFsGsBase ? X86_CR4_FSGSBASE : 0)
943 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
944 | (fFxSaveRstor ? X86_CR4_OSFXSR : 0));
945 return ~fGstMask;
946}
947
948
949/**
950 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
951 * area.
952 *
953 * @returns @c true if it's different, @c false otherwise.
954 * @param pVmcsInfo The VMCS info. object.
955 */
956DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
957{
958 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
959 && pVmcsInfo->pvGuestMsrStore);
960}
961
962
963/**
964 * Sets the given Processor-based VM-execution controls.
965 *
966 * @param pVmxTransient The VMX-transient structure.
967 * @param uProcCtls The Processor-based VM-execution controls to set.
968 */
969static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
970{
971 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
972 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
973 {
974 pVmcsInfo->u32ProcCtls |= uProcCtls;
975 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
976 AssertRC(rc);
977 }
978}
979
980
981/**
982 * Removes the given Processor-based VM-execution controls.
983 *
984 * @param pVCpu The cross context virtual CPU structure.
985 * @param pVmxTransient The VMX-transient structure.
986 * @param uProcCtls The Processor-based VM-execution controls to remove.
987 *
988 * @remarks When executing a nested-guest, this will not remove any of the specified
989 * controls if the nested hypervisor has set any one of them.
990 */
991static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
992{
993 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
994 if (pVmcsInfo->u32ProcCtls & uProcCtls)
995 {
996#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
997 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
998 ? true
999 : !CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uProcCtls);
1000#else
1001 NOREF(pVCpu);
1002 bool const fRemoveCtls = true;
1003#endif
1004 if (fRemoveCtls)
1005 {
1006 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
1007 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1008 AssertRC(rc);
1009 }
1010 }
1011}
1012
1013
1014/**
1015 * Sets the TSC offset for the current VMCS.
1016 *
1017 * @param uTscOffset The TSC offset to set.
1018 * @param pVmcsInfo The VMCS info. object.
1019 */
1020static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
1021{
1022 if (pVmcsInfo->u64TscOffset != uTscOffset)
1023 {
1024 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
1025 AssertRC(rc);
1026 pVmcsInfo->u64TscOffset = uTscOffset;
1027 }
1028}
1029
1030
1031/**
1032 * Adds one or more exceptions to the exception bitmap and commits it to the current
1033 * VMCS.
1034 *
1035 * @param pVmxTransient The VMX-transient structure.
1036 * @param uXcptMask The exception(s) to add.
1037 */
1038static void hmR0VmxAddXcptInterceptMask(PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1039{
1040 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1041 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1042 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1043 {
1044 uXcptBitmap |= uXcptMask;
1045 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1046 AssertRC(rc);
1047 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1048 }
1049}
1050
1051
1052/**
1053 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1054 *
1055 * @param pVmxTransient The VMX-transient structure.
1056 * @param uXcpt The exception to add.
1057 */
1058static void hmR0VmxAddXcptIntercept(PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1059{
1060 Assert(uXcpt <= X86_XCPT_LAST);
1061 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1062}
1063
1064
1065/**
1066 * Remove one or more exceptions from the exception bitmap and commits it to the
1067 * current VMCS.
1068 *
1069 * This takes care of not removing the exception intercept if a nested-guest
1070 * requires the exception to be intercepted.
1071 *
1072 * @returns VBox status code.
1073 * @param pVCpu The cross context virtual CPU structure.
1074 * @param pVmxTransient The VMX-transient structure.
1075 * @param uXcptMask The exception(s) to remove.
1076 */
1077static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1078{
1079 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1080 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1081 if (u32XcptBitmap & uXcptMask)
1082 {
1083#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1084 if (!pVmxTransient->fIsNestedGuest)
1085 { /* likely */ }
1086 else
1087 {
1088 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1089 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1090 }
1091#endif
1092#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1093 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1094 | RT_BIT(X86_XCPT_DE)
1095 | RT_BIT(X86_XCPT_NM)
1096 | RT_BIT(X86_XCPT_TS)
1097 | RT_BIT(X86_XCPT_UD)
1098 | RT_BIT(X86_XCPT_NP)
1099 | RT_BIT(X86_XCPT_SS)
1100 | RT_BIT(X86_XCPT_GP)
1101 | RT_BIT(X86_XCPT_PF)
1102 | RT_BIT(X86_XCPT_MF));
1103#elif defined(HMVMX_ALWAYS_TRAP_PF)
1104 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1105#endif
1106 if (uXcptMask)
1107 {
1108 /* Validate we are not removing any essential exception intercepts. */
1109 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1110 NOREF(pVCpu);
1111 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1112 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1113
1114 /* Remove it from the exception bitmap. */
1115 u32XcptBitmap &= ~uXcptMask;
1116
1117 /* Commit and update the cache if necessary. */
1118 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1119 {
1120 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1121 AssertRC(rc);
1122 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1123 }
1124 }
1125 }
1126 return VINF_SUCCESS;
1127}
1128
1129
1130/**
1131 * Remove an exceptions from the exception bitmap and commits it to the current
1132 * VMCS.
1133 *
1134 * @returns VBox status code.
1135 * @param pVCpu The cross context virtual CPU structure.
1136 * @param pVmxTransient The VMX-transient structure.
1137 * @param uXcpt The exception to remove.
1138 */
1139static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1140{
1141 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1142}
1143
1144
1145/**
1146 * Loads the VMCS specified by the VMCS info. object.
1147 *
1148 * @returns VBox status code.
1149 * @param pVmcsInfo The VMCS info. object.
1150 *
1151 * @remarks Can be called with interrupts disabled.
1152 */
1153static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1154{
1155 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1156 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1157
1158 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1159 if (RT_SUCCESS(rc))
1160 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1161 return rc;
1162}
1163
1164
1165/**
1166 * Clears the VMCS specified by the VMCS info. object.
1167 *
1168 * @returns VBox status code.
1169 * @param pVmcsInfo The VMCS info. object.
1170 *
1171 * @remarks Can be called with interrupts disabled.
1172 */
1173static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1174{
1175 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1176 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1177
1178 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1179 if (RT_SUCCESS(rc))
1180 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1181 return rc;
1182}
1183
1184
1185#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1186/**
1187 * Loads the shadow VMCS specified by the VMCS info. object.
1188 *
1189 * @returns VBox status code.
1190 * @param pVmcsInfo The VMCS info. object.
1191 *
1192 * @remarks Can be called with interrupts disabled.
1193 */
1194static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1195{
1196 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1197 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1198
1199 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1200 if (RT_SUCCESS(rc))
1201 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1202 return rc;
1203}
1204
1205
1206/**
1207 * Clears the shadow VMCS specified by the VMCS info. object.
1208 *
1209 * @returns VBox status code.
1210 * @param pVmcsInfo The VMCS info. object.
1211 *
1212 * @remarks Can be called with interrupts disabled.
1213 */
1214static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1215{
1216 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1217 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1218
1219 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1220 if (RT_SUCCESS(rc))
1221 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1222 return rc;
1223}
1224
1225
1226/**
1227 * Switches from and to the specified VMCSes.
1228 *
1229 * @returns VBox status code.
1230 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1231 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1232 *
1233 * @remarks Called with interrupts disabled.
1234 */
1235static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1236{
1237 /*
1238 * Clear the VMCS we are switching out if it has not already been cleared.
1239 * This will sync any CPU internal data back to the VMCS.
1240 */
1241 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1242 {
1243 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1244 if (RT_SUCCESS(rc))
1245 {
1246 /*
1247 * The shadow VMCS, if any, would not be active at this point since we
1248 * would have cleared it while importing the virtual hardware-virtualization
1249 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1250 * clear the shadow VMCS here, just assert for safety.
1251 */
1252 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1253 }
1254 else
1255 return rc;
1256 }
1257
1258 /*
1259 * Clear the VMCS we are switching to if it has not already been cleared.
1260 * This will initialize the VMCS launch state to "clear" required for loading it.
1261 *
1262 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1263 */
1264 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1265 {
1266 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1267 if (RT_SUCCESS(rc))
1268 { /* likely */ }
1269 else
1270 return rc;
1271 }
1272
1273 /*
1274 * Finally, load the VMCS we are switching to.
1275 */
1276 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1277}
1278
1279
1280/**
1281 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1282 * caller.
1283 *
1284 * @returns VBox status code.
1285 * @param pVCpu The cross context virtual CPU structure.
1286 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1287 * true) or guest VMCS (pass false).
1288 */
1289static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1290{
1291 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1292 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1293
1294 PVMXVMCSINFO pVmcsInfoFrom;
1295 PVMXVMCSINFO pVmcsInfoTo;
1296 if (fSwitchToNstGstVmcs)
1297 {
1298 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1299 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1300 }
1301 else
1302 {
1303 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1304 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1305 }
1306
1307 /*
1308 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1309 * preemption hook code path acquires the current VMCS.
1310 */
1311 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1312
1313 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1314 if (RT_SUCCESS(rc))
1315 {
1316 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1317
1318 /*
1319 * If we are switching to a VMCS that was executed on a different host CPU or was
1320 * never executed before, flag that we need to export the host state before executing
1321 * guest/nested-guest code using hardware-assisted VMX.
1322 *
1323 * This could probably be done in a preemptible context since the preemption hook
1324 * will flag the necessary change in host context. However, since preemption is
1325 * already disabled and to avoid making assumptions about host specific code in
1326 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1327 * disabled.
1328 */
1329 if (pVmcsInfoTo->idHostCpuState == RTMpCpuId())
1330 { /* likely */ }
1331 else
1332 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1333
1334 ASMSetFlags(fEFlags);
1335
1336 /*
1337 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1338 * flag that we need to update the host MSR values there. Even if we decide in the
1339 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1340 * if its content differs, we would have to update the host MSRs anyway.
1341 */
1342 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1343 }
1344 else
1345 ASMSetFlags(fEFlags);
1346 return rc;
1347}
1348#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1349
1350
1351/**
1352 * Updates the VM's last error record.
1353 *
1354 * If there was a VMX instruction error, reads the error data from the VMCS and
1355 * updates VCPU's last error record as well.
1356 *
1357 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1358 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1359 * VERR_VMX_INVALID_VMCS_FIELD.
1360 * @param rc The error code.
1361 */
1362static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1363{
1364 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1365 || rc == VERR_VMX_UNABLE_TO_START_VM)
1366 {
1367 AssertPtrReturnVoid(pVCpu);
1368 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1369 }
1370 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1371}
1372
1373
1374#ifdef VBOX_STRICT
1375/**
1376 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1377 * transient structure.
1378 *
1379 * @param pVmxTransient The VMX-transient structure.
1380 */
1381DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1382{
1383 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1384 AssertRC(rc);
1385}
1386
1387
1388/**
1389 * Reads the VM-entry exception error code field from the VMCS into
1390 * the VMX transient structure.
1391 *
1392 * @param pVmxTransient The VMX-transient structure.
1393 */
1394DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1395{
1396 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1397 AssertRC(rc);
1398}
1399
1400
1401/**
1402 * Reads the VM-entry exception error code field from the VMCS into
1403 * the VMX transient structure.
1404 *
1405 * @param pVmxTransient The VMX-transient structure.
1406 */
1407DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1408{
1409 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1410 AssertRC(rc);
1411}
1412#endif /* VBOX_STRICT */
1413
1414
1415/**
1416 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1417 * transient structure.
1418 *
1419 * @param pVmxTransient The VMX-transient structure.
1420 */
1421DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1422{
1423 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1424 {
1425 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1426 AssertRC(rc);
1427 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1428 }
1429}
1430
1431
1432/**
1433 * Reads the VM-exit interruption error code from the VMCS into the VMX
1434 * transient structure.
1435 *
1436 * @param pVmxTransient The VMX-transient structure.
1437 */
1438DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1439{
1440 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1441 {
1442 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1443 AssertRC(rc);
1444 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1445 }
1446}
1447
1448
1449/**
1450 * Reads the VM-exit instruction length field from the VMCS into the VMX
1451 * transient structure.
1452 *
1453 * @param pVmxTransient The VMX-transient structure.
1454 */
1455DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1456{
1457 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1458 {
1459 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1460 AssertRC(rc);
1461 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1462 }
1463}
1464
1465
1466/**
1467 * Reads the VM-exit instruction-information field from the VMCS into
1468 * the VMX transient structure.
1469 *
1470 * @param pVmxTransient The VMX-transient structure.
1471 */
1472DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1473{
1474 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1475 {
1476 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1477 AssertRC(rc);
1478 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1479 }
1480}
1481
1482
1483/**
1484 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1485 *
1486 * @param pVmxTransient The VMX-transient structure.
1487 */
1488DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1489{
1490 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1491 {
1492 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1493 AssertRC(rc);
1494 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1495 }
1496}
1497
1498
1499/**
1500 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1501 *
1502 * @param pVmxTransient The VMX-transient structure.
1503 */
1504DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1505{
1506 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1507 {
1508 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1509 AssertRC(rc);
1510 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1511 }
1512}
1513
1514
1515/**
1516 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1517 *
1518 * @param pVmxTransient The VMX-transient structure.
1519 */
1520DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1521{
1522 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1523 {
1524 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1525 AssertRC(rc);
1526 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1527 }
1528}
1529
1530#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1531/**
1532 * Reads the Guest pending-debug exceptions from the VMCS into the VMX transient
1533 * structure.
1534 *
1535 * @param pVmxTransient The VMX-transient structure.
1536 */
1537DECLINLINE(void) hmR0VmxReadGuestPendingDbgXctps(PVMXTRANSIENT pVmxTransient)
1538{
1539 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PENDING_DBG_XCPTS))
1540 {
1541 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &pVmxTransient->uGuestPendingDbgXcpts);
1542 AssertRC(rc);
1543 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PENDING_DBG_XCPTS;
1544 }
1545}
1546#endif
1547
1548/**
1549 * Reads the IDT-vectoring information field from the VMCS into the VMX
1550 * transient structure.
1551 *
1552 * @param pVmxTransient The VMX-transient structure.
1553 *
1554 * @remarks No-long-jump zone!!!
1555 */
1556DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1557{
1558 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1559 {
1560 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1561 AssertRC(rc);
1562 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1563 }
1564}
1565
1566
1567/**
1568 * Reads the IDT-vectoring error code from the VMCS into the VMX
1569 * transient structure.
1570 *
1571 * @param pVmxTransient The VMX-transient structure.
1572 */
1573DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1574{
1575 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1576 {
1577 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1578 AssertRC(rc);
1579 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1580 }
1581}
1582
1583#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1584/**
1585 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1586 *
1587 * @param pVmxTransient The VMX-transient structure.
1588 */
1589static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1590{
1591 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1592 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1593 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1594 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1595 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1596 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1597 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1598 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1599 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1600 AssertRC(rc);
1601 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1602 | HMVMX_READ_EXIT_INSTR_LEN
1603 | HMVMX_READ_EXIT_INSTR_INFO
1604 | HMVMX_READ_IDT_VECTORING_INFO
1605 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1606 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1607 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1608 | HMVMX_READ_GUEST_LINEAR_ADDR
1609 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1610}
1611#endif
1612
1613/**
1614 * Enters VMX root mode operation on the current CPU.
1615 *
1616 * @returns VBox status code.
1617 * @param pHostCpu The HM physical-CPU structure.
1618 * @param pVM The cross context VM structure. Can be
1619 * NULL, after a resume.
1620 * @param HCPhysCpuPage Physical address of the VMXON region.
1621 * @param pvCpuPage Pointer to the VMXON region.
1622 */
1623static int hmR0VmxEnterRootMode(PHMPHYSCPU pHostCpu, PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1624{
1625 Assert(pHostCpu);
1626 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1627 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1628 Assert(pvCpuPage);
1629 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1630
1631 if (pVM)
1632 {
1633 /* Write the VMCS revision identifier to the VMXON region. */
1634 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1635 }
1636
1637 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1638 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1639
1640 /* Enable the VMX bit in CR4 if necessary. */
1641 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1642
1643 /* Record whether VMXE was already prior to us enabling it above. */
1644 pHostCpu->fVmxeAlreadyEnabled = RT_BOOL(uOldCr4 & X86_CR4_VMXE);
1645
1646 /* Enter VMX root mode. */
1647 int rc = VMXEnable(HCPhysCpuPage);
1648 if (RT_FAILURE(rc))
1649 {
1650 /* Restore CR4.VMXE if it was not set prior to our attempt to set it above. */
1651 if (!pHostCpu->fVmxeAlreadyEnabled)
1652 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1653
1654 if (pVM)
1655 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1656 }
1657
1658 /* Restore interrupts. */
1659 ASMSetFlags(fEFlags);
1660 return rc;
1661}
1662
1663
1664/**
1665 * Exits VMX root mode operation on the current CPU.
1666 *
1667 * @returns VBox status code.
1668 * @param pHostCpu The HM physical-CPU structure.
1669 */
1670static int hmR0VmxLeaveRootMode(PHMPHYSCPU pHostCpu)
1671{
1672 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1673
1674 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1675 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1676
1677 /* If we're for some reason not in VMX root mode, then don't leave it. */
1678 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1679
1680 int rc;
1681 if (uHostCr4 & X86_CR4_VMXE)
1682 {
1683 /* Exit VMX root mode and clear the VMX bit in CR4. */
1684 VMXDisable();
1685
1686 /* Clear CR4.VMXE only if it was clear prior to use setting it. */
1687 if (!pHostCpu->fVmxeAlreadyEnabled)
1688 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1689
1690 rc = VINF_SUCCESS;
1691 }
1692 else
1693 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1694
1695 /* Restore interrupts. */
1696 ASMSetFlags(fEFlags);
1697 return rc;
1698}
1699
1700
1701/**
1702 * Allocates pages specified as specified by an array of VMX page allocation info
1703 * objects.
1704 *
1705 * The pages contents are zero'd after allocation.
1706 *
1707 * @returns VBox status code.
1708 * @param hMemObj The ring-0 memory object associated with the allocation.
1709 * @param paAllocInfo The pointer to the first element of the VMX
1710 * page-allocation info object array.
1711 * @param cEntries The number of elements in the @a paAllocInfo array.
1712 */
1713static int hmR0VmxPagesAllocZ(RTR0MEMOBJ hMemObj, PVMXPAGEALLOCINFO paAllocInfo, uint32_t cEntries)
1714{
1715 /* Figure out how many pages to allocate. */
1716 uint32_t cPages = 0;
1717 for (uint32_t iPage = 0; iPage < cEntries; iPage++)
1718 cPages += !!paAllocInfo[iPage].fValid;
1719
1720 /* Allocate the pages. */
1721 if (cPages)
1722 {
1723 size_t const cbPages = cPages << X86_PAGE_4K_SHIFT;
1724 int rc = RTR0MemObjAllocPage(&hMemObj, cbPages, false /* fExecutable */);
1725 if (RT_FAILURE(rc))
1726 return rc;
1727
1728 /* Zero the contents and assign each page to the corresponding VMX page-allocation entry. */
1729 void *pvFirstPage = RTR0MemObjAddress(hMemObj);
1730 ASMMemZero32(pvFirstPage, cbPages);
1731
1732 uint32_t iPage = 0;
1733 for (uint32_t i = 0; i < cEntries; i++)
1734 if (paAllocInfo[i].fValid)
1735 {
1736 RTHCPHYS const HCPhysPage = RTR0MemObjGetPagePhysAddr(hMemObj, iPage);
1737 void *pvPage = (void *)((uintptr_t)pvFirstPage + (iPage << X86_PAGE_4K_SHIFT));
1738 Assert(HCPhysPage && HCPhysPage != NIL_RTHCPHYS);
1739 AssertPtr(pvPage);
1740
1741 Assert(paAllocInfo[iPage].pHCPhys);
1742 Assert(paAllocInfo[iPage].ppVirt);
1743 *paAllocInfo[iPage].pHCPhys = HCPhysPage;
1744 *paAllocInfo[iPage].ppVirt = pvPage;
1745
1746 /* Move to next page. */
1747 ++iPage;
1748 }
1749
1750 /* Make sure all valid (requested) pages have been assigned. */
1751 Assert(iPage == cPages);
1752 }
1753 return VINF_SUCCESS;
1754}
1755
1756
1757/**
1758 * Frees pages allocated using hmR0VmxPagesAllocZ.
1759 *
1760 * @param hMemObj The ring-0 memory object associated with the allocation.
1761 */
1762DECL_FORCE_INLINE(void) hmR0VmxPagesFree(RTR0MEMOBJ hMemObj)
1763{
1764 /* We can cleanup wholesale since it's all one allocation. */
1765 RTR0MemObjFree(hMemObj, true /* fFreeMappings */);
1766}
1767
1768
1769/**
1770 * Initializes a VMCS info. object.
1771 *
1772 * @param pVmcsInfo The VMCS info. object.
1773 */
1774static void hmR0VmxVmcsInfoInit(PVMXVMCSINFO pVmcsInfo)
1775{
1776 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1777
1778 Assert(pVmcsInfo->hMemObj == NIL_RTR0MEMOBJ);
1779 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1780 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1781 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1782 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1783 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1784 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1785 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1786 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1787 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1788 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
1789 pVmcsInfo->idHostCpuExec = NIL_RTCPUID;
1790}
1791
1792
1793/**
1794 * Frees the VT-x structures for a VMCS info. object.
1795 *
1796 * @param pVmcsInfo The VMCS info. object.
1797 */
1798static void hmR0VmxVmcsInfoFree(PVMXVMCSINFO pVmcsInfo)
1799{
1800 if (pVmcsInfo->hMemObj != NIL_RTR0MEMOBJ)
1801 {
1802 hmR0VmxPagesFree(pVmcsInfo->hMemObj);
1803 hmR0VmxVmcsInfoInit(pVmcsInfo);
1804 }
1805}
1806
1807
1808/**
1809 * Allocates the VT-x structures for a VMCS info. object.
1810 *
1811 * @returns VBox status code.
1812 * @param pVCpu The cross context virtual CPU structure.
1813 * @param pVmcsInfo The VMCS info. object.
1814 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1815 *
1816 * @remarks The caller is expected to take care of any and all allocation failures.
1817 * This function will not perform any cleanup for failures half-way
1818 * through.
1819 */
1820static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1821{
1822 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1823
1824 bool const fMsrBitmaps = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS);
1825 bool const fShadowVmcs = !fIsNstGstVmcs ? pVM->hm.s.vmx.fUseVmcsShadowing : pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing;
1826 Assert(!pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing); /* VMCS shadowing is not yet exposed to the guest. */
1827 VMXPAGEALLOCINFO aAllocInfo[] = {
1828 { true, 0 /* Unused */, &pVmcsInfo->HCPhysVmcs, &pVmcsInfo->pvVmcs },
1829 { true, 0 /* Unused */, &pVmcsInfo->HCPhysGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad },
1830 { true, 0 /* Unused */, &pVmcsInfo->HCPhysHostMsrLoad, &pVmcsInfo->pvHostMsrLoad },
1831 { fMsrBitmaps, 0 /* Unused */, &pVmcsInfo->HCPhysMsrBitmap, &pVmcsInfo->pvMsrBitmap },
1832 { fShadowVmcs, 0 /* Unused */, &pVmcsInfo->HCPhysShadowVmcs, &pVmcsInfo->pvShadowVmcs },
1833 };
1834
1835 int rc = hmR0VmxPagesAllocZ(pVmcsInfo->hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1836 if (RT_FAILURE(rc))
1837 return rc;
1838
1839 /*
1840 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1841 * Because they contain a symmetric list of guest MSRs to load on VM-entry and store on VM-exit.
1842 */
1843 AssertCompile(RT_ELEMENTS(aAllocInfo) > 0);
1844 Assert(pVmcsInfo->HCPhysGuestMsrLoad != NIL_RTHCPHYS);
1845 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1846 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1847
1848 /*
1849 * Get the virtual-APIC page rather than allocating them again.
1850 */
1851 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1852 {
1853 if (!fIsNstGstVmcs)
1854 {
1855 if (PDMHasApic(pVM))
1856 {
1857 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1858 if (RT_FAILURE(rc))
1859 return rc;
1860 Assert(pVmcsInfo->pbVirtApic);
1861 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1862 }
1863 }
1864 else
1865 {
1866 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(&pVCpu->cpum.GstCtx, &pVmcsInfo->HCPhysVirtApic);
1867 Assert(pVmcsInfo->pbVirtApic);
1868 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1869 }
1870 }
1871
1872 return VINF_SUCCESS;
1873}
1874
1875
1876/**
1877 * Free all VT-x structures for the VM.
1878 *
1879 * @returns IPRT status code.
1880 * @param pVM The cross context VM structure.
1881 */
1882static void hmR0VmxStructsFree(PVMCC pVM)
1883{
1884 hmR0VmxPagesFree(pVM->hm.s.vmx.hMemObj);
1885#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1886 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1887 {
1888 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1889 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1890 }
1891#endif
1892
1893 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1894 {
1895 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1896 hmR0VmxVmcsInfoFree(&pVCpu->hm.s.vmx.VmcsInfo);
1897#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1898 if (pVM->cpum.ro.GuestFeatures.fVmx)
1899 hmR0VmxVmcsInfoFree(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1900#endif
1901 }
1902}
1903
1904
1905/**
1906 * Allocate all VT-x structures for the VM.
1907 *
1908 * @returns IPRT status code.
1909 * @param pVM The cross context VM structure.
1910 *
1911 * @remarks This functions will cleanup on memory allocation failures.
1912 */
1913static int hmR0VmxStructsAlloc(PVMCC pVM)
1914{
1915 /*
1916 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1917 * The VMCS size cannot be more than 4096 bytes.
1918 *
1919 * See Intel spec. Appendix A.1 "Basic VMX Information".
1920 */
1921 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1922 if (cbVmcs <= X86_PAGE_4K_SIZE)
1923 { /* likely */ }
1924 else
1925 {
1926 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1927 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1928 }
1929
1930 /*
1931 * Allocate per-VM VT-x structures.
1932 */
1933 bool const fVirtApicAccess = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
1934 bool const fUseVmcsShadowing = pVM->hm.s.vmx.fUseVmcsShadowing;
1935 VMXPAGEALLOCINFO aAllocInfo[] = {
1936 { fVirtApicAccess, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess },
1937 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap },
1938 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap },
1939#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1940 { true, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysScratch, &(PRTR0PTR)pVM->hm.s.vmx.pbScratch },
1941#endif
1942 };
1943
1944 int rc = hmR0VmxPagesAllocZ(pVM->hm.s.vmx.hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1945 if (RT_FAILURE(rc))
1946 goto cleanup;
1947
1948#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1949 /* Allocate the shadow VMCS-fields array. */
1950 if (fUseVmcsShadowing)
1951 {
1952 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
1953 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
1954 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1955 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1956 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
1957 && pVM->hm.s.vmx.paShadowVmcsRoFields))
1958 { /* likely */ }
1959 else
1960 {
1961 rc = VERR_NO_MEMORY;
1962 goto cleanup;
1963 }
1964 }
1965#endif
1966
1967 /*
1968 * Allocate per-VCPU VT-x structures.
1969 */
1970 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1971 {
1972 /* Allocate the guest VMCS structures. */
1973 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1974 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
1975 if (RT_FAILURE(rc))
1976 goto cleanup;
1977
1978#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1979 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
1980 if (pVM->cpum.ro.GuestFeatures.fVmx)
1981 {
1982 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
1983 if (RT_FAILURE(rc))
1984 goto cleanup;
1985 }
1986#endif
1987 }
1988
1989 return VINF_SUCCESS;
1990
1991cleanup:
1992 hmR0VmxStructsFree(pVM);
1993 Assert(rc != VINF_SUCCESS);
1994 return rc;
1995}
1996
1997
1998/**
1999 * Pre-initializes non-zero fields in VMX structures that will be allocated.
2000 *
2001 * @param pVM The cross context VM structure.
2002 */
2003static void hmR0VmxStructsInit(PVMCC pVM)
2004{
2005 /* Paranoia. */
2006 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
2007#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2008 Assert(pVM->hm.s.vmx.pbScratch == NULL);
2009#endif
2010
2011 /*
2012 * Initialize members up-front so we can cleanup en masse on allocation failures.
2013 */
2014#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2015 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
2016#endif
2017 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
2018 pVM->hm.s.vmx.HCPhysVmreadBitmap = NIL_RTHCPHYS;
2019 pVM->hm.s.vmx.HCPhysVmwriteBitmap = NIL_RTHCPHYS;
2020 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2021 {
2022 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2023 hmR0VmxVmcsInfoInit(&pVCpu->hm.s.vmx.VmcsInfo);
2024 hmR0VmxVmcsInfoInit(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
2025 }
2026}
2027
2028#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2029/**
2030 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2031 *
2032 * @returns @c true if the MSR is intercepted, @c false otherwise.
2033 * @param pvMsrBitmap The MSR bitmap.
2034 * @param offMsr The MSR byte offset.
2035 * @param iBit The bit offset from the byte offset.
2036 */
2037DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2038{
2039 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2040 Assert(pbMsrBitmap);
2041 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2042 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2043}
2044#endif
2045
2046/**
2047 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2048 *
2049 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2050 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2051 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2052 * the read/write access of this MSR.
2053 *
2054 * @param pVCpu The cross context virtual CPU structure.
2055 * @param pVmcsInfo The VMCS info. object.
2056 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2057 * @param idMsr The MSR value.
2058 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2059 * include both a read -and- a write permission!
2060 *
2061 * @sa CPUMGetVmxMsrPermission.
2062 * @remarks Can be called with interrupts disabled.
2063 */
2064static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2065{
2066 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2067 Assert(pbMsrBitmap);
2068 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2069
2070 /*
2071 * MSR-bitmap Layout:
2072 * Byte index MSR range Interpreted as
2073 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2074 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2075 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2076 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2077 *
2078 * A bit corresponding to an MSR within the above range causes a VM-exit
2079 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2080 * the MSR range, it always cause a VM-exit.
2081 *
2082 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2083 */
2084 uint16_t const offBitmapRead = 0;
2085 uint16_t const offBitmapWrite = 0x800;
2086 uint16_t offMsr;
2087 int32_t iBit;
2088 if (idMsr <= UINT32_C(0x00001fff))
2089 {
2090 offMsr = 0;
2091 iBit = idMsr;
2092 }
2093 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2094 {
2095 offMsr = 0x400;
2096 iBit = idMsr - UINT32_C(0xc0000000);
2097 }
2098 else
2099 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2100
2101 /*
2102 * Set the MSR read permission.
2103 */
2104 uint16_t const offMsrRead = offBitmapRead + offMsr;
2105 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2106 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2107 {
2108#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2109 bool const fClear = !fIsNstGstVmcs ? true
2110 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2111#else
2112 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2113 bool const fClear = true;
2114#endif
2115 if (fClear)
2116 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2117 }
2118 else
2119 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2120
2121 /*
2122 * Set the MSR write permission.
2123 */
2124 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2125 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2126 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2127 {
2128#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2129 bool const fClear = !fIsNstGstVmcs ? true
2130 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2131#else
2132 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2133 bool const fClear = true;
2134#endif
2135 if (fClear)
2136 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2137 }
2138 else
2139 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2140}
2141
2142
2143/**
2144 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2145 * area.
2146 *
2147 * @returns VBox status code.
2148 * @param pVCpu The cross context virtual CPU structure.
2149 * @param pVmcsInfo The VMCS info. object.
2150 * @param cMsrs The number of MSRs.
2151 */
2152static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2153{
2154 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2155 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2156 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2157 {
2158 /* Commit the MSR counts to the VMCS and update the cache. */
2159 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2160 {
2161 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2162 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2163 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2164 pVmcsInfo->cEntryMsrLoad = cMsrs;
2165 pVmcsInfo->cExitMsrStore = cMsrs;
2166 pVmcsInfo->cExitMsrLoad = cMsrs;
2167 }
2168 return VINF_SUCCESS;
2169 }
2170
2171 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2172 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2173 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2174}
2175
2176
2177/**
2178 * Adds a new (or updates the value of an existing) guest/host MSR
2179 * pair to be swapped during the world-switch as part of the
2180 * auto-load/store MSR area in the VMCS.
2181 *
2182 * @returns VBox status code.
2183 * @param pVCpu The cross context virtual CPU structure.
2184 * @param pVmxTransient The VMX-transient structure.
2185 * @param idMsr The MSR.
2186 * @param uGuestMsrValue Value of the guest MSR.
2187 * @param fSetReadWrite Whether to set the guest read/write access of this
2188 * MSR (thus not causing a VM-exit).
2189 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2190 * necessary.
2191 */
2192static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2193 bool fSetReadWrite, bool fUpdateHostMsr)
2194{
2195 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2196 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2197 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2198 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2199 uint32_t i;
2200
2201 /* Paranoia. */
2202 Assert(pGuestMsrLoad);
2203
2204 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2205
2206 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2207 for (i = 0; i < cMsrs; i++)
2208 {
2209 if (pGuestMsrLoad[i].u32Msr == idMsr)
2210 break;
2211 }
2212
2213 bool fAdded = false;
2214 if (i == cMsrs)
2215 {
2216 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2217 ++cMsrs;
2218 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2219 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2220
2221 /* Set the guest to read/write this MSR without causing VM-exits. */
2222 if ( fSetReadWrite
2223 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2224 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2225
2226 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2227 fAdded = true;
2228 }
2229
2230 /* Update the MSR value for the newly added or already existing MSR. */
2231 pGuestMsrLoad[i].u32Msr = idMsr;
2232 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2233
2234 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2235 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2236 {
2237 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2238 pGuestMsrStore[i].u32Msr = idMsr;
2239 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2240 }
2241
2242 /* Update the corresponding slot in the host MSR area. */
2243 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2244 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2245 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2246 pHostMsr[i].u32Msr = idMsr;
2247
2248 /*
2249 * Only if the caller requests to update the host MSR value AND we've newly added the
2250 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2251 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2252 *
2253 * We do this for performance reasons since reading MSRs may be quite expensive.
2254 */
2255 if (fAdded)
2256 {
2257 if (fUpdateHostMsr)
2258 {
2259 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2260 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2261 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2262 }
2263 else
2264 {
2265 /* Someone else can do the work. */
2266 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2267 }
2268 }
2269 return VINF_SUCCESS;
2270}
2271
2272
2273/**
2274 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2275 * auto-load/store MSR area in the VMCS.
2276 *
2277 * @returns VBox status code.
2278 * @param pVCpu The cross context virtual CPU structure.
2279 * @param pVmxTransient The VMX-transient structure.
2280 * @param idMsr The MSR.
2281 */
2282static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2283{
2284 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2285 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2286 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2287 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2288
2289 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2290
2291 for (uint32_t i = 0; i < cMsrs; i++)
2292 {
2293 /* Find the MSR. */
2294 if (pGuestMsrLoad[i].u32Msr == idMsr)
2295 {
2296 /*
2297 * If it's the last MSR, we only need to reduce the MSR count.
2298 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2299 */
2300 if (i < cMsrs - 1)
2301 {
2302 /* Remove it from the VM-entry MSR-load area. */
2303 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2304 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2305
2306 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2307 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2308 {
2309 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2310 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2311 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2312 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2313 }
2314
2315 /* Remove it from the VM-exit MSR-load area. */
2316 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2317 Assert(pHostMsr[i].u32Msr == idMsr);
2318 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2319 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2320 }
2321
2322 /* Reduce the count to reflect the removed MSR and bail. */
2323 --cMsrs;
2324 break;
2325 }
2326 }
2327
2328 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2329 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2330 {
2331 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2332 AssertRCReturn(rc, rc);
2333
2334 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2335 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2336 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2337
2338 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2339 return VINF_SUCCESS;
2340 }
2341
2342 return VERR_NOT_FOUND;
2343}
2344
2345
2346/**
2347 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2348 *
2349 * @returns @c true if found, @c false otherwise.
2350 * @param pVmcsInfo The VMCS info. object.
2351 * @param idMsr The MSR to find.
2352 */
2353static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2354{
2355 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2356 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2357 Assert(pMsrs);
2358 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2359 for (uint32_t i = 0; i < cMsrs; i++)
2360 {
2361 if (pMsrs[i].u32Msr == idMsr)
2362 return true;
2363 }
2364 return false;
2365}
2366
2367
2368/**
2369 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2370 *
2371 * @param pVCpu The cross context virtual CPU structure.
2372 * @param pVmcsInfo The VMCS info. object.
2373 *
2374 * @remarks No-long-jump zone!!!
2375 */
2376static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2377{
2378 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2379
2380 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2381 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2382 Assert(pHostMsrLoad);
2383 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2384 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2385 for (uint32_t i = 0; i < cMsrs; i++)
2386 {
2387 /*
2388 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2389 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2390 */
2391 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2392 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2393 else
2394 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2395 }
2396}
2397
2398
2399/**
2400 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2401 * perform lazy restoration of the host MSRs while leaving VT-x.
2402 *
2403 * @param pVCpu The cross context virtual CPU structure.
2404 *
2405 * @remarks No-long-jump zone!!!
2406 */
2407static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2408{
2409 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2410
2411 /*
2412 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2413 */
2414 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2415 {
2416 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2417 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2418 {
2419 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2420 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2421 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2422 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2423 }
2424 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2425 }
2426}
2427
2428
2429/**
2430 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2431 * lazily while leaving VT-x.
2432 *
2433 * @returns true if it does, false otherwise.
2434 * @param pVCpu The cross context virtual CPU structure.
2435 * @param idMsr The MSR to check.
2436 */
2437static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2438{
2439 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2440 {
2441 switch (idMsr)
2442 {
2443 case MSR_K8_LSTAR:
2444 case MSR_K6_STAR:
2445 case MSR_K8_SF_MASK:
2446 case MSR_K8_KERNEL_GS_BASE:
2447 return true;
2448 }
2449 }
2450 return false;
2451}
2452
2453
2454/**
2455 * Loads a set of guests MSRs to allow read/passthru to the guest.
2456 *
2457 * The name of this function is slightly confusing. This function does NOT
2458 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2459 * common prefix for functions dealing with "lazy restoration" of the shared
2460 * MSRs.
2461 *
2462 * @param pVCpu The cross context virtual CPU structure.
2463 *
2464 * @remarks No-long-jump zone!!!
2465 */
2466static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2467{
2468 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2469 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2470
2471 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2472 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2473 {
2474 /*
2475 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2476 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2477 * we can skip a few MSR writes.
2478 *
2479 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2480 * guest MSR values in the guest-CPU context might be different to what's currently
2481 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2482 * CPU, see @bugref{8728}.
2483 */
2484 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2485 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2486 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2487 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2488 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2489 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2490 {
2491#ifdef VBOX_STRICT
2492 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2493 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2494 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2495 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2496#endif
2497 }
2498 else
2499 {
2500 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2501 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2502 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2503 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2504 }
2505 }
2506 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2507}
2508
2509
2510/**
2511 * Performs lazy restoration of the set of host MSRs if they were previously
2512 * loaded with guest MSR values.
2513 *
2514 * @param pVCpu The cross context virtual CPU structure.
2515 *
2516 * @remarks No-long-jump zone!!!
2517 * @remarks The guest MSRs should have been saved back into the guest-CPU
2518 * context by hmR0VmxImportGuestState()!!!
2519 */
2520static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2521{
2522 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2523 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2524
2525 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2526 {
2527 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2528 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2529 {
2530 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2531 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2532 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2533 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2534 }
2535 }
2536 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2537}
2538
2539
2540/**
2541 * Verifies that our cached values of the VMCS fields are all consistent with
2542 * what's actually present in the VMCS.
2543 *
2544 * @returns VBox status code.
2545 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2546 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2547 * VMCS content. HMCPU error-field is
2548 * updated, see VMX_VCI_XXX.
2549 * @param pVCpu The cross context virtual CPU structure.
2550 * @param pVmcsInfo The VMCS info. object.
2551 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2552 */
2553static int hmR0VmxCheckCachedVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2554{
2555 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2556
2557 uint32_t u32Val;
2558 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2559 AssertRC(rc);
2560 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2561 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2562 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2563 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2564
2565 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2566 AssertRC(rc);
2567 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2568 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2569 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2570 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2571
2572 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2573 AssertRC(rc);
2574 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2575 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2576 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2577 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2578
2579 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2580 AssertRC(rc);
2581 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2582 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2583 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2584 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2585
2586 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2587 {
2588 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2589 AssertRC(rc);
2590 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2591 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2592 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2593 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2594 }
2595
2596 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2597 AssertRC(rc);
2598 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2599 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2600 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2601 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2602
2603 uint64_t u64Val;
2604 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2605 AssertRC(rc);
2606 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2607 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2608 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2609 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2610
2611 NOREF(pcszVmcs);
2612 return VINF_SUCCESS;
2613}
2614
2615
2616#ifdef VBOX_STRICT
2617/**
2618 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2619 *
2620 * @param pVCpu The cross context virtual CPU structure.
2621 * @param pVmcsInfo The VMCS info. object.
2622 */
2623static void hmR0VmxCheckHostEferMsr(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2624{
2625 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2626
2627 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2628 {
2629 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2630 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2631 uint64_t uVmcsEferMsrVmcs;
2632 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2633 AssertRC(rc);
2634
2635 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2636 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2637 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2638 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2639 }
2640}
2641
2642
2643/**
2644 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2645 * VMCS are correct.
2646 *
2647 * @param pVCpu The cross context virtual CPU structure.
2648 * @param pVmcsInfo The VMCS info. object.
2649 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2650 */
2651static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2652{
2653 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2654
2655 /* Read the various MSR-area counts from the VMCS. */
2656 uint32_t cEntryLoadMsrs;
2657 uint32_t cExitStoreMsrs;
2658 uint32_t cExitLoadMsrs;
2659 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2660 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2661 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2662
2663 /* Verify all the MSR counts are the same. */
2664 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2665 Assert(cExitStoreMsrs == cExitLoadMsrs);
2666 uint32_t const cMsrs = cExitLoadMsrs;
2667
2668 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2669 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2670
2671 /* Verify the MSR counts are within the allocated page size. */
2672 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2673
2674 /* Verify the relevant contents of the MSR areas match. */
2675 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2676 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2677 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2678 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2679 for (uint32_t i = 0; i < cMsrs; i++)
2680 {
2681 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2682 if (fSeparateExitMsrStorePage)
2683 {
2684 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2685 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2686 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2687 }
2688
2689 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2690 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2691 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2692
2693 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2694 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2695 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2696 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2697
2698 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2699 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2700 if (fIsEferMsr)
2701 {
2702 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2703 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2704 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2705 }
2706
2707 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2708 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2709 {
2710 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2711 if (fIsEferMsr)
2712 {
2713 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2714 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2715 }
2716 else
2717 {
2718 if (!fIsNstGstVmcs)
2719 {
2720 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2721 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2722 }
2723 else
2724 {
2725 /*
2726 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2727 * execute a nested-guest with MSR passthrough.
2728 *
2729 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2730 * allow passthrough too.
2731 */
2732 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2733 Assert(pvMsrBitmapNstGst);
2734 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2735 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2736 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2737 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2738 }
2739 }
2740 }
2741
2742 /* Move to the next MSR. */
2743 pHostMsrLoad++;
2744 pGuestMsrLoad++;
2745 pGuestMsrStore++;
2746 }
2747}
2748#endif /* VBOX_STRICT */
2749
2750
2751/**
2752 * Flushes the TLB using EPT.
2753 *
2754 * @returns VBox status code.
2755 * @param pVCpu The cross context virtual CPU structure of the calling
2756 * EMT. Can be NULL depending on @a enmTlbFlush.
2757 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2758 * enmTlbFlush.
2759 * @param enmTlbFlush Type of flush.
2760 *
2761 * @remarks Caller is responsible for making sure this function is called only
2762 * when NestedPaging is supported and providing @a enmTlbFlush that is
2763 * supported by the CPU.
2764 * @remarks Can be called with interrupts disabled.
2765 */
2766static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2767{
2768 uint64_t au64Descriptor[2];
2769 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2770 au64Descriptor[0] = 0;
2771 else
2772 {
2773 Assert(pVCpu);
2774 Assert(pVmcsInfo);
2775 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2776 }
2777 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2778
2779 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2780 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2781
2782 if ( RT_SUCCESS(rc)
2783 && pVCpu)
2784 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2785}
2786
2787
2788/**
2789 * Flushes the TLB using VPID.
2790 *
2791 * @returns VBox status code.
2792 * @param pVCpu The cross context virtual CPU structure of the calling
2793 * EMT. Can be NULL depending on @a enmTlbFlush.
2794 * @param enmTlbFlush Type of flush.
2795 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2796 * on @a enmTlbFlush).
2797 *
2798 * @remarks Can be called with interrupts disabled.
2799 */
2800static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2801{
2802 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2803
2804 uint64_t au64Descriptor[2];
2805 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2806 {
2807 au64Descriptor[0] = 0;
2808 au64Descriptor[1] = 0;
2809 }
2810 else
2811 {
2812 AssertPtr(pVCpu);
2813 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2814 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2815 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2816 au64Descriptor[1] = GCPtr;
2817 }
2818
2819 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2820 AssertMsg(rc == VINF_SUCCESS,
2821 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2822
2823 if ( RT_SUCCESS(rc)
2824 && pVCpu)
2825 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2826 NOREF(rc);
2827}
2828
2829
2830/**
2831 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2832 * otherwise there is nothing really to invalidate.
2833 *
2834 * @returns VBox status code.
2835 * @param pVCpu The cross context virtual CPU structure.
2836 * @param GCVirt Guest virtual address of the page to invalidate.
2837 */
2838VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2839{
2840 AssertPtr(pVCpu);
2841 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2842
2843 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2844 {
2845 /*
2846 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2847 * the EPT case. See @bugref{6043} and @bugref{6177}.
2848 *
2849 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2850 * as this function maybe called in a loop with individual addresses.
2851 */
2852 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2853 if (pVM->hm.s.vmx.fVpid)
2854 {
2855 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2856 if (fVpidFlush)
2857 {
2858 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2859 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2860 }
2861 else
2862 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2863 }
2864 else if (pVM->hm.s.fNestedPaging)
2865 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2866 }
2867
2868 return VINF_SUCCESS;
2869}
2870
2871
2872/**
2873 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2874 * case where neither EPT nor VPID is supported by the CPU.
2875 *
2876 * @param pHostCpu The HM physical-CPU structure.
2877 * @param pVCpu The cross context virtual CPU structure.
2878 *
2879 * @remarks Called with interrupts disabled.
2880 */
2881static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2882{
2883 AssertPtr(pVCpu);
2884 AssertPtr(pHostCpu);
2885
2886 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2887
2888 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2889 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2890 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2891 pVCpu->hm.s.fForceTLBFlush = false;
2892 return;
2893}
2894
2895
2896/**
2897 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2898 *
2899 * @param pHostCpu The HM physical-CPU structure.
2900 * @param pVCpu The cross context virtual CPU structure.
2901 * @param pVmcsInfo The VMCS info. object.
2902 *
2903 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2904 * nomenclature. The reason is, to avoid confusion in compare statements
2905 * since the host-CPU copies are named "ASID".
2906 *
2907 * @remarks Called with interrupts disabled.
2908 */
2909static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2910{
2911#ifdef VBOX_WITH_STATISTICS
2912 bool fTlbFlushed = false;
2913# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2914# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2915 if (!fTlbFlushed) \
2916 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2917 } while (0)
2918#else
2919# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2920# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2921#endif
2922
2923 AssertPtr(pVCpu);
2924 AssertPtr(pHostCpu);
2925 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2926
2927 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2928 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2929 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2930 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2931
2932 /*
2933 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2934 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2935 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2936 * cannot reuse the current ASID anymore.
2937 */
2938 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2939 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2940 {
2941 ++pHostCpu->uCurrentAsid;
2942 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2943 {
2944 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2945 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2946 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2947 }
2948
2949 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2950 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2951 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2952
2953 /*
2954 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2955 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2956 */
2957 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2958 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2959 HMVMX_SET_TAGGED_TLB_FLUSHED();
2960 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2961 }
2962 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2963 {
2964 /*
2965 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2966 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2967 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2968 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2969 * mappings, see @bugref{6568}.
2970 *
2971 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2972 */
2973 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2974 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2975 HMVMX_SET_TAGGED_TLB_FLUSHED();
2976 }
2977 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
2978 {
2979 /*
2980 * The nested-guest specifies its own guest-physical address to use as the APIC-access
2981 * address which requires flushing the TLB of EPT cached structures.
2982 *
2983 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
2984 */
2985 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2986 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
2987 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
2988 HMVMX_SET_TAGGED_TLB_FLUSHED();
2989 }
2990
2991
2992 pVCpu->hm.s.fForceTLBFlush = false;
2993 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
2994
2995 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
2996 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
2997 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2998 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
2999 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3000 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3001 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3002 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3003 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3004
3005 /* Update VMCS with the VPID. */
3006 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3007 AssertRC(rc);
3008
3009#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3010}
3011
3012
3013/**
3014 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3015 *
3016 * @param pHostCpu The HM physical-CPU structure.
3017 * @param pVCpu The cross context virtual CPU structure.
3018 * @param pVmcsInfo The VMCS info. object.
3019 *
3020 * @remarks Called with interrupts disabled.
3021 */
3022static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3023{
3024 AssertPtr(pVCpu);
3025 AssertPtr(pHostCpu);
3026 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3027 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3028 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3029
3030 /*
3031 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3032 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3033 */
3034 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3035 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3036 {
3037 pVCpu->hm.s.fForceTLBFlush = true;
3038 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3039 }
3040
3041 /* Check for explicit TLB flushes. */
3042 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3043 {
3044 pVCpu->hm.s.fForceTLBFlush = true;
3045 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3046 }
3047
3048 /* Check for TLB flushes while switching to/from a nested-guest. */
3049 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3050 {
3051 pVCpu->hm.s.fForceTLBFlush = true;
3052 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3053 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3054 }
3055
3056 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3057 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3058
3059 if (pVCpu->hm.s.fForceTLBFlush)
3060 {
3061 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3062 pVCpu->hm.s.fForceTLBFlush = false;
3063 }
3064}
3065
3066
3067/**
3068 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3069 *
3070 * @param pHostCpu The HM physical-CPU structure.
3071 * @param pVCpu The cross context virtual CPU structure.
3072 *
3073 * @remarks Called with interrupts disabled.
3074 */
3075static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3076{
3077 AssertPtr(pVCpu);
3078 AssertPtr(pHostCpu);
3079 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3080 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3081 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3082
3083 /*
3084 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3085 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3086 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3087 * cannot reuse the current ASID anymore.
3088 */
3089 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3090 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3091 {
3092 pVCpu->hm.s.fForceTLBFlush = true;
3093 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3094 }
3095
3096 /* Check for explicit TLB flushes. */
3097 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3098 {
3099 /*
3100 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3101 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3102 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3103 * include fExplicitFlush's too) - an obscure corner case.
3104 */
3105 pVCpu->hm.s.fForceTLBFlush = true;
3106 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3107 }
3108
3109 /* Check for TLB flushes while switching to/from a nested-guest. */
3110 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3111 {
3112 pVCpu->hm.s.fForceTLBFlush = true;
3113 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3114 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3115 }
3116
3117 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3118 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3119 if (pVCpu->hm.s.fForceTLBFlush)
3120 {
3121 ++pHostCpu->uCurrentAsid;
3122 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3123 {
3124 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3125 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3126 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3127 }
3128
3129 pVCpu->hm.s.fForceTLBFlush = false;
3130 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3131 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3132 if (pHostCpu->fFlushAsidBeforeUse)
3133 {
3134 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3135 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3136 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3137 {
3138 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3139 pHostCpu->fFlushAsidBeforeUse = false;
3140 }
3141 else
3142 {
3143 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3144 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3145 }
3146 }
3147 }
3148
3149 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3150 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3151 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3152 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3153 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3154 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3155 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3156
3157 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3158 AssertRC(rc);
3159}
3160
3161
3162/**
3163 * Flushes the guest TLB entry based on CPU capabilities.
3164 *
3165 * @param pHostCpu The HM physical-CPU structure.
3166 * @param pVCpu The cross context virtual CPU structure.
3167 * @param pVmcsInfo The VMCS info. object.
3168 *
3169 * @remarks Called with interrupts disabled.
3170 */
3171static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3172{
3173#ifdef HMVMX_ALWAYS_FLUSH_TLB
3174 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3175#endif
3176 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3177 switch (pVM->hm.s.vmx.enmTlbFlushType)
3178 {
3179 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3180 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3181 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3182 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3183 default:
3184 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3185 break;
3186 }
3187 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3188}
3189
3190
3191/**
3192 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3193 * TLB entries from the host TLB before VM-entry.
3194 *
3195 * @returns VBox status code.
3196 * @param pVM The cross context VM structure.
3197 */
3198static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3199{
3200 /*
3201 * Determine optimal flush type for nested paging.
3202 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3203 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3204 */
3205 if (pVM->hm.s.fNestedPaging)
3206 {
3207 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3208 {
3209 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3210 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3211 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3212 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3213 else
3214 {
3215 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3216 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3217 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3218 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3219 }
3220
3221 /* Make sure the write-back cacheable memory type for EPT is supported. */
3222 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3223 {
3224 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3225 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3226 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3227 }
3228
3229 /* EPT requires a page-walk length of 4. */
3230 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3231 {
3232 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3233 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3234 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3235 }
3236 }
3237 else
3238 {
3239 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3240 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3241 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3242 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3243 }
3244 }
3245
3246 /*
3247 * Determine optimal flush type for VPID.
3248 */
3249 if (pVM->hm.s.vmx.fVpid)
3250 {
3251 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3252 {
3253 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3254 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3255 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3256 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3257 else
3258 {
3259 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3260 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3261 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3262 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3263 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3264 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3265 pVM->hm.s.vmx.fVpid = false;
3266 }
3267 }
3268 else
3269 {
3270 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3271 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3272 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3273 pVM->hm.s.vmx.fVpid = false;
3274 }
3275 }
3276
3277 /*
3278 * Setup the handler for flushing tagged-TLBs.
3279 */
3280 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3281 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3282 else if (pVM->hm.s.fNestedPaging)
3283 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3284 else if (pVM->hm.s.vmx.fVpid)
3285 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3286 else
3287 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3288 return VINF_SUCCESS;
3289}
3290
3291
3292#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3293/**
3294 * Sets up the shadow VMCS fields arrays.
3295 *
3296 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3297 * executing the guest.
3298 *
3299 * @returns VBox status code.
3300 * @param pVM The cross context VM structure.
3301 */
3302static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3303{
3304 /*
3305 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3306 * when the host does not support it.
3307 */
3308 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3309 if ( !fGstVmwriteAll
3310 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3311 { /* likely. */ }
3312 else
3313 {
3314 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3315 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3316 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3317 }
3318
3319 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3320 uint32_t cRwFields = 0;
3321 uint32_t cRoFields = 0;
3322 for (uint32_t i = 0; i < cVmcsFields; i++)
3323 {
3324 VMXVMCSFIELD VmcsField;
3325 VmcsField.u = g_aVmcsFields[i];
3326
3327 /*
3328 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3329 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3330 * in the shadow VMCS fields array as they would be redundant.
3331 *
3332 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3333 * we must not include it in the shadow VMCS fields array. Guests attempting to
3334 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3335 * the required behavior.
3336 */
3337 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3338 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3339 {
3340 /*
3341 * Read-only fields are placed in a separate array so that while syncing shadow
3342 * VMCS fields later (which is more performance critical) we can avoid branches.
3343 *
3344 * However, if the guest can write to all fields (including read-only fields),
3345 * we treat it a as read/write field. Otherwise, writing to these fields would
3346 * cause a VMWRITE instruction error while syncing the shadow VMCS.
3347 */
3348 if ( fGstVmwriteAll
3349 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3350 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3351 else
3352 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3353 }
3354 }
3355
3356 /* Update the counts. */
3357 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3358 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3359 return VINF_SUCCESS;
3360}
3361
3362
3363/**
3364 * Sets up the VMREAD and VMWRITE bitmaps.
3365 *
3366 * @param pVM The cross context VM structure.
3367 */
3368static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3369{
3370 /*
3371 * By default, ensure guest attempts to access any VMCS fields cause VM-exits.
3372 */
3373 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3374 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3375 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3376 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3377 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3378
3379 /*
3380 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3381 * VMREAD and VMWRITE bitmaps.
3382 */
3383 {
3384 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3385 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3386 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3387 {
3388 uint32_t const uVmcsField = paShadowVmcsFields[i];
3389 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3390 Assert(uVmcsField >> 3 < cbBitmap);
3391 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3392 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3393 }
3394 }
3395
3396 /*
3397 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3398 * if the host supports VMWRITE to all supported VMCS fields.
3399 */
3400 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3401 {
3402 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3403 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3404 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3405 {
3406 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3407 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3408 Assert(uVmcsField >> 3 < cbBitmap);
3409 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3410 }
3411 }
3412}
3413#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3414
3415
3416/**
3417 * Sets up the virtual-APIC page address for the VMCS.
3418 *
3419 * @param pVmcsInfo The VMCS info. object.
3420 */
3421DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3422{
3423 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3424 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3425 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3426 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3427 AssertRC(rc);
3428}
3429
3430
3431/**
3432 * Sets up the MSR-bitmap address for the VMCS.
3433 *
3434 * @param pVmcsInfo The VMCS info. object.
3435 */
3436DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3437{
3438 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3439 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3440 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3441 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3442 AssertRC(rc);
3443}
3444
3445
3446/**
3447 * Sets up the APIC-access page address for the VMCS.
3448 *
3449 * @param pVCpu The cross context virtual CPU structure.
3450 */
3451DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3452{
3453 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3454 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3455 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3456 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3457 AssertRC(rc);
3458}
3459
3460
3461#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3462/**
3463 * Sets up the VMREAD bitmap address for the VMCS.
3464 *
3465 * @param pVCpu The cross context virtual CPU structure.
3466 */
3467DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3468{
3469 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3470 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3471 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3472 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3473 AssertRC(rc);
3474}
3475
3476
3477/**
3478 * Sets up the VMWRITE bitmap address for the VMCS.
3479 *
3480 * @param pVCpu The cross context virtual CPU structure.
3481 */
3482DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3483{
3484 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3485 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3486 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3487 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3488 AssertRC(rc);
3489}
3490#endif
3491
3492
3493/**
3494 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3495 * in the VMCS.
3496 *
3497 * @returns VBox status code.
3498 * @param pVmcsInfo The VMCS info. object.
3499 */
3500DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3501{
3502 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3503 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3504 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3505
3506 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3507 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3508 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3509
3510 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3511 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3512 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3513
3514 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3515 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3516 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3517 return VINF_SUCCESS;
3518}
3519
3520
3521/**
3522 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3523 *
3524 * @param pVCpu The cross context virtual CPU structure.
3525 * @param pVmcsInfo The VMCS info. object.
3526 */
3527static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3528{
3529 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3530
3531 /*
3532 * By default, ensure guest attempts to access any MSR cause VM-exits.
3533 * This shall later be relaxed for specific MSRs as necessary.
3534 *
3535 * Note: For nested-guests, the entire bitmap will be merged prior to
3536 * executing the nested-guest using hardware-assisted VMX and hence there
3537 * is no need to perform this operation. See hmR0VmxMergeMsrBitmapNested.
3538 */
3539 Assert(pVmcsInfo->pvMsrBitmap);
3540 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
3541
3542 /*
3543 * The guest can access the following MSRs (read, write) without causing
3544 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3545 */
3546 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3547 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3548 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3549 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3550 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3551 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3552
3553 /*
3554 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3555 * associated with then. We never need to intercept access (writes need to be
3556 * executed without causing a VM-exit, reads will #GP fault anyway).
3557 *
3558 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3559 * read/write them. We swap the the guest/host MSR value using the
3560 * auto-load/store MSR area.
3561 */
3562 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3563 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3564 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3565 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3566 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3567 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3568
3569 /*
3570 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3571 * required for 64-bit guests.
3572 */
3573 if (pVM->hm.s.fAllow64BitGuests)
3574 {
3575 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3576 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3577 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3578 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3579 }
3580
3581 /*
3582 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3583 */
3584#ifdef VBOX_STRICT
3585 Assert(pVmcsInfo->pvMsrBitmap);
3586 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3587 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3588#endif
3589}
3590
3591
3592/**
3593 * Sets up pin-based VM-execution controls in the VMCS.
3594 *
3595 * @returns VBox status code.
3596 * @param pVCpu The cross context virtual CPU structure.
3597 * @param pVmcsInfo The VMCS info. object.
3598 */
3599static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3600{
3601 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3602 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3603 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3604
3605 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3606 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3607
3608 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3609 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3610
3611 /* Enable the VMX-preemption timer. */
3612 if (pVM->hm.s.vmx.fUsePreemptTimer)
3613 {
3614 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3615 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3616 }
3617
3618#if 0
3619 /* Enable posted-interrupt processing. */
3620 if (pVM->hm.s.fPostedIntrs)
3621 {
3622 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3623 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3624 fVal |= VMX_PIN_CTLS_POSTED_INT;
3625 }
3626#endif
3627
3628 if ((fVal & fZap) != fVal)
3629 {
3630 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3631 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3632 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3633 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3634 }
3635
3636 /* Commit it to the VMCS and update our cache. */
3637 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3638 AssertRC(rc);
3639 pVmcsInfo->u32PinCtls = fVal;
3640
3641 return VINF_SUCCESS;
3642}
3643
3644
3645/**
3646 * Sets up secondary processor-based VM-execution controls in the VMCS.
3647 *
3648 * @returns VBox status code.
3649 * @param pVCpu The cross context virtual CPU structure.
3650 * @param pVmcsInfo The VMCS info. object.
3651 */
3652static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3653{
3654 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3655 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3656 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3657
3658 /* WBINVD causes a VM-exit. */
3659 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3660 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3661
3662 /* Enable EPT (aka nested-paging). */
3663 if (pVM->hm.s.fNestedPaging)
3664 fVal |= VMX_PROC_CTLS2_EPT;
3665
3666 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3667 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3668 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3669 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3670 fVal |= VMX_PROC_CTLS2_INVPCID;
3671
3672 /* Enable VPID. */
3673 if (pVM->hm.s.vmx.fVpid)
3674 fVal |= VMX_PROC_CTLS2_VPID;
3675
3676 /* Enable unrestricted guest execution. */
3677 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3678 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3679
3680#if 0
3681 if (pVM->hm.s.fVirtApicRegs)
3682 {
3683 /* Enable APIC-register virtualization. */
3684 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3685 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3686
3687 /* Enable virtual-interrupt delivery. */
3688 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3689 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3690 }
3691#endif
3692
3693 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3694 where the TPR shadow resides. */
3695 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3696 * done dynamically. */
3697 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3698 {
3699 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3700 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3701 }
3702
3703 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3704 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3705 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3706 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3707 fVal |= VMX_PROC_CTLS2_RDTSCP;
3708
3709 /* Enable Pause-Loop exiting. */
3710 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3711 && pVM->hm.s.vmx.cPleGapTicks
3712 && pVM->hm.s.vmx.cPleWindowTicks)
3713 {
3714 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3715
3716 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3717 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3718 }
3719
3720 if ((fVal & fZap) != fVal)
3721 {
3722 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3723 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3724 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3725 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3726 }
3727
3728 /* Commit it to the VMCS and update our cache. */
3729 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3730 AssertRC(rc);
3731 pVmcsInfo->u32ProcCtls2 = fVal;
3732
3733 return VINF_SUCCESS;
3734}
3735
3736
3737/**
3738 * Sets up processor-based VM-execution controls in the VMCS.
3739 *
3740 * @returns VBox status code.
3741 * @param pVCpu The cross context virtual CPU structure.
3742 * @param pVmcsInfo The VMCS info. object.
3743 */
3744static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3745{
3746 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3747 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3748 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3749
3750 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3751 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3752 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3753 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3754 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3755 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3756 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3757
3758 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3759 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3760 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3761 {
3762 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3763 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3764 }
3765
3766 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3767 if (!pVM->hm.s.fNestedPaging)
3768 {
3769 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3770 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3771 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3772 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3773 }
3774
3775 /* Use TPR shadowing if supported by the CPU. */
3776 if ( PDMHasApic(pVM)
3777 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
3778 {
3779 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3780 /* CR8 writes cause a VM-exit based on TPR threshold. */
3781 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3782 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3783 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3784 }
3785 else
3786 {
3787 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3788 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3789 if (pVM->hm.s.fAllow64BitGuests)
3790 {
3791 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3792 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3793 }
3794 }
3795
3796 /* Use MSR-bitmaps if supported by the CPU. */
3797 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3798 {
3799 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3800 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3801 }
3802
3803 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3804 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3805 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3806
3807 if ((fVal & fZap) != fVal)
3808 {
3809 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3810 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3811 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3812 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3813 }
3814
3815 /* Commit it to the VMCS and update our cache. */
3816 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3817 AssertRC(rc);
3818 pVmcsInfo->u32ProcCtls = fVal;
3819
3820 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3821 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3822 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3823
3824 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3825 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3826 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3827
3828 /* Sanity check, should not really happen. */
3829 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3830 { /* likely */ }
3831 else
3832 {
3833 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3834 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3835 }
3836
3837 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3838 return VINF_SUCCESS;
3839}
3840
3841
3842/**
3843 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3844 * Processor-based VM-execution) control fields in the VMCS.
3845 *
3846 * @returns VBox status code.
3847 * @param pVCpu The cross context virtual CPU structure.
3848 * @param pVmcsInfo The VMCS info. object.
3849 */
3850static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3851{
3852#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3853 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3854 {
3855 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3856 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3857 }
3858#endif
3859
3860 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3861 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3862 AssertRC(rc);
3863
3864 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3865 if (RT_SUCCESS(rc))
3866 {
3867 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3868 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3869
3870 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
3871 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
3872
3873 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3874 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3875 return VINF_SUCCESS;
3876 }
3877 else
3878 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3879 return rc;
3880}
3881
3882
3883/**
3884 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3885 *
3886 * We shall setup those exception intercepts that don't change during the
3887 * lifetime of the VM here. The rest are done dynamically while loading the
3888 * guest state.
3889 *
3890 * @param pVCpu The cross context virtual CPU structure.
3891 * @param pVmcsInfo The VMCS info. object.
3892 */
3893static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3894{
3895 /*
3896 * The following exceptions are always intercepted:
3897 *
3898 * #AC - To prevent the guest from hanging the CPU.
3899 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3900 * recursive #DBs can cause a CPU hang.
3901 * #PF - To sync our shadow page tables when nested-paging is not used.
3902 */
3903 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3904 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3905 | RT_BIT(X86_XCPT_DB)
3906 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3907
3908 /* Commit it to the VMCS. */
3909 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3910 AssertRC(rc);
3911
3912 /* Update our cache of the exception bitmap. */
3913 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3914}
3915
3916
3917#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3918/**
3919 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3920 *
3921 * @returns VBox status code.
3922 * @param pVCpu The cross context virtual CPU structure.
3923 * @param pVmcsInfo The VMCS info. object.
3924 */
3925static int hmR0VmxSetupVmcsCtlsNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3926{
3927 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3928 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3929 AssertRC(rc);
3930
3931 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3932 if (RT_SUCCESS(rc))
3933 {
3934 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3935 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3936
3937 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
3938 Assert(!pVmcsInfo->u64Cr0Mask);
3939 Assert(!pVmcsInfo->u64Cr4Mask);
3940 return VINF_SUCCESS;
3941 }
3942 else
3943 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
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(PVMCPUCC 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 PVMCC 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 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
3992#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3993 /*
3994 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
3995 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
3996 * making it fit for use when VMCS shadowing is later enabled.
3997 */
3998 if (pVmcsInfo->pvShadowVmcs)
3999 {
4000 VMXVMCSREVID VmcsRevId;
4001 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4002 VmcsRevId.n.fIsShadowVmcs = 1;
4003 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4004 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4005 if (RT_SUCCESS(rc))
4006 { /* likely */ }
4007 else
4008 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4009 }
4010#endif
4011 }
4012 else
4013 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4014 }
4015 else
4016 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4017 }
4018 else
4019 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4020 }
4021 else
4022 {
4023#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4024 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4025 if (RT_SUCCESS(rc))
4026 { /* likely */ }
4027 else
4028 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4029#else
4030 AssertFailed();
4031#endif
4032 }
4033 }
4034 else
4035 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4036 }
4037 else
4038 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4039
4040 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4041 if (RT_SUCCESS(rc))
4042 {
4043 rc = hmR0VmxClearVmcs(pVmcsInfo);
4044 if (RT_SUCCESS(rc))
4045 { /* likely */ }
4046 else
4047 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4048 }
4049
4050 /*
4051 * Update the last-error record both for failures and success, so we
4052 * can propagate the status code back to ring-3 for diagnostics.
4053 */
4054 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4055 NOREF(pszVmcs);
4056 return rc;
4057}
4058
4059
4060/**
4061 * Does global VT-x initialization (called during module initialization).
4062 *
4063 * @returns VBox status code.
4064 */
4065VMMR0DECL(int) VMXR0GlobalInit(void)
4066{
4067#ifdef HMVMX_USE_FUNCTION_TABLE
4068 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4069# ifdef VBOX_STRICT
4070 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4071 Assert(g_apfnVMExitHandlers[i]);
4072# endif
4073#endif
4074 return VINF_SUCCESS;
4075}
4076
4077
4078/**
4079 * Does global VT-x termination (called during module termination).
4080 */
4081VMMR0DECL(void) VMXR0GlobalTerm()
4082{
4083 /* Nothing to do currently. */
4084}
4085
4086
4087/**
4088 * Sets up and activates VT-x on the current CPU.
4089 *
4090 * @returns VBox status code.
4091 * @param pHostCpu The HM physical-CPU structure.
4092 * @param pVM The cross context VM structure. Can be
4093 * NULL after a host resume operation.
4094 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4095 * fEnabledByHost is @c true).
4096 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4097 * @a fEnabledByHost is @c true).
4098 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4099 * enable VT-x on the host.
4100 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4101 */
4102VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4103 PCSUPHWVIRTMSRS pHwvirtMsrs)
4104{
4105 AssertPtr(pHostCpu);
4106 AssertPtr(pHwvirtMsrs);
4107 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4108
4109 /* Enable VT-x if it's not already enabled by the host. */
4110 if (!fEnabledByHost)
4111 {
4112 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4113 if (RT_FAILURE(rc))
4114 return rc;
4115 }
4116
4117 /*
4118 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4119 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4120 * invalidated when flushing by VPID.
4121 */
4122 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4123 {
4124 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4125 pHostCpu->fFlushAsidBeforeUse = false;
4126 }
4127 else
4128 pHostCpu->fFlushAsidBeforeUse = true;
4129
4130 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4131 ++pHostCpu->cTlbFlushes;
4132
4133 return VINF_SUCCESS;
4134}
4135
4136
4137/**
4138 * Deactivates VT-x on the current CPU.
4139 *
4140 * @returns VBox status code.
4141 * @param pHostCpu The HM physical-CPU structure.
4142 * @param pvCpuPage Pointer to the VMXON region.
4143 * @param HCPhysCpuPage Physical address of the VMXON region.
4144 *
4145 * @remarks This function should never be called when SUPR0EnableVTx() or
4146 * similar was used to enable VT-x on the host.
4147 */
4148VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4149{
4150 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4151
4152 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4153 return hmR0VmxLeaveRootMode(pHostCpu);
4154}
4155
4156
4157/**
4158 * Does per-VM VT-x initialization.
4159 *
4160 * @returns VBox status code.
4161 * @param pVM The cross context VM structure.
4162 */
4163VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4164{
4165 AssertPtr(pVM);
4166 LogFlowFunc(("pVM=%p\n", pVM));
4167
4168 hmR0VmxStructsInit(pVM);
4169 int rc = hmR0VmxStructsAlloc(pVM);
4170 if (RT_FAILURE(rc))
4171 {
4172 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4173 return rc;
4174 }
4175
4176 /* Setup the crash dump page. */
4177#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4178 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
4179 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
4180#endif
4181 return VINF_SUCCESS;
4182}
4183
4184
4185/**
4186 * Does per-VM VT-x termination.
4187 *
4188 * @returns VBox status code.
4189 * @param pVM The cross context VM structure.
4190 */
4191VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4192{
4193 AssertPtr(pVM);
4194 LogFlowFunc(("pVM=%p\n", pVM));
4195
4196#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4197 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4198 {
4199 Assert(pVM->hm.s.vmx.pvScratch);
4200 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4201 }
4202#endif
4203 hmR0VmxStructsFree(pVM);
4204 return VINF_SUCCESS;
4205}
4206
4207
4208/**
4209 * Sets up the VM for execution using hardware-assisted VMX.
4210 * This function is only called once per-VM during initialization.
4211 *
4212 * @returns VBox status code.
4213 * @param pVM The cross context VM structure.
4214 */
4215VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4216{
4217 AssertPtr(pVM);
4218 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4219
4220 LogFlowFunc(("pVM=%p\n", pVM));
4221
4222 /*
4223 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4224 * without causing a #GP.
4225 */
4226 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4227 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4228 { /* likely */ }
4229 else
4230 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4231
4232 /*
4233 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4234 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4235 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4236 */
4237 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4238 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4239 || !pVM->hm.s.vmx.pRealModeTSS))
4240 {
4241 LogRelFunc(("Invalid real-on-v86 state.\n"));
4242 return VERR_INTERNAL_ERROR;
4243 }
4244
4245 /* Initialize these always, see hmR3InitFinalizeR0().*/
4246 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4247 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4248
4249 /* Setup the tagged-TLB flush handlers. */
4250 int rc = hmR0VmxSetupTaggedTlb(pVM);
4251 if (RT_FAILURE(rc))
4252 {
4253 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4254 return rc;
4255 }
4256
4257#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4258 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4259 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4260 {
4261 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4262 if (RT_SUCCESS(rc))
4263 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4264 else
4265 {
4266 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4267 return rc;
4268 }
4269 }
4270#endif
4271
4272 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4273 {
4274 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4275 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4276
4277 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4278 if (RT_SUCCESS(rc))
4279 {
4280#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4281 if (pVM->cpum.ro.GuestFeatures.fVmx)
4282 {
4283 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4284 if (RT_SUCCESS(rc))
4285 { /* likely */ }
4286 else
4287 {
4288 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4289 return rc;
4290 }
4291 }
4292#endif
4293 }
4294 else
4295 {
4296 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4297 return rc;
4298 }
4299 }
4300
4301 return VINF_SUCCESS;
4302}
4303
4304
4305/**
4306 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4307 * the VMCS.
4308 */
4309static void hmR0VmxExportHostControlRegs(void)
4310{
4311 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4312 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4313 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, ASMGetCR4()); AssertRC(rc);
4314}
4315
4316
4317/**
4318 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4319 * the host-state area in the VMCS.
4320 *
4321 * @returns VBox status code.
4322 * @param pVCpu The cross context virtual CPU structure.
4323 */
4324static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu)
4325{
4326/**
4327 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4328 * requirements. See hmR0VmxExportHostSegmentRegs().
4329 */
4330#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_selValue) \
4331 if ((a_selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4332 { \
4333 bool fValidSelector = true; \
4334 if ((a_selValue) & X86_SEL_LDT) \
4335 { \
4336 uint32_t const uAttr = ASMGetSegAttr(a_selValue); \
4337 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4338 } \
4339 if (fValidSelector) \
4340 { \
4341 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4342 pVCpu->hm.s.vmx.RestoreHost.uHostSel##a_Seg = (a_selValue); \
4343 } \
4344 (a_selValue) = 0; \
4345 }
4346
4347 /*
4348 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4349 * will be messed up. We should -not- save the messed up state without restoring
4350 * the original host-state, see @bugref{7240}.
4351 *
4352 * This apparently can happen (most likely the FPU changes), deal with it rather than
4353 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4354 */
4355 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4356 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4357 {
4358 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4359 pVCpu->idCpu));
4360 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4361 }
4362 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4363
4364 /*
4365 * Host segment registers.
4366 */
4367 RTSEL uSelES = ASMGetES();
4368 RTSEL uSelCS = ASMGetCS();
4369 RTSEL uSelSS = ASMGetSS();
4370 RTSEL uSelDS = ASMGetDS();
4371 RTSEL uSelFS = ASMGetFS();
4372 RTSEL uSelGS = ASMGetGS();
4373 RTSEL uSelTR = ASMGetTR();
4374
4375 /*
4376 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4377 * gain VM-entry and restore them before we get preempted.
4378 *
4379 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4380 */
4381 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4382 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4383 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4384 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4385
4386 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4387 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4388 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4389 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4390 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4391 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4392 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4393 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4394 Assert(uSelCS);
4395 Assert(uSelTR);
4396
4397 /* Write these host selector fields into the host-state area in the VMCS. */
4398 int rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, uSelCS); AssertRC(rc);
4399 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, uSelSS); AssertRC(rc);
4400 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4401 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4402 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4403 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4404 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, uSelTR); AssertRC(rc);
4405
4406 /*
4407 * Host GDTR and IDTR.
4408 */
4409 RTGDTR Gdtr;
4410 RTIDTR Idtr;
4411 RT_ZERO(Gdtr);
4412 RT_ZERO(Idtr);
4413 ASMGetGDTR(&Gdtr);
4414 ASMGetIDTR(&Idtr);
4415 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt); AssertRC(rc);
4416 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt); AssertRC(rc);
4417
4418 /*
4419 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4420 * them to the maximum limit (0xffff) on every VM-exit.
4421 */
4422 if (Gdtr.cbGdt != 0xffff)
4423 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4424
4425 /*
4426 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4427 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4428 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4429 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4430 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4431 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4432 * at 0xffff on hosts where we are sure it won't cause trouble.
4433 */
4434#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4435 if (Idtr.cbIdt < 0x0fff)
4436#else
4437 if (Idtr.cbIdt != 0xffff)
4438#endif
4439 {
4440 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4441 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4442 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4443 }
4444
4445 /*
4446 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4447 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4448 * RPL should be too in most cases.
4449 */
4450 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4451 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4452
4453 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4454 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4455
4456 /*
4457 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4458 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4459 * restoration if the host has something else. Task switching is not supported in 64-bit
4460 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4461 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4462 *
4463 * [1] See Intel spec. 3.5 "System Descriptor Types".
4464 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4465 */
4466 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4467 Assert(pDesc->System.u4Type == 11);
4468 if ( pDesc->System.u16LimitLow != 0x67
4469 || pDesc->System.u4LimitHigh)
4470 {
4471 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4472 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4473 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4474 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4475 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4476 }
4477
4478 /*
4479 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4480 */
4481 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4482 {
4483 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4484 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4485 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4486 {
4487 /* The GDT is read-only but the writable GDT is available. */
4488 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4489 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4490 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4491 AssertRCReturn(rc, rc);
4492 }
4493 }
4494
4495 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase);
4496 AssertRC(rc);
4497
4498 /*
4499 * Host FS base and GS base.
4500 */
4501 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4502 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4503 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, u64FSBase); AssertRC(rc);
4504 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, u64GSBase); AssertRC(rc);
4505
4506 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4507 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4508 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4509 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4510 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4511
4512 return VINF_SUCCESS;
4513#undef VMXLOCAL_ADJUST_HOST_SEG
4514}
4515
4516
4517/**
4518 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4519 * host-state area of the VMCS.
4520 *
4521 * These MSRs will be automatically restored on the host after every successful
4522 * VM-exit.
4523 *
4524 * @param pVCpu The cross context virtual CPU structure.
4525 *
4526 * @remarks No-long-jump zone!!!
4527 */
4528static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4529{
4530 AssertPtr(pVCpu);
4531
4532 /*
4533 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4534 * rather than swapping them on every VM-entry.
4535 */
4536 hmR0VmxLazySaveHostMsrs(pVCpu);
4537
4538 /*
4539 * Host Sysenter MSRs.
4540 */
4541 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4542 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4543 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4544
4545 /*
4546 * Host EFER MSR.
4547 *
4548 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4549 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4550 */
4551 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4552 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4553 {
4554 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4555 AssertRC(rc);
4556 }
4557
4558 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4559 * hmR0VmxExportGuestEntryExitCtls(). */
4560}
4561
4562
4563/**
4564 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4565 *
4566 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4567 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4568 *
4569 * @returns true if we need to load guest EFER, false otherwise.
4570 * @param pVCpu The cross context virtual CPU structure.
4571 * @param pVmxTransient The VMX-transient structure.
4572 *
4573 * @remarks Requires EFER, CR4.
4574 * @remarks No-long-jump zone!!!
4575 */
4576static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4577{
4578#ifdef HMVMX_ALWAYS_SWAP_EFER
4579 RT_NOREF2(pVCpu, pVmxTransient);
4580 return true;
4581#else
4582 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4583 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4584 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4585 uint64_t const u64GuestEfer = pCtx->msrEFER;
4586
4587# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4588 /*
4589 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4590 * the nested-guest.
4591 */
4592 if ( pVmxTransient->fIsNestedGuest
4593 && ( CPUMIsGuestVmxEntryCtlsSet(pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4594 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4595 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4596 return true;
4597# else
4598 RT_NOREF(pVmxTransient);
4599#endif
4600
4601 /*
4602 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4603 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4604 */
4605 if ( CPUMIsGuestInLongModeEx(pCtx)
4606 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4607 return true;
4608
4609 /*
4610 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4611 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4612 *
4613 * See Intel spec. 4.5 "IA-32e Paging".
4614 * See Intel spec. 4.1.1 "Three Paging Modes".
4615 *
4616 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4617 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4618 */
4619 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4620 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4621 if ( (pCtx->cr4 & X86_CR4_PAE)
4622 && (pCtx->cr0 & X86_CR0_PG))
4623 {
4624 /*
4625 * If nested paging is not used, verify that the guest paging mode matches the
4626 * shadow paging mode which is/will be placed in the VMCS (which is what will
4627 * actually be used while executing the guest and not the CR4 shadow value).
4628 */
4629 AssertMsg(pVM->hm.s.fNestedPaging || ( pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4630 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4631 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4632 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX),
4633 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4634 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4635 {
4636 /* Verify that the host is NX capable. */
4637 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4638 return true;
4639 }
4640 }
4641
4642 return false;
4643#endif
4644}
4645
4646
4647/**
4648 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4649 * VMCS.
4650 *
4651 * This is typically required when the guest changes paging mode.
4652 *
4653 * @returns VBox status code.
4654 * @param pVCpu The cross context virtual CPU structure.
4655 * @param pVmxTransient The VMX-transient structure.
4656 *
4657 * @remarks Requires EFER.
4658 * @remarks No-long-jump zone!!!
4659 */
4660static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4661{
4662 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4663 {
4664 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4665 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4666 bool const fGstInLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
4667
4668 /*
4669 * VMRUN function.
4670 * If the guest is in long mode, use the 64-bit guest handler, else the 32-bit guest handler.
4671 * The host is always 64-bit since we no longer support 32-bit hosts.
4672 */
4673 if (fGstInLongMode)
4674 {
4675#ifndef VBOX_WITH_64_BITS_GUESTS
4676 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
4677#else
4678 Assert(pVM->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
4679 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
4680#endif
4681 }
4682 else
4683 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
4684
4685 /*
4686 * VM-entry controls.
4687 */
4688 {
4689 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4690 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4691
4692 /*
4693 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4694 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4695 *
4696 * For nested-guests, this is a mandatory VM-entry control. It's also
4697 * required because we do not want to leak host bits to the nested-guest.
4698 */
4699 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4700
4701 /*
4702 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4703 *
4704 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4705 * required to get the nested-guest working with hardware-assisted VMX execution.
4706 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
4707 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4708 * here rather than while merging the guest VMCS controls.
4709 */
4710 if (fGstInLongMode)
4711 {
4712 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
4713 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4714 }
4715 else
4716 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4717
4718 /*
4719 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4720 *
4721 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4722 * regardless of whether the nested-guest VMCS specifies it because we are free to
4723 * load whatever MSRs we require and we do not need to modify the guest visible copy
4724 * of the VM-entry MSR load area.
4725 */
4726 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4727 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4728 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4729 else
4730 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4731
4732 /*
4733 * The following should -not- be set (since we're not in SMM mode):
4734 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4735 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4736 */
4737
4738 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4739 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4740
4741 if ((fVal & fZap) == fVal)
4742 { /* likely */ }
4743 else
4744 {
4745 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4746 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4747 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4748 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4749 }
4750
4751 /* Commit it to the VMCS. */
4752 if (pVmcsInfo->u32EntryCtls != fVal)
4753 {
4754 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4755 AssertRC(rc);
4756 pVmcsInfo->u32EntryCtls = fVal;
4757 }
4758 }
4759
4760 /*
4761 * VM-exit controls.
4762 */
4763 {
4764 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4765 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4766
4767 /*
4768 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4769 * supported the 1-setting of this bit.
4770 *
4771 * For nested-guests, we set the "save debug controls" as the converse
4772 * "load debug controls" is mandatory for nested-guests anyway.
4773 */
4774 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4775
4776 /*
4777 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4778 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4779 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4780 * hmR0VmxExportHostMsrs().
4781 *
4782 * For nested-guests, we always set this bit as we do not support 32-bit
4783 * hosts.
4784 */
4785 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4786
4787 /*
4788 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4789 *
4790 * For nested-guests, we should use the "save IA32_EFER" control if we also
4791 * used the "load IA32_EFER" control while exporting VM-entry controls.
4792 */
4793 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4794 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4795 {
4796 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4797 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4798 }
4799
4800 /*
4801 * Enable saving of the VMX-preemption timer value on VM-exit.
4802 * For nested-guests, currently not exposed/used.
4803 */
4804 if ( pVM->hm.s.vmx.fUsePreemptTimer
4805 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4806 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4807
4808 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4809 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4810
4811 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
4812 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
4813 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
4814
4815 if ((fVal & fZap) == fVal)
4816 { /* likely */ }
4817 else
4818 {
4819 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
4820 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
4821 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
4822 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4823 }
4824
4825 /* Commit it to the VMCS. */
4826 if (pVmcsInfo->u32ExitCtls != fVal)
4827 {
4828 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
4829 AssertRC(rc);
4830 pVmcsInfo->u32ExitCtls = fVal;
4831 }
4832 }
4833
4834 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
4835 }
4836 return VINF_SUCCESS;
4837}
4838
4839
4840/**
4841 * Sets the TPR threshold in the VMCS.
4842 *
4843 * @param pVmcsInfo The VMCS info. object.
4844 * @param u32TprThreshold The TPR threshold (task-priority class only).
4845 */
4846DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
4847{
4848 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
4849 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
4850 RT_NOREF(pVmcsInfo);
4851 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
4852 AssertRC(rc);
4853}
4854
4855
4856/**
4857 * Exports the guest APIC TPR state into the VMCS.
4858 *
4859 * @param pVCpu The cross context virtual CPU structure.
4860 * @param pVmxTransient The VMX-transient structure.
4861 *
4862 * @remarks No-long-jump zone!!!
4863 */
4864static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4865{
4866 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
4867 {
4868 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
4869
4870 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4871 if (!pVmxTransient->fIsNestedGuest)
4872 {
4873 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
4874 && APICIsEnabled(pVCpu))
4875 {
4876 /*
4877 * Setup TPR shadowing.
4878 */
4879 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
4880 {
4881 bool fPendingIntr = false;
4882 uint8_t u8Tpr = 0;
4883 uint8_t u8PendingIntr = 0;
4884 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
4885 AssertRC(rc);
4886
4887 /*
4888 * If there are interrupts pending but masked by the TPR, instruct VT-x to
4889 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
4890 * priority of the pending interrupt so we can deliver the interrupt. If there
4891 * are no interrupts pending, set threshold to 0 to not cause any
4892 * TPR-below-threshold VM-exits.
4893 */
4894 uint32_t u32TprThreshold = 0;
4895 if (fPendingIntr)
4896 {
4897 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
4898 (which is the Task-Priority Class). */
4899 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
4900 const uint8_t u8TprPriority = u8Tpr >> 4;
4901 if (u8PendingPriority <= u8TprPriority)
4902 u32TprThreshold = u8PendingPriority;
4903 }
4904
4905 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
4906 }
4907 }
4908 }
4909 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
4910 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
4911 }
4912}
4913
4914
4915/**
4916 * Gets the guest interruptibility-state.
4917 *
4918 * @returns Guest's interruptibility-state.
4919 * @param pVCpu The cross context virtual CPU structure.
4920 *
4921 * @remarks No-long-jump zone!!!
4922 */
4923static uint32_t hmR0VmxGetGuestIntrState(PVMCPUCC pVCpu)
4924{
4925 /*
4926 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
4927 */
4928 uint32_t fIntrState = 0;
4929 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4930 {
4931 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
4932 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
4933
4934 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4935 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
4936 {
4937 if (pCtx->eflags.Bits.u1IF)
4938 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
4939 else
4940 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
4941 }
4942 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4943 {
4944 /*
4945 * We can clear the inhibit force flag as even if we go back to the recompiler
4946 * without executing guest code in VT-x, the flag's condition to be cleared is
4947 * met and thus the cleared state is correct.
4948 */
4949 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
4950 }
4951 }
4952
4953 /*
4954 * Check if we should inhibit NMI delivery.
4955 */
4956 if (CPUMIsGuestNmiBlocking(pVCpu))
4957 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
4958
4959 /*
4960 * Validate.
4961 */
4962#ifdef VBOX_STRICT
4963 /* We don't support block-by-SMI yet.*/
4964 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
4965
4966 /* Block-by-STI must not be set when interrupts are disabled. */
4967 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
4968 {
4969 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
4970 Assert(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_IF);
4971 }
4972#endif
4973
4974 return fIntrState;
4975}
4976
4977
4978/**
4979 * Exports the exception intercepts required for guest execution in the VMCS.
4980 *
4981 * @param pVCpu The cross context virtual CPU structure.
4982 * @param pVmxTransient The VMX-transient structure.
4983 *
4984 * @remarks No-long-jump zone!!!
4985 */
4986static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4987{
4988 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
4989 {
4990 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
4991 if ( !pVmxTransient->fIsNestedGuest
4992 && pVCpu->hm.s.fGIMTrapXcptUD)
4993 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
4994 else
4995 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
4996
4997 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
4998 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
4999 }
5000}
5001
5002
5003/**
5004 * Exports the guest's RIP into the guest-state area in the VMCS.
5005 *
5006 * @param pVCpu The cross context virtual CPU structure.
5007 *
5008 * @remarks No-long-jump zone!!!
5009 */
5010static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5011{
5012 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5013 {
5014 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5015
5016 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5017 AssertRC(rc);
5018
5019 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5020 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5021 }
5022}
5023
5024
5025/**
5026 * Exports the guest's RSP into the guest-state area in the VMCS.
5027 *
5028 * @param pVCpu The cross context virtual CPU structure.
5029 *
5030 * @remarks No-long-jump zone!!!
5031 */
5032static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5033{
5034 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5035 {
5036 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5037
5038 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5039 AssertRC(rc);
5040
5041 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5042 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5043 }
5044}
5045
5046
5047/**
5048 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5049 *
5050 * @param pVCpu The cross context virtual CPU structure.
5051 * @param pVmxTransient The VMX-transient structure.
5052 *
5053 * @remarks No-long-jump zone!!!
5054 */
5055static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5056{
5057 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5058 {
5059 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5060
5061 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5062 Let us assert it as such and use 32-bit VMWRITE. */
5063 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5064 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5065 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5066 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5067
5068 /*
5069 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5070 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5071 * can run the real-mode guest code under Virtual 8086 mode.
5072 */
5073 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5074 if (pVmcsInfo->RealMode.fRealOnV86Active)
5075 {
5076 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5077 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5078 Assert(!pVmxTransient->fIsNestedGuest);
5079 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5080 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5081 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5082 }
5083
5084 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5085 AssertRC(rc);
5086
5087 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5088 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5089 }
5090}
5091
5092
5093#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5094/**
5095 * Copies the nested-guest VMCS to the shadow VMCS.
5096 *
5097 * @returns VBox status code.
5098 * @param pVCpu The cross context virtual CPU structure.
5099 * @param pVmcsInfo The VMCS info. object.
5100 *
5101 * @remarks No-long-jump zone!!!
5102 */
5103static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5104{
5105 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5106 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5107
5108 /*
5109 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5110 * current VMCS, as we may try saving guest lazy MSRs.
5111 *
5112 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5113 * calling the import VMCS code which is currently performing the guest MSR reads
5114 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5115 * and the rest of the VMX leave session machinery.
5116 */
5117 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5118
5119 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5120 if (RT_SUCCESS(rc))
5121 {
5122 /*
5123 * Copy all guest read/write VMCS fields.
5124 *
5125 * We don't check for VMWRITE failures here for performance reasons and
5126 * because they are not expected to fail, barring irrecoverable conditions
5127 * like hardware errors.
5128 */
5129 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5130 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5131 {
5132 uint64_t u64Val;
5133 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5134 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5135 VMXWriteVmcs64(uVmcsField, u64Val);
5136 }
5137
5138 /*
5139 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5140 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5141 */
5142 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5143 {
5144 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5145 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5146 {
5147 uint64_t u64Val;
5148 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5149 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5150 VMXWriteVmcs64(uVmcsField, u64Val);
5151 }
5152 }
5153
5154 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5155 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5156 }
5157
5158 ASMSetFlags(fEFlags);
5159 return rc;
5160}
5161
5162
5163/**
5164 * Copies the shadow VMCS to the nested-guest VMCS.
5165 *
5166 * @returns VBox status code.
5167 * @param pVCpu The cross context virtual CPU structure.
5168 * @param pVmcsInfo The VMCS info. object.
5169 *
5170 * @remarks Called with interrupts disabled.
5171 */
5172static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5173{
5174 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5175 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5176 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5177
5178 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5179 if (RT_SUCCESS(rc))
5180 {
5181 /*
5182 * Copy guest read/write fields from the shadow VMCS.
5183 * Guest read-only fields cannot be modified, so no need to copy them.
5184 *
5185 * We don't check for VMREAD failures here for performance reasons and
5186 * because they are not expected to fail, barring irrecoverable conditions
5187 * like hardware errors.
5188 */
5189 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5190 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5191 {
5192 uint64_t u64Val;
5193 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5194 VMXReadVmcs64(uVmcsField, &u64Val);
5195 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5196 }
5197
5198 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5199 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5200 }
5201 return rc;
5202}
5203
5204
5205/**
5206 * Enables VMCS shadowing for the given VMCS info. object.
5207 *
5208 * @param pVmcsInfo The VMCS info. object.
5209 *
5210 * @remarks No-long-jump zone!!!
5211 */
5212static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5213{
5214 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5215 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5216 {
5217 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5218 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5219 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5220 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5221 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5222 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5223 Log4Func(("Enabled\n"));
5224 }
5225}
5226
5227
5228/**
5229 * Disables VMCS shadowing for the given VMCS info. object.
5230 *
5231 * @param pVmcsInfo The VMCS info. object.
5232 *
5233 * @remarks No-long-jump zone!!!
5234 */
5235static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5236{
5237 /*
5238 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5239 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5240 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5241 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5242 *
5243 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5244 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5245 */
5246 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5247 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5248 {
5249 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5250 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5251 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5252 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5253 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5254 Log4Func(("Disabled\n"));
5255 }
5256}
5257#endif
5258
5259
5260/**
5261 * Exports the guest hardware-virtualization state.
5262 *
5263 * @returns VBox status code.
5264 * @param pVCpu The cross context virtual CPU structure.
5265 * @param pVmxTransient The VMX-transient structure.
5266 *
5267 * @remarks No-long-jump zone!!!
5268 */
5269static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5270{
5271 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5272 {
5273#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5274 /*
5275 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5276 * VMCS shadowing.
5277 */
5278 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5279 {
5280 /*
5281 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5282 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5283 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5284 *
5285 * We check for VMX root mode here in case the guest executes VMXOFF without
5286 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5287 * not clear the current VMCS pointer.
5288 */
5289 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5290 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5291 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5292 && CPUMIsGuestVmxCurrentVmcsValid(&pVCpu->cpum.GstCtx))
5293 {
5294 /* Paranoia. */
5295 Assert(!pVmxTransient->fIsNestedGuest);
5296
5297 /*
5298 * For performance reasons, also check if the nested hypervisor's current VMCS
5299 * was newly loaded or modified before copying it to the shadow VMCS.
5300 */
5301 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5302 {
5303 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5304 AssertRCReturn(rc, rc);
5305 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5306 }
5307 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5308 }
5309 else
5310 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5311 }
5312#else
5313 NOREF(pVmxTransient);
5314#endif
5315 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5316 }
5317 return VINF_SUCCESS;
5318}
5319
5320
5321/**
5322 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5323 *
5324 * The guest FPU state is always pre-loaded hence we don't need to bother about
5325 * sharing FPU related CR0 bits between the guest and host.
5326 *
5327 * @returns VBox status code.
5328 * @param pVCpu The cross context virtual CPU structure.
5329 * @param pVmxTransient The VMX-transient structure.
5330 *
5331 * @remarks No-long-jump zone!!!
5332 */
5333static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5334{
5335 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5336 {
5337 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5338 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5339
5340 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
5341 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5342 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5343 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5344 else
5345 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5346
5347 if (!pVmxTransient->fIsNestedGuest)
5348 {
5349 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5350 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5351 uint64_t const u64ShadowCr0 = u64GuestCr0;
5352 Assert(!RT_HI_U32(u64GuestCr0));
5353
5354 /*
5355 * Setup VT-x's view of the guest CR0.
5356 */
5357 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5358 if (pVM->hm.s.fNestedPaging)
5359 {
5360 if (CPUMIsGuestPagingEnabled(pVCpu))
5361 {
5362 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5363 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5364 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5365 }
5366 else
5367 {
5368 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5369 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5370 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5371 }
5372
5373 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5374 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5375 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5376 }
5377 else
5378 {
5379 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5380 u64GuestCr0 |= X86_CR0_WP;
5381 }
5382
5383 /*
5384 * Guest FPU bits.
5385 *
5386 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5387 * using CR0.TS.
5388 *
5389 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5390 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5391 */
5392 u64GuestCr0 |= X86_CR0_NE;
5393
5394 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5395 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5396
5397 /*
5398 * Update exception intercepts.
5399 */
5400 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5401 if (pVmcsInfo->RealMode.fRealOnV86Active)
5402 {
5403 Assert(PDMVmmDevHeapIsEnabled(pVM));
5404 Assert(pVM->hm.s.vmx.pRealModeTSS);
5405 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5406 }
5407 else
5408 {
5409 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5410 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5411 if (fInterceptMF)
5412 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5413 }
5414
5415 /* Additional intercepts for debugging, define these yourself explicitly. */
5416#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5417 uXcptBitmap |= 0
5418 | RT_BIT(X86_XCPT_BP)
5419 | RT_BIT(X86_XCPT_DE)
5420 | RT_BIT(X86_XCPT_NM)
5421 | RT_BIT(X86_XCPT_TS)
5422 | RT_BIT(X86_XCPT_UD)
5423 | RT_BIT(X86_XCPT_NP)
5424 | RT_BIT(X86_XCPT_SS)
5425 | RT_BIT(X86_XCPT_GP)
5426 | RT_BIT(X86_XCPT_PF)
5427 | RT_BIT(X86_XCPT_MF)
5428 ;
5429#elif defined(HMVMX_ALWAYS_TRAP_PF)
5430 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5431#endif
5432 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5433 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5434 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5435
5436 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5437 u64GuestCr0 |= fSetCr0;
5438 u64GuestCr0 &= fZapCr0;
5439 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5440
5441 /* Commit the CR0 and related fields to the guest VMCS. */
5442 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5443 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5444 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5445 {
5446 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5447 AssertRC(rc);
5448 }
5449 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5450 {
5451 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5452 AssertRC(rc);
5453 }
5454
5455 /* Update our caches. */
5456 pVmcsInfo->u32ProcCtls = uProcCtls;
5457 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5458
5459 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5460 }
5461 else
5462 {
5463 /*
5464 * With nested-guests, we may have extended the guest/host mask here since we
5465 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5466 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5467 * originally supplied. We must copy those bits from the nested-guest CR0 into
5468 * the nested-guest CR0 read-shadow.
5469 */
5470 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5471 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5472 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(&pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5473 Assert(!RT_HI_U32(u64GuestCr0));
5474 Assert(u64GuestCr0 & X86_CR0_NE);
5475
5476 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5477 u64GuestCr0 |= fSetCr0;
5478 u64GuestCr0 &= fZapCr0;
5479 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5480
5481 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5482 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5483 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5484
5485 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5486 }
5487
5488 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5489 }
5490
5491 return VINF_SUCCESS;
5492}
5493
5494
5495/**
5496 * Exports the guest control registers (CR3, CR4) into the guest-state area
5497 * in the VMCS.
5498 *
5499 * @returns VBox strict status code.
5500 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5501 * without unrestricted guest access and the VMMDev is not presently
5502 * mapped (e.g. EFI32).
5503 *
5504 * @param pVCpu The cross context virtual CPU structure.
5505 * @param pVmxTransient The VMX-transient structure.
5506 *
5507 * @remarks No-long-jump zone!!!
5508 */
5509static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5510{
5511 int rc = VINF_SUCCESS;
5512 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5513
5514 /*
5515 * Guest CR2.
5516 * It's always loaded in the assembler code. Nothing to do here.
5517 */
5518
5519 /*
5520 * Guest CR3.
5521 */
5522 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5523 {
5524 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5525
5526 if (pVM->hm.s.fNestedPaging)
5527 {
5528 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5529 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5530
5531 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5532 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5533 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5534 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5535
5536 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5537 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5538 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5539
5540 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5541 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5542 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5543 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5544 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5545 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5546 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5547
5548 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5549 AssertRC(rc);
5550
5551 uint64_t u64GuestCr3;
5552 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5553 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5554 || CPUMIsGuestPagingEnabledEx(pCtx))
5555 {
5556 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5557 if (CPUMIsGuestInPAEModeEx(pCtx))
5558 {
5559 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5560 AssertRC(rc);
5561 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5562 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5563 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5564 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5565 }
5566
5567 /*
5568 * The guest's view of its CR3 is unblemished with nested paging when the
5569 * guest is using paging or we have unrestricted guest execution to handle
5570 * the guest when it's not using paging.
5571 */
5572 u64GuestCr3 = pCtx->cr3;
5573 }
5574 else
5575 {
5576 /*
5577 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5578 * thinks it accesses physical memory directly, we use our identity-mapped
5579 * page table to map guest-linear to guest-physical addresses. EPT takes care
5580 * of translating it to host-physical addresses.
5581 */
5582 RTGCPHYS GCPhys;
5583 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5584
5585 /* We obtain it here every time as the guest could have relocated this PCI region. */
5586 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5587 if (RT_SUCCESS(rc))
5588 { /* likely */ }
5589 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5590 {
5591 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5592 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5593 }
5594 else
5595 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5596
5597 u64GuestCr3 = GCPhys;
5598 }
5599
5600 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5601 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5602 AssertRC(rc);
5603 }
5604 else
5605 {
5606 Assert(!pVmxTransient->fIsNestedGuest);
5607 /* Non-nested paging case, just use the hypervisor's CR3. */
5608 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5609
5610 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5611 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5612 AssertRC(rc);
5613 }
5614
5615 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5616 }
5617
5618 /*
5619 * Guest CR4.
5620 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5621 */
5622 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5623 {
5624 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5625 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5626
5627 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
5628 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5629
5630 /*
5631 * With nested-guests, we may have extended the guest/host mask here (since we
5632 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5633 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5634 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5635 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5636 */
5637 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5638 uint64_t u64GuestCr4 = pCtx->cr4;
5639 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5640 ? pCtx->cr4
5641 : CPUMGetGuestVmxMaskedCr4(pCtx, pVmcsInfo->u64Cr4Mask);
5642 Assert(!RT_HI_U32(u64GuestCr4));
5643
5644 /*
5645 * Setup VT-x's view of the guest CR4.
5646 *
5647 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5648 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5649 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5650 *
5651 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5652 */
5653 if (pVmcsInfo->RealMode.fRealOnV86Active)
5654 {
5655 Assert(pVM->hm.s.vmx.pRealModeTSS);
5656 Assert(PDMVmmDevHeapIsEnabled(pVM));
5657 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5658 }
5659
5660 if (pVM->hm.s.fNestedPaging)
5661 {
5662 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5663 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5664 {
5665 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5666 u64GuestCr4 |= X86_CR4_PSE;
5667 /* Our identity mapping is a 32-bit page directory. */
5668 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5669 }
5670 /* else use guest CR4.*/
5671 }
5672 else
5673 {
5674 Assert(!pVmxTransient->fIsNestedGuest);
5675
5676 /*
5677 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5678 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5679 */
5680 switch (pVCpu->hm.s.enmShadowMode)
5681 {
5682 case PGMMODE_REAL: /* Real-mode. */
5683 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5684 case PGMMODE_32_BIT: /* 32-bit paging. */
5685 {
5686 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5687 break;
5688 }
5689
5690 case PGMMODE_PAE: /* PAE paging. */
5691 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5692 {
5693 u64GuestCr4 |= X86_CR4_PAE;
5694 break;
5695 }
5696
5697 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5698 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5699 {
5700#ifdef VBOX_WITH_64_BITS_GUESTS
5701 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
5702 Assert(u64GuestCr4 & X86_CR4_PAE);
5703 break;
5704#endif
5705 }
5706 default:
5707 AssertFailed();
5708 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5709 }
5710 }
5711
5712 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
5713 u64GuestCr4 |= fSetCr4;
5714 u64GuestCr4 &= fZapCr4;
5715
5716 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
5717 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
5718 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
5719
5720 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5721 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5722
5723 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5724
5725 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5726 }
5727 return rc;
5728}
5729
5730
5731/**
5732 * Exports the guest debug registers into the guest-state area in the VMCS.
5733 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5734 *
5735 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5736 *
5737 * @returns VBox status code.
5738 * @param pVCpu The cross context virtual CPU structure.
5739 * @param pVmxTransient The VMX-transient structure.
5740 *
5741 * @remarks No-long-jump zone!!!
5742 */
5743static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5744{
5745 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5746
5747 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5748 * stepping. */
5749 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5750 if (pVmxTransient->fIsNestedGuest)
5751 {
5752 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5753 AssertRC(rc);
5754
5755 /* Always intercept Mov DRx accesses for the nested-guest for now. */
5756 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5757 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
5758 AssertRC(rc);
5759 return VINF_SUCCESS;
5760 }
5761
5762#ifdef VBOX_STRICT
5763 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5764 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5765 {
5766 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5767 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5768 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5769 }
5770#endif
5771
5772 bool fSteppingDB = false;
5773 bool fInterceptMovDRx = false;
5774 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5775 if (pVCpu->hm.s.fSingleInstruction)
5776 {
5777 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5778 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5779 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5780 {
5781 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5782 Assert(fSteppingDB == false);
5783 }
5784 else
5785 {
5786 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5787 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5788 pVCpu->hm.s.fClearTrapFlag = true;
5789 fSteppingDB = true;
5790 }
5791 }
5792
5793 uint64_t u64GuestDr7;
5794 if ( fSteppingDB
5795 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5796 {
5797 /*
5798 * Use the combined guest and host DRx values found in the hypervisor register set
5799 * because the hypervisor debugger has breakpoints active or someone is single stepping
5800 * on the host side without a monitor trap flag.
5801 *
5802 * Note! DBGF expects a clean DR6 state before executing guest code.
5803 */
5804 if (!CPUMIsHyperDebugStateActive(pVCpu))
5805 {
5806 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5807 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5808 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5809 }
5810
5811 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
5812 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
5813 pVCpu->hm.s.fUsingHyperDR7 = true;
5814 fInterceptMovDRx = true;
5815 }
5816 else
5817 {
5818 /*
5819 * If the guest has enabled debug registers, we need to load them prior to
5820 * executing guest code so they'll trigger at the right time.
5821 */
5822 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
5823 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
5824 {
5825 if (!CPUMIsGuestDebugStateActive(pVCpu))
5826 {
5827 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
5828 Assert(CPUMIsGuestDebugStateActive(pVCpu));
5829 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
5830 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
5831 }
5832 Assert(!fInterceptMovDRx);
5833 }
5834 else if (!CPUMIsGuestDebugStateActive(pVCpu))
5835 {
5836 /*
5837 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
5838 * must intercept #DB in order to maintain a correct DR6 guest value, and
5839 * because we need to intercept it to prevent nested #DBs from hanging the
5840 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
5841 */
5842 fInterceptMovDRx = true;
5843 }
5844
5845 /* Update DR7 with the actual guest value. */
5846 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
5847 pVCpu->hm.s.fUsingHyperDR7 = false;
5848 }
5849
5850 if (fInterceptMovDRx)
5851 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5852 else
5853 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
5854
5855 /*
5856 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
5857 * monitor-trap flag and update our cache.
5858 */
5859 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5860 {
5861 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5862 AssertRC(rc);
5863 pVmcsInfo->u32ProcCtls = uProcCtls;
5864 }
5865
5866 /*
5867 * Update guest DR7.
5868 */
5869 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
5870 AssertRC(rc);
5871
5872 /*
5873 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
5874 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
5875 *
5876 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5877 */
5878 if (fSteppingDB)
5879 {
5880 Assert(pVCpu->hm.s.fSingleInstruction);
5881 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
5882
5883 uint32_t fIntrState = 0;
5884 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
5885 AssertRC(rc);
5886
5887 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
5888 {
5889 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
5890 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
5891 AssertRC(rc);
5892 }
5893 }
5894
5895 return VINF_SUCCESS;
5896}
5897
5898
5899#ifdef VBOX_STRICT
5900/**
5901 * Strict function to validate segment registers.
5902 *
5903 * @param pVCpu The cross context virtual CPU structure.
5904 * @param pVmcsInfo The VMCS info. object.
5905 *
5906 * @remarks Will import guest CR0 on strict builds during validation of
5907 * segments.
5908 */
5909static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5910{
5911 /*
5912 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
5913 *
5914 * The reason we check for attribute value 0 in this function and not just the unusable bit is
5915 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
5916 * unusable bit and doesn't change the guest-context value.
5917 */
5918 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5919 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5920 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
5921 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
5922 && ( !CPUMIsGuestInRealModeEx(pCtx)
5923 && !CPUMIsGuestInV86ModeEx(pCtx)))
5924 {
5925 /* Protected mode checks */
5926 /* CS */
5927 Assert(pCtx->cs.Attr.n.u1Present);
5928 Assert(!(pCtx->cs.Attr.u & 0xf00));
5929 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
5930 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
5931 || !(pCtx->cs.Attr.n.u1Granularity));
5932 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
5933 || (pCtx->cs.Attr.n.u1Granularity));
5934 /* CS cannot be loaded with NULL in protected mode. */
5935 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
5936 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
5937 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
5938 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
5939 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
5940 else
5941 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
5942 /* SS */
5943 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5944 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
5945 if ( !(pCtx->cr0 & X86_CR0_PE)
5946 || pCtx->cs.Attr.n.u4Type == 3)
5947 {
5948 Assert(!pCtx->ss.Attr.n.u2Dpl);
5949 }
5950 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
5951 {
5952 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5953 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
5954 Assert(pCtx->ss.Attr.n.u1Present);
5955 Assert(!(pCtx->ss.Attr.u & 0xf00));
5956 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
5957 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
5958 || !(pCtx->ss.Attr.n.u1Granularity));
5959 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
5960 || (pCtx->ss.Attr.n.u1Granularity));
5961 }
5962 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
5963 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
5964 {
5965 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5966 Assert(pCtx->ds.Attr.n.u1Present);
5967 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
5968 Assert(!(pCtx->ds.Attr.u & 0xf00));
5969 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
5970 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
5971 || !(pCtx->ds.Attr.n.u1Granularity));
5972 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
5973 || (pCtx->ds.Attr.n.u1Granularity));
5974 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5975 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
5976 }
5977 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
5978 {
5979 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5980 Assert(pCtx->es.Attr.n.u1Present);
5981 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
5982 Assert(!(pCtx->es.Attr.u & 0xf00));
5983 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
5984 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
5985 || !(pCtx->es.Attr.n.u1Granularity));
5986 Assert( !(pCtx->es.u32Limit & 0xfff00000)
5987 || (pCtx->es.Attr.n.u1Granularity));
5988 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5989 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
5990 }
5991 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
5992 {
5993 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5994 Assert(pCtx->fs.Attr.n.u1Present);
5995 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
5996 Assert(!(pCtx->fs.Attr.u & 0xf00));
5997 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
5998 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
5999 || !(pCtx->fs.Attr.n.u1Granularity));
6000 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6001 || (pCtx->fs.Attr.n.u1Granularity));
6002 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6003 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6004 }
6005 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6006 {
6007 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6008 Assert(pCtx->gs.Attr.n.u1Present);
6009 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6010 Assert(!(pCtx->gs.Attr.u & 0xf00));
6011 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6012 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6013 || !(pCtx->gs.Attr.n.u1Granularity));
6014 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6015 || (pCtx->gs.Attr.n.u1Granularity));
6016 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6017 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6018 }
6019 /* 64-bit capable CPUs. */
6020 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6021 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6022 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6023 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6024 }
6025 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6026 || ( CPUMIsGuestInRealModeEx(pCtx)
6027 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6028 {
6029 /* Real and v86 mode checks. */
6030 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6031 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6032 if (pVmcsInfo->RealMode.fRealOnV86Active)
6033 {
6034 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6035 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6036 }
6037 else
6038 {
6039 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6040 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6041 }
6042
6043 /* CS */
6044 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6045 Assert(pCtx->cs.u32Limit == 0xffff);
6046 Assert(u32CSAttr == 0xf3);
6047 /* SS */
6048 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6049 Assert(pCtx->ss.u32Limit == 0xffff);
6050 Assert(u32SSAttr == 0xf3);
6051 /* DS */
6052 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6053 Assert(pCtx->ds.u32Limit == 0xffff);
6054 Assert(u32DSAttr == 0xf3);
6055 /* ES */
6056 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6057 Assert(pCtx->es.u32Limit == 0xffff);
6058 Assert(u32ESAttr == 0xf3);
6059 /* FS */
6060 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6061 Assert(pCtx->fs.u32Limit == 0xffff);
6062 Assert(u32FSAttr == 0xf3);
6063 /* GS */
6064 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6065 Assert(pCtx->gs.u32Limit == 0xffff);
6066 Assert(u32GSAttr == 0xf3);
6067 /* 64-bit capable CPUs. */
6068 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6069 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6070 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6071 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6072 }
6073}
6074#endif /* VBOX_STRICT */
6075
6076
6077/**
6078 * Exports a guest segment register into the guest-state area in the VMCS.
6079 *
6080 * @returns VBox status code.
6081 * @param pVCpu The cross context virtual CPU structure.
6082 * @param pVmcsInfo The VMCS info. object.
6083 * @param iSegReg The segment register number (X86_SREG_XXX).
6084 * @param pSelReg Pointer to the segment selector.
6085 *
6086 * @remarks No-long-jump zone!!!
6087 */
6088static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6089{
6090 Assert(iSegReg < X86_SREG_COUNT);
6091 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6092 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6093 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6094 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6095
6096 uint32_t u32Access = pSelReg->Attr.u;
6097 if (pVmcsInfo->RealMode.fRealOnV86Active)
6098 {
6099 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6100 u32Access = 0xf3;
6101 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6102 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6103 RT_NOREF_PV(pVCpu);
6104 }
6105 else
6106 {
6107 /*
6108 * The way to differentiate between whether this is really a null selector or was just
6109 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6110 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6111 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6112 * NULL selectors loaded in protected-mode have their attribute as 0.
6113 */
6114 if (!u32Access)
6115 u32Access = X86DESCATTR_UNUSABLE;
6116 }
6117
6118 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6119 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6120 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6121
6122 /*
6123 * Commit it to the VMCS.
6124 */
6125 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc);
6126 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc);
6127 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc);
6128 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc);
6129 return VINF_SUCCESS;
6130}
6131
6132
6133/**
6134 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6135 * area in the VMCS.
6136 *
6137 * @returns VBox status code.
6138 * @param pVCpu The cross context virtual CPU structure.
6139 * @param pVmxTransient The VMX-transient structure.
6140 *
6141 * @remarks Will import guest CR0 on strict builds during validation of
6142 * segments.
6143 * @remarks No-long-jump zone!!!
6144 */
6145static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6146{
6147 int rc = VERR_INTERNAL_ERROR_5;
6148 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6149 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6150 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6151
6152 /*
6153 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6154 */
6155 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6156 {
6157 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6158 {
6159 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6160 if (pVmcsInfo->RealMode.fRealOnV86Active)
6161 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6162 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6163 AssertRC(rc);
6164 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6165 }
6166
6167 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6168 {
6169 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6170 if (pVmcsInfo->RealMode.fRealOnV86Active)
6171 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6172 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6173 AssertRC(rc);
6174 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6175 }
6176
6177 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6178 {
6179 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6180 if (pVmcsInfo->RealMode.fRealOnV86Active)
6181 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6182 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6183 AssertRC(rc);
6184 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6185 }
6186
6187 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6188 {
6189 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6190 if (pVmcsInfo->RealMode.fRealOnV86Active)
6191 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6192 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6193 AssertRC(rc);
6194 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6195 }
6196
6197 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6198 {
6199 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6200 if (pVmcsInfo->RealMode.fRealOnV86Active)
6201 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6202 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6203 AssertRC(rc);
6204 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6205 }
6206
6207 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6208 {
6209 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6210 if (pVmcsInfo->RealMode.fRealOnV86Active)
6211 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6212 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6213 AssertRC(rc);
6214 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6215 }
6216
6217#ifdef VBOX_STRICT
6218 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6219#endif
6220 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6221 pCtx->cs.Attr.u));
6222 }
6223
6224 /*
6225 * Guest TR.
6226 */
6227 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6228 {
6229 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6230
6231 /*
6232 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6233 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6234 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6235 */
6236 uint16_t u16Sel;
6237 uint32_t u32Limit;
6238 uint64_t u64Base;
6239 uint32_t u32AccessRights;
6240 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6241 {
6242 u16Sel = pCtx->tr.Sel;
6243 u32Limit = pCtx->tr.u32Limit;
6244 u64Base = pCtx->tr.u64Base;
6245 u32AccessRights = pCtx->tr.Attr.u;
6246 }
6247 else
6248 {
6249 Assert(!pVmxTransient->fIsNestedGuest);
6250 Assert(pVM->hm.s.vmx.pRealModeTSS);
6251 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6252
6253 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6254 RTGCPHYS GCPhys;
6255 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6256 AssertRCReturn(rc, rc);
6257
6258 X86DESCATTR DescAttr;
6259 DescAttr.u = 0;
6260 DescAttr.n.u1Present = 1;
6261 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6262
6263 u16Sel = 0;
6264 u32Limit = HM_VTX_TSS_SIZE;
6265 u64Base = GCPhys;
6266 u32AccessRights = DescAttr.u;
6267 }
6268
6269 /* Validate. */
6270 Assert(!(u16Sel & RT_BIT(2)));
6271 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6272 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6273 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6274 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6275 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6276 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6277 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6278 Assert( (u32Limit & 0xfff) == 0xfff
6279 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6280 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6281 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6282
6283 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6284 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6285 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6286 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6287
6288 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6289 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6290 }
6291
6292 /*
6293 * Guest GDTR.
6294 */
6295 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6296 {
6297 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6298
6299 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6300 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6301
6302 /* Validate. */
6303 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6304
6305 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6306 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6307 }
6308
6309 /*
6310 * Guest LDTR.
6311 */
6312 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6313 {
6314 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6315
6316 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6317 uint32_t u32Access;
6318 if ( !pVmxTransient->fIsNestedGuest
6319 && !pCtx->ldtr.Attr.u)
6320 u32Access = X86DESCATTR_UNUSABLE;
6321 else
6322 u32Access = pCtx->ldtr.Attr.u;
6323
6324 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6325 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6326 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6327 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6328
6329 /* Validate. */
6330 if (!(u32Access & X86DESCATTR_UNUSABLE))
6331 {
6332 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6333 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6334 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6335 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6336 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6337 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6338 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6339 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6340 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6341 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6342 }
6343
6344 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6345 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6346 }
6347
6348 /*
6349 * Guest IDTR.
6350 */
6351 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6352 {
6353 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6354
6355 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6356 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6357
6358 /* Validate. */
6359 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6360
6361 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6362 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6363 }
6364
6365 return VINF_SUCCESS;
6366}
6367
6368
6369/**
6370 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6371 * areas.
6372 *
6373 * These MSRs will automatically be loaded to the host CPU on every successful
6374 * VM-entry and stored from the host CPU on every successful VM-exit.
6375 *
6376 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6377 * actual host MSR values are not- updated here for performance reasons. See
6378 * hmR0VmxExportHostMsrs().
6379 *
6380 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6381 *
6382 * @returns VBox status code.
6383 * @param pVCpu The cross context virtual CPU structure.
6384 * @param pVmxTransient The VMX-transient structure.
6385 *
6386 * @remarks No-long-jump zone!!!
6387 */
6388static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6389{
6390 AssertPtr(pVCpu);
6391 AssertPtr(pVmxTransient);
6392
6393 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6394 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6395
6396 /*
6397 * MSRs that we use the auto-load/store MSR area in the VMCS.
6398 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6399 * nothing to do here. The host MSR values are updated when it's safe in
6400 * hmR0VmxLazySaveHostMsrs().
6401 *
6402 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6403 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6404 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6405 * for any MSR that are not part of the lazy MSRs so we do not need to place
6406 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6407 */
6408 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6409 {
6410 /* No auto-load/store MSRs currently. */
6411 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6412 }
6413
6414 /*
6415 * Guest Sysenter MSRs.
6416 */
6417 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6418 {
6419 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6420
6421 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6422 {
6423 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6424 AssertRC(rc);
6425 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6426 }
6427
6428 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6429 {
6430 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6431 AssertRC(rc);
6432 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6433 }
6434
6435 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6436 {
6437 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6438 AssertRC(rc);
6439 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6440 }
6441 }
6442
6443 /*
6444 * Guest/host EFER MSR.
6445 */
6446 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6447 {
6448 /* Whether we are using the VMCS to swap the EFER MSR must have been
6449 determined earlier while exporting VM-entry/VM-exit controls. */
6450 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6451 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6452
6453 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6454 {
6455 /*
6456 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6457 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6458 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6459 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6460 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6461 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6462 * during VM-entry.
6463 */
6464 uint64_t uGuestEferMsr = pCtx->msrEFER;
6465 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6466 {
6467 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6468 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6469 else
6470 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6471 }
6472
6473 /*
6474 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6475 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6476 */
6477 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6478 {
6479 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6480 AssertRC(rc);
6481 }
6482 else
6483 {
6484 /*
6485 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6486 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6487 */
6488 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6489 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6490 AssertRCReturn(rc, rc);
6491 }
6492
6493 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6494 }
6495 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6496 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6497
6498 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6499 }
6500
6501 /*
6502 * Other MSRs.
6503 * Speculation Control (R/W).
6504 */
6505 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6506 {
6507 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6508 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6509 {
6510 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6511 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6512 AssertRCReturn(rc, rc);
6513 }
6514 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6515 }
6516
6517 return VINF_SUCCESS;
6518}
6519
6520
6521/**
6522 * Wrapper for running the guest code in VT-x.
6523 *
6524 * @returns VBox status code, no informational status codes.
6525 * @param pVCpu The cross context virtual CPU structure.
6526 * @param pVmxTransient The VMX-transient structure.
6527 *
6528 * @remarks No-long-jump zone!!!
6529 */
6530DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6531{
6532 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6533 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6534 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6535
6536 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6537
6538 /*
6539 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6540 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6541 * callee-saved and thus the need for this XMM wrapper.
6542 *
6543 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6544 */
6545 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6546 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6547 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6548#ifdef VBOX_WITH_KERNEL_USING_XMM
6549 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6550#else
6551 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu);
6552#endif
6553 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6554 return rc;
6555}
6556
6557
6558/**
6559 * Reports world-switch error and dumps some useful debug info.
6560 *
6561 * @param pVCpu The cross context virtual CPU structure.
6562 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6563 * @param pVmxTransient The VMX-transient structure (only
6564 * exitReason updated).
6565 */
6566static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6567{
6568 Assert(pVCpu);
6569 Assert(pVmxTransient);
6570 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6571
6572 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6573 switch (rcVMRun)
6574 {
6575 case VERR_VMX_INVALID_VMXON_PTR:
6576 AssertFailed();
6577 break;
6578 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6579 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6580 {
6581 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6582 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6583 AssertRC(rc);
6584 hmR0VmxReadExitQualVmcs(pVmxTransient);
6585
6586 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6587 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6588 Cannot do it here as we may have been long preempted. */
6589
6590#ifdef VBOX_STRICT
6591 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6592 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6593 pVmxTransient->uExitReason));
6594 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6595 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6596 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6597 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6598 else
6599 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6600 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6601 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6602
6603 static struct
6604 {
6605 /** Name of the field to log. */
6606 const char *pszName;
6607 /** The VMCS field. */
6608 uint32_t uVmcsField;
6609 /** Whether host support of this field needs to be checked. */
6610 bool fCheckSupport;
6611 } const s_aVmcsFields[] =
6612 {
6613 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6614 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6615 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6616 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6617 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6618 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6619 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6620 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6621 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6622 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6623 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6624 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6625 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6626 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6627 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6628 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6629 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6630 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6631 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6632 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6633 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6634 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6635 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6636 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6637 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6638 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6639 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6640 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6641 /* The order of selector fields below are fixed! */
6642 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6643 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6644 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6645 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6646 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6647 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6648 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6649 /* End of ordered selector fields. */
6650 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6651 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6652 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6653 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6654 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6655 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6656 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6657 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6658 };
6659
6660 RTGDTR HostGdtr;
6661 ASMGetGDTR(&HostGdtr);
6662
6663 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6664 for (uint32_t i = 0; i < cVmcsFields; i++)
6665 {
6666 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
6667
6668 bool fSupported;
6669 if (!s_aVmcsFields[i].fCheckSupport)
6670 fSupported = true;
6671 else
6672 {
6673 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6674 switch (uVmcsField)
6675 {
6676 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
6677 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
6678 case VMX_VMCS32_CTRL_PROC_EXEC2:
6679 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
6680 break;
6681 default:
6682 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
6683 }
6684 }
6685
6686 if (fSupported)
6687 {
6688 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
6689 switch (uWidth)
6690 {
6691 case VMX_VMCSFIELD_WIDTH_16BIT:
6692 {
6693 uint16_t u16Val;
6694 rc = VMXReadVmcs16(uVmcsField, &u16Val);
6695 AssertRC(rc);
6696 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
6697
6698 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
6699 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
6700 {
6701 if (u16Val < HostGdtr.cbGdt)
6702 {
6703 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
6704 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
6705 "Host FS", "Host GS", "Host TR" };
6706 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
6707 Assert(idxSel < RT_ELEMENTS(s_apszSel));
6708 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
6709 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
6710 }
6711 else
6712 Log4((" Selector value exceeds GDT limit!\n"));
6713 }
6714 break;
6715 }
6716
6717 case VMX_VMCSFIELD_WIDTH_32BIT:
6718 {
6719 uint32_t u32Val;
6720 rc = VMXReadVmcs32(uVmcsField, &u32Val);
6721 AssertRC(rc);
6722 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
6723 break;
6724 }
6725
6726 case VMX_VMCSFIELD_WIDTH_64BIT:
6727 case VMX_VMCSFIELD_WIDTH_NATURAL:
6728 {
6729 uint64_t u64Val;
6730 rc = VMXReadVmcs64(uVmcsField, &u64Val);
6731 AssertRC(rc);
6732 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
6733 break;
6734 }
6735 }
6736 }
6737 }
6738
6739 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6740 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6741 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6742 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6743 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6744 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6745#endif /* VBOX_STRICT */
6746 break;
6747 }
6748
6749 default:
6750 /* Impossible */
6751 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6752 break;
6753 }
6754}
6755
6756
6757/**
6758 * Sets up the usage of TSC-offsetting and updates the VMCS.
6759 *
6760 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6761 * VMX-preemption timer.
6762 *
6763 * @returns VBox status code.
6764 * @param pVCpu The cross context virtual CPU structure.
6765 * @param pVmxTransient The VMX-transient structure.
6766 *
6767 * @remarks No-long-jump zone!!!
6768 */
6769static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6770{
6771 bool fOffsettedTsc;
6772 bool fParavirtTsc;
6773 uint64_t uTscOffset;
6774 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6775 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6776
6777 if (pVM->hm.s.vmx.fUsePreemptTimer)
6778 {
6779 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
6780
6781 /* Make sure the returned values have sane upper and lower boundaries. */
6782 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
6783 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
6784 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
6785 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
6786
6787 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
6788 * preemption timers here. We probably need to clamp the preemption timer,
6789 * after converting the timer value to the host. */
6790 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
6791 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
6792 AssertRC(rc);
6793 }
6794 else
6795 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
6796
6797 if (fParavirtTsc)
6798 {
6799 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
6800 information before every VM-entry, hence disable it for performance sake. */
6801#if 0
6802 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
6803 AssertRC(rc);
6804#endif
6805 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
6806 }
6807
6808 if ( fOffsettedTsc
6809 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
6810 {
6811 if (pVmxTransient->fIsNestedGuest)
6812 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
6813 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
6814 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6815 }
6816 else
6817 {
6818 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
6819 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6820 }
6821}
6822
6823
6824/**
6825 * Gets the IEM exception flags for the specified vector and IDT vectoring /
6826 * VM-exit interruption info type.
6827 *
6828 * @returns The IEM exception flags.
6829 * @param uVector The event vector.
6830 * @param uVmxEventType The VMX event type.
6831 *
6832 * @remarks This function currently only constructs flags required for
6833 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
6834 * and CR2 aspects of an exception are not included).
6835 */
6836static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
6837{
6838 uint32_t fIemXcptFlags;
6839 switch (uVmxEventType)
6840 {
6841 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
6842 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
6843 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
6844 break;
6845
6846 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
6847 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
6848 break;
6849
6850 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
6851 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
6852 break;
6853
6854 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
6855 {
6856 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6857 if (uVector == X86_XCPT_BP)
6858 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
6859 else if (uVector == X86_XCPT_OF)
6860 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
6861 else
6862 {
6863 fIemXcptFlags = 0;
6864 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
6865 }
6866 break;
6867 }
6868
6869 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
6870 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6871 break;
6872
6873 default:
6874 fIemXcptFlags = 0;
6875 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
6876 break;
6877 }
6878 return fIemXcptFlags;
6879}
6880
6881
6882/**
6883 * Sets an event as a pending event to be injected into the guest.
6884 *
6885 * @param pVCpu The cross context virtual CPU structure.
6886 * @param u32IntInfo The VM-entry interruption-information field.
6887 * @param cbInstr The VM-entry instruction length in bytes (for
6888 * software interrupts, exceptions and privileged
6889 * software exceptions).
6890 * @param u32ErrCode The VM-entry exception error code.
6891 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
6892 * page-fault.
6893 */
6894DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
6895 RTGCUINTPTR GCPtrFaultAddress)
6896{
6897 Assert(!pVCpu->hm.s.Event.fPending);
6898 pVCpu->hm.s.Event.fPending = true;
6899 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
6900 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
6901 pVCpu->hm.s.Event.cbInstr = cbInstr;
6902 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
6903}
6904
6905
6906/**
6907 * Sets an external interrupt as pending-for-injection into the VM.
6908 *
6909 * @param pVCpu The cross context virtual CPU structure.
6910 * @param u8Interrupt The external interrupt vector.
6911 */
6912DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
6913{
6914 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
6915 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
6916 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6917 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6918 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6919}
6920
6921
6922/**
6923 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
6924 *
6925 * @param pVCpu The cross context virtual CPU structure.
6926 */
6927DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
6928{
6929 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
6930 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
6931 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6932 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6933 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6934}
6935
6936
6937/**
6938 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
6939 *
6940 * @param pVCpu The cross context virtual CPU structure.
6941 */
6942DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
6943{
6944 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
6945 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6946 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6947 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6948 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6949}
6950
6951
6952/**
6953 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
6954 *
6955 * @param pVCpu The cross context virtual CPU structure.
6956 */
6957DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
6958{
6959 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
6960 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6961 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6962 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6963 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6964}
6965
6966
6967/**
6968 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
6969 *
6970 * @param pVCpu The cross context virtual CPU structure.
6971 */
6972DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
6973{
6974 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
6975 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6976 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6977 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6978 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6979}
6980
6981
6982#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
6983/**
6984 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
6985 *
6986 * @param pVCpu The cross context virtual CPU structure.
6987 * @param u32ErrCode The error code for the general-protection exception.
6988 */
6989DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
6990{
6991 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
6992 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6993 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6994 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6995 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
6996}
6997
6998
6999/**
7000 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7001 *
7002 * @param pVCpu The cross context virtual CPU structure.
7003 * @param u32ErrCode The error code for the stack exception.
7004 */
7005DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7006{
7007 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7008 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7009 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7010 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7011 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7012}
7013#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7014
7015
7016/**
7017 * Fixes up attributes for the specified segment register.
7018 *
7019 * @param pVCpu The cross context virtual CPU structure.
7020 * @param pSelReg The segment register that needs fixing.
7021 * @param idxSel The VMCS field for the corresponding segment register.
7022 */
7023static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7024{
7025 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7026
7027 /*
7028 * If VT-x marks the segment as unusable, most other bits remain undefined:
7029 * - For CS the L, D and G bits have meaning.
7030 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7031 * - For the remaining data segments no bits are defined.
7032 *
7033 * The present bit and the unusable bit has been observed to be set at the
7034 * same time (the selector was supposed to be invalid as we started executing
7035 * a V8086 interrupt in ring-0).
7036 *
7037 * What should be important for the rest of the VBox code, is that the P bit is
7038 * cleared. Some of the other VBox code recognizes the unusable bit, but
7039 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7040 * safe side here, we'll strip off P and other bits we don't care about. If
7041 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7042 *
7043 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7044 */
7045#ifdef VBOX_STRICT
7046 uint32_t const uAttr = pSelReg->Attr.u;
7047#endif
7048
7049 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7050 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7051 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7052
7053#ifdef VBOX_STRICT
7054 VMMRZCallRing3Disable(pVCpu);
7055 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7056# ifdef DEBUG_bird
7057 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7058 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7059 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7060# endif
7061 VMMRZCallRing3Enable(pVCpu);
7062 NOREF(uAttr);
7063#endif
7064 RT_NOREF2(pVCpu, idxSel);
7065}
7066
7067
7068/**
7069 * Imports a guest segment register from the current VMCS into the guest-CPU
7070 * context.
7071 *
7072 * @param pVCpu The cross context virtual CPU structure.
7073 * @param iSegReg The segment register number (X86_SREG_XXX).
7074 *
7075 * @remarks Called with interrupts and/or preemption disabled.
7076 */
7077static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint8_t iSegReg)
7078{
7079 Assert(iSegReg < X86_SREG_COUNT);
7080
7081 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7082 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7083 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7084 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7085
7086 uint16_t u16Sel;
7087 uint64_t u64Base;
7088 uint32_t u32Limit, u32Attr;
7089 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc);
7090 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc);
7091 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc);
7092 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc);
7093
7094 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7095 pSelReg->Sel = u16Sel;
7096 pSelReg->ValidSel = u16Sel;
7097 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7098 pSelReg->u32Limit = u32Limit;
7099 pSelReg->u64Base = u64Base;
7100 pSelReg->Attr.u = u32Attr;
7101 if (u32Attr & X86DESCATTR_UNUSABLE)
7102 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7103}
7104
7105
7106/**
7107 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7108 *
7109 * @param pVCpu The cross context virtual CPU structure.
7110 *
7111 * @remarks Called with interrupts and/or preemption disabled.
7112 */
7113static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7114{
7115 uint16_t u16Sel;
7116 uint64_t u64Base;
7117 uint32_t u32Limit, u32Attr;
7118 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7119 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7120 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7121 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7122
7123 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7124 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7125 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7126 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7127 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7128 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7129 if (u32Attr & X86DESCATTR_UNUSABLE)
7130 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7131}
7132
7133
7134/**
7135 * Imports the guest TR from the current VMCS into the guest-CPU context.
7136 *
7137 * @param pVCpu The cross context virtual CPU structure.
7138 *
7139 * @remarks Called with interrupts and/or preemption disabled.
7140 */
7141static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7142{
7143 uint16_t u16Sel;
7144 uint64_t u64Base;
7145 uint32_t u32Limit, u32Attr;
7146 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7147 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7148 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7149 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7150
7151 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7152 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7153 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7154 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7155 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7156 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7157 /* TR is the only selector that can never be unusable. */
7158 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7159}
7160
7161
7162/**
7163 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7164 *
7165 * @param pVCpu The cross context virtual CPU structure.
7166 *
7167 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7168 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7169 * instead!!!
7170 */
7171static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7172{
7173 uint64_t u64Val;
7174 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7175 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7176 {
7177 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7178 AssertRC(rc);
7179
7180 pCtx->rip = u64Val;
7181 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7182 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7183 }
7184}
7185
7186
7187/**
7188 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7189 *
7190 * @param pVCpu The cross context virtual CPU structure.
7191 * @param pVmcsInfo The VMCS info. object.
7192 *
7193 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7194 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7195 * instead!!!
7196 */
7197static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7198{
7199 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7200 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7201 {
7202 uint64_t u64Val;
7203 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7204 AssertRC(rc);
7205
7206 pCtx->rflags.u64 = u64Val;
7207 if (pVmcsInfo->RealMode.fRealOnV86Active)
7208 {
7209 pCtx->eflags.Bits.u1VM = 0;
7210 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7211 }
7212 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7213 }
7214}
7215
7216
7217/**
7218 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7219 * context.
7220 *
7221 * @param pVCpu The cross context virtual CPU structure.
7222 * @param pVmcsInfo The VMCS info. object.
7223 *
7224 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7225 * do not log!
7226 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7227 * instead!!!
7228 */
7229static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7230{
7231 uint32_t u32Val;
7232 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7233 if (!u32Val)
7234 {
7235 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7236 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7237 CPUMSetGuestNmiBlocking(pVCpu, false);
7238 }
7239 else
7240 {
7241 /*
7242 * We must import RIP here to set our EM interrupt-inhibited state.
7243 * We also import RFLAGS as our code that evaluates pending interrupts
7244 * before VM-entry requires it.
7245 */
7246 hmR0VmxImportGuestRip(pVCpu);
7247 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7248
7249 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7250 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7251 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7252 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7253
7254 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7255 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7256 }
7257}
7258
7259
7260/**
7261 * Worker for VMXR0ImportStateOnDemand.
7262 *
7263 * @returns VBox status code.
7264 * @param pVCpu The cross context virtual CPU structure.
7265 * @param pVmcsInfo The VMCS info. object.
7266 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7267 */
7268static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7269{
7270 int rc = VINF_SUCCESS;
7271 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7272 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7273 uint32_t u32Val;
7274
7275 /*
7276 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7277 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7278 * neither are other host platforms.
7279 *
7280 * Committing this temporarily as it prevents BSOD.
7281 *
7282 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7283 */
7284#ifdef RT_OS_WINDOWS
7285 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7286 return VERR_HM_IPE_1;
7287#endif
7288
7289 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7290
7291 /*
7292 * We disable interrupts to make the updating of the state and in particular
7293 * the fExtrn modification atomic wrt to preemption hooks.
7294 */
7295 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7296
7297 fWhat &= pCtx->fExtrn;
7298 if (fWhat)
7299 {
7300 do
7301 {
7302 if (fWhat & CPUMCTX_EXTRN_RIP)
7303 hmR0VmxImportGuestRip(pVCpu);
7304
7305 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7306 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7307
7308 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7309 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7310
7311 if (fWhat & CPUMCTX_EXTRN_RSP)
7312 {
7313 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7314 AssertRC(rc);
7315 }
7316
7317 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7318 {
7319 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7320 if (fWhat & CPUMCTX_EXTRN_CS)
7321 {
7322 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7323 hmR0VmxImportGuestRip(pVCpu);
7324 if (fRealOnV86Active)
7325 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7326 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7327 }
7328 if (fWhat & CPUMCTX_EXTRN_SS)
7329 {
7330 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7331 if (fRealOnV86Active)
7332 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7333 }
7334 if (fWhat & CPUMCTX_EXTRN_DS)
7335 {
7336 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7337 if (fRealOnV86Active)
7338 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7339 }
7340 if (fWhat & CPUMCTX_EXTRN_ES)
7341 {
7342 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7343 if (fRealOnV86Active)
7344 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7345 }
7346 if (fWhat & CPUMCTX_EXTRN_FS)
7347 {
7348 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7349 if (fRealOnV86Active)
7350 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7351 }
7352 if (fWhat & CPUMCTX_EXTRN_GS)
7353 {
7354 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7355 if (fRealOnV86Active)
7356 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7357 }
7358 }
7359
7360 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7361 {
7362 if (fWhat & CPUMCTX_EXTRN_LDTR)
7363 hmR0VmxImportGuestLdtr(pVCpu);
7364
7365 if (fWhat & CPUMCTX_EXTRN_GDTR)
7366 {
7367 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7368 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7369 pCtx->gdtr.cbGdt = u32Val;
7370 }
7371
7372 /* Guest IDTR. */
7373 if (fWhat & CPUMCTX_EXTRN_IDTR)
7374 {
7375 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7376 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7377 pCtx->idtr.cbIdt = u32Val;
7378 }
7379
7380 /* Guest TR. */
7381 if (fWhat & CPUMCTX_EXTRN_TR)
7382 {
7383 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7384 don't need to import that one. */
7385 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7386 hmR0VmxImportGuestTr(pVCpu);
7387 }
7388 }
7389
7390 if (fWhat & CPUMCTX_EXTRN_DR7)
7391 {
7392 if (!pVCpu->hm.s.fUsingHyperDR7)
7393 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7394 }
7395
7396 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7397 {
7398 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7399 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7400 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7401 pCtx->SysEnter.cs = u32Val;
7402 }
7403
7404 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7405 {
7406 if ( pVM->hm.s.fAllow64BitGuests
7407 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7408 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7409 }
7410
7411 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7412 {
7413 if ( pVM->hm.s.fAllow64BitGuests
7414 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7415 {
7416 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7417 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7418 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7419 }
7420 }
7421
7422 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7423 {
7424 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7425 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7426 Assert(pMsrs);
7427 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7428 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7429 for (uint32_t i = 0; i < cMsrs; i++)
7430 {
7431 uint32_t const idMsr = pMsrs[i].u32Msr;
7432 switch (idMsr)
7433 {
7434 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7435 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7436 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7437 default:
7438 {
7439 pCtx->fExtrn = 0;
7440 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7441 ASMSetFlags(fEFlags);
7442 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7443 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7444 }
7445 }
7446 }
7447 }
7448
7449 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7450 {
7451 if (fWhat & CPUMCTX_EXTRN_CR0)
7452 {
7453 uint64_t u64Cr0;
7454 uint64_t u64Shadow;
7455 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7456 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7457#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7458 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7459 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7460#else
7461 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7462 {
7463 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7464 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7465 }
7466 else
7467 {
7468 /*
7469 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7470 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7471 * re-construct CR0. See @bugref{9180#c95} for details.
7472 */
7473 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7474 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7475 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7476 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7477 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7478 }
7479#endif
7480 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7481 CPUMSetGuestCR0(pVCpu, u64Cr0);
7482 VMMRZCallRing3Enable(pVCpu);
7483 }
7484
7485 if (fWhat & CPUMCTX_EXTRN_CR4)
7486 {
7487 uint64_t u64Cr4;
7488 uint64_t u64Shadow;
7489 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7490 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7491#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7492 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7493 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7494#else
7495 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7496 {
7497 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7498 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7499 }
7500 else
7501 {
7502 /*
7503 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7504 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7505 * re-construct CR4. See @bugref{9180#c95} for details.
7506 */
7507 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7508 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7509 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7510 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7511 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7512 }
7513#endif
7514 pCtx->cr4 = u64Cr4;
7515 }
7516
7517 if (fWhat & CPUMCTX_EXTRN_CR3)
7518 {
7519 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7520 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7521 || ( pVM->hm.s.fNestedPaging
7522 && CPUMIsGuestPagingEnabledEx(pCtx)))
7523 {
7524 uint64_t u64Cr3;
7525 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7526 if (pCtx->cr3 != u64Cr3)
7527 {
7528 pCtx->cr3 = u64Cr3;
7529 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7530 }
7531
7532 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7533 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7534 if (CPUMIsGuestInPAEModeEx(pCtx))
7535 {
7536 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7537 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7538 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7539 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7540 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7541 }
7542 }
7543 }
7544 }
7545
7546#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7547 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7548 {
7549 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7550 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7551 {
7552 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7553 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7554 if (RT_SUCCESS(rc))
7555 { /* likely */ }
7556 else
7557 break;
7558 }
7559 }
7560#endif
7561 } while (0);
7562
7563 if (RT_SUCCESS(rc))
7564 {
7565 /* Update fExtrn. */
7566 pCtx->fExtrn &= ~fWhat;
7567
7568 /* If everything has been imported, clear the HM keeper bit. */
7569 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7570 {
7571 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7572 Assert(!pCtx->fExtrn);
7573 }
7574 }
7575 }
7576 else
7577 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7578
7579 /*
7580 * Restore interrupts.
7581 */
7582 ASMSetFlags(fEFlags);
7583
7584 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7585
7586 if (RT_SUCCESS(rc))
7587 { /* likely */ }
7588 else
7589 return rc;
7590
7591 /*
7592 * Honor any pending CR3 updates.
7593 *
7594 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7595 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7596 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7597 *
7598 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7599 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7600 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7601 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7602 *
7603 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7604 */
7605 if (VMMRZCallRing3IsEnabled(pVCpu))
7606 {
7607 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7608 {
7609 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7610 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7611 }
7612
7613 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7614 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7615
7616 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7617 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7618 }
7619
7620 return VINF_SUCCESS;
7621}
7622
7623
7624/**
7625 * Saves the guest state from the VMCS into the guest-CPU context.
7626 *
7627 * @returns VBox status code.
7628 * @param pVCpu The cross context virtual CPU structure.
7629 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7630 */
7631VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
7632{
7633 AssertPtr(pVCpu);
7634 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7635 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7636}
7637
7638
7639/**
7640 * Check per-VM and per-VCPU force flag actions that require us to go back to
7641 * ring-3 for one reason or another.
7642 *
7643 * @returns Strict VBox status code (i.e. informational status codes too)
7644 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7645 * ring-3.
7646 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7647 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7648 * interrupts)
7649 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7650 * all EMTs to be in ring-3.
7651 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7652 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7653 * to the EM loop.
7654 *
7655 * @param pVCpu The cross context virtual CPU structure.
7656 * @param pVmxTransient The VMX-transient structure.
7657 * @param fStepping Whether we are single-stepping the guest using the
7658 * hypervisor debugger.
7659 *
7660 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
7661 * is no longer in VMX non-root mode.
7662 */
7663static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, bool fStepping)
7664{
7665 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7666
7667 /*
7668 * Update pending interrupts into the APIC's IRR.
7669 */
7670 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7671 APICUpdatePendingInterrupts(pVCpu);
7672
7673 /*
7674 * Anything pending? Should be more likely than not if we're doing a good job.
7675 */
7676 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7677 if ( !fStepping
7678 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7679 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7680 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7681 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7682 return VINF_SUCCESS;
7683
7684 /* Pending PGM C3 sync. */
7685 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7686 {
7687 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7688 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7689 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7690 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7691 if (rcStrict != VINF_SUCCESS)
7692 {
7693 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
7694 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
7695 return rcStrict;
7696 }
7697 }
7698
7699 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7700 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7701 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7702 {
7703 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7704 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7705 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
7706 return rc;
7707 }
7708
7709 /* Pending VM request packets, such as hardware interrupts. */
7710 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7711 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7712 {
7713 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
7714 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7715 return VINF_EM_PENDING_REQUEST;
7716 }
7717
7718 /* Pending PGM pool flushes. */
7719 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7720 {
7721 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
7722 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7723 return VINF_PGM_POOL_FLUSH_PENDING;
7724 }
7725
7726 /* Pending DMA requests. */
7727 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7728 {
7729 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
7730 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7731 return VINF_EM_RAW_TO_R3;
7732 }
7733
7734#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7735 /*
7736 * Pending nested-guest events.
7737 *
7738 * Please note the priority of these events are specified and important.
7739 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
7740 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
7741 */
7742 if (pVmxTransient->fIsNestedGuest)
7743 {
7744 /* Pending nested-guest APIC-write. */
7745 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
7746 {
7747 Log4Func(("Pending nested-guest APIC-write\n"));
7748 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
7749 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7750 return rcStrict;
7751 }
7752
7753 /* Pending nested-guest monitor-trap flag (MTF). */
7754 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
7755 {
7756 Log4Func(("Pending nested-guest MTF\n"));
7757 VBOXSTRICTRC rcStrict = IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */);
7758 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7759 return rcStrict;
7760 }
7761
7762 /* Pending nested-guest VMX-preemption timer expired. */
7763 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
7764 {
7765 Log4Func(("Pending nested-guest MTF\n"));
7766 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitPreemptTimer(pVCpu);
7767 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7768 return rcStrict;
7769 }
7770 }
7771#else
7772 NOREF(pVmxTransient);
7773#endif
7774
7775 return VINF_SUCCESS;
7776}
7777
7778
7779/**
7780 * Converts any TRPM trap into a pending HM event. This is typically used when
7781 * entering from ring-3 (not longjmp returns).
7782 *
7783 * @param pVCpu The cross context virtual CPU structure.
7784 */
7785static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
7786{
7787 Assert(TRPMHasTrap(pVCpu));
7788 Assert(!pVCpu->hm.s.Event.fPending);
7789
7790 uint8_t uVector;
7791 TRPMEVENT enmTrpmEvent;
7792 uint32_t uErrCode;
7793 RTGCUINTPTR GCPtrFaultAddress;
7794 uint8_t cbInstr;
7795 bool fIcebp;
7796
7797 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
7798 AssertRC(rc);
7799
7800 uint32_t u32IntInfo;
7801 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
7802 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
7803
7804 rc = TRPMResetTrap(pVCpu);
7805 AssertRC(rc);
7806 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
7807 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
7808
7809 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
7810}
7811
7812
7813/**
7814 * Converts the pending HM event into a TRPM trap.
7815 *
7816 * @param pVCpu The cross context virtual CPU structure.
7817 */
7818static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
7819{
7820 Assert(pVCpu->hm.s.Event.fPending);
7821
7822 /* If a trap was already pending, we did something wrong! */
7823 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
7824
7825 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
7826 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
7827 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
7828
7829 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
7830
7831 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
7832 AssertRC(rc);
7833
7834 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
7835 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
7836
7837 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
7838 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
7839 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
7840 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
7841
7842 if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
7843 TRPMSetTrapDueToIcebp(pVCpu);
7844
7845 /* We're now done converting the pending event. */
7846 pVCpu->hm.s.Event.fPending = false;
7847}
7848
7849
7850/**
7851 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
7852 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
7853 *
7854 * @param pVCpu The cross context virtual CPU structure.
7855 * @param pVmcsInfo The VMCS info. object.
7856 */
7857static void hmR0VmxSetIntWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7858{
7859 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7860 {
7861 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
7862 {
7863 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
7864 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7865 AssertRC(rc);
7866 }
7867 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
7868}
7869
7870
7871/**
7872 * Clears the interrupt-window exiting control in the VMCS.
7873 *
7874 * @param pVmcsInfo The VMCS info. object.
7875 */
7876DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7877{
7878 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7879 {
7880 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
7881 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7882 AssertRC(rc);
7883 }
7884}
7885
7886
7887/**
7888 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
7889 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
7890 *
7891 * @param pVCpu The cross context virtual CPU structure.
7892 * @param pVmcsInfo The VMCS info. object.
7893 */
7894static void hmR0VmxSetNmiWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7895{
7896 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7897 {
7898 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
7899 {
7900 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7901 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7902 AssertRC(rc);
7903 Log4Func(("Setup NMI-window exiting\n"));
7904 }
7905 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
7906}
7907
7908
7909/**
7910 * Clears the NMI-window exiting control in the VMCS.
7911 *
7912 * @param pVmcsInfo The VMCS info. object.
7913 */
7914DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7915{
7916 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7917 {
7918 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7919 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7920 AssertRC(rc);
7921 }
7922}
7923
7924
7925/**
7926 * Does the necessary state syncing before returning to ring-3 for any reason
7927 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
7928 *
7929 * @returns VBox status code.
7930 * @param pVCpu The cross context virtual CPU structure.
7931 * @param fImportState Whether to import the guest state from the VMCS back
7932 * to the guest-CPU context.
7933 *
7934 * @remarks No-long-jmp zone!!!
7935 */
7936static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
7937{
7938 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
7939 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
7940
7941 RTCPUID const idCpu = RTMpCpuId();
7942 Log4Func(("HostCpuId=%u\n", idCpu));
7943
7944 /*
7945 * !!! IMPORTANT !!!
7946 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
7947 */
7948
7949 /* Save the guest state if necessary. */
7950 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7951 if (fImportState)
7952 {
7953 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
7954 AssertRCReturn(rc, rc);
7955 }
7956
7957 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
7958 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
7959 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
7960
7961 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
7962#ifdef VBOX_STRICT
7963 if (CPUMIsHyperDebugStateActive(pVCpu))
7964 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
7965#endif
7966 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
7967 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
7968 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
7969
7970 /* Restore host-state bits that VT-x only restores partially. */
7971 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
7972 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
7973 {
7974 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
7975 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
7976 }
7977 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
7978
7979 /* Restore the lazy host MSRs as we're leaving VT-x context. */
7980 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
7981 {
7982 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
7983 if (!fImportState)
7984 {
7985 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
7986 AssertRCReturn(rc, rc);
7987 }
7988 hmR0VmxLazyRestoreHostMsrs(pVCpu);
7989 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
7990 }
7991 else
7992 pVCpu->hm.s.vmx.fLazyMsrs = 0;
7993
7994 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
7995 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
7996
7997 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
7998 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
7999 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8000 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8001 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8002 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8003 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8004 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8005 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8006 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8007
8008 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8009
8010 /** @todo This partially defeats the purpose of having preemption hooks.
8011 * The problem is, deregistering the hooks should be moved to a place that
8012 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8013 * context.
8014 */
8015 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8016 AssertRCReturn(rc, rc);
8017
8018#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8019 /*
8020 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8021 * clear a shadow VMCS before allowing that VMCS to become active on another
8022 * logical processor. We may or may not be importing guest state which clears
8023 * it, so cover for it here.
8024 *
8025 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8026 */
8027 if ( pVmcsInfo->pvShadowVmcs
8028 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8029 {
8030 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8031 AssertRCReturn(rc, rc);
8032 }
8033
8034 /*
8035 * Flag that we need to re-export the host state if we switch to this VMCS before
8036 * executing guest or nested-guest code.
8037 */
8038 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8039#endif
8040
8041 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8042 NOREF(idCpu);
8043 return VINF_SUCCESS;
8044}
8045
8046
8047/**
8048 * Leaves the VT-x session.
8049 *
8050 * @returns VBox status code.
8051 * @param pVCpu The cross context virtual CPU structure.
8052 *
8053 * @remarks No-long-jmp zone!!!
8054 */
8055static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8056{
8057 HM_DISABLE_PREEMPT(pVCpu);
8058 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8059 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8060 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8061
8062 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8063 and done this from the VMXR0ThreadCtxCallback(). */
8064 if (!pVCpu->hm.s.fLeaveDone)
8065 {
8066 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8067 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8068 pVCpu->hm.s.fLeaveDone = true;
8069 }
8070 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8071
8072 /*
8073 * !!! IMPORTANT !!!
8074 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8075 */
8076
8077 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8078 /** @todo Deregistering here means we need to VMCLEAR always
8079 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8080 * for calling VMMR0ThreadCtxHookDisable here! */
8081 VMMR0ThreadCtxHookDisable(pVCpu);
8082
8083 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8084 int rc = HMR0LeaveCpu(pVCpu);
8085 HM_RESTORE_PREEMPT();
8086 return rc;
8087}
8088
8089
8090/**
8091 * Does the necessary state syncing before doing a longjmp to ring-3.
8092 *
8093 * @returns VBox status code.
8094 * @param pVCpu The cross context virtual CPU structure.
8095 *
8096 * @remarks No-long-jmp zone!!!
8097 */
8098DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8099{
8100 return hmR0VmxLeaveSession(pVCpu);
8101}
8102
8103
8104/**
8105 * Take necessary actions before going back to ring-3.
8106 *
8107 * An action requires us to go back to ring-3. This function does the necessary
8108 * steps before we can safely return to ring-3. This is not the same as longjmps
8109 * to ring-3, this is voluntary and prepares the guest so it may continue
8110 * executing outside HM (recompiler/IEM).
8111 *
8112 * @returns VBox status code.
8113 * @param pVCpu The cross context virtual CPU structure.
8114 * @param rcExit The reason for exiting to ring-3. Can be
8115 * VINF_VMM_UNKNOWN_RING3_CALL.
8116 */
8117static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8118{
8119 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8120
8121 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8122 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8123 {
8124 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8125 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8126 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8127 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8128 }
8129
8130 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8131 VMMRZCallRing3Disable(pVCpu);
8132 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8133
8134 /*
8135 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8136 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8137 *
8138 * This is because execution may continue from ring-3 and we would need to inject
8139 * the event from there (hence place it back in TRPM).
8140 */
8141 if (pVCpu->hm.s.Event.fPending)
8142 {
8143 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8144 Assert(!pVCpu->hm.s.Event.fPending);
8145
8146 /* Clear the events from the VMCS. */
8147 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc);
8148 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0); AssertRC(rc);
8149 }
8150#ifdef VBOX_STRICT
8151 else
8152 {
8153 /*
8154 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8155 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8156 * occasionally, see @bugref{9180#c42}.
8157 *
8158 * However, if the VM-entry failed, any VM entry-interruption info. field would
8159 * be left unmodified as the event would not have been injected to the guest. In
8160 * such cases, don't assert, we're not going to continue guest execution anyway.
8161 */
8162 uint32_t uExitReason;
8163 uint32_t uEntryIntInfo;
8164 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8165 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8166 AssertRC(rc);
8167 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8168 }
8169#endif
8170
8171 /*
8172 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8173 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8174 * (e.g. TPR below threshold).
8175 */
8176 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8177 {
8178 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8179 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8180 }
8181
8182 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8183 and if we're injecting an event we should have a TRPM trap pending. */
8184 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8185#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8186 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8187#endif
8188
8189 /* Save guest state and restore host state bits. */
8190 int rc = hmR0VmxLeaveSession(pVCpu);
8191 AssertRCReturn(rc, rc);
8192 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8193
8194 /* Thread-context hooks are unregistered at this point!!! */
8195 /* Ring-3 callback notifications are unregistered at this point!!! */
8196
8197 /* Sync recompiler state. */
8198 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8199 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8200 | CPUM_CHANGED_LDTR
8201 | CPUM_CHANGED_GDTR
8202 | CPUM_CHANGED_IDTR
8203 | CPUM_CHANGED_TR
8204 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8205 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8206 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8207 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8208
8209 Assert(!pVCpu->hm.s.fClearTrapFlag);
8210
8211 /* Update the exit-to-ring 3 reason. */
8212 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8213
8214 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8215 if ( rcExit != VINF_EM_RAW_INTERRUPT
8216 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8217 {
8218 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8219 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8220 }
8221
8222 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8223 VMMRZCallRing3Enable(pVCpu);
8224 return rc;
8225}
8226
8227
8228/**
8229 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8230 * longjump to ring-3 and possibly get preempted.
8231 *
8232 * @returns VBox status code.
8233 * @param pVCpu The cross context virtual CPU structure.
8234 * @param enmOperation The operation causing the ring-3 longjump.
8235 */
8236VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8237{
8238 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8239 {
8240 /*
8241 * !!! IMPORTANT !!!
8242 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8243 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8244 */
8245 VMMRZCallRing3RemoveNotification(pVCpu);
8246 VMMRZCallRing3Disable(pVCpu);
8247 HM_DISABLE_PREEMPT(pVCpu);
8248
8249 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8250 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8251 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8252 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8253
8254 /* Restore host-state bits that VT-x only restores partially. */
8255 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8256 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8257 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8258 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8259
8260 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8261 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8262 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8263
8264 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8265 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8266 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8267
8268 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8269 cleared as part of importing the guest state above. */
8270 hmR0VmxClearVmcs(pVmcsInfo);
8271
8272 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8273 VMMR0ThreadCtxHookDisable(pVCpu);
8274
8275 /* Leave HM context. This takes care of local init (term). */
8276 HMR0LeaveCpu(pVCpu);
8277 HM_RESTORE_PREEMPT();
8278 return VINF_SUCCESS;
8279 }
8280
8281 Assert(pVCpu);
8282 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8283 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8284
8285 VMMRZCallRing3Disable(pVCpu);
8286 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8287
8288 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8289
8290 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8291 AssertRCReturn(rc, rc);
8292
8293 VMMRZCallRing3Enable(pVCpu);
8294 return VINF_SUCCESS;
8295}
8296
8297
8298/**
8299 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8300 * stack.
8301 *
8302 * @returns Strict VBox status code (i.e. informational status codes too).
8303 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8304 * @param pVCpu The cross context virtual CPU structure.
8305 * @param uValue The value to push to the guest stack.
8306 */
8307static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8308{
8309 /*
8310 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8311 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8312 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8313 */
8314 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8315 if (pCtx->sp == 1)
8316 return VINF_EM_RESET;
8317 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8318 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8319 AssertRC(rc);
8320 return rc;
8321}
8322
8323
8324/**
8325 * Injects an event into the guest upon VM-entry by updating the relevant fields
8326 * in the VM-entry area in the VMCS.
8327 *
8328 * @returns Strict VBox status code (i.e. informational status codes too).
8329 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8330 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8331 *
8332 * @param pVCpu The cross context virtual CPU structure.
8333 * @param pVmxTransient The VMX-transient structure.
8334 * @param pEvent The event being injected.
8335 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8336 * will be updated if necessary. This cannot not be NULL.
8337 * @param fStepping Whether we're single-stepping guest execution and should
8338 * return VINF_EM_DBG_STEPPED if the event is injected
8339 * directly (registers modified by us, not by hardware on
8340 * VM-entry).
8341 */
8342static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8343 uint32_t *pfIntrState)
8344{
8345 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8346 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8347 Assert(pfIntrState);
8348
8349 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8350 uint32_t u32IntInfo = pEvent->u64IntInfo;
8351 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8352 uint32_t const cbInstr = pEvent->cbInstr;
8353 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8354 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8355 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8356
8357#ifdef VBOX_STRICT
8358 /*
8359 * Validate the error-code-valid bit for hardware exceptions.
8360 * No error codes for exceptions in real-mode.
8361 *
8362 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8363 */
8364 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8365 && !CPUMIsGuestInRealModeEx(pCtx))
8366 {
8367 switch (uVector)
8368 {
8369 case X86_XCPT_PF:
8370 case X86_XCPT_DF:
8371 case X86_XCPT_TS:
8372 case X86_XCPT_NP:
8373 case X86_XCPT_SS:
8374 case X86_XCPT_GP:
8375 case X86_XCPT_AC:
8376 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8377 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8378 RT_FALL_THRU();
8379 default:
8380 break;
8381 }
8382 }
8383
8384 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8385 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8386 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8387#endif
8388
8389 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8390
8391 /*
8392 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8393 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8394 * interrupt handler in the (real-mode) guest.
8395 *
8396 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8397 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8398 */
8399 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8400 {
8401 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8402 {
8403 /*
8404 * For CPUs with unrestricted guest execution enabled and with the guest
8405 * in real-mode, we must not set the deliver-error-code bit.
8406 *
8407 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8408 */
8409 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8410 }
8411 else
8412 {
8413 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8414 Assert(PDMVmmDevHeapIsEnabled(pVM));
8415 Assert(pVM->hm.s.vmx.pRealModeTSS);
8416 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8417
8418 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8419 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8420 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8421 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8422 AssertRCReturn(rc2, rc2);
8423
8424 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8425 size_t const cbIdtEntry = sizeof(X86IDTR16);
8426 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8427 {
8428 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8429 if (uVector == X86_XCPT_DF)
8430 return VINF_EM_RESET;
8431
8432 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8433 No error codes for exceptions in real-mode. */
8434 if (uVector == X86_XCPT_GP)
8435 {
8436 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8437 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8438 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8439 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8440 HMEVENT EventXcptDf;
8441 RT_ZERO(EventXcptDf);
8442 EventXcptDf.u64IntInfo = uXcptDfInfo;
8443 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8444 }
8445
8446 /*
8447 * If we're injecting an event with no valid IDT entry, inject a #GP.
8448 * No error codes for exceptions in real-mode.
8449 *
8450 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8451 */
8452 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8453 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8454 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8455 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8456 HMEVENT EventXcptGp;
8457 RT_ZERO(EventXcptGp);
8458 EventXcptGp.u64IntInfo = uXcptGpInfo;
8459 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8460 }
8461
8462 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8463 uint16_t uGuestIp = pCtx->ip;
8464 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8465 {
8466 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8467 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8468 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8469 }
8470 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8471 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8472
8473 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8474 X86IDTR16 IdtEntry;
8475 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8476 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8477 AssertRCReturn(rc2, rc2);
8478
8479 /* Construct the stack frame for the interrupt/exception handler. */
8480 VBOXSTRICTRC rcStrict;
8481 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8482 if (rcStrict == VINF_SUCCESS)
8483 {
8484 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8485 if (rcStrict == VINF_SUCCESS)
8486 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8487 }
8488
8489 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8490 if (rcStrict == VINF_SUCCESS)
8491 {
8492 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8493 pCtx->rip = IdtEntry.offSel;
8494 pCtx->cs.Sel = IdtEntry.uSel;
8495 pCtx->cs.ValidSel = IdtEntry.uSel;
8496 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8497 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8498 && uVector == X86_XCPT_PF)
8499 pCtx->cr2 = GCPtrFault;
8500
8501 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8502 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8503 | HM_CHANGED_GUEST_RSP);
8504
8505 /*
8506 * If we delivered a hardware exception (other than an NMI) and if there was
8507 * block-by-STI in effect, we should clear it.
8508 */
8509 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8510 {
8511 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8512 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8513 Log4Func(("Clearing inhibition due to STI\n"));
8514 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8515 }
8516
8517 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8518 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8519
8520 /*
8521 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8522 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8523 */
8524 pVCpu->hm.s.Event.fPending = false;
8525
8526 /*
8527 * If we eventually support nested-guest execution without unrestricted guest execution,
8528 * we should set fInterceptEvents here.
8529 */
8530 Assert(!pVmxTransient->fIsNestedGuest);
8531
8532 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8533 if (fStepping)
8534 rcStrict = VINF_EM_DBG_STEPPED;
8535 }
8536 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8537 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8538 return rcStrict;
8539 }
8540 }
8541
8542 /*
8543 * Validate.
8544 */
8545 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8546 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8547
8548 /*
8549 * Inject the event into the VMCS.
8550 */
8551 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8552 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8553 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8554 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8555 AssertRC(rc);
8556
8557 /*
8558 * Update guest CR2 if this is a page-fault.
8559 */
8560 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8561 pCtx->cr2 = GCPtrFault;
8562
8563 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8564 return VINF_SUCCESS;
8565}
8566
8567
8568/**
8569 * Evaluates the event to be delivered to the guest and sets it as the pending
8570 * event.
8571 *
8572 * Toggling of interrupt force-flags here is safe since we update TRPM on premature
8573 * exits to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must
8574 * NOT restore these force-flags.
8575 *
8576 * @returns Strict VBox status code (i.e. informational status codes too).
8577 * @param pVCpu The cross context virtual CPU structure.
8578 * @param pVmxTransient The VMX-transient structure.
8579 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8580 */
8581static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8582{
8583 Assert(pfIntrState);
8584 Assert(!TRPMHasTrap(pVCpu));
8585
8586 /*
8587 * Compute/update guest-interruptibility state related FFs.
8588 * The FFs will be used below while evaluating events to be injected.
8589 */
8590 *pfIntrState = hmR0VmxGetGuestIntrState(pVCpu);
8591
8592 /*
8593 * Evaluate if a new event needs to be injected.
8594 * An event that's already pending has already performed all necessary checks.
8595 */
8596 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8597 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8598 if ( !pVCpu->hm.s.Event.fPending
8599 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
8600 {
8601 /** @todo SMI. SMIs take priority over NMIs. */
8602
8603 /*
8604 * NMIs.
8605 * NMIs take priority over external interrupts.
8606 */
8607 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8608 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8609 {
8610 /*
8611 * For a guest, the FF always indicates the guest's ability to receive an NMI.
8612 *
8613 * For a nested-guest, the FF always indicates the outer guest's ability to
8614 * receive an NMI while the guest-interruptibility state bit depends on whether
8615 * the nested-hypervisor is using virtual-NMIs.
8616 */
8617 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
8618 {
8619#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8620 if ( fIsNestedGuest
8621 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_NMI_EXIT))
8622 return IEMExecVmxVmexitXcptNmi(pVCpu);
8623#endif
8624 hmR0VmxSetPendingXcptNmi(pVCpu);
8625 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8626 Log4Func(("NMI pending injection\n"));
8627
8628 /* We've injected the NMI, bail. */
8629 return VINF_SUCCESS;
8630 }
8631 else if (!fIsNestedGuest)
8632 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8633 }
8634
8635 /*
8636 * External interrupts (PIC/APIC).
8637 * Once PDMGetInterrupt() returns a valid interrupt we -must- deliver it.
8638 * We cannot re-request the interrupt from the controller again.
8639 */
8640 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8641 && !pVCpu->hm.s.fSingleInstruction)
8642 {
8643 Assert(!DBGFIsStepping(pVCpu));
8644 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8645 AssertRC(rc);
8646
8647 if (pCtx->eflags.u32 & X86_EFL_IF)
8648 {
8649#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8650 if ( fIsNestedGuest
8651 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8652 && !CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8653 {
8654 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
8655 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8656 return rcStrict;
8657 }
8658#endif
8659 uint8_t u8Interrupt;
8660 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8661 if (RT_SUCCESS(rc))
8662 {
8663#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8664 if ( fIsNestedGuest
8665 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8666 && CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8667 {
8668 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8669 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8670 return rcStrict;
8671 }
8672#endif
8673 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8674 Log4Func(("External interrupt (%#x) pending injection\n", u8Interrupt));
8675 }
8676 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8677 {
8678 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8679
8680 if ( !fIsNestedGuest
8681 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8682 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
8683 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
8684
8685 /*
8686 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8687 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8688 * need to re-set this force-flag here.
8689 */
8690 }
8691 else
8692 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8693
8694 /* We've injected the interrupt or taken necessary action, bail. */
8695 return VINF_SUCCESS;
8696 }
8697 else if (!fIsNestedGuest)
8698 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8699 }
8700 }
8701 else if (!fIsNestedGuest)
8702 {
8703 /*
8704 * An event is being injected or we are in an interrupt shadow. Check if another event is
8705 * pending. If so, instruct VT-x to cause a VM-exit as soon as the guest is ready to accept
8706 * the pending event.
8707 */
8708 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8709 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8710 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8711 && !pVCpu->hm.s.fSingleInstruction)
8712 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8713 }
8714 /* else: for nested-guests, NMI/interrupt-window exiting will be picked up when merging VMCS controls. */
8715
8716 return VINF_SUCCESS;
8717}
8718
8719
8720/**
8721 * Injects any pending events into the guest if the guest is in a state to
8722 * receive them.
8723 *
8724 * @returns Strict VBox status code (i.e. informational status codes too).
8725 * @param pVCpu The cross context virtual CPU structure.
8726 * @param pVmxTransient The VMX-transient structure.
8727 * @param fIntrState The VT-x guest-interruptibility state.
8728 * @param fStepping Whether we are single-stepping the guest using the
8729 * hypervisor debugger and should return
8730 * VINF_EM_DBG_STEPPED if the event was dispatched
8731 * directly.
8732 */
8733static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
8734{
8735 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8736 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8737
8738#ifdef VBOX_STRICT
8739 /*
8740 * Verify guest-interruptibility state.
8741 *
8742 * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
8743 * since injecting an event may modify the interruptibility state and we must thus always
8744 * use fIntrState.
8745 */
8746 {
8747 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8748 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8749 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
8750 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
8751 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
8752 Assert(!TRPMHasTrap(pVCpu));
8753 NOREF(fBlockMovSS); NOREF(fBlockSti);
8754 }
8755#endif
8756
8757 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
8758 if (pVCpu->hm.s.Event.fPending)
8759 {
8760 /*
8761 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
8762 * pending even while injecting an event and in this case, we want a VM-exit as soon as
8763 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
8764 *
8765 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
8766 */
8767 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
8768#ifdef VBOX_STRICT
8769 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8770 {
8771 Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
8772 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
8773 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8774 }
8775 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
8776 {
8777 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
8778 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
8779 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8780 }
8781#endif
8782 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
8783 uIntType));
8784
8785 /*
8786 * Inject the event and get any changes to the guest-interruptibility state.
8787 *
8788 * The guest-interruptibility state may need to be updated if we inject the event
8789 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
8790 */
8791 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
8792 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
8793
8794 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8795 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
8796 else
8797 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
8798 }
8799
8800 /*
8801 * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
8802 * is an interrupt shadow (block-by-STI or block-by-MOV SS).
8803 */
8804 if ( (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
8805 && !pVmxTransient->fIsNestedGuest)
8806 {
8807 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
8808
8809 if (!pVCpu->hm.s.fSingleInstruction)
8810 {
8811 /*
8812 * Set or clear the BS bit depending on whether the trap flag is active or not. We need
8813 * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
8814 */
8815 Assert(!DBGFIsStepping(pVCpu));
8816 uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
8817 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
8818 AssertRC(rc);
8819 }
8820 else
8821 {
8822 /*
8823 * We must not deliver a debug exception when single-stepping over STI/Mov-SS in the
8824 * hypervisor debugger using EFLAGS.TF but rather clear interrupt inhibition. However,
8825 * we take care of this case in hmR0VmxExportSharedDebugState and also the case if
8826 * we use MTF, so just make sure it's called before executing guest-code.
8827 */
8828 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR_MASK);
8829 }
8830 }
8831 /* else: for nested-guest currently handling while merging controls. */
8832
8833 /*
8834 * Finally, update the guest-interruptibility state.
8835 *
8836 * This is required for the real-on-v86 software interrupt injection, for
8837 * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
8838 */
8839 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
8840 AssertRC(rc);
8841
8842 /*
8843 * There's no need to clear the VM-entry interruption-information field here if we're not
8844 * injecting anything. VT-x clears the valid bit on every VM-exit.
8845 *
8846 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
8847 */
8848
8849 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
8850 return rcStrict;
8851}
8852
8853
8854/**
8855 * Enters the VT-x session.
8856 *
8857 * @returns VBox status code.
8858 * @param pVCpu The cross context virtual CPU structure.
8859 */
8860VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
8861{
8862 AssertPtr(pVCpu);
8863 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
8864 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8865
8866 LogFlowFunc(("pVCpu=%p\n", pVCpu));
8867 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8868 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8869
8870#ifdef VBOX_STRICT
8871 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
8872 RTCCUINTREG uHostCr4 = ASMGetCR4();
8873 if (!(uHostCr4 & X86_CR4_VMXE))
8874 {
8875 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
8876 return VERR_VMX_X86_CR4_VMXE_CLEARED;
8877 }
8878#endif
8879
8880 /*
8881 * Load the appropriate VMCS as the current and active one.
8882 */
8883 PVMXVMCSINFO pVmcsInfo;
8884 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
8885 if (!fInNestedGuestMode)
8886 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
8887 else
8888 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
8889 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
8890 if (RT_SUCCESS(rc))
8891 {
8892 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
8893 pVCpu->hm.s.fLeaveDone = false;
8894 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8895
8896 /*
8897 * Do the EMT scheduled L1D flush here if needed.
8898 */
8899 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8900 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8901 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
8902 hmR0MdsClear();
8903 }
8904 return rc;
8905}
8906
8907
8908/**
8909 * The thread-context callback (only on platforms which support it).
8910 *
8911 * @param enmEvent The thread-context event.
8912 * @param pVCpu The cross context virtual CPU structure.
8913 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
8914 * @thread EMT(pVCpu)
8915 */
8916VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
8917{
8918 AssertPtr(pVCpu);
8919 RT_NOREF1(fGlobalInit);
8920
8921 switch (enmEvent)
8922 {
8923 case RTTHREADCTXEVENT_OUT:
8924 {
8925 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8926 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8927 VMCPU_ASSERT_EMT(pVCpu);
8928
8929 /* No longjmps (logger flushes, locks) in this fragile context. */
8930 VMMRZCallRing3Disable(pVCpu);
8931 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
8932
8933 /* Restore host-state (FPU, debug etc.) */
8934 if (!pVCpu->hm.s.fLeaveDone)
8935 {
8936 /*
8937 * Do -not- import the guest-state here as we might already be in the middle of importing
8938 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
8939 */
8940 hmR0VmxLeave(pVCpu, false /* fImportState */);
8941 pVCpu->hm.s.fLeaveDone = true;
8942 }
8943
8944 /* Leave HM context, takes care of local init (term). */
8945 int rc = HMR0LeaveCpu(pVCpu);
8946 AssertRC(rc);
8947
8948 /* Restore longjmp state. */
8949 VMMRZCallRing3Enable(pVCpu);
8950 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
8951 break;
8952 }
8953
8954 case RTTHREADCTXEVENT_IN:
8955 {
8956 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8957 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8958 VMCPU_ASSERT_EMT(pVCpu);
8959
8960 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
8961 VMMRZCallRing3Disable(pVCpu);
8962 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
8963
8964 /* Initialize the bare minimum state required for HM. This takes care of
8965 initializing VT-x if necessary (onlined CPUs, local init etc.) */
8966 int rc = hmR0EnterCpu(pVCpu);
8967 AssertRC(rc);
8968 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8969 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8970
8971 /* Load the active VMCS as the current one. */
8972 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8973 rc = hmR0VmxLoadVmcs(pVmcsInfo);
8974 AssertRC(rc);
8975 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8976 pVCpu->hm.s.fLeaveDone = false;
8977
8978 /* Do the EMT scheduled L1D flush if needed. */
8979 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8980 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8981
8982 /* Restore longjmp state. */
8983 VMMRZCallRing3Enable(pVCpu);
8984 break;
8985 }
8986
8987 default:
8988 break;
8989 }
8990}
8991
8992
8993/**
8994 * Exports the host state into the VMCS host-state area.
8995 * Sets up the VM-exit MSR-load area.
8996 *
8997 * The CPU state will be loaded from these fields on every successful VM-exit.
8998 *
8999 * @returns VBox status code.
9000 * @param pVCpu The cross context virtual CPU structure.
9001 *
9002 * @remarks No-long-jump zone!!!
9003 */
9004static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
9005{
9006 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9007
9008 int rc = VINF_SUCCESS;
9009 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9010 {
9011 hmR0VmxExportHostControlRegs();
9012
9013 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
9014 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9015
9016 hmR0VmxExportHostMsrs(pVCpu);
9017
9018 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9019 }
9020 return rc;
9021}
9022
9023
9024/**
9025 * Saves the host state in the VMCS host-state.
9026 *
9027 * @returns VBox status code.
9028 * @param pVCpu The cross context virtual CPU structure.
9029 *
9030 * @remarks No-long-jump zone!!!
9031 */
9032VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
9033{
9034 AssertPtr(pVCpu);
9035 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9036
9037 /*
9038 * Export the host state here while entering HM context.
9039 * When thread-context hooks are used, we might get preempted and have to re-save the host
9040 * state but most of the time we won't be, so do it here before we disable interrupts.
9041 */
9042 return hmR0VmxExportHostState(pVCpu);
9043}
9044
9045
9046/**
9047 * Exports the guest state into the VMCS guest-state area.
9048 *
9049 * The will typically be done before VM-entry when the guest-CPU state and the
9050 * VMCS state may potentially be out of sync.
9051 *
9052 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9053 * VM-entry controls.
9054 * Sets up the appropriate VMX non-root function to execute guest code based on
9055 * the guest CPU mode.
9056 *
9057 * @returns VBox strict status code.
9058 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9059 * without unrestricted guest execution and the VMMDev is not presently
9060 * mapped (e.g. EFI32).
9061 *
9062 * @param pVCpu The cross context virtual CPU structure.
9063 * @param pVmxTransient The VMX-transient structure.
9064 *
9065 * @remarks No-long-jump zone!!!
9066 */
9067static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9068{
9069 AssertPtr(pVCpu);
9070 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9071 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9072
9073 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9074
9075 /*
9076 * Determine real-on-v86 mode.
9077 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9078 */
9079 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9080 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9081 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9082 pVmcsInfo->RealMode.fRealOnV86Active = false;
9083 else
9084 {
9085 Assert(!pVmxTransient->fIsNestedGuest);
9086 pVmcsInfo->RealMode.fRealOnV86Active = true;
9087 }
9088
9089 /*
9090 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9091 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9092 */
9093 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9094 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9095
9096 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9097 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9098
9099 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9100 if (rcStrict == VINF_SUCCESS)
9101 { /* likely */ }
9102 else
9103 {
9104 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9105 return rcStrict;
9106 }
9107
9108 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9109 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9110
9111 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9112 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9113
9114 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9115 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9116 hmR0VmxExportGuestRip(pVCpu);
9117 hmR0VmxExportGuestRsp(pVCpu);
9118 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9119
9120 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9121 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9122
9123 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9124 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9125 | HM_CHANGED_GUEST_CR2
9126 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9127 | HM_CHANGED_GUEST_X87
9128 | HM_CHANGED_GUEST_SSE_AVX
9129 | HM_CHANGED_GUEST_OTHER_XSAVE
9130 | HM_CHANGED_GUEST_XCRx
9131 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9132 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9133 | HM_CHANGED_GUEST_TSC_AUX
9134 | HM_CHANGED_GUEST_OTHER_MSRS
9135 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9136
9137 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9138 return rc;
9139}
9140
9141
9142/**
9143 * Exports the state shared between the host and guest into the VMCS.
9144 *
9145 * @param pVCpu The cross context virtual CPU structure.
9146 * @param pVmxTransient The VMX-transient structure.
9147 *
9148 * @remarks No-long-jump zone!!!
9149 */
9150static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9151{
9152 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9153 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9154
9155 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9156 {
9157 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9158 AssertRC(rc);
9159 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9160
9161 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9162 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9163 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9164 }
9165
9166 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9167 {
9168 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9169 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9170 }
9171
9172 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9173 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9174}
9175
9176
9177/**
9178 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9179 *
9180 * @returns Strict VBox status code (i.e. informational status codes too).
9181 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9182 * without unrestricted guest execution and the VMMDev is not presently
9183 * mapped (e.g. EFI32).
9184 *
9185 * @param pVCpu The cross context virtual CPU structure.
9186 * @param pVmxTransient The VMX-transient structure.
9187 *
9188 * @remarks No-long-jump zone!!!
9189 */
9190static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9191{
9192 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9193 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9194 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9195
9196#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9197 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9198#endif
9199
9200 /*
9201 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9202 * changes. First try to export only these without going through all other changed-flag checks.
9203 */
9204 VBOXSTRICTRC rcStrict;
9205 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9206 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9207 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9208
9209 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9210 if ( (fCtxChanged & fMinimalMask)
9211 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9212 {
9213 hmR0VmxExportGuestRip(pVCpu);
9214 hmR0VmxExportGuestRsp(pVCpu);
9215 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9216 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9217 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9218 }
9219 /* If anything else also changed, go through the full export routine and export as required. */
9220 else if (fCtxChanged & fCtxMask)
9221 {
9222 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9223 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9224 { /* likely */}
9225 else
9226 {
9227 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9228 VBOXSTRICTRC_VAL(rcStrict)));
9229 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9230 return rcStrict;
9231 }
9232 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9233 }
9234 /* Nothing changed, nothing to load here. */
9235 else
9236 rcStrict = VINF_SUCCESS;
9237
9238#ifdef VBOX_STRICT
9239 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9240 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9241 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9242#endif
9243 return rcStrict;
9244}
9245
9246
9247/**
9248 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9249 * and update error record fields accordingly.
9250 *
9251 * @returns VMX_IGS_* error codes.
9252 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9253 * wrong with the guest state.
9254 *
9255 * @param pVCpu The cross context virtual CPU structure.
9256 * @param pVmcsInfo The VMCS info. object.
9257 *
9258 * @remarks This function assumes our cache of the VMCS controls
9259 * are valid, i.e. hmR0VmxCheckCachedVmcsCtls() succeeded.
9260 */
9261static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9262{
9263#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9264#define HMVMX_CHECK_BREAK(expr, err) do { \
9265 if (!(expr)) { uError = (err); break; } \
9266 } while (0)
9267
9268 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9269 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9270 uint32_t uError = VMX_IGS_ERROR;
9271 uint32_t u32IntrState = 0;
9272 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9273 do
9274 {
9275 int rc;
9276
9277 /*
9278 * Guest-interruptibility state.
9279 *
9280 * Read this first so that any check that fails prior to those that actually
9281 * require the guest-interruptibility state would still reflect the correct
9282 * VMCS value and avoids causing further confusion.
9283 */
9284 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9285 AssertRC(rc);
9286
9287 uint32_t u32Val;
9288 uint64_t u64Val;
9289
9290 /*
9291 * CR0.
9292 */
9293 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9294 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9295 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9296 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9297 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9298 if (fUnrestrictedGuest)
9299 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9300
9301 uint64_t u64GuestCr0;
9302 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9303 AssertRC(rc);
9304 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9305 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9306 if ( !fUnrestrictedGuest
9307 && (u64GuestCr0 & X86_CR0_PG)
9308 && !(u64GuestCr0 & X86_CR0_PE))
9309 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9310
9311 /*
9312 * CR4.
9313 */
9314 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9315 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9316 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9317
9318 uint64_t u64GuestCr4;
9319 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9320 AssertRC(rc);
9321 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9322 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9323
9324 /*
9325 * IA32_DEBUGCTL MSR.
9326 */
9327 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9328 AssertRC(rc);
9329 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9330 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9331 {
9332 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9333 }
9334 uint64_t u64DebugCtlMsr = u64Val;
9335
9336#ifdef VBOX_STRICT
9337 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9338 AssertRC(rc);
9339 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9340#endif
9341 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9342
9343 /*
9344 * RIP and RFLAGS.
9345 */
9346 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9347 AssertRC(rc);
9348 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9349 if ( !fLongModeGuest
9350 || !pCtx->cs.Attr.n.u1Long)
9351 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9352 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9353 * must be identical if the "IA-32e mode guest" VM-entry
9354 * control is 1 and CS.L is 1. No check applies if the
9355 * CPU supports 64 linear-address bits. */
9356
9357 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9358 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9359 AssertRC(rc);
9360 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9361 VMX_IGS_RFLAGS_RESERVED);
9362 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9363 uint32_t const u32Eflags = u64Val;
9364
9365 if ( fLongModeGuest
9366 || ( fUnrestrictedGuest
9367 && !(u64GuestCr0 & X86_CR0_PE)))
9368 {
9369 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9370 }
9371
9372 uint32_t u32EntryInfo;
9373 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9374 AssertRC(rc);
9375 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9376 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9377
9378 /*
9379 * 64-bit checks.
9380 */
9381 if (fLongModeGuest)
9382 {
9383 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9384 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9385 }
9386
9387 if ( !fLongModeGuest
9388 && (u64GuestCr4 & X86_CR4_PCIDE))
9389 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9390
9391 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9392 * 51:32 beyond the processor's physical-address width are 0. */
9393
9394 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9395 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9396 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9397
9398 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9399 AssertRC(rc);
9400 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9401
9402 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9403 AssertRC(rc);
9404 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9405
9406 /*
9407 * PERF_GLOBAL MSR.
9408 */
9409 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9410 {
9411 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9412 AssertRC(rc);
9413 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9414 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9415 }
9416
9417 /*
9418 * PAT MSR.
9419 */
9420 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9421 {
9422 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9423 AssertRC(rc);
9424 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9425 for (unsigned i = 0; i < 8; i++)
9426 {
9427 uint8_t u8Val = (u64Val & 0xff);
9428 if ( u8Val != 0 /* UC */
9429 && u8Val != 1 /* WC */
9430 && u8Val != 4 /* WT */
9431 && u8Val != 5 /* WP */
9432 && u8Val != 6 /* WB */
9433 && u8Val != 7 /* UC- */)
9434 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9435 u64Val >>= 8;
9436 }
9437 }
9438
9439 /*
9440 * EFER MSR.
9441 */
9442 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9443 {
9444 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9445 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9446 AssertRC(rc);
9447 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9448 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9449 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9450 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9451 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9452 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9453 * iemVmxVmentryCheckGuestState(). */
9454 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9455 || !(u64GuestCr0 & X86_CR0_PG)
9456 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9457 VMX_IGS_EFER_LMA_LME_MISMATCH);
9458 }
9459
9460 /*
9461 * Segment registers.
9462 */
9463 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9464 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9465 if (!(u32Eflags & X86_EFL_VM))
9466 {
9467 /* CS */
9468 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9469 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9470 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9471 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9472 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9473 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9474 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9475 /* CS cannot be loaded with NULL in protected mode. */
9476 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9477 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9478 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9479 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9480 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9481 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9482 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9483 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9484 else
9485 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9486
9487 /* SS */
9488 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9489 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9490 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9491 if ( !(pCtx->cr0 & X86_CR0_PE)
9492 || pCtx->cs.Attr.n.u4Type == 3)
9493 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9494
9495 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9496 {
9497 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9498 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9499 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9500 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9501 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9502 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9503 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9504 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9505 }
9506
9507 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9508 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9509 {
9510 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9511 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9512 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9513 || pCtx->ds.Attr.n.u4Type > 11
9514 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9515 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9516 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9517 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9518 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9519 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9520 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9521 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9522 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9523 }
9524 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9525 {
9526 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9527 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9528 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9529 || pCtx->es.Attr.n.u4Type > 11
9530 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9531 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9532 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9533 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9534 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9535 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9536 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9537 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9538 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9539 }
9540 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9541 {
9542 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9543 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9544 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9545 || pCtx->fs.Attr.n.u4Type > 11
9546 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9547 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9548 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9549 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9550 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9551 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9552 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9553 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9554 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9555 }
9556 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9557 {
9558 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9559 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9560 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9561 || pCtx->gs.Attr.n.u4Type > 11
9562 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9563 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9564 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9565 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9566 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9567 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9568 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9569 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9570 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9571 }
9572 /* 64-bit capable CPUs. */
9573 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9574 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9575 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9576 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9577 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9578 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9579 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9580 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9581 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9582 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9583 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9584 }
9585 else
9586 {
9587 /* V86 mode checks. */
9588 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9589 if (pVmcsInfo->RealMode.fRealOnV86Active)
9590 {
9591 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9592 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9593 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9594 }
9595 else
9596 {
9597 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9598 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9599 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9600 }
9601
9602 /* CS */
9603 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9604 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9605 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9606 /* SS */
9607 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9608 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9609 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9610 /* DS */
9611 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9612 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9613 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9614 /* ES */
9615 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9616 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9617 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9618 /* FS */
9619 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9620 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9621 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9622 /* GS */
9623 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9624 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9625 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9626 /* 64-bit capable CPUs. */
9627 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9628 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9629 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9630 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9631 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9632 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9633 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9634 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9635 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9636 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9637 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9638 }
9639
9640 /*
9641 * TR.
9642 */
9643 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9644 /* 64-bit capable CPUs. */
9645 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9646 if (fLongModeGuest)
9647 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9648 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9649 else
9650 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9651 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9652 VMX_IGS_TR_ATTR_TYPE_INVALID);
9653 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9654 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9655 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9656 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9657 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9658 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9659 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9660 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9661
9662 /*
9663 * GDTR and IDTR (64-bit capable checks).
9664 */
9665 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9666 AssertRC(rc);
9667 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9668
9669 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9670 AssertRC(rc);
9671 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9672
9673 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9674 AssertRC(rc);
9675 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9676
9677 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9678 AssertRC(rc);
9679 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9680
9681 /*
9682 * Guest Non-Register State.
9683 */
9684 /* Activity State. */
9685 uint32_t u32ActivityState;
9686 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9687 AssertRC(rc);
9688 HMVMX_CHECK_BREAK( !u32ActivityState
9689 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9690 VMX_IGS_ACTIVITY_STATE_INVALID);
9691 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9692 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9693
9694 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9695 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9696 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9697
9698 /** @todo Activity state and injecting interrupts. Left as a todo since we
9699 * currently don't use activity states but ACTIVE. */
9700
9701 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9702 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9703
9704 /* Guest interruptibility-state. */
9705 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9706 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9707 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9708 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9709 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9710 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9711 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9712 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9713 {
9714 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9715 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9716 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9717 }
9718 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9719 {
9720 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9721 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9722 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9723 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
9724 }
9725 /** @todo Assumes the processor is not in SMM. */
9726 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9727 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
9728 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9729 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9730 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
9731 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
9732 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9733 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
9734
9735 /* Pending debug exceptions. */
9736 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
9737 AssertRC(rc);
9738 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
9739 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
9740 u32Val = u64Val; /* For pending debug exceptions checks below. */
9741
9742 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9743 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
9744 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
9745 {
9746 if ( (u32Eflags & X86_EFL_TF)
9747 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9748 {
9749 /* Bit 14 is PendingDebug.BS. */
9750 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
9751 }
9752 if ( !(u32Eflags & X86_EFL_TF)
9753 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9754 {
9755 /* Bit 14 is PendingDebug.BS. */
9756 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
9757 }
9758 }
9759
9760 /* VMCS link pointer. */
9761 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
9762 AssertRC(rc);
9763 if (u64Val != UINT64_C(0xffffffffffffffff))
9764 {
9765 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
9766 /** @todo Bits beyond the processor's physical-address width MBZ. */
9767 /** @todo SMM checks. */
9768 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
9769 Assert(pVmcsInfo->pvShadowVmcs);
9770 VMXVMCSREVID VmcsRevId;
9771 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
9772 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
9773 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
9774 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
9775 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
9776 }
9777
9778 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
9779 * not using nested paging? */
9780 if ( pVM->hm.s.fNestedPaging
9781 && !fLongModeGuest
9782 && CPUMIsGuestInPAEModeEx(pCtx))
9783 {
9784 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
9785 AssertRC(rc);
9786 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9787
9788 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
9789 AssertRC(rc);
9790 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9791
9792 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
9793 AssertRC(rc);
9794 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9795
9796 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
9797 AssertRC(rc);
9798 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9799 }
9800
9801 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
9802 if (uError == VMX_IGS_ERROR)
9803 uError = VMX_IGS_REASON_NOT_FOUND;
9804 } while (0);
9805
9806 pVCpu->hm.s.u32HMError = uError;
9807 pVCpu->hm.s.vmx.LastError.u32GuestIntrState = u32IntrState;
9808 return uError;
9809
9810#undef HMVMX_ERROR_BREAK
9811#undef HMVMX_CHECK_BREAK
9812}
9813
9814
9815/**
9816 * Map the APIC-access page for virtualizing APIC accesses.
9817 *
9818 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
9819 * this not done as part of exporting guest state, see @bugref{8721}.
9820 *
9821 * @returns VBox status code.
9822 * @param pVCpu The cross context virtual CPU structure.
9823 */
9824static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
9825{
9826 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9827 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
9828
9829 Assert(PDMHasApic(pVM));
9830 Assert(u64MsrApicBase);
9831
9832 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
9833 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
9834
9835 /* Unalias the existing mapping. */
9836 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
9837 AssertRCReturn(rc, rc);
9838
9839 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
9840 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
9841 rc = IOMR0MmioMapMmioHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
9842 AssertRCReturn(rc, rc);
9843
9844 /* Update the per-VCPU cache of the APIC base MSR. */
9845 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
9846 return VINF_SUCCESS;
9847}
9848
9849
9850/**
9851 * Worker function passed to RTMpOnSpecific() that is to be called on the target
9852 * CPU.
9853 *
9854 * @param idCpu The ID for the CPU the function is called on.
9855 * @param pvUser1 Null, not used.
9856 * @param pvUser2 Null, not used.
9857 */
9858static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
9859{
9860 RT_NOREF3(idCpu, pvUser1, pvUser2);
9861 VMXDispatchHostNmi();
9862}
9863
9864
9865/**
9866 * Dispatching an NMI on the host CPU that received it.
9867 *
9868 * @returns VBox status code.
9869 * @param pVCpu The cross context virtual CPU structure.
9870 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
9871 * executing when receiving the host NMI in VMX non-root
9872 * operation.
9873 */
9874static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9875{
9876 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
9877 Assert(idCpu != NIL_RTCPUID);
9878
9879 /*
9880 * We don't want to delay dispatching the NMI any more than we have to. However,
9881 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
9882 * after executing guest or nested-guest code for the following reasons:
9883 *
9884 * - We would need to perform VMREADs with interrupts disabled and is orders of
9885 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
9886 * supported by the host hypervisor.
9887 *
9888 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
9889 * longer period of time just for handling an edge case like host NMIs which do
9890 * not occur nearly as frequently as other VM-exits.
9891 *
9892 * Let's cover the most likely scenario first. Check if we are on the target CPU
9893 * and dispatch the NMI right away. This should be much faster than calling into
9894 * RTMpOnSpecific() machinery.
9895 */
9896 bool fDispatched = false;
9897 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
9898 if (idCpu == RTMpCpuId())
9899 {
9900 VMXDispatchHostNmi();
9901 fDispatched = true;
9902 }
9903 ASMSetFlags(fEFlags);
9904 if (fDispatched)
9905 {
9906 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
9907 return VINF_SUCCESS;
9908 }
9909
9910 /*
9911 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
9912 * there should be no race or recursion even if we are unlucky enough to be preempted
9913 * (to the target CPU) without dispatching the host NMI above.
9914 */
9915 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
9916 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
9917}
9918
9919
9920#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9921/**
9922 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
9923 * nested-guest using hardware-assisted VMX.
9924 *
9925 * @param pVCpu The cross context virtual CPU structure.
9926 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
9927 * @param pVmcsInfoGst The guest VMCS info. object.
9928 */
9929static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
9930{
9931 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
9932 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
9933 Assert(pu64MsrBitmap);
9934
9935 /*
9936 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
9937 * MSR that is intercepted by the guest is also intercepted while executing the
9938 * nested-guest using hardware-assisted VMX.
9939 *
9940 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
9941 * nested-guest VM-exit even if the outer guest is not intercepting some
9942 * MSRs. We cannot assume the caller has initialized the nested-guest
9943 * MSR bitmap in this case.
9944 *
9945 * The nested hypervisor may also switch whether it uses MSR bitmaps for
9946 * each VM-entry, hence initializing it once per-VM while setting up the
9947 * nested-guest VMCS is not sufficient.
9948 */
9949 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9950 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
9951 {
9952 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
9953 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
9954 Assert(pu64MsrBitmapNstGst);
9955 Assert(pu64MsrBitmapGst);
9956
9957 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
9958 for (uint32_t i = 0; i < cFrags; i++)
9959 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
9960 }
9961 else
9962 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
9963}
9964
9965
9966/**
9967 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
9968 * hardware-assisted VMX execution of the nested-guest.
9969 *
9970 * For a guest, we don't modify these controls once we set up the VMCS and hence
9971 * this function is never called.
9972 *
9973 * For nested-guests since the nested hypervisor provides these controls on every
9974 * nested-guest VM-entry and could potentially change them everytime we need to
9975 * merge them before every nested-guest VM-entry.
9976 *
9977 * @returns VBox status code.
9978 * @param pVCpu The cross context virtual CPU structure.
9979 */
9980static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
9981{
9982 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9983 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
9984 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9985 Assert(pVmcsNstGst);
9986
9987 /*
9988 * Merge the controls with the requirements of the guest VMCS.
9989 *
9990 * We do not need to validate the nested-guest VMX features specified in the nested-guest
9991 * VMCS with the features supported by the physical CPU as it's already done by the
9992 * VMLAUNCH/VMRESUME instruction emulation.
9993 *
9994 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
9995 * derived from the VMX features supported by the physical CPU.
9996 */
9997
9998 /* Pin-based VM-execution controls. */
9999 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10000
10001 /* Processor-based VM-execution controls. */
10002 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10003 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10004 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10005 | VMX_PROC_CTLS_USE_TPR_SHADOW
10006 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10007
10008 /* Secondary processor-based VM-execution controls. */
10009 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10010 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10011 | VMX_PROC_CTLS2_INVPCID
10012 | VMX_PROC_CTLS2_VMCS_SHADOWING
10013 | VMX_PROC_CTLS2_RDTSCP
10014 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10015 | VMX_PROC_CTLS2_APIC_REG_VIRT
10016 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10017 | VMX_PROC_CTLS2_VMFUNC));
10018
10019 /*
10020 * VM-entry controls:
10021 * These controls contains state that depends on the nested-guest state (primarily
10022 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10023 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
10024 * properly continue executing the nested-guest if the EFER MSR changes but does not
10025 * cause a nested-guest VM-exits.
10026 *
10027 * VM-exit controls:
10028 * These controls specify the host state on return. We cannot use the controls from
10029 * the nested hypervisor state as is as it would contain the guest state rather than
10030 * the host state. Since the host state is subject to change (e.g. preemption, trips
10031 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10032 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10033 *
10034 * VM-entry MSR-load:
10035 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10036 * context by the VMLAUNCH/VMRESUME instruction emulation.
10037 *
10038 * VM-exit MSR-store:
10039 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10040 * back into the VM-exit MSR-store area.
10041 *
10042 * VM-exit MSR-load areas:
10043 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10044 * can entirely ignore what the nested hypervisor wants to load here.
10045 */
10046
10047 /*
10048 * Exception bitmap.
10049 *
10050 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10051 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10052 * code more flexible if intercepting exceptions become more dynamic in the future we do
10053 * it as part of exporting the nested-guest state.
10054 */
10055 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10056
10057 /*
10058 * CR0/CR4 guest/host mask.
10059 *
10060 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10061 * cause VM-exits, so we need to merge them here.
10062 */
10063 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10064 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10065
10066 /*
10067 * Page-fault error-code mask and match.
10068 *
10069 * Although we require unrestricted guest execution (and thereby nested-paging) for
10070 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10071 * normally intercept #PFs, it might intercept them for debugging purposes.
10072 *
10073 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10074 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10075 */
10076 uint32_t u32XcptPFMask;
10077 uint32_t u32XcptPFMatch;
10078 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10079 {
10080 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10081 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10082 }
10083 else
10084 {
10085 u32XcptPFMask = 0;
10086 u32XcptPFMatch = 0;
10087 }
10088
10089 /*
10090 * Pause-Loop exiting.
10091 */
10092 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10093 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10094
10095 /*
10096 * Pending debug exceptions.
10097 * Currently just copy whatever the nested-guest provides us.
10098 */
10099 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10100
10101 /*
10102 * I/O Bitmap.
10103 *
10104 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10105 * intercept all I/O port accesses.
10106 */
10107 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10108 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10109
10110 /*
10111 * VMCS shadowing.
10112 *
10113 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10114 * enabled while executing the nested-guest.
10115 */
10116 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10117
10118 /*
10119 * APIC-access page.
10120 */
10121 RTHCPHYS HCPhysApicAccess;
10122 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10123 {
10124 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10125 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10126
10127 /** @todo NSTVMX: This is not really correct but currently is required to make
10128 * things work. We need to re-enable the page handler when we fallback to
10129 * IEM execution of the nested-guest! */
10130 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10131
10132 void *pvPage;
10133 PGMPAGEMAPLOCK PgLockApicAccess;
10134 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10135 if (RT_SUCCESS(rc))
10136 {
10137 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10138 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10139
10140 /** @todo Handle proper releasing of page-mapping lock later. */
10141 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10142 }
10143 else
10144 return rc;
10145 }
10146 else
10147 HCPhysApicAccess = 0;
10148
10149 /*
10150 * Virtual-APIC page and TPR threshold.
10151 */
10152 RTHCPHYS HCPhysVirtApic;
10153 uint32_t u32TprThreshold;
10154 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10155 {
10156 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10157 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10158
10159 void *pvPage;
10160 PGMPAGEMAPLOCK PgLockVirtApic;
10161 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10162 if (RT_SUCCESS(rc))
10163 {
10164 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10165 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10166
10167 /** @todo Handle proper releasing of page-mapping lock later. */
10168 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10169 }
10170 else
10171 return rc;
10172
10173 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10174 }
10175 else
10176 {
10177 HCPhysVirtApic = 0;
10178 u32TprThreshold = 0;
10179
10180 /*
10181 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10182 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10183 * be taken care of by EPT/shadow paging.
10184 */
10185 if (pVM->hm.s.fAllow64BitGuests)
10186 {
10187 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10188 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10189 }
10190 }
10191
10192 /*
10193 * Validate basic assumptions.
10194 */
10195 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10196 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10197 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10198 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10199
10200 /*
10201 * Commit it to the nested-guest VMCS.
10202 */
10203 int rc = VINF_SUCCESS;
10204 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10205 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10206 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10207 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10208 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10209 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10210 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10211 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10212 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10213 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10214 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10215 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10216 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10217 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10218 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10219 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10220 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10221 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10222 {
10223 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10224 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10225 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10226 }
10227 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10228 {
10229 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10230 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10231 }
10232 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10233 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10234 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10235 AssertRC(rc);
10236
10237 /*
10238 * Update the nested-guest VMCS cache.
10239 */
10240 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10241 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10242 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10243 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10244 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10245 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10246 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10247 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10248 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10249
10250 /*
10251 * We need to flush the TLB if we are switching the APIC-access page address.
10252 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10253 */
10254 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10255 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10256
10257 /*
10258 * MSR bitmap.
10259 *
10260 * The MSR bitmap address has already been initialized while setting up the nested-guest
10261 * VMCS, here we need to merge the MSR bitmaps.
10262 */
10263 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10264 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10265
10266 return VINF_SUCCESS;
10267}
10268#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10269
10270
10271/**
10272 * Does the preparations before executing guest code in VT-x.
10273 *
10274 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10275 * recompiler/IEM. We must be cautious what we do here regarding committing
10276 * guest-state information into the VMCS assuming we assuredly execute the
10277 * guest in VT-x mode.
10278 *
10279 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10280 * the common-state (TRPM/forceflags), we must undo those changes so that the
10281 * recompiler/IEM can (and should) use them when it resumes guest execution.
10282 * Otherwise such operations must be done when we can no longer exit to ring-3.
10283 *
10284 * @returns Strict VBox status code (i.e. informational status codes too).
10285 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10286 * have been disabled.
10287 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10288 * pending events).
10289 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10290 * double-fault into the guest.
10291 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10292 * dispatched directly.
10293 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10294 *
10295 * @param pVCpu The cross context virtual CPU structure.
10296 * @param pVmxTransient The VMX-transient structure.
10297 * @param fStepping Whether we are single-stepping the guest in the
10298 * hypervisor debugger. Makes us ignore some of the reasons
10299 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10300 * if event dispatching took place.
10301 */
10302static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10303{
10304 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10305
10306 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10307
10308#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10309 if (pVmxTransient->fIsNestedGuest)
10310 {
10311 RT_NOREF2(pVCpu, fStepping);
10312 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10313 return VINF_EM_RESCHEDULE_REM;
10314 }
10315#endif
10316
10317#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10318 PGMRZDynMapFlushAutoSet(pVCpu);
10319#endif
10320
10321 /*
10322 * Check and process force flag actions, some of which might require us to go back to ring-3.
10323 */
10324 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, pVmxTransient, fStepping);
10325 if (rcStrict == VINF_SUCCESS)
10326 {
10327 /* FFs don't get set all the time. */
10328#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10329 if ( pVmxTransient->fIsNestedGuest
10330 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10331 {
10332 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10333 return VINF_VMX_VMEXIT;
10334 }
10335#endif
10336 }
10337 else
10338 return rcStrict;
10339
10340 /*
10341 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10342 */
10343 /** @todo Doing this from ring-3 after VM setup phase causes a
10344 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
10345 * idea why atm. */
10346 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10347 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10348 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10349 && PDMHasApic(pVM))
10350 {
10351 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10352 AssertRCReturn(rc, rc);
10353 }
10354
10355#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10356 /*
10357 * Merge guest VMCS controls with the nested-guest VMCS controls.
10358 *
10359 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10360 * saved state), we should be okay with merging controls as we initialize the
10361 * guest VMCS controls as part of VM setup phase.
10362 */
10363 if ( pVmxTransient->fIsNestedGuest
10364 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10365 {
10366 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10367 AssertRCReturn(rc, rc);
10368 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10369 }
10370#endif
10371
10372 /*
10373 * Evaluate events to be injected into the guest.
10374 *
10375 * Events in TRPM can be injected without inspecting the guest state.
10376 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10377 * guest to cause a VM-exit the next time they are ready to receive the event.
10378 *
10379 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10380 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10381 * subject to interecption. Otherwise, we should have checked and injected them
10382 * manually elsewhere (IEM).
10383 */
10384 if (TRPMHasTrap(pVCpu))
10385 {
10386 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10387 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10388 }
10389
10390 uint32_t fIntrState;
10391 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10392
10393#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10394 /*
10395 * While evaluating pending events if something failed (unlikely) or if we were
10396 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10397 */
10398 if (rcStrict != VINF_SUCCESS)
10399 return rcStrict;
10400 if ( pVmxTransient->fIsNestedGuest
10401 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10402 {
10403 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10404 return VINF_VMX_VMEXIT;
10405 }
10406#else
10407 Assert(rcStrict == VINF_SUCCESS);
10408#endif
10409
10410 /*
10411 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10412 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10413 * also result in triple-faulting the VM.
10414 *
10415 * With nested-guests, the above does not apply since unrestricted guest execution is a
10416 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10417 */
10418 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10419 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10420 { /* likely */ }
10421 else
10422 {
10423 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10424 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10425 return rcStrict;
10426 }
10427
10428 /*
10429 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10430 * import CR3 themselves. We will need to update them here, as even as late as the above
10431 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10432 * the below force flags to be set.
10433 */
10434 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10435 {
10436 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10437 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10438 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10439 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10440 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10441 }
10442 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10443 {
10444 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10445 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10446 }
10447
10448#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10449 /* Paranoia. */
10450 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10451#endif
10452
10453 /*
10454 * No longjmps to ring-3 from this point on!!!
10455 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10456 * This also disables flushing of the R0-logger instance (if any).
10457 */
10458 VMMRZCallRing3Disable(pVCpu);
10459
10460 /*
10461 * Export the guest state bits.
10462 *
10463 * We cannot perform longjmps while loading the guest state because we do not preserve the
10464 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10465 * CPU migration.
10466 *
10467 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10468 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10469 */
10470 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10471 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10472 { /* likely */ }
10473 else
10474 {
10475 VMMRZCallRing3Enable(pVCpu);
10476 return rcStrict;
10477 }
10478
10479 /*
10480 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10481 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10482 * preemption disabled for a while. Since this is purely to aid the
10483 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10484 * disable interrupt on NT.
10485 *
10486 * We need to check for force-flags that could've possible been altered since we last
10487 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10488 * see @bugref{6398}).
10489 *
10490 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10491 * to ring-3 before executing guest code.
10492 */
10493 pVmxTransient->fEFlags = ASMIntDisableFlags();
10494
10495 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10496 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10497 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10498 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10499 {
10500 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10501 {
10502#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10503 /*
10504 * If we are executing a nested-guest make sure that we should intercept subsequent
10505 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10506 * the VM-exit instruction emulation happy.
10507 */
10508 if (pVmxTransient->fIsNestedGuest)
10509 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10510#endif
10511
10512 /*
10513 * We've injected any pending events. This is really the point of no return (to ring-3).
10514 *
10515 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10516 * returns from this function, so do -not- enable them here.
10517 */
10518 pVCpu->hm.s.Event.fPending = false;
10519 return VINF_SUCCESS;
10520 }
10521
10522 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10523 rcStrict = VINF_EM_RAW_INTERRUPT;
10524 }
10525 else
10526 {
10527 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10528 rcStrict = VINF_EM_RAW_TO_R3;
10529 }
10530
10531 ASMSetFlags(pVmxTransient->fEFlags);
10532 VMMRZCallRing3Enable(pVCpu);
10533
10534 return rcStrict;
10535}
10536
10537
10538/**
10539 * Final preparations before executing guest code using hardware-assisted VMX.
10540 *
10541 * We can no longer get preempted to a different host CPU and there are no returns
10542 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10543 * failures), this function is not intended to fail sans unrecoverable hardware
10544 * errors.
10545 *
10546 * @param pVCpu The cross context virtual CPU structure.
10547 * @param pVmxTransient The VMX-transient structure.
10548 *
10549 * @remarks Called with preemption disabled.
10550 * @remarks No-long-jump zone!!!
10551 */
10552static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10553{
10554 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10555 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10556 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10557 Assert(!pVCpu->hm.s.Event.fPending);
10558
10559 /*
10560 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10561 */
10562 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10563 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10564
10565 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10566 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10567 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10568 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10569
10570 if (!CPUMIsGuestFPUStateActive(pVCpu))
10571 {
10572 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10573 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10574 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10575 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10576 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10577 }
10578
10579 /*
10580 * Re-export the host state bits as we may've been preempted (only happens when
10581 * thread-context hooks are used or when the VM start function changes) or if
10582 * the host CR0 is modified while loading the guest FPU state above.
10583 *
10584 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10585 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10586 * see @bugref{8432}.
10587 *
10588 * This may also happen when switching to/from a nested-guest VMCS without leaving
10589 * ring-0.
10590 */
10591 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10592 {
10593 hmR0VmxExportHostState(pVCpu);
10594 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10595 }
10596 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10597
10598 /*
10599 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10600 */
10601 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10602 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10603 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10604
10605 /*
10606 * Store status of the shared guest/host debug state at the time of VM-entry.
10607 */
10608 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10609 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10610
10611 /*
10612 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10613 * more than one conditional check. The post-run side of our code shall determine
10614 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10615 */
10616 if (pVmcsInfo->pbVirtApic)
10617 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10618
10619 /*
10620 * Update the host MSRs values in the VM-exit MSR-load area.
10621 */
10622 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10623 {
10624 if (pVmcsInfo->cExitMsrLoad > 0)
10625 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10626 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10627 }
10628
10629 /*
10630 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10631 * VMX-preemption timer based on the next virtual sync clock deadline.
10632 */
10633 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10634 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10635 {
10636 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10637 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10638 }
10639
10640 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
10641 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
10642 if (!fIsRdtscIntercepted)
10643 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
10644 else
10645 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
10646
10647 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10648 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10649 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10650 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
10651 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
10652 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
10653
10654 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10655
10656 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10657 as we're about to start executing the guest. */
10658
10659 /*
10660 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10661 *
10662 * This is done this late as updating the TSC offsetting/preemption timer above
10663 * figures out if we can skip intercepting RDTSCP by calculating the number of
10664 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10665 */
10666 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10667 && !fIsRdtscIntercepted)
10668 {
10669 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10670
10671 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
10672 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
10673 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10674 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10675 AssertRC(rc);
10676 Assert(!pVmxTransient->fRemoveTscAuxMsr);
10677 pVmxTransient->fRemoveTscAuxMsr = true;
10678 }
10679
10680#ifdef VBOX_STRICT
10681 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
10682 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
10683 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10684 AssertRC(hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
10685#endif
10686
10687#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10688 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10689 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
10690 * see @bugref{9180#c54}. */
10691 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10692 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10693 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10694#endif
10695}
10696
10697
10698/**
10699 * First C routine invoked after running guest code using hardware-assisted VMX.
10700 *
10701 * @param pVCpu The cross context virtual CPU structure.
10702 * @param pVmxTransient The VMX-transient structure.
10703 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10704 *
10705 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10706 *
10707 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10708 * unconditionally when it is safe to do so.
10709 */
10710static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10711{
10712 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10713
10714 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10715 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10716 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10717 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10718 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10719 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10720
10721 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10722 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10723 {
10724 uint64_t uGstTsc;
10725 if (!pVmxTransient->fIsNestedGuest)
10726 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10727 else
10728 {
10729 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10730 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
10731 }
10732 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
10733 }
10734
10735 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
10736 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
10737 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10738
10739 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
10740 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
10741#ifdef VBOX_STRICT
10742 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
10743#endif
10744 Assert(!ASMIntAreEnabled());
10745 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
10746 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10747
10748#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
10749 /*
10750 * Clean all the VMCS fields in the transient structure before reading
10751 * anything from the VMCS.
10752 */
10753 pVmxTransient->uExitReason = 0;
10754 pVmxTransient->uExitIntErrorCode = 0;
10755 pVmxTransient->uExitQual = 0;
10756 pVmxTransient->uGuestLinearAddr = 0;
10757 pVmxTransient->uExitIntInfo = 0;
10758 pVmxTransient->cbExitInstr = 0;
10759 pVmxTransient->ExitInstrInfo.u = 0;
10760 pVmxTransient->uEntryIntInfo = 0;
10761 pVmxTransient->uEntryXcptErrorCode = 0;
10762 pVmxTransient->cbEntryInstr = 0;
10763 pVmxTransient->uIdtVectoringInfo = 0;
10764 pVmxTransient->uIdtVectoringErrorCode = 0;
10765#endif
10766
10767 /*
10768 * Save the basic VM-exit reason and check if the VM-entry failed.
10769 * See Intel spec. 24.9.1 "Basic VM-exit Information".
10770 */
10771 uint32_t uExitReason;
10772 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
10773 AssertRC(rc);
10774 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
10775 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
10776
10777 /*
10778 * Log the VM-exit before logging anything else as otherwise it might be a
10779 * tad confusing what happens before and after the world-switch.
10780 */
10781 HMVMX_LOG_EXIT(pVCpu, uExitReason);
10782
10783 /*
10784 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
10785 * bitmap permissions, if it was added before VM-entry.
10786 */
10787 if (pVmxTransient->fRemoveTscAuxMsr)
10788 {
10789 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
10790 pVmxTransient->fRemoveTscAuxMsr = false;
10791 }
10792
10793 /*
10794 * Check if VMLAUNCH/VMRESUME succeeded.
10795 * If this failed, we cause a guru meditation and cease further execution.
10796 *
10797 * However, if we are executing a nested-guest we might fail if we use the
10798 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
10799 */
10800 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
10801 {
10802 /*
10803 * Update the VM-exit history array here even if the VM-entry failed due to:
10804 * - Invalid guest state.
10805 * - MSR loading.
10806 * - Machine-check event.
10807 *
10808 * In any of the above cases we will still have a "valid" VM-exit reason
10809 * despite @a fVMEntryFailed being false.
10810 *
10811 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
10812 *
10813 * Note! We don't have CS or RIP at this point. Will probably address that later
10814 * by amending the history entry added here.
10815 */
10816 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
10817 UINT64_MAX, uHostTsc);
10818
10819 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
10820 {
10821 VMMRZCallRing3Enable(pVCpu);
10822
10823 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10824 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10825
10826#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
10827 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
10828#endif
10829
10830 /*
10831 * Import the guest-interruptibility state always as we need it while evaluating
10832 * injecting events on re-entry.
10833 *
10834 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
10835 * checking for real-mode while exporting the state because all bits that cause
10836 * mode changes wrt CR0 are intercepted.
10837 */
10838 uint64_t const fImportMask = CPUMCTX_EXTRN_HM_VMX_INT_STATE
10839#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
10840 | HMVMX_CPUMCTX_EXTRN_ALL
10841#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
10842 | CPUMCTX_EXTRN_RFLAGS
10843#endif
10844 ;
10845 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImportMask);
10846 AssertRC(rc);
10847
10848 /*
10849 * Sync the TPR shadow with our APIC state.
10850 */
10851 if ( !pVmxTransient->fIsNestedGuest
10852 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
10853 {
10854 Assert(pVmcsInfo->pbVirtApic);
10855 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
10856 {
10857 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
10858 AssertRC(rc);
10859 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
10860 }
10861 }
10862
10863 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10864 return;
10865 }
10866 }
10867#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10868 else if (pVmxTransient->fIsNestedGuest)
10869 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
10870#endif
10871 else
10872 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
10873
10874 VMMRZCallRing3Enable(pVCpu);
10875}
10876
10877
10878/**
10879 * Runs the guest code using hardware-assisted VMX the normal way.
10880 *
10881 * @returns VBox status code.
10882 * @param pVCpu The cross context virtual CPU structure.
10883 * @param pcLoops Pointer to the number of executed loops.
10884 */
10885static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
10886{
10887 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10888 Assert(pcLoops);
10889 Assert(*pcLoops <= cMaxResumeLoops);
10890 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10891
10892#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10893 /*
10894 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
10895 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
10896 * guest VMCS while entering the VMX ring-0 session.
10897 */
10898 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10899 {
10900 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
10901 if (RT_SUCCESS(rc))
10902 { /* likely */ }
10903 else
10904 {
10905 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
10906 return rc;
10907 }
10908 }
10909#endif
10910
10911 VMXTRANSIENT VmxTransient;
10912 RT_ZERO(VmxTransient);
10913 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10914
10915 /* Paranoia. */
10916 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
10917
10918 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10919 for (;;)
10920 {
10921 Assert(!HMR0SuspendPending());
10922 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10923 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10924
10925 /*
10926 * Preparatory work for running nested-guest code, this may force us to
10927 * return to ring-3.
10928 *
10929 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10930 */
10931 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10932 if (rcStrict != VINF_SUCCESS)
10933 break;
10934
10935 /* Interrupts are disabled at this point! */
10936 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10937 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10938 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10939 /* Interrupts are re-enabled at this point! */
10940
10941 /*
10942 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10943 */
10944 if (RT_SUCCESS(rcRun))
10945 { /* very likely */ }
10946 else
10947 {
10948 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10949 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10950 return rcRun;
10951 }
10952
10953 /*
10954 * Profile the VM-exit.
10955 */
10956 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10957 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10958 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10959 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10960 HMVMX_START_EXIT_DISPATCH_PROF();
10961
10962 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10963
10964 /*
10965 * Handle the VM-exit.
10966 */
10967#ifdef HMVMX_USE_FUNCTION_TABLE
10968 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
10969#else
10970 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
10971#endif
10972 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10973 if (rcStrict == VINF_SUCCESS)
10974 {
10975 if (++(*pcLoops) <= cMaxResumeLoops)
10976 continue;
10977 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10978 rcStrict = VINF_EM_RAW_INTERRUPT;
10979 }
10980 break;
10981 }
10982
10983 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10984 return rcStrict;
10985}
10986
10987
10988#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10989/**
10990 * Runs the nested-guest code using hardware-assisted VMX.
10991 *
10992 * @returns VBox status code.
10993 * @param pVCpu The cross context virtual CPU structure.
10994 * @param pcLoops Pointer to the number of executed loops.
10995 *
10996 * @sa hmR0VmxRunGuestCodeNormal.
10997 */
10998static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
10999{
11000 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11001 Assert(pcLoops);
11002 Assert(*pcLoops <= cMaxResumeLoops);
11003 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11004
11005 /*
11006 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11007 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11008 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11009 */
11010 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11011 {
11012 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11013 if (RT_SUCCESS(rc))
11014 { /* likely */ }
11015 else
11016 {
11017 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11018 return rc;
11019 }
11020 }
11021
11022 VMXTRANSIENT VmxTransient;
11023 RT_ZERO(VmxTransient);
11024 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11025 VmxTransient.fIsNestedGuest = true;
11026
11027 /* Paranoia. */
11028 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11029
11030 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11031 for (;;)
11032 {
11033 Assert(!HMR0SuspendPending());
11034 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11035 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11036
11037 /*
11038 * Preparatory work for running guest code, this may force us to
11039 * return to ring-3.
11040 *
11041 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11042 */
11043 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11044 if (rcStrict != VINF_SUCCESS)
11045 break;
11046
11047 /* Interrupts are disabled at this point! */
11048 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11049 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11050 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11051 /* Interrupts are re-enabled at this point! */
11052
11053 /*
11054 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11055 */
11056 if (RT_SUCCESS(rcRun))
11057 { /* very likely */ }
11058 else
11059 {
11060 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11061 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11062 return rcRun;
11063 }
11064
11065 /*
11066 * Profile the VM-exit.
11067 */
11068 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11069 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11070 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11071 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11072 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11073 HMVMX_START_EXIT_DISPATCH_PROF();
11074
11075 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11076
11077 /*
11078 * Handle the VM-exit.
11079 */
11080 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11081 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11082 if (rcStrict == VINF_SUCCESS)
11083 {
11084 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11085 {
11086 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11087 rcStrict = VINF_VMX_VMEXIT;
11088 }
11089 else
11090 {
11091 if (++(*pcLoops) <= cMaxResumeLoops)
11092 continue;
11093 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11094 rcStrict = VINF_EM_RAW_INTERRUPT;
11095 }
11096 }
11097 else
11098 Assert(rcStrict != VINF_VMX_VMEXIT);
11099 break;
11100 }
11101
11102 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11103 return rcStrict;
11104}
11105#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11106
11107
11108/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11109 * probes.
11110 *
11111 * The following few functions and associated structure contains the bloat
11112 * necessary for providing detailed debug events and dtrace probes as well as
11113 * reliable host side single stepping. This works on the principle of
11114 * "subclassing" the normal execution loop and workers. We replace the loop
11115 * method completely and override selected helpers to add necessary adjustments
11116 * to their core operation.
11117 *
11118 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11119 * any performance for debug and analysis features.
11120 *
11121 * @{
11122 */
11123
11124/**
11125 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11126 * the debug run loop.
11127 */
11128typedef struct VMXRUNDBGSTATE
11129{
11130 /** The RIP we started executing at. This is for detecting that we stepped. */
11131 uint64_t uRipStart;
11132 /** The CS we started executing with. */
11133 uint16_t uCsStart;
11134
11135 /** Whether we've actually modified the 1st execution control field. */
11136 bool fModifiedProcCtls : 1;
11137 /** Whether we've actually modified the 2nd execution control field. */
11138 bool fModifiedProcCtls2 : 1;
11139 /** Whether we've actually modified the exception bitmap. */
11140 bool fModifiedXcptBitmap : 1;
11141
11142 /** We desire the modified the CR0 mask to be cleared. */
11143 bool fClearCr0Mask : 1;
11144 /** We desire the modified the CR4 mask to be cleared. */
11145 bool fClearCr4Mask : 1;
11146 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11147 uint32_t fCpe1Extra;
11148 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11149 uint32_t fCpe1Unwanted;
11150 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11151 uint32_t fCpe2Extra;
11152 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11153 uint32_t bmXcptExtra;
11154 /** The sequence number of the Dtrace provider settings the state was
11155 * configured against. */
11156 uint32_t uDtraceSettingsSeqNo;
11157 /** VM-exits to check (one bit per VM-exit). */
11158 uint32_t bmExitsToCheck[3];
11159
11160 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11161 uint32_t fProcCtlsInitial;
11162 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11163 uint32_t fProcCtls2Initial;
11164 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11165 uint32_t bmXcptInitial;
11166} VMXRUNDBGSTATE;
11167AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11168typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11169
11170
11171/**
11172 * Initializes the VMXRUNDBGSTATE structure.
11173 *
11174 * @param pVCpu The cross context virtual CPU structure of the
11175 * calling EMT.
11176 * @param pVmxTransient The VMX-transient structure.
11177 * @param pDbgState The debug state to initialize.
11178 */
11179static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11180{
11181 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11182 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11183
11184 pDbgState->fModifiedProcCtls = false;
11185 pDbgState->fModifiedProcCtls2 = false;
11186 pDbgState->fModifiedXcptBitmap = false;
11187 pDbgState->fClearCr0Mask = false;
11188 pDbgState->fClearCr4Mask = false;
11189 pDbgState->fCpe1Extra = 0;
11190 pDbgState->fCpe1Unwanted = 0;
11191 pDbgState->fCpe2Extra = 0;
11192 pDbgState->bmXcptExtra = 0;
11193 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11194 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11195 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11196}
11197
11198
11199/**
11200 * Updates the VMSC fields with changes requested by @a pDbgState.
11201 *
11202 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11203 * immediately before executing guest code, i.e. when interrupts are disabled.
11204 * We don't check status codes here as we cannot easily assert or return in the
11205 * latter case.
11206 *
11207 * @param pVCpu The cross context virtual CPU structure.
11208 * @param pVmxTransient The VMX-transient structure.
11209 * @param pDbgState The debug state.
11210 */
11211static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11212{
11213 /*
11214 * Ensure desired flags in VMCS control fields are set.
11215 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11216 *
11217 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11218 * there should be no stale data in pCtx at this point.
11219 */
11220 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11221 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11222 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11223 {
11224 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11225 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11226 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11227 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11228 pDbgState->fModifiedProcCtls = true;
11229 }
11230
11231 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11232 {
11233 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11234 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11235 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11236 pDbgState->fModifiedProcCtls2 = true;
11237 }
11238
11239 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11240 {
11241 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11242 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11243 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11244 pDbgState->fModifiedXcptBitmap = true;
11245 }
11246
11247 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11248 {
11249 pVmcsInfo->u64Cr0Mask = 0;
11250 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11251 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11252 }
11253
11254 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11255 {
11256 pVmcsInfo->u64Cr4Mask = 0;
11257 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11258 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11259 }
11260
11261 NOREF(pVCpu);
11262}
11263
11264
11265/**
11266 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11267 * re-entry next time around.
11268 *
11269 * @returns Strict VBox status code (i.e. informational status codes too).
11270 * @param pVCpu The cross context virtual CPU structure.
11271 * @param pVmxTransient The VMX-transient structure.
11272 * @param pDbgState The debug state.
11273 * @param rcStrict The return code from executing the guest using single
11274 * stepping.
11275 */
11276static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11277 VBOXSTRICTRC rcStrict)
11278{
11279 /*
11280 * Restore VM-exit control settings as we may not reenter this function the
11281 * next time around.
11282 */
11283 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11284
11285 /* We reload the initial value, trigger what we can of recalculations the
11286 next time around. From the looks of things, that's all that's required atm. */
11287 if (pDbgState->fModifiedProcCtls)
11288 {
11289 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11290 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11291 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11292 AssertRC(rc2);
11293 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11294 }
11295
11296 /* We're currently the only ones messing with this one, so just restore the
11297 cached value and reload the field. */
11298 if ( pDbgState->fModifiedProcCtls2
11299 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11300 {
11301 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11302 AssertRC(rc2);
11303 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11304 }
11305
11306 /* If we've modified the exception bitmap, we restore it and trigger
11307 reloading and partial recalculation the next time around. */
11308 if (pDbgState->fModifiedXcptBitmap)
11309 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11310
11311 return rcStrict;
11312}
11313
11314
11315/**
11316 * Configures VM-exit controls for current DBGF and DTrace settings.
11317 *
11318 * This updates @a pDbgState and the VMCS execution control fields to reflect
11319 * the necessary VM-exits demanded by DBGF and DTrace.
11320 *
11321 * @param pVCpu The cross context virtual CPU structure.
11322 * @param pVmxTransient The VMX-transient structure. May update
11323 * fUpdatedTscOffsettingAndPreemptTimer.
11324 * @param pDbgState The debug state.
11325 */
11326static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11327{
11328 /*
11329 * Take down the dtrace serial number so we can spot changes.
11330 */
11331 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11332 ASMCompilerBarrier();
11333
11334 /*
11335 * We'll rebuild most of the middle block of data members (holding the
11336 * current settings) as we go along here, so start by clearing it all.
11337 */
11338 pDbgState->bmXcptExtra = 0;
11339 pDbgState->fCpe1Extra = 0;
11340 pDbgState->fCpe1Unwanted = 0;
11341 pDbgState->fCpe2Extra = 0;
11342 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11343 pDbgState->bmExitsToCheck[i] = 0;
11344
11345 /*
11346 * Software interrupts (INT XXh) - no idea how to trigger these...
11347 */
11348 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11349 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11350 || VBOXVMM_INT_SOFTWARE_ENABLED())
11351 {
11352 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11353 }
11354
11355 /*
11356 * INT3 breakpoints - triggered by #BP exceptions.
11357 */
11358 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11359 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11360
11361 /*
11362 * Exception bitmap and XCPT events+probes.
11363 */
11364 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11365 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11366 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11367
11368 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11369 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11370 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11371 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11372 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11373 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11374 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11375 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11376 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11377 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11378 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11379 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11380 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11381 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11382 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11383 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11384 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11385 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11386
11387 if (pDbgState->bmXcptExtra)
11388 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11389
11390 /*
11391 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11392 *
11393 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11394 * So, when adding/changing/removing please don't forget to update it.
11395 *
11396 * Some of the macros are picking up local variables to save horizontal space,
11397 * (being able to see it in a table is the lesser evil here).
11398 */
11399#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11400 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11401 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11402#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11403 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11404 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11405 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11406 } else do { } while (0)
11407#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11408 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11409 { \
11410 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11411 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11412 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11413 } else do { } while (0)
11414#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11415 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11416 { \
11417 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11418 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11419 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11420 } else do { } while (0)
11421#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11422 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11423 { \
11424 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11425 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11426 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11427 } else do { } while (0)
11428
11429 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11430 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11431 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11432 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11433 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11434
11435 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11436 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11437 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11438 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11439 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11440 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11441 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11442 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11443 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11444 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11445 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11446 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11447 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11448 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11449 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11450 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11451 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11452 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11453 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11454 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11455 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11456 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11457 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11458 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11459 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11460 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11461 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11462 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11463 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11464 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11465 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11466 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11467 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11468 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11469 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11470 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11471
11472 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11473 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11474 {
11475 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11476 | CPUMCTX_EXTRN_APIC_TPR);
11477 AssertRC(rc);
11478
11479#if 0 /** @todo fix me */
11480 pDbgState->fClearCr0Mask = true;
11481 pDbgState->fClearCr4Mask = true;
11482#endif
11483 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11484 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11485 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11486 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11487 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11488 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11489 require clearing here and in the loop if we start using it. */
11490 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11491 }
11492 else
11493 {
11494 if (pDbgState->fClearCr0Mask)
11495 {
11496 pDbgState->fClearCr0Mask = false;
11497 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11498 }
11499 if (pDbgState->fClearCr4Mask)
11500 {
11501 pDbgState->fClearCr4Mask = false;
11502 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11503 }
11504 }
11505 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11506 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11507
11508 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11509 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11510 {
11511 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11512 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11513 }
11514 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11515 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11516
11517 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11518 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11519 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11520 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11521 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11522 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11523 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11524 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11525#if 0 /** @todo too slow, fix handler. */
11526 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11527#endif
11528 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11529
11530 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11531 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11532 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11533 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11534 {
11535 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11536 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11537 }
11538 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11539 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11540 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11541 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11542
11543 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11544 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11545 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11546 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11547 {
11548 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11549 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11550 }
11551 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11552 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11553 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11554 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11555
11556 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11557 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11558 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11559 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11560 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11561 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11562 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11563 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11564 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11565 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11566 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11567 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11568 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11569 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11570 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11571 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11572 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11573 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11574 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11575 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11576 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11577 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11578
11579#undef IS_EITHER_ENABLED
11580#undef SET_ONLY_XBM_IF_EITHER_EN
11581#undef SET_CPE1_XBM_IF_EITHER_EN
11582#undef SET_CPEU_XBM_IF_EITHER_EN
11583#undef SET_CPE2_XBM_IF_EITHER_EN
11584
11585 /*
11586 * Sanitize the control stuff.
11587 */
11588 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11589 if (pDbgState->fCpe2Extra)
11590 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11591 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11592 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11593 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11594 {
11595 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11596 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11597 }
11598
11599 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11600 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11601 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11602 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11603}
11604
11605
11606/**
11607 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11608 * appropriate.
11609 *
11610 * The caller has checked the VM-exit against the
11611 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11612 * already, so we don't have to do that either.
11613 *
11614 * @returns Strict VBox status code (i.e. informational status codes too).
11615 * @param pVCpu The cross context virtual CPU structure.
11616 * @param pVmxTransient The VMX-transient structure.
11617 * @param uExitReason The VM-exit reason.
11618 *
11619 * @remarks The name of this function is displayed by dtrace, so keep it short
11620 * and to the point. No longer than 33 chars long, please.
11621 */
11622static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11623{
11624 /*
11625 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11626 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11627 *
11628 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11629 * does. Must add/change/remove both places. Same ordering, please.
11630 *
11631 * Added/removed events must also be reflected in the next section
11632 * where we dispatch dtrace events.
11633 */
11634 bool fDtrace1 = false;
11635 bool fDtrace2 = false;
11636 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11637 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11638 uint32_t uEventArg = 0;
11639#define SET_EXIT(a_EventSubName) \
11640 do { \
11641 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11642 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11643 } while (0)
11644#define SET_BOTH(a_EventSubName) \
11645 do { \
11646 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11647 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11648 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11649 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11650 } while (0)
11651 switch (uExitReason)
11652 {
11653 case VMX_EXIT_MTF:
11654 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11655
11656 case VMX_EXIT_XCPT_OR_NMI:
11657 {
11658 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11659 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11660 {
11661 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11662 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11663 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11664 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11665 {
11666 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11667 {
11668 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11669 uEventArg = pVmxTransient->uExitIntErrorCode;
11670 }
11671 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11672 switch (enmEvent1)
11673 {
11674 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11675 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11676 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11677 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11678 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11679 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11680 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11681 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11682 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11683 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11684 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11685 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11686 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11687 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11688 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11689 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11690 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11691 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11692 default: break;
11693 }
11694 }
11695 else
11696 AssertFailed();
11697 break;
11698
11699 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11700 uEventArg = idxVector;
11701 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11702 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11703 break;
11704 }
11705 break;
11706 }
11707
11708 case VMX_EXIT_TRIPLE_FAULT:
11709 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11710 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11711 break;
11712 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11713 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11714 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11715 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11716 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11717
11718 /* Instruction specific VM-exits: */
11719 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11720 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11721 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11722 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11723 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11724 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11725 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11726 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
11727 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
11728 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
11729 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
11730 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
11731 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
11732 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
11733 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
11734 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
11735 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
11736 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
11737 case VMX_EXIT_MOV_CRX:
11738 hmR0VmxReadExitQualVmcs(pVmxTransient);
11739 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
11740 SET_BOTH(CRX_READ);
11741 else
11742 SET_BOTH(CRX_WRITE);
11743 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
11744 break;
11745 case VMX_EXIT_MOV_DRX:
11746 hmR0VmxReadExitQualVmcs(pVmxTransient);
11747 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
11748 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
11749 SET_BOTH(DRX_READ);
11750 else
11751 SET_BOTH(DRX_WRITE);
11752 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
11753 break;
11754 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
11755 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
11756 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
11757 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
11758 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
11759 case VMX_EXIT_GDTR_IDTR_ACCESS:
11760 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11761 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
11762 {
11763 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
11764 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
11765 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
11766 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
11767 }
11768 break;
11769
11770 case VMX_EXIT_LDTR_TR_ACCESS:
11771 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11772 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
11773 {
11774 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
11775 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
11776 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
11777 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
11778 }
11779 break;
11780
11781 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
11782 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
11783 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
11784 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
11785 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
11786 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
11787 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
11788 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
11789 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
11790 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
11791 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
11792
11793 /* Events that aren't relevant at this point. */
11794 case VMX_EXIT_EXT_INT:
11795 case VMX_EXIT_INT_WINDOW:
11796 case VMX_EXIT_NMI_WINDOW:
11797 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11798 case VMX_EXIT_PREEMPT_TIMER:
11799 case VMX_EXIT_IO_INSTR:
11800 break;
11801
11802 /* Errors and unexpected events. */
11803 case VMX_EXIT_INIT_SIGNAL:
11804 case VMX_EXIT_SIPI:
11805 case VMX_EXIT_IO_SMI:
11806 case VMX_EXIT_SMI:
11807 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11808 case VMX_EXIT_ERR_MSR_LOAD:
11809 case VMX_EXIT_ERR_MACHINE_CHECK:
11810 case VMX_EXIT_PML_FULL:
11811 case VMX_EXIT_VIRTUALIZED_EOI:
11812 break;
11813
11814 default:
11815 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
11816 break;
11817 }
11818#undef SET_BOTH
11819#undef SET_EXIT
11820
11821 /*
11822 * Dtrace tracepoints go first. We do them here at once so we don't
11823 * have to copy the guest state saving and stuff a few dozen times.
11824 * Down side is that we've got to repeat the switch, though this time
11825 * we use enmEvent since the probes are a subset of what DBGF does.
11826 */
11827 if (fDtrace1 || fDtrace2)
11828 {
11829 hmR0VmxReadExitQualVmcs(pVmxTransient);
11830 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11831 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
11832 switch (enmEvent1)
11833 {
11834 /** @todo consider which extra parameters would be helpful for each probe. */
11835 case DBGFEVENT_END: break;
11836 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
11837 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
11838 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
11839 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
11840 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
11841 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
11842 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
11843 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
11844 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
11845 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
11846 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
11847 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
11848 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
11849 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
11850 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
11851 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
11852 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
11853 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
11854 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11855 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11856 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
11857 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
11858 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
11859 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
11860 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
11861 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
11862 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
11863 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11864 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11865 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11866 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11867 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11868 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
11869 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11870 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
11871 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
11872 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
11873 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
11874 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
11875 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
11876 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
11877 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
11878 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
11879 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
11880 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
11881 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
11882 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
11883 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
11884 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
11885 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
11886 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
11887 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
11888 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
11889 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
11890 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
11891 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
11892 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
11893 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
11894 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
11895 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
11896 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
11897 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
11898 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
11899 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
11900 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
11901 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
11902 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
11903 }
11904 switch (enmEvent2)
11905 {
11906 /** @todo consider which extra parameters would be helpful for each probe. */
11907 case DBGFEVENT_END: break;
11908 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
11909 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11910 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
11911 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
11912 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
11913 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
11914 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
11915 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
11916 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
11917 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11918 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11919 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11920 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11921 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11922 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
11923 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11924 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
11925 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
11926 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
11927 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
11928 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
11929 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
11930 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
11931 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
11932 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
11933 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
11934 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
11935 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
11936 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
11937 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
11938 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
11939 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
11940 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
11941 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
11942 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
11943 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
11944 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
11945 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
11946 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
11947 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
11948 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
11949 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
11950 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
11951 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
11952 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
11953 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
11954 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
11955 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
11956 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
11957 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
11958 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
11959 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
11960 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
11961 }
11962 }
11963
11964 /*
11965 * Fire of the DBGF event, if enabled (our check here is just a quick one,
11966 * the DBGF call will do a full check).
11967 *
11968 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
11969 * Note! If we have to events, we prioritize the first, i.e. the instruction
11970 * one, in order to avoid event nesting.
11971 */
11972 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11973 if ( enmEvent1 != DBGFEVENT_END
11974 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
11975 {
11976 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11977 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
11978 if (rcStrict != VINF_SUCCESS)
11979 return rcStrict;
11980 }
11981 else if ( enmEvent2 != DBGFEVENT_END
11982 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
11983 {
11984 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11985 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
11986 if (rcStrict != VINF_SUCCESS)
11987 return rcStrict;
11988 }
11989
11990 return VINF_SUCCESS;
11991}
11992
11993
11994/**
11995 * Single-stepping VM-exit filtering.
11996 *
11997 * This is preprocessing the VM-exits and deciding whether we've gotten far
11998 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
11999 * handling is performed.
12000 *
12001 * @returns Strict VBox status code (i.e. informational status codes too).
12002 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12003 * @param pVmxTransient The VMX-transient structure.
12004 * @param pDbgState The debug state.
12005 */
12006DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12007{
12008 /*
12009 * Expensive (saves context) generic dtrace VM-exit probe.
12010 */
12011 uint32_t const uExitReason = pVmxTransient->uExitReason;
12012 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12013 { /* more likely */ }
12014 else
12015 {
12016 hmR0VmxReadExitQualVmcs(pVmxTransient);
12017 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12018 AssertRC(rc);
12019 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12020 }
12021
12022 /*
12023 * Check for host NMI, just to get that out of the way.
12024 */
12025 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12026 { /* normally likely */ }
12027 else
12028 {
12029 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12030 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12031 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12032 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12033 }
12034
12035 /*
12036 * Check for single stepping event if we're stepping.
12037 */
12038 if (pVCpu->hm.s.fSingleInstruction)
12039 {
12040 switch (uExitReason)
12041 {
12042 case VMX_EXIT_MTF:
12043 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12044
12045 /* Various events: */
12046 case VMX_EXIT_XCPT_OR_NMI:
12047 case VMX_EXIT_EXT_INT:
12048 case VMX_EXIT_TRIPLE_FAULT:
12049 case VMX_EXIT_INT_WINDOW:
12050 case VMX_EXIT_NMI_WINDOW:
12051 case VMX_EXIT_TASK_SWITCH:
12052 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12053 case VMX_EXIT_APIC_ACCESS:
12054 case VMX_EXIT_EPT_VIOLATION:
12055 case VMX_EXIT_EPT_MISCONFIG:
12056 case VMX_EXIT_PREEMPT_TIMER:
12057
12058 /* Instruction specific VM-exits: */
12059 case VMX_EXIT_CPUID:
12060 case VMX_EXIT_GETSEC:
12061 case VMX_EXIT_HLT:
12062 case VMX_EXIT_INVD:
12063 case VMX_EXIT_INVLPG:
12064 case VMX_EXIT_RDPMC:
12065 case VMX_EXIT_RDTSC:
12066 case VMX_EXIT_RSM:
12067 case VMX_EXIT_VMCALL:
12068 case VMX_EXIT_VMCLEAR:
12069 case VMX_EXIT_VMLAUNCH:
12070 case VMX_EXIT_VMPTRLD:
12071 case VMX_EXIT_VMPTRST:
12072 case VMX_EXIT_VMREAD:
12073 case VMX_EXIT_VMRESUME:
12074 case VMX_EXIT_VMWRITE:
12075 case VMX_EXIT_VMXOFF:
12076 case VMX_EXIT_VMXON:
12077 case VMX_EXIT_MOV_CRX:
12078 case VMX_EXIT_MOV_DRX:
12079 case VMX_EXIT_IO_INSTR:
12080 case VMX_EXIT_RDMSR:
12081 case VMX_EXIT_WRMSR:
12082 case VMX_EXIT_MWAIT:
12083 case VMX_EXIT_MONITOR:
12084 case VMX_EXIT_PAUSE:
12085 case VMX_EXIT_GDTR_IDTR_ACCESS:
12086 case VMX_EXIT_LDTR_TR_ACCESS:
12087 case VMX_EXIT_INVEPT:
12088 case VMX_EXIT_RDTSCP:
12089 case VMX_EXIT_INVVPID:
12090 case VMX_EXIT_WBINVD:
12091 case VMX_EXIT_XSETBV:
12092 case VMX_EXIT_RDRAND:
12093 case VMX_EXIT_INVPCID:
12094 case VMX_EXIT_VMFUNC:
12095 case VMX_EXIT_RDSEED:
12096 case VMX_EXIT_XSAVES:
12097 case VMX_EXIT_XRSTORS:
12098 {
12099 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12100 AssertRCReturn(rc, rc);
12101 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12102 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12103 return VINF_EM_DBG_STEPPED;
12104 break;
12105 }
12106
12107 /* Errors and unexpected events: */
12108 case VMX_EXIT_INIT_SIGNAL:
12109 case VMX_EXIT_SIPI:
12110 case VMX_EXIT_IO_SMI:
12111 case VMX_EXIT_SMI:
12112 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12113 case VMX_EXIT_ERR_MSR_LOAD:
12114 case VMX_EXIT_ERR_MACHINE_CHECK:
12115 case VMX_EXIT_PML_FULL:
12116 case VMX_EXIT_VIRTUALIZED_EOI:
12117 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12118 break;
12119
12120 default:
12121 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12122 break;
12123 }
12124 }
12125
12126 /*
12127 * Check for debugger event breakpoints and dtrace probes.
12128 */
12129 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12130 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12131 {
12132 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12133 if (rcStrict != VINF_SUCCESS)
12134 return rcStrict;
12135 }
12136
12137 /*
12138 * Normal processing.
12139 */
12140#ifdef HMVMX_USE_FUNCTION_TABLE
12141 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12142#else
12143 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12144#endif
12145}
12146
12147
12148/**
12149 * Single steps guest code using hardware-assisted VMX.
12150 *
12151 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12152 * but single-stepping through the hypervisor debugger.
12153 *
12154 * @returns Strict VBox status code (i.e. informational status codes too).
12155 * @param pVCpu The cross context virtual CPU structure.
12156 * @param pcLoops Pointer to the number of executed loops.
12157 *
12158 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12159 */
12160static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12161{
12162 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12163 Assert(pcLoops);
12164 Assert(*pcLoops <= cMaxResumeLoops);
12165
12166 VMXTRANSIENT VmxTransient;
12167 RT_ZERO(VmxTransient);
12168 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12169
12170 /* Set HMCPU indicators. */
12171 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12172 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12173 pVCpu->hm.s.fDebugWantRdTscExit = false;
12174 pVCpu->hm.s.fUsingDebugLoop = true;
12175
12176 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12177 VMXRUNDBGSTATE DbgState;
12178 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12179 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12180
12181 /*
12182 * The loop.
12183 */
12184 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12185 for (;;)
12186 {
12187 Assert(!HMR0SuspendPending());
12188 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12189 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12190 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12191
12192 /* Set up VM-execution controls the next two can respond to. */
12193 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12194
12195 /*
12196 * Preparatory work for running guest code, this may force us to
12197 * return to ring-3.
12198 *
12199 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12200 */
12201 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12202 if (rcStrict != VINF_SUCCESS)
12203 break;
12204
12205 /* Interrupts are disabled at this point! */
12206 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12207
12208 /* Override any obnoxious code in the above two calls. */
12209 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12210
12211 /*
12212 * Finally execute the guest.
12213 */
12214 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12215
12216 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12217 /* Interrupts are re-enabled at this point! */
12218
12219 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12220 if (RT_SUCCESS(rcRun))
12221 { /* very likely */ }
12222 else
12223 {
12224 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12225 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12226 return rcRun;
12227 }
12228
12229 /* Profile the VM-exit. */
12230 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12231 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12232 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12233 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12234 HMVMX_START_EXIT_DISPATCH_PROF();
12235
12236 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12237
12238 /*
12239 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12240 */
12241 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12242 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12243 if (rcStrict != VINF_SUCCESS)
12244 break;
12245 if (++(*pcLoops) > cMaxResumeLoops)
12246 {
12247 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12248 rcStrict = VINF_EM_RAW_INTERRUPT;
12249 break;
12250 }
12251
12252 /*
12253 * Stepping: Did the RIP change, if so, consider it a single step.
12254 * Otherwise, make sure one of the TFs gets set.
12255 */
12256 if (fStepping)
12257 {
12258 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12259 AssertRC(rc);
12260 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12261 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12262 {
12263 rcStrict = VINF_EM_DBG_STEPPED;
12264 break;
12265 }
12266 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12267 }
12268
12269 /*
12270 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12271 */
12272 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12273 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12274 }
12275
12276 /*
12277 * Clear the X86_EFL_TF if necessary.
12278 */
12279 if (pVCpu->hm.s.fClearTrapFlag)
12280 {
12281 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12282 AssertRC(rc);
12283 pVCpu->hm.s.fClearTrapFlag = false;
12284 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12285 }
12286 /** @todo there seems to be issues with the resume flag when the monitor trap
12287 * flag is pending without being used. Seen early in bios init when
12288 * accessing APIC page in protected mode. */
12289
12290 /*
12291 * Restore VM-exit control settings as we may not re-enter this function the
12292 * next time around.
12293 */
12294 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12295
12296 /* Restore HMCPU indicators. */
12297 pVCpu->hm.s.fUsingDebugLoop = false;
12298 pVCpu->hm.s.fDebugWantRdTscExit = false;
12299 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12300
12301 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12302 return rcStrict;
12303}
12304
12305
12306/** @} */
12307
12308
12309/**
12310 * Checks if any expensive dtrace probes are enabled and we should go to the
12311 * debug loop.
12312 *
12313 * @returns true if we should use debug loop, false if not.
12314 */
12315static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12316{
12317 /* It's probably faster to OR the raw 32-bit counter variables together.
12318 Since the variables are in an array and the probes are next to one
12319 another (more or less), we have good locality. So, better read
12320 eight-nine cache lines ever time and only have one conditional, than
12321 128+ conditionals, right? */
12322 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12323 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12324 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12325 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12326 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12327 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12328 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12329 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12330 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12331 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12332 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12333 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12334 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12335 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12336 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12337 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12338 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12339 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12340 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12341 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12342 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12343 ) != 0
12344 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12345 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12346 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12347 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12348 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12349 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12350 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12351 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12352 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12353 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12354 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12355 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12356 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12357 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12358 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12359 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12360 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12361 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12362 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12363 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12364 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12365 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12366 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12367 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12368 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12369 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12370 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12371 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12372 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12373 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12374 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12375 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12376 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12377 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12378 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12379 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12380 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12381 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12382 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12383 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12384 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12385 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12386 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12387 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12388 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12389 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12390 ) != 0
12391 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12392 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12393 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12394 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12395 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12396 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12397 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12398 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12399 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12400 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12401 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12402 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12403 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12404 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12405 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12406 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12407 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12408 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12409 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12410 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12411 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12412 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12413 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12414 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12415 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12416 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12417 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12418 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12419 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12420 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12421 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12422 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12423 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12424 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12425 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12426 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12427 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12428 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12429 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12430 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12431 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12432 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12433 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12434 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12435 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12436 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12437 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12438 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12439 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12440 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12441 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12442 ) != 0;
12443}
12444
12445
12446/**
12447 * Runs the guest using hardware-assisted VMX.
12448 *
12449 * @returns Strict VBox status code (i.e. informational status codes too).
12450 * @param pVCpu The cross context virtual CPU structure.
12451 */
12452VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12453{
12454 AssertPtr(pVCpu);
12455 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12456 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12457 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12458 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12459
12460 VBOXSTRICTRC rcStrict;
12461 uint32_t cLoops = 0;
12462 for (;;)
12463 {
12464#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12465 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12466#else
12467 NOREF(pCtx);
12468 bool const fInNestedGuestMode = false;
12469#endif
12470 if (!fInNestedGuestMode)
12471 {
12472 if ( !pVCpu->hm.s.fUseDebugLoop
12473 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12474 && !DBGFIsStepping(pVCpu)
12475 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12476 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12477 else
12478 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12479 }
12480#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12481 else
12482 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12483
12484 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12485 {
12486 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12487 continue;
12488 }
12489 if (rcStrict == VINF_VMX_VMEXIT)
12490 {
12491 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12492 continue;
12493 }
12494#endif
12495 break;
12496 }
12497
12498 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12499 switch (rcLoop)
12500 {
12501 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12502 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12503 }
12504
12505 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12506 if (RT_FAILURE(rc2))
12507 {
12508 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12509 rcStrict = rc2;
12510 }
12511 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12512 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12513 return rcStrict;
12514}
12515
12516
12517#ifndef HMVMX_USE_FUNCTION_TABLE
12518/**
12519 * Handles a guest VM-exit from hardware-assisted VMX execution.
12520 *
12521 * @returns Strict VBox status code (i.e. informational status codes too).
12522 * @param pVCpu The cross context virtual CPU structure.
12523 * @param pVmxTransient The VMX-transient structure.
12524 */
12525DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12526{
12527#ifdef DEBUG_ramshankar
12528# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12529 do { \
12530 if (a_fSave != 0) \
12531 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12532 VBOXSTRICTRC rcStrict = a_CallExpr; \
12533 if (a_fSave != 0) \
12534 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12535 return rcStrict; \
12536 } while (0)
12537#else
12538# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12539#endif
12540 uint32_t const uExitReason = pVmxTransient->uExitReason;
12541 switch (uExitReason)
12542 {
12543 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12544 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12545 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12546 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12547 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12548 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12549 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12550 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12551 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12552 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12553 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12554 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12555 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12556 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12557 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12558 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12559 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12560 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12561 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12562 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12563 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12564 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12565 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12566 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12567 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12568 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12569 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12570 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12571 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12572 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12573#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12574 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12575 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12576 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12577 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12578 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12579 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12580 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12581 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12582 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12583 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12584 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12585#else
12586 case VMX_EXIT_VMCLEAR:
12587 case VMX_EXIT_VMLAUNCH:
12588 case VMX_EXIT_VMPTRLD:
12589 case VMX_EXIT_VMPTRST:
12590 case VMX_EXIT_VMREAD:
12591 case VMX_EXIT_VMRESUME:
12592 case VMX_EXIT_VMWRITE:
12593 case VMX_EXIT_VMXOFF:
12594 case VMX_EXIT_VMXON:
12595 case VMX_EXIT_INVVPID:
12596 case VMX_EXIT_INVEPT:
12597 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12598#endif
12599
12600 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12601 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12602 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12603
12604 case VMX_EXIT_INIT_SIGNAL:
12605 case VMX_EXIT_SIPI:
12606 case VMX_EXIT_IO_SMI:
12607 case VMX_EXIT_SMI:
12608 case VMX_EXIT_ERR_MSR_LOAD:
12609 case VMX_EXIT_ERR_MACHINE_CHECK:
12610 case VMX_EXIT_PML_FULL:
12611 case VMX_EXIT_VIRTUALIZED_EOI:
12612 case VMX_EXIT_GDTR_IDTR_ACCESS:
12613 case VMX_EXIT_LDTR_TR_ACCESS:
12614 case VMX_EXIT_APIC_WRITE:
12615 case VMX_EXIT_RDRAND:
12616 case VMX_EXIT_RSM:
12617 case VMX_EXIT_VMFUNC:
12618 case VMX_EXIT_ENCLS:
12619 case VMX_EXIT_RDSEED:
12620 case VMX_EXIT_XSAVES:
12621 case VMX_EXIT_XRSTORS:
12622 case VMX_EXIT_UMWAIT:
12623 case VMX_EXIT_TPAUSE:
12624 default:
12625 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12626 }
12627#undef VMEXIT_CALL_RET
12628}
12629#endif /* !HMVMX_USE_FUNCTION_TABLE */
12630
12631
12632#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12633/**
12634 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12635 *
12636 * @returns Strict VBox status code (i.e. informational status codes too).
12637 * @param pVCpu The cross context virtual CPU structure.
12638 * @param pVmxTransient The VMX-transient structure.
12639 */
12640DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12641{
12642 /** @todo NSTVMX: Remove after debugging page-fault issue. */
12643#ifdef DEBUG_ramshankar
12644 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12645 Log4Func(("cs:rip=%#04x:%#RX64 rsp=%#RX64 eflags=%#RX32 cr3=%#RX64\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
12646 pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.u32, pVCpu->cpum.GstCtx.cr3));
12647#endif
12648
12649 uint32_t const uExitReason = pVmxTransient->uExitReason;
12650 switch (uExitReason)
12651 {
12652 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
12653 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
12654 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
12655 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
12656 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
12657
12658 /*
12659 * We shouldn't direct host physical interrupts to the nested-guest.
12660 */
12661 case VMX_EXIT_EXT_INT:
12662 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
12663
12664 /*
12665 * Instructions that cause VM-exits unconditionally or the condition is
12666 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12667 * happens, it's guaranteed to be a nested-guest VM-exit).
12668 *
12669 * - Provides VM-exit instruction length ONLY.
12670 */
12671 case VMX_EXIT_CPUID: /* Unconditional. */
12672 case VMX_EXIT_VMCALL:
12673 case VMX_EXIT_GETSEC:
12674 case VMX_EXIT_INVD:
12675 case VMX_EXIT_XSETBV:
12676 case VMX_EXIT_VMLAUNCH:
12677 case VMX_EXIT_VMRESUME:
12678 case VMX_EXIT_VMXOFF:
12679 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
12680 case VMX_EXIT_VMFUNC:
12681 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
12682
12683 /*
12684 * Instructions that cause VM-exits unconditionally or the condition is
12685 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12686 * happens, it's guaranteed to be a nested-guest VM-exit).
12687 *
12688 * - Provides VM-exit instruction length.
12689 * - Provides VM-exit information.
12690 * - Optionally provides Exit qualification.
12691 *
12692 * Since Exit qualification is 0 for all VM-exits where it is not
12693 * applicable, reading and passing it to the guest should produce
12694 * defined behavior.
12695 *
12696 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
12697 */
12698 case VMX_EXIT_INVEPT: /* Unconditional. */
12699 case VMX_EXIT_INVVPID:
12700 case VMX_EXIT_VMCLEAR:
12701 case VMX_EXIT_VMPTRLD:
12702 case VMX_EXIT_VMPTRST:
12703 case VMX_EXIT_VMXON:
12704 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
12705 case VMX_EXIT_LDTR_TR_ACCESS:
12706 case VMX_EXIT_RDRAND:
12707 case VMX_EXIT_RDSEED:
12708 case VMX_EXIT_XSAVES:
12709 case VMX_EXIT_XRSTORS:
12710 case VMX_EXIT_UMWAIT:
12711 case VMX_EXIT_TPAUSE:
12712 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
12713
12714 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
12715 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
12716 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
12717 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
12718 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
12719 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
12720 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
12721 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
12722 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
12723 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
12724 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
12725 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
12726 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
12727 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
12728 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
12729 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
12730 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
12731 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
12732 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
12733
12734 case VMX_EXIT_PREEMPT_TIMER:
12735 {
12736 /** @todo NSTVMX: Preempt timer. */
12737 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
12738 }
12739
12740 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
12741 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
12742
12743 case VMX_EXIT_VMREAD:
12744 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
12745
12746 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
12747 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
12748
12749 case VMX_EXIT_INIT_SIGNAL:
12750 case VMX_EXIT_SIPI:
12751 case VMX_EXIT_IO_SMI:
12752 case VMX_EXIT_SMI:
12753 case VMX_EXIT_ERR_MSR_LOAD:
12754 case VMX_EXIT_ERR_MACHINE_CHECK:
12755 case VMX_EXIT_PML_FULL:
12756 case VMX_EXIT_RSM:
12757 default:
12758 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12759 }
12760}
12761#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12762
12763
12764/** @name VM-exit helpers.
12765 * @{
12766 */
12767/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12768/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
12769/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12770
12771/** Macro for VM-exits called unexpectedly. */
12772#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
12773 do { \
12774 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
12775 return VERR_VMX_UNEXPECTED_EXIT; \
12776 } while (0)
12777
12778#ifdef VBOX_STRICT
12779/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
12780# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
12781 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
12782
12783# define HMVMX_ASSERT_PREEMPT_CPUID() \
12784 do { \
12785 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
12786 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
12787 } while (0)
12788
12789# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12790 do { \
12791 AssertPtr((a_pVCpu)); \
12792 AssertPtr((a_pVmxTransient)); \
12793 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
12794 Assert((a_pVmxTransient)->pVmcsInfo); \
12795 Assert(ASMIntAreEnabled()); \
12796 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12797 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
12798 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
12799 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12800 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
12801 HMVMX_ASSERT_PREEMPT_CPUID(); \
12802 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12803 } while (0)
12804
12805# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12806 do { \
12807 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
12808 Assert((a_pVmxTransient)->fIsNestedGuest); \
12809 } while (0)
12810
12811# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12812 do { \
12813 Log4Func(("\n")); \
12814 } while (0)
12815#else
12816# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12817 do { \
12818 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12819 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
12820 } while (0)
12821
12822# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12823 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
12824
12825# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
12826#endif
12827
12828#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12829/** Macro that does the necessary privilege checks and intercepted VM-exits for
12830 * guests that attempted to execute a VMX instruction. */
12831# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
12832 do \
12833 { \
12834 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
12835 if (rcStrictTmp == VINF_SUCCESS) \
12836 { /* likely */ } \
12837 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12838 { \
12839 Assert((a_pVCpu)->hm.s.Event.fPending); \
12840 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
12841 return VINF_SUCCESS; \
12842 } \
12843 else \
12844 { \
12845 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
12846 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
12847 } \
12848 } while (0)
12849
12850/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
12851# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
12852 do \
12853 { \
12854 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
12855 (a_pGCPtrEffAddr)); \
12856 if (rcStrictTmp == VINF_SUCCESS) \
12857 { /* likely */ } \
12858 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12859 { \
12860 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
12861 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
12862 NOREF(uXcptTmp); \
12863 return VINF_SUCCESS; \
12864 } \
12865 else \
12866 { \
12867 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
12868 return rcStrictTmp; \
12869 } \
12870 } while (0)
12871#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12872
12873
12874/**
12875 * Advances the guest RIP by the specified number of bytes.
12876 *
12877 * @param pVCpu The cross context virtual CPU structure.
12878 * @param cbInstr Number of bytes to advance the RIP by.
12879 *
12880 * @remarks No-long-jump zone!!!
12881 */
12882DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
12883{
12884 /* Advance the RIP. */
12885 pVCpu->cpum.GstCtx.rip += cbInstr;
12886 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
12887
12888 /* Update interrupt inhibition. */
12889 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
12890 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
12891 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
12892}
12893
12894
12895/**
12896 * Advances the guest RIP after reading it from the VMCS.
12897 *
12898 * @returns VBox status code, no informational status codes.
12899 * @param pVCpu The cross context virtual CPU structure.
12900 * @param pVmxTransient The VMX-transient structure.
12901 *
12902 * @remarks No-long-jump zone!!!
12903 */
12904static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12905{
12906 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
12907 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
12908 AssertRCReturn(rc, rc);
12909
12910 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
12911 return VINF_SUCCESS;
12912}
12913
12914
12915/**
12916 * Handle a condition that occurred while delivering an event through the guest or
12917 * nested-guest IDT.
12918 *
12919 * @returns Strict VBox status code (i.e. informational status codes too).
12920 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
12921 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
12922 * to continue execution of the guest which will delivery the \#DF.
12923 * @retval VINF_EM_RESET if we detected a triple-fault condition.
12924 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
12925 *
12926 * @param pVCpu The cross context virtual CPU structure.
12927 * @param pVmxTransient The VMX-transient structure.
12928 *
12929 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
12930 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
12931 * is due to an EPT violation, PML full or SPP-related event.
12932 *
12933 * @remarks No-long-jump zone!!!
12934 */
12935static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12936{
12937 Assert(!pVCpu->hm.s.Event.fPending);
12938 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
12939 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
12940 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
12941 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
12942 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
12943
12944 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
12945 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12946 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
12947 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
12948 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
12949 {
12950 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
12951 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
12952
12953 /*
12954 * If the event was a software interrupt (generated with INT n) or a software exception
12955 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
12956 * can handle the VM-exit and continue guest execution which will re-execute the
12957 * instruction rather than re-injecting the exception, as that can cause premature
12958 * trips to ring-3 before injection and involve TRPM which currently has no way of
12959 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
12960 * the problem).
12961 */
12962 IEMXCPTRAISE enmRaise;
12963 IEMXCPTRAISEINFO fRaiseInfo;
12964 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
12965 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
12966 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
12967 {
12968 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
12969 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12970 }
12971 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
12972 {
12973 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
12974 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
12975 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
12976
12977 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
12978 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
12979
12980 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
12981
12982 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
12983 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
12984 {
12985 pVmxTransient->fVectoringPF = true;
12986 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12987 }
12988 }
12989 else
12990 {
12991 /*
12992 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
12993 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
12994 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
12995 */
12996 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
12997 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12998 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
12999 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13000 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13001 }
13002
13003 /*
13004 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13005 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13006 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13007 * subsequent VM-entry would fail, see @bugref{7445}.
13008 *
13009 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13010 */
13011 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13012 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13013 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13014 && CPUMIsGuestNmiBlocking(pVCpu))
13015 {
13016 CPUMSetGuestNmiBlocking(pVCpu, false);
13017 }
13018
13019 switch (enmRaise)
13020 {
13021 case IEMXCPTRAISE_CURRENT_XCPT:
13022 {
13023 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13024 Assert(rcStrict == VINF_SUCCESS);
13025 break;
13026 }
13027
13028 case IEMXCPTRAISE_PREV_EVENT:
13029 {
13030 uint32_t u32ErrCode;
13031 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13032 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13033 else
13034 u32ErrCode = 0;
13035
13036 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13037 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13038 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13039 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13040
13041 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13042 pVCpu->hm.s.Event.u32ErrCode));
13043 Assert(rcStrict == VINF_SUCCESS);
13044 break;
13045 }
13046
13047 case IEMXCPTRAISE_REEXEC_INSTR:
13048 Assert(rcStrict == VINF_SUCCESS);
13049 break;
13050
13051 case IEMXCPTRAISE_DOUBLE_FAULT:
13052 {
13053 /*
13054 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13055 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13056 */
13057 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13058 {
13059 pVmxTransient->fVectoringDoublePF = true;
13060 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13061 pVCpu->cpum.GstCtx.cr2));
13062 rcStrict = VINF_SUCCESS;
13063 }
13064 else
13065 {
13066 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13067 hmR0VmxSetPendingXcptDF(pVCpu);
13068 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13069 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13070 rcStrict = VINF_HM_DOUBLE_FAULT;
13071 }
13072 break;
13073 }
13074
13075 case IEMXCPTRAISE_TRIPLE_FAULT:
13076 {
13077 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13078 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13079 rcStrict = VINF_EM_RESET;
13080 break;
13081 }
13082
13083 case IEMXCPTRAISE_CPU_HANG:
13084 {
13085 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13086 rcStrict = VERR_EM_GUEST_CPU_HANG;
13087 break;
13088 }
13089
13090 default:
13091 {
13092 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13093 rcStrict = VERR_VMX_IPE_2;
13094 break;
13095 }
13096 }
13097 }
13098 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13099 && !CPUMIsGuestNmiBlocking(pVCpu))
13100 {
13101 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13102 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13103 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13104 {
13105 /*
13106 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13107 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13108 * that virtual NMIs remain blocked until the IRET execution is completed.
13109 *
13110 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13111 */
13112 CPUMSetGuestNmiBlocking(pVCpu, true);
13113 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13114 }
13115 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13116 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13117 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13118 {
13119 /*
13120 * Execution of IRET caused an EPT violation, page-modification log-full event or
13121 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13122 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13123 * that virtual NMIs remain blocked until the IRET execution is completed.
13124 *
13125 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13126 */
13127 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13128 {
13129 CPUMSetGuestNmiBlocking(pVCpu, true);
13130 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13131 }
13132 }
13133 }
13134
13135 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13136 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13137 return rcStrict;
13138}
13139
13140
13141#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13142/**
13143 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13144 * guest attempting to execute a VMX instruction.
13145 *
13146 * @returns Strict VBox status code (i.e. informational status codes too).
13147 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13148 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13149 *
13150 * @param pVCpu The cross context virtual CPU structure.
13151 * @param uExitReason The VM-exit reason.
13152 *
13153 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13154 * @remarks No-long-jump zone!!!
13155 */
13156static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13157{
13158 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13159 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13160
13161 /*
13162 * The physical CPU would have already checked the CPU mode/code segment.
13163 * We shall just assert here for paranoia.
13164 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13165 */
13166 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13167 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13168 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13169
13170 if (uExitReason == VMX_EXIT_VMXON)
13171 {
13172 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13173
13174 /*
13175 * We check CR4.VMXE because it is required to be always set while in VMX operation
13176 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13177 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13178 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13179 */
13180 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13181 {
13182 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13183 hmR0VmxSetPendingXcptUD(pVCpu);
13184 return VINF_HM_PENDING_XCPT;
13185 }
13186 }
13187 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13188 {
13189 /*
13190 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13191 * (other than VMXON), we need to raise a #UD.
13192 */
13193 Log4Func(("Not in VMX root mode -> #UD\n"));
13194 hmR0VmxSetPendingXcptUD(pVCpu);
13195 return VINF_HM_PENDING_XCPT;
13196 }
13197
13198 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13199 return VINF_SUCCESS;
13200}
13201
13202
13203/**
13204 * Decodes the memory operand of an instruction that caused a VM-exit.
13205 *
13206 * The Exit qualification field provides the displacement field for memory
13207 * operand instructions, if any.
13208 *
13209 * @returns Strict VBox status code (i.e. informational status codes too).
13210 * @retval VINF_SUCCESS if the operand was successfully decoded.
13211 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13212 * operand.
13213 * @param pVCpu The cross context virtual CPU structure.
13214 * @param uExitInstrInfo The VM-exit instruction information field.
13215 * @param enmMemAccess The memory operand's access type (read or write).
13216 * @param GCPtrDisp The instruction displacement field, if any. For
13217 * RIP-relative addressing pass RIP + displacement here.
13218 * @param pGCPtrMem Where to store the effective destination memory address.
13219 *
13220 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13221 * virtual-8086 mode hence skips those checks while verifying if the
13222 * segment is valid.
13223 */
13224static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13225 PRTGCPTR pGCPtrMem)
13226{
13227 Assert(pGCPtrMem);
13228 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13229 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13230 | CPUMCTX_EXTRN_CR0);
13231
13232 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13233 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13234 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13235
13236 VMXEXITINSTRINFO ExitInstrInfo;
13237 ExitInstrInfo.u = uExitInstrInfo;
13238 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13239 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13240 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13241 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13242 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13243 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13244 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13245 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13246 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13247
13248 /*
13249 * Validate instruction information.
13250 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13251 */
13252 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13253 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13254 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13255 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13256 AssertLogRelMsgReturn(fIsMemOperand,
13257 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13258
13259 /*
13260 * Compute the complete effective address.
13261 *
13262 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13263 * See AMD spec. 4.5.2 "Segment Registers".
13264 */
13265 RTGCPTR GCPtrMem = GCPtrDisp;
13266 if (fBaseRegValid)
13267 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13268 if (fIdxRegValid)
13269 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13270
13271 RTGCPTR const GCPtrOff = GCPtrMem;
13272 if ( !fIsLongMode
13273 || iSegReg >= X86_SREG_FS)
13274 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13275 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13276
13277 /*
13278 * Validate effective address.
13279 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13280 */
13281 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13282 Assert(cbAccess > 0);
13283 if (fIsLongMode)
13284 {
13285 if (X86_IS_CANONICAL(GCPtrMem))
13286 {
13287 *pGCPtrMem = GCPtrMem;
13288 return VINF_SUCCESS;
13289 }
13290
13291 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13292 * "Data Limit Checks in 64-bit Mode". */
13293 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13294 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13295 return VINF_HM_PENDING_XCPT;
13296 }
13297
13298 /*
13299 * This is a watered down version of iemMemApplySegment().
13300 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13301 * and segment CPL/DPL checks are skipped.
13302 */
13303 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13304 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13305 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13306
13307 /* Check if the segment is present and usable. */
13308 if ( pSel->Attr.n.u1Present
13309 && !pSel->Attr.n.u1Unusable)
13310 {
13311 Assert(pSel->Attr.n.u1DescType);
13312 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13313 {
13314 /* Check permissions for the data segment. */
13315 if ( enmMemAccess == VMXMEMACCESS_WRITE
13316 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13317 {
13318 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13319 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13320 return VINF_HM_PENDING_XCPT;
13321 }
13322
13323 /* Check limits if it's a normal data segment. */
13324 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13325 {
13326 if ( GCPtrFirst32 > pSel->u32Limit
13327 || GCPtrLast32 > pSel->u32Limit)
13328 {
13329 Log4Func(("Data segment limit exceeded. "
13330 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13331 GCPtrLast32, pSel->u32Limit));
13332 if (iSegReg == X86_SREG_SS)
13333 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13334 else
13335 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13336 return VINF_HM_PENDING_XCPT;
13337 }
13338 }
13339 else
13340 {
13341 /* Check limits if it's an expand-down data segment.
13342 Note! The upper boundary is defined by the B bit, not the G bit! */
13343 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13344 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13345 {
13346 Log4Func(("Expand-down data segment limit exceeded. "
13347 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13348 GCPtrLast32, pSel->u32Limit));
13349 if (iSegReg == X86_SREG_SS)
13350 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13351 else
13352 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13353 return VINF_HM_PENDING_XCPT;
13354 }
13355 }
13356 }
13357 else
13358 {
13359 /* Check permissions for the code segment. */
13360 if ( enmMemAccess == VMXMEMACCESS_WRITE
13361 || ( enmMemAccess == VMXMEMACCESS_READ
13362 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13363 {
13364 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13365 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13366 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13367 return VINF_HM_PENDING_XCPT;
13368 }
13369
13370 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13371 if ( GCPtrFirst32 > pSel->u32Limit
13372 || GCPtrLast32 > pSel->u32Limit)
13373 {
13374 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13375 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13376 if (iSegReg == X86_SREG_SS)
13377 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13378 else
13379 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13380 return VINF_HM_PENDING_XCPT;
13381 }
13382 }
13383 }
13384 else
13385 {
13386 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13387 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13388 return VINF_HM_PENDING_XCPT;
13389 }
13390
13391 *pGCPtrMem = GCPtrMem;
13392 return VINF_SUCCESS;
13393}
13394#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13395
13396
13397/**
13398 * VM-exit helper for LMSW.
13399 */
13400static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13401{
13402 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13403 AssertRCReturn(rc, rc);
13404
13405 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13406 AssertMsg( rcStrict == VINF_SUCCESS
13407 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13408
13409 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13410 if (rcStrict == VINF_IEM_RAISED_XCPT)
13411 {
13412 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13413 rcStrict = VINF_SUCCESS;
13414 }
13415
13416 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13417 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13418 return rcStrict;
13419}
13420
13421
13422/**
13423 * VM-exit helper for CLTS.
13424 */
13425static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13426{
13427 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13428 AssertRCReturn(rc, rc);
13429
13430 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13431 AssertMsg( rcStrict == VINF_SUCCESS
13432 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13433
13434 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13435 if (rcStrict == VINF_IEM_RAISED_XCPT)
13436 {
13437 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13438 rcStrict = VINF_SUCCESS;
13439 }
13440
13441 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13442 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13443 return rcStrict;
13444}
13445
13446
13447/**
13448 * VM-exit helper for MOV from CRx (CRx read).
13449 */
13450static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13451{
13452 Assert(iCrReg < 16);
13453 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13454
13455 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13456 AssertRCReturn(rc, rc);
13457
13458 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13459 AssertMsg( rcStrict == VINF_SUCCESS
13460 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13461
13462 if (iGReg == X86_GREG_xSP)
13463 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13464 else
13465 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13466#ifdef VBOX_WITH_STATISTICS
13467 switch (iCrReg)
13468 {
13469 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13470 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13471 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13472 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13473 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13474 }
13475#endif
13476 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13477 return rcStrict;
13478}
13479
13480
13481/**
13482 * VM-exit helper for MOV to CRx (CRx write).
13483 */
13484static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13485{
13486 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13487 AssertRCReturn(rc, rc);
13488
13489 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13490 AssertMsg( rcStrict == VINF_SUCCESS
13491 || rcStrict == VINF_IEM_RAISED_XCPT
13492 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13493
13494 switch (iCrReg)
13495 {
13496 case 0:
13497 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13498 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13499 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13500 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13501 break;
13502
13503 case 2:
13504 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13505 /* Nothing to do here, CR2 it's not part of the VMCS. */
13506 break;
13507
13508 case 3:
13509 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13510 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13511 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13512 break;
13513
13514 case 4:
13515 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13516 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13517 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13518 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13519 break;
13520
13521 case 8:
13522 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13523 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13524 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13525 break;
13526
13527 default:
13528 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13529 break;
13530 }
13531
13532 if (rcStrict == VINF_IEM_RAISED_XCPT)
13533 {
13534 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13535 rcStrict = VINF_SUCCESS;
13536 }
13537 return rcStrict;
13538}
13539
13540
13541/**
13542 * VM-exit exception handler for \#PF (Page-fault exception).
13543 *
13544 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13545 */
13546static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13547{
13548 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13549 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13550 hmR0VmxReadExitQualVmcs(pVmxTransient);
13551
13552 if (!pVM->hm.s.fNestedPaging)
13553 { /* likely */ }
13554 else
13555 {
13556#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13557 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
13558#endif
13559 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13560 if (!pVmxTransient->fVectoringDoublePF)
13561 {
13562 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13563 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13564 }
13565 else
13566 {
13567 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13568 Assert(!pVmxTransient->fIsNestedGuest);
13569 hmR0VmxSetPendingXcptDF(pVCpu);
13570 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13571 }
13572 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13573 return VINF_SUCCESS;
13574 }
13575
13576 Assert(!pVmxTransient->fIsNestedGuest);
13577
13578 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13579 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13580 if (pVmxTransient->fVectoringPF)
13581 {
13582 Assert(pVCpu->hm.s.Event.fPending);
13583 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13584 }
13585
13586 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13587 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13588 AssertRCReturn(rc, rc);
13589
13590 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13591 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13592
13593 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13594 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13595
13596 Log4Func(("#PF: rc=%Rrc\n", rc));
13597 if (rc == VINF_SUCCESS)
13598 {
13599 /*
13600 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13601 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13602 */
13603 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13604 TRPMResetTrap(pVCpu);
13605 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13606 return rc;
13607 }
13608
13609 if (rc == VINF_EM_RAW_GUEST_TRAP)
13610 {
13611 if (!pVmxTransient->fVectoringDoublePF)
13612 {
13613 /* It's a guest page fault and needs to be reflected to the guest. */
13614 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
13615 TRPMResetTrap(pVCpu);
13616 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13617 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13618 uGstErrorCode, pVmxTransient->uExitQual);
13619 }
13620 else
13621 {
13622 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13623 TRPMResetTrap(pVCpu);
13624 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
13625 hmR0VmxSetPendingXcptDF(pVCpu);
13626 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
13627 }
13628
13629 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13630 return VINF_SUCCESS;
13631 }
13632
13633 TRPMResetTrap(pVCpu);
13634 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
13635 return rc;
13636}
13637
13638
13639/**
13640 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
13641 *
13642 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13643 */
13644static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13645{
13646 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13647 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
13648
13649 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
13650 AssertRCReturn(rc, rc);
13651
13652 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
13653 {
13654 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
13655 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
13656
13657 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
13658 * provides VM-exit instruction length. If this causes problem later,
13659 * disassemble the instruction like it's done on AMD-V. */
13660 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13661 AssertRCReturn(rc2, rc2);
13662 return rc;
13663 }
13664
13665 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
13666 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13667 return VINF_SUCCESS;
13668}
13669
13670
13671/**
13672 * VM-exit exception handler for \#BP (Breakpoint exception).
13673 *
13674 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13675 */
13676static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13677{
13678 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13679 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
13680
13681 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13682 AssertRCReturn(rc, rc);
13683
13684 if (!pVmxTransient->fIsNestedGuest)
13685 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
13686 else
13687 rc = VINF_EM_RAW_GUEST_TRAP;
13688
13689 if (rc == VINF_EM_RAW_GUEST_TRAP)
13690 {
13691 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13692 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13693 rc = VINF_SUCCESS;
13694 }
13695
13696 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
13697 return rc;
13698}
13699
13700
13701/**
13702 * VM-exit exception handler for \#AC (Alignment-check exception).
13703 *
13704 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13705 */
13706static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13707{
13708 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13709 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
13710
13711 /* Re-inject it. We'll detect any nesting before getting here. */
13712 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13713 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13714 return VINF_SUCCESS;
13715}
13716
13717
13718/**
13719 * VM-exit exception handler for \#DB (Debug exception).
13720 *
13721 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13722 */
13723static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13724{
13725 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13726 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
13727
13728 /*
13729 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
13730 */
13731 hmR0VmxReadExitQualVmcs(pVmxTransient);
13732
13733 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
13734 uint64_t const uDR6 = X86_DR6_INIT_VAL
13735 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
13736 | X86_DR6_BD | X86_DR6_BS));
13737
13738 int rc;
13739 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13740 if (!pVmxTransient->fIsNestedGuest)
13741 {
13742 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
13743
13744 /*
13745 * Prevents stepping twice over the same instruction when the guest is stepping using
13746 * EFLAGS.TF and the hypervisor debugger is stepping using MTF.
13747 * Testcase: DOSQEMM, break (using "ba x 1") at cs:rip 0x70:0x774 and step (using "t").
13748 */
13749 if ( rc == VINF_EM_DBG_STEPPED
13750 && (pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MONITOR_TRAP_FLAG))
13751 {
13752 Assert(pVCpu->hm.s.fSingleInstruction);
13753 rc = VINF_EM_RAW_GUEST_TRAP;
13754 }
13755 }
13756 else
13757 rc = VINF_EM_RAW_GUEST_TRAP;
13758 Log6Func(("rc=%Rrc\n", rc));
13759 if (rc == VINF_EM_RAW_GUEST_TRAP)
13760 {
13761 /*
13762 * The exception was for the guest. Update DR6, DR7.GD and
13763 * IA32_DEBUGCTL.LBR before forwarding it.
13764 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
13765 */
13766 VMMRZCallRing3Disable(pVCpu);
13767 HM_DISABLE_PREEMPT(pVCpu);
13768
13769 pCtx->dr[6] &= ~X86_DR6_B_MASK;
13770 pCtx->dr[6] |= uDR6;
13771 if (CPUMIsGuestDebugStateActive(pVCpu))
13772 ASMSetDR6(pCtx->dr[6]);
13773
13774 HM_RESTORE_PREEMPT();
13775 VMMRZCallRing3Enable(pVCpu);
13776
13777 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
13778 AssertRCReturn(rc, rc);
13779
13780 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
13781 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
13782
13783 /* Paranoia. */
13784 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
13785 pCtx->dr[7] |= X86_DR7_RA1_MASK;
13786
13787 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
13788 AssertRC(rc);
13789
13790 /*
13791 * Raise #DB in the guest.
13792 *
13793 * It is important to reflect exactly what the VM-exit gave us (preserving the
13794 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
13795 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
13796 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
13797 *
13798 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
13799 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
13800 */
13801 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13802 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13803 return VINF_SUCCESS;
13804 }
13805
13806 /*
13807 * Not a guest trap, must be a hypervisor related debug event then.
13808 * Update DR6 in case someone is interested in it.
13809 */
13810 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
13811 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
13812 CPUMSetHyperDR6(pVCpu, uDR6);
13813
13814 return rc;
13815}
13816
13817
13818/**
13819 * Hacks its way around the lovely mesa driver's backdoor accesses.
13820 *
13821 * @sa hmR0SvmHandleMesaDrvGp.
13822 */
13823static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13824{
13825 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
13826 RT_NOREF(pCtx);
13827
13828 /* For now we'll just skip the instruction. */
13829 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13830}
13831
13832
13833/**
13834 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
13835 * backdoor logging w/o checking what it is running inside.
13836 *
13837 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
13838 * backdoor port and magic numbers loaded in registers.
13839 *
13840 * @returns true if it is, false if it isn't.
13841 * @sa hmR0SvmIsMesaDrvGp.
13842 */
13843DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13844{
13845 /* 0xed: IN eAX,dx */
13846 uint8_t abInstr[1];
13847 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
13848 return false;
13849
13850 /* Check that it is #GP(0). */
13851 if (pVmxTransient->uExitIntErrorCode != 0)
13852 return false;
13853
13854 /* Check magic and port. */
13855 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
13856 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
13857 if (pCtx->rax != UINT32_C(0x564d5868))
13858 return false;
13859 if (pCtx->dx != UINT32_C(0x5658))
13860 return false;
13861
13862 /* Flat ring-3 CS. */
13863 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
13864 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
13865 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
13866 if (pCtx->cs.Attr.n.u2Dpl != 3)
13867 return false;
13868 if (pCtx->cs.u64Base != 0)
13869 return false;
13870
13871 /* Check opcode. */
13872 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
13873 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
13874 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
13875 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
13876 if (RT_FAILURE(rc))
13877 return false;
13878 if (abInstr[0] != 0xed)
13879 return false;
13880
13881 return true;
13882}
13883
13884
13885/**
13886 * VM-exit exception handler for \#GP (General-protection exception).
13887 *
13888 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13889 */
13890static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13891{
13892 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13893 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
13894
13895 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13896 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13897 if (pVmcsInfo->RealMode.fRealOnV86Active)
13898 { /* likely */ }
13899 else
13900 {
13901#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13902 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
13903#endif
13904 /*
13905 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
13906 * executing a nested-guest, reflect #GP to the guest or nested-guest.
13907 */
13908 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13909 AssertRCReturn(rc, rc);
13910 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
13911 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
13912
13913 if ( pVmxTransient->fIsNestedGuest
13914 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
13915 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
13916 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13917 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13918 else
13919 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
13920 return rc;
13921 }
13922
13923 Assert(CPUMIsGuestInRealModeEx(pCtx));
13924 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
13925 Assert(!pVmxTransient->fIsNestedGuest);
13926
13927 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13928 AssertRCReturn(rc, rc);
13929
13930 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
13931 if (rcStrict == VINF_SUCCESS)
13932 {
13933 if (!CPUMIsGuestInRealModeEx(pCtx))
13934 {
13935 /*
13936 * The guest is no longer in real-mode, check if we can continue executing the
13937 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
13938 */
13939 pVmcsInfo->RealMode.fRealOnV86Active = false;
13940 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
13941 {
13942 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
13943 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13944 }
13945 else
13946 {
13947 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
13948 rcStrict = VINF_EM_RESCHEDULE;
13949 }
13950 }
13951 else
13952 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13953 }
13954 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13955 {
13956 rcStrict = VINF_SUCCESS;
13957 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13958 }
13959 return VBOXSTRICTRC_VAL(rcStrict);
13960}
13961
13962
13963/**
13964 * VM-exit exception handler wrapper for all other exceptions that are not handled
13965 * by a specific handler.
13966 *
13967 * This simply re-injects the exception back into the VM without any special
13968 * processing.
13969 *
13970 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13971 */
13972static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13973{
13974 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13975
13976#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13977 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13978 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
13979 ("uVector=%#x u32XcptBitmap=%#X32\n",
13980 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
13981 NOREF(pVmcsInfo);
13982#endif
13983
13984 /*
13985 * Re-inject the exception into the guest. This cannot be a double-fault condition which
13986 * would have been handled while checking exits due to event delivery.
13987 */
13988 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13989
13990#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13991 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
13992 AssertRCReturn(rc, rc);
13993 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
13994#endif
13995
13996#ifdef VBOX_WITH_STATISTICS
13997 switch (uVector)
13998 {
13999 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14000 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14001 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14002 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14003 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14004 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14005 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14006 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14007 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14008 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14009 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14010 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14011 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14012 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14013 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14014 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14015 default:
14016 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14017 break;
14018 }
14019#endif
14020
14021 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14022 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14023 NOREF(uVector);
14024
14025 /* Re-inject the original exception into the guest. */
14026 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14027 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14028 return VINF_SUCCESS;
14029}
14030
14031
14032/**
14033 * VM-exit exception handler for all exceptions (except NMIs!).
14034 *
14035 * @remarks This may be called for both guests and nested-guests. Take care to not
14036 * make assumptions and avoid doing anything that is not relevant when
14037 * executing a nested-guest (e.g., Mesa driver hacks).
14038 */
14039static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14040{
14041 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14042
14043 /*
14044 * If this VM-exit occurred while delivering an event through the guest IDT, take
14045 * action based on the return code and additional hints (e.g. for page-faults)
14046 * that will be updated in the VMX transient structure.
14047 */
14048 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14049 if (rcStrict == VINF_SUCCESS)
14050 {
14051 /*
14052 * If an exception caused a VM-exit due to delivery of an event, the original
14053 * event may have to be re-injected into the guest. We shall reinject it and
14054 * continue guest execution. However, page-fault is a complicated case and
14055 * needs additional processing done in hmR0VmxExitXcptPF().
14056 */
14057 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14058 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14059 if ( !pVCpu->hm.s.Event.fPending
14060 || uVector == X86_XCPT_PF)
14061 {
14062 switch (uVector)
14063 {
14064 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14065 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14066 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14067 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14068 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14069 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14070 default:
14071 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14072 }
14073 }
14074 /* else: inject pending event before resuming guest execution. */
14075 }
14076 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14077 {
14078 Assert(pVCpu->hm.s.Event.fPending);
14079 rcStrict = VINF_SUCCESS;
14080 }
14081
14082 return rcStrict;
14083}
14084/** @} */
14085
14086
14087/** @name VM-exit handlers.
14088 * @{
14089 */
14090/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14091/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14092/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14093
14094/**
14095 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14096 */
14097HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14098{
14099 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14100 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14101 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14102 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14103 return VINF_SUCCESS;
14104 return VINF_EM_RAW_INTERRUPT;
14105}
14106
14107
14108/**
14109 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14110 * VM-exit.
14111 */
14112HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14113{
14114 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14115 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14116
14117 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14118
14119 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14120 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14121 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14122
14123 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14124 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14125 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14126 NOREF(pVmcsInfo);
14127
14128 VBOXSTRICTRC rcStrict;
14129 switch (uExitIntType)
14130 {
14131 /*
14132 * Host physical NMIs:
14133 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14134 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14135 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14136 *
14137 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14138 * See Intel spec. 27.5.5 "Updating Non-Register State".
14139 */
14140 case VMX_EXIT_INT_INFO_TYPE_NMI:
14141 {
14142 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14143 break;
14144 }
14145
14146 /*
14147 * Privileged software exceptions (#DB from ICEBP),
14148 * Software exceptions (#BP and #OF),
14149 * Hardware exceptions:
14150 * Process the required exceptions and resume guest execution if possible.
14151 */
14152 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14153 Assert(uVector == X86_XCPT_DB);
14154 RT_FALL_THRU();
14155 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14156 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14157 RT_FALL_THRU();
14158 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14159 {
14160 NOREF(uVector);
14161 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14162 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14163 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14164 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14165
14166 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14167 break;
14168 }
14169
14170 default:
14171 {
14172 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14173 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14174 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14175 break;
14176 }
14177 }
14178
14179 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14180 return rcStrict;
14181}
14182
14183
14184/**
14185 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14186 */
14187HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14188{
14189 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14190
14191 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14192 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14193 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14194
14195 /* Evaluate and deliver pending events and resume guest execution. */
14196 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14197 return VINF_SUCCESS;
14198}
14199
14200
14201/**
14202 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14203 */
14204HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14205{
14206 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14207
14208 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14209 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14210 {
14211 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14212 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14213 }
14214
14215 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14216
14217 /*
14218 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14219 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14220 */
14221 uint32_t fIntrState;
14222 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14223 AssertRC(rc);
14224 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14225 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14226 {
14227 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14228 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14229
14230 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14231 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14232 AssertRC(rc);
14233 }
14234
14235 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14236 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14237
14238 /* Evaluate and deliver pending events and resume guest execution. */
14239 return VINF_SUCCESS;
14240}
14241
14242
14243/**
14244 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14245 */
14246HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14247{
14248 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14249 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14250}
14251
14252
14253/**
14254 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14255 */
14256HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14257{
14258 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14259 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14260}
14261
14262
14263/**
14264 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14265 */
14266HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14267{
14268 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14269
14270 /*
14271 * Get the state we need and update the exit history entry.
14272 */
14273 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14274 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14275
14276 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14277 AssertRCReturn(rc, rc);
14278
14279 VBOXSTRICTRC rcStrict;
14280 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14281 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14282 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14283 if (!pExitRec)
14284 {
14285 /*
14286 * Regular CPUID instruction execution.
14287 */
14288 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14289 if (rcStrict == VINF_SUCCESS)
14290 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14291 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14292 {
14293 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14294 rcStrict = VINF_SUCCESS;
14295 }
14296 }
14297 else
14298 {
14299 /*
14300 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14301 */
14302 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14303 AssertRCReturn(rc2, rc2);
14304
14305 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14306 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14307
14308 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14309 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14310
14311 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14312 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14313 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14314 }
14315 return rcStrict;
14316}
14317
14318
14319/**
14320 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14321 */
14322HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14323{
14324 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14325
14326 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14327 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14328 AssertRCReturn(rc, rc);
14329
14330 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14331 return VINF_EM_RAW_EMULATE_INSTR;
14332
14333 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14334 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14335}
14336
14337
14338/**
14339 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14340 */
14341HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14342{
14343 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14344
14345 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14346 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14347 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14348 AssertRCReturn(rc, rc);
14349
14350 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14351 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14352 {
14353 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14354 we must reset offsetting on VM-entry. See @bugref{6634}. */
14355 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14356 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14357 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14358 }
14359 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14360 {
14361 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14362 rcStrict = VINF_SUCCESS;
14363 }
14364 return rcStrict;
14365}
14366
14367
14368/**
14369 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14370 */
14371HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14372{
14373 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14374
14375 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14376 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14377 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14378 AssertRCReturn(rc, rc);
14379
14380 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14381 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14382 {
14383 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14384 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14385 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14386 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14387 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14388 }
14389 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14390 {
14391 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14392 rcStrict = VINF_SUCCESS;
14393 }
14394 return rcStrict;
14395}
14396
14397
14398/**
14399 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14400 */
14401HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14402{
14403 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14404
14405 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14406 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14407 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14408 AssertRCReturn(rc, rc);
14409
14410 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14411 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14412 if (RT_LIKELY(rc == VINF_SUCCESS))
14413 {
14414 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14415 Assert(pVmxTransient->cbExitInstr == 2);
14416 }
14417 else
14418 {
14419 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14420 rc = VERR_EM_INTERPRETER;
14421 }
14422 return rc;
14423}
14424
14425
14426/**
14427 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14428 */
14429HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14430{
14431 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14432
14433 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14434 if (EMAreHypercallInstructionsEnabled(pVCpu))
14435 {
14436 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14437 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14438 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14439 AssertRCReturn(rc, rc);
14440
14441 /* Perform the hypercall. */
14442 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14443 if (rcStrict == VINF_SUCCESS)
14444 {
14445 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14446 AssertRCReturn(rc, rc);
14447 }
14448 else
14449 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14450 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14451 || RT_FAILURE(rcStrict));
14452
14453 /* If the hypercall changes anything other than guest's general-purpose registers,
14454 we would need to reload the guest changed bits here before VM-entry. */
14455 }
14456 else
14457 Log4Func(("Hypercalls not enabled\n"));
14458
14459 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14460 if (RT_FAILURE(rcStrict))
14461 {
14462 hmR0VmxSetPendingXcptUD(pVCpu);
14463 rcStrict = VINF_SUCCESS;
14464 }
14465
14466 return rcStrict;
14467}
14468
14469
14470/**
14471 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14472 */
14473HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14474{
14475 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14476 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
14477
14478 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14479 hmR0VmxReadExitQualVmcs(pVmxTransient);
14480 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14481 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14482 AssertRCReturn(rc, rc);
14483
14484 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14485
14486 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14487 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14488 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14489 {
14490 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14491 rcStrict = VINF_SUCCESS;
14492 }
14493 else
14494 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14495 VBOXSTRICTRC_VAL(rcStrict)));
14496 return rcStrict;
14497}
14498
14499
14500/**
14501 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14502 */
14503HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14504{
14505 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14506
14507 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14508 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14509 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14510 AssertRCReturn(rc, rc);
14511
14512 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14513 if (rcStrict == VINF_SUCCESS)
14514 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14515 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14516 {
14517 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14518 rcStrict = VINF_SUCCESS;
14519 }
14520
14521 return rcStrict;
14522}
14523
14524
14525/**
14526 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14527 */
14528HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14529{
14530 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14531
14532 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14533 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14534 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14535 AssertRCReturn(rc, rc);
14536
14537 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14538 if (RT_SUCCESS(rcStrict))
14539 {
14540 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14541 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14542 rcStrict = VINF_SUCCESS;
14543 }
14544
14545 return rcStrict;
14546}
14547
14548
14549/**
14550 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14551 * VM-exit.
14552 */
14553HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14554{
14555 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14556 return VINF_EM_RESET;
14557}
14558
14559
14560/**
14561 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14562 */
14563HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14564{
14565 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14566
14567 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14568 AssertRCReturn(rc, rc);
14569
14570 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14571 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14572 rc = VINF_SUCCESS;
14573 else
14574 rc = VINF_EM_HALT;
14575
14576 if (rc != VINF_SUCCESS)
14577 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14578 return rc;
14579}
14580
14581
14582/**
14583 * VM-exit handler for instructions that result in a \#UD exception delivered to
14584 * the guest.
14585 */
14586HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14587{
14588 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14589 hmR0VmxSetPendingXcptUD(pVCpu);
14590 return VINF_SUCCESS;
14591}
14592
14593
14594/**
14595 * VM-exit handler for expiry of the VMX-preemption timer.
14596 */
14597HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14598{
14599 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14600
14601 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14602 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14603
14604 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14605 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14606 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14607 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14608 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14609}
14610
14611
14612/**
14613 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14614 */
14615HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14616{
14617 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14618
14619 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14620 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14621 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
14622 AssertRCReturn(rc, rc);
14623
14624 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
14625 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14626 : HM_CHANGED_RAISED_XCPT_MASK);
14627
14628 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14629 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
14630
14631 return rcStrict;
14632}
14633
14634
14635/**
14636 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
14637 */
14638HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14639{
14640 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14641
14642#if 1
14643 /** @todo Use VM-exit instruction information. */
14644 return VERR_EM_INTERPRETER;
14645#else
14646 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14647 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
14648 hmR0VmxReadExitQualVmcs(pVmxTransient);
14649 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
14650 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14651 AssertRCReturn(rc, rc);
14652
14653 /* Paranoia. Ensure this has a memory operand. */
14654 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
14655
14656 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
14657 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14658 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
14659 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
14660
14661 RTGCPTR GCPtrDesc;
14662 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
14663
14664 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
14665 GCPtrDesc, uType);
14666 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14667 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14668 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14669 {
14670 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14671 rcStrict = VINF_SUCCESS;
14672 }
14673 return rcStrict;
14674#endif
14675}
14676
14677
14678/**
14679 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
14680 * VM-exit.
14681 */
14682HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14683{
14684 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14685 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14686 AssertRCReturn(rc, rc);
14687
14688 rc = hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
14689 if (RT_FAILURE(rc))
14690 return rc;
14691
14692 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
14693 NOREF(uInvalidReason);
14694
14695#ifdef VBOX_STRICT
14696 uint32_t fIntrState;
14697 uint64_t u64Val;
14698 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
14699 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
14700 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
14701
14702 Log4(("uInvalidReason %u\n", uInvalidReason));
14703 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
14704 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
14705 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
14706
14707 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
14708 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
14709 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
14710 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
14711 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
14712 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
14713 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
14714 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14715 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
14716 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
14717 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
14718 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14719 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
14720 {
14721 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
14722 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
14723 }
14724 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
14725#endif
14726
14727 return VERR_VMX_INVALID_GUEST_STATE;
14728}
14729
14730/**
14731 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
14732 */
14733HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14734{
14735 /*
14736 * Cumulative notes of all recognized but unexpected VM-exits.
14737 *
14738 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
14739 * nested-paging is used.
14740 *
14741 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
14742 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
14743 * this function (and thereby stop VM execution) for handling such instructions.
14744 *
14745 *
14746 * VMX_EXIT_INIT_SIGNAL:
14747 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
14748 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
14749 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
14750 *
14751 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
14752 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
14753 * See Intel spec. "23.8 Restrictions on VMX operation".
14754 *
14755 * VMX_EXIT_SIPI:
14756 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
14757 * activity state is used. We don't make use of it as our guests don't have direct
14758 * access to the host local APIC.
14759 *
14760 * See Intel spec. 25.3 "Other Causes of VM-exits".
14761 *
14762 * VMX_EXIT_IO_SMI:
14763 * VMX_EXIT_SMI:
14764 * This can only happen if we support dual-monitor treatment of SMI, which can be
14765 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
14766 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
14767 * VMX root mode or receive an SMI. If we get here, something funny is going on.
14768 *
14769 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
14770 * See Intel spec. 25.3 "Other Causes of VM-Exits"
14771 *
14772 * VMX_EXIT_ERR_MSR_LOAD:
14773 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
14774 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
14775 * execution.
14776 *
14777 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
14778 *
14779 * VMX_EXIT_ERR_MACHINE_CHECK:
14780 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
14781 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
14782 * #MC exception abort class exception is raised. We thus cannot assume a
14783 * reasonable chance of continuing any sort of execution and we bail.
14784 *
14785 * See Intel spec. 15.1 "Machine-check Architecture".
14786 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
14787 *
14788 * VMX_EXIT_PML_FULL:
14789 * VMX_EXIT_VIRTUALIZED_EOI:
14790 * VMX_EXIT_APIC_WRITE:
14791 * We do not currently support any of these features and thus they are all unexpected
14792 * VM-exits.
14793 *
14794 * VMX_EXIT_GDTR_IDTR_ACCESS:
14795 * VMX_EXIT_LDTR_TR_ACCESS:
14796 * VMX_EXIT_RDRAND:
14797 * VMX_EXIT_RSM:
14798 * VMX_EXIT_VMFUNC:
14799 * VMX_EXIT_ENCLS:
14800 * VMX_EXIT_RDSEED:
14801 * VMX_EXIT_XSAVES:
14802 * VMX_EXIT_XRSTORS:
14803 * VMX_EXIT_UMWAIT:
14804 * VMX_EXIT_TPAUSE:
14805 * These VM-exits are -not- caused unconditionally by execution of the corresponding
14806 * instruction. Any VM-exit for these instructions indicate a hardware problem,
14807 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
14808 *
14809 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
14810 */
14811 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14812 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
14813 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14814}
14815
14816
14817/**
14818 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
14819 */
14820HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14821{
14822 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14823
14824 /** @todo Optimize this: We currently drag in the whole MSR state
14825 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14826 * MSRs required. That would require changes to IEM and possibly CPUM too.
14827 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14828 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14829 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14830 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14831 switch (idMsr)
14832 {
14833 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14834 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14835 }
14836
14837 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14838 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14839 AssertRCReturn(rc, rc);
14840
14841 Log4Func(("ecx=%#RX32\n", idMsr));
14842
14843#ifdef VBOX_STRICT
14844 Assert(!pVmxTransient->fIsNestedGuest);
14845 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
14846 {
14847 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
14848 && idMsr != MSR_K6_EFER)
14849 {
14850 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
14851 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14852 }
14853 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14854 {
14855 Assert(pVmcsInfo->pvMsrBitmap);
14856 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14857 if (fMsrpm & VMXMSRPM_ALLOW_RD)
14858 {
14859 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
14860 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14861 }
14862 }
14863 }
14864#endif
14865
14866 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
14867 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
14868 if (rcStrict == VINF_SUCCESS)
14869 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14870 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14871 {
14872 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14873 rcStrict = VINF_SUCCESS;
14874 }
14875 else
14876 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14877
14878 return rcStrict;
14879}
14880
14881
14882/**
14883 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
14884 */
14885HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14886{
14887 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14888
14889 /** @todo Optimize this: We currently drag in the whole MSR state
14890 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14891 * MSRs required. That would require changes to IEM and possibly CPUM too.
14892 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14893 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14894 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14895
14896 /*
14897 * The FS and GS base MSRs are not part of the above all-MSRs mask.
14898 * Although we don't need to fetch the base as it will be overwritten shortly, while
14899 * loading guest-state we would also load the entire segment register including limit
14900 * and attributes and thus we need to load them here.
14901 */
14902 switch (idMsr)
14903 {
14904 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14905 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14906 }
14907
14908 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14909 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14910 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14911 AssertRCReturn(rc, rc);
14912
14913 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
14914
14915 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
14916 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
14917
14918 if (rcStrict == VINF_SUCCESS)
14919 {
14920 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14921
14922 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
14923 if ( idMsr == MSR_IA32_APICBASE
14924 || ( idMsr >= MSR_IA32_X2APIC_START
14925 && idMsr <= MSR_IA32_X2APIC_END))
14926 {
14927 /*
14928 * We've already saved the APIC related guest-state (TPR) in post-run phase.
14929 * When full APIC register virtualization is implemented we'll have to make
14930 * sure APIC state is saved from the VMCS before IEM changes it.
14931 */
14932 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
14933 }
14934 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
14935 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14936 else if (idMsr == MSR_K6_EFER)
14937 {
14938 /*
14939 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
14940 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
14941 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
14942 */
14943 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
14944 }
14945
14946 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
14947 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
14948 {
14949 switch (idMsr)
14950 {
14951 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
14952 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
14953 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
14954 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
14955 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
14956 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
14957 default:
14958 {
14959 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14960 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
14961 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14962 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
14963 break;
14964 }
14965 }
14966 }
14967#ifdef VBOX_STRICT
14968 else
14969 {
14970 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
14971 switch (idMsr)
14972 {
14973 case MSR_IA32_SYSENTER_CS:
14974 case MSR_IA32_SYSENTER_EIP:
14975 case MSR_IA32_SYSENTER_ESP:
14976 case MSR_K8_FS_BASE:
14977 case MSR_K8_GS_BASE:
14978 {
14979 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
14980 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14981 }
14982
14983 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
14984 default:
14985 {
14986 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14987 {
14988 /* EFER MSR writes are always intercepted. */
14989 if (idMsr != MSR_K6_EFER)
14990 {
14991 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
14992 idMsr));
14993 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14994 }
14995 }
14996
14997 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14998 {
14999 Assert(pVmcsInfo->pvMsrBitmap);
15000 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15001 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15002 {
15003 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15004 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15005 }
15006 }
15007 break;
15008 }
15009 }
15010 }
15011#endif /* VBOX_STRICT */
15012 }
15013 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15014 {
15015 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15016 rcStrict = VINF_SUCCESS;
15017 }
15018 else
15019 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15020
15021 return rcStrict;
15022}
15023
15024
15025/**
15026 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15027 */
15028HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15029{
15030 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15031
15032 /** @todo The guest has likely hit a contended spinlock. We might want to
15033 * poke a schedule different guest VCPU. */
15034 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15035 if (RT_SUCCESS(rc))
15036 return VINF_EM_RAW_INTERRUPT;
15037
15038 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15039 return rc;
15040}
15041
15042
15043/**
15044 * VM-exit handler for when the TPR value is lowered below the specified
15045 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15046 */
15047HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15048{
15049 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15050 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15051
15052 /*
15053 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15054 * We'll re-evaluate pending interrupts and inject them before the next VM
15055 * entry so we can just continue execution here.
15056 */
15057 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15058 return VINF_SUCCESS;
15059}
15060
15061
15062/**
15063 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15064 * VM-exit.
15065 *
15066 * @retval VINF_SUCCESS when guest execution can continue.
15067 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15068 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15069 * incompatible guest state for VMX execution (real-on-v86 case).
15070 */
15071HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15072{
15073 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15074 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15075
15076 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15077 hmR0VmxReadExitQualVmcs(pVmxTransient);
15078 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15079
15080 VBOXSTRICTRC rcStrict;
15081 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15082 uint64_t const uExitQual = pVmxTransient->uExitQual;
15083 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15084 switch (uAccessType)
15085 {
15086 /*
15087 * MOV to CRx.
15088 */
15089 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15090 {
15091 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15092 AssertRCReturn(rc, rc);
15093
15094 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15095 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15096 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15097 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15098
15099 /*
15100 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15101 * - When nested paging isn't used.
15102 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15103 * - We are executing in the VM debug loop.
15104 */
15105 Assert( iCrReg != 3
15106 || !pVM->hm.s.fNestedPaging
15107 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15108 || pVCpu->hm.s.fUsingDebugLoop);
15109
15110 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15111 Assert( iCrReg != 8
15112 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15113
15114 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15115 AssertMsg( rcStrict == VINF_SUCCESS
15116 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15117
15118 /*
15119 * This is a kludge for handling switches back to real mode when we try to use
15120 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15121 * deal with special selector values, so we have to return to ring-3 and run
15122 * there till the selector values are V86 mode compatible.
15123 *
15124 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15125 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15126 * this function.
15127 */
15128 if ( iCrReg == 0
15129 && rcStrict == VINF_SUCCESS
15130 && !pVM->hm.s.vmx.fUnrestrictedGuest
15131 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15132 && (uOldCr0 & X86_CR0_PE)
15133 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15134 {
15135 /** @todo Check selectors rather than returning all the time. */
15136 Assert(!pVmxTransient->fIsNestedGuest);
15137 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15138 rcStrict = VINF_EM_RESCHEDULE_REM;
15139 }
15140 break;
15141 }
15142
15143 /*
15144 * MOV from CRx.
15145 */
15146 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15147 {
15148 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15149 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15150
15151 /*
15152 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15153 * - When nested paging isn't used.
15154 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15155 * - We are executing in the VM debug loop.
15156 */
15157 Assert( iCrReg != 3
15158 || !pVM->hm.s.fNestedPaging
15159 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15160 || pVCpu->hm.s.fUsingDebugLoop);
15161
15162 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15163 Assert( iCrReg != 8
15164 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15165
15166 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15167 break;
15168 }
15169
15170 /*
15171 * CLTS (Clear Task-Switch Flag in CR0).
15172 */
15173 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15174 {
15175 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15176 break;
15177 }
15178
15179 /*
15180 * LMSW (Load Machine-Status Word into CR0).
15181 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15182 */
15183 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15184 {
15185 RTGCPTR GCPtrEffDst;
15186 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15187 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15188 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15189 if (fMemOperand)
15190 {
15191 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15192 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15193 }
15194 else
15195 GCPtrEffDst = NIL_RTGCPTR;
15196 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15197 break;
15198 }
15199
15200 default:
15201 {
15202 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15203 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15204 }
15205 }
15206
15207 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15208 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15209 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15210
15211 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15212 NOREF(pVM);
15213 return rcStrict;
15214}
15215
15216
15217/**
15218 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15219 * VM-exit.
15220 */
15221HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15222{
15223 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15224 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15225
15226 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15227 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15228 hmR0VmxReadExitQualVmcs(pVmxTransient);
15229 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15230 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15231 | CPUMCTX_EXTRN_EFER);
15232 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15233 AssertRCReturn(rc, rc);
15234
15235 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15236 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15237 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15238 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15239 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15240 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15241 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15242 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15243
15244 /*
15245 * Update exit history to see if this exit can be optimized.
15246 */
15247 VBOXSTRICTRC rcStrict;
15248 PCEMEXITREC pExitRec = NULL;
15249 if ( !fGstStepping
15250 && !fDbgStepping)
15251 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15252 !fIOString
15253 ? !fIOWrite
15254 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15255 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15256 : !fIOWrite
15257 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15258 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15259 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15260 if (!pExitRec)
15261 {
15262 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15263 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15264
15265 uint32_t const cbValue = s_aIOSizes[uIOSize];
15266 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15267 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15268 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15269 if (fIOString)
15270 {
15271 /*
15272 * INS/OUTS - I/O String instruction.
15273 *
15274 * Use instruction-information if available, otherwise fall back on
15275 * interpreting the instruction.
15276 */
15277 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15278 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15279 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15280 if (fInsOutsInfo)
15281 {
15282 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15283 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15284 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15285 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15286 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15287 if (fIOWrite)
15288 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15289 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15290 else
15291 {
15292 /*
15293 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15294 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15295 * See Intel Instruction spec. for "INS".
15296 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15297 */
15298 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15299 }
15300 }
15301 else
15302 rcStrict = IEMExecOne(pVCpu);
15303
15304 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15305 fUpdateRipAlready = true;
15306 }
15307 else
15308 {
15309 /*
15310 * IN/OUT - I/O instruction.
15311 */
15312 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15313 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15314 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15315 if (fIOWrite)
15316 {
15317 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15318 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15319 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15320 && !pCtx->eflags.Bits.u1TF)
15321 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15322 }
15323 else
15324 {
15325 uint32_t u32Result = 0;
15326 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15327 if (IOM_SUCCESS(rcStrict))
15328 {
15329 /* Save result of I/O IN instr. in AL/AX/EAX. */
15330 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15331 }
15332 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15333 && !pCtx->eflags.Bits.u1TF)
15334 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15335 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15336 }
15337 }
15338
15339 if (IOM_SUCCESS(rcStrict))
15340 {
15341 if (!fUpdateRipAlready)
15342 {
15343 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15344 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15345 }
15346
15347 /*
15348 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15349 * while booting Fedora 17 64-bit guest.
15350 *
15351 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15352 */
15353 if (fIOString)
15354 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15355
15356 /*
15357 * If any I/O breakpoints are armed, we need to check if one triggered
15358 * and take appropriate action.
15359 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15360 */
15361 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15362 AssertRCReturn(rc, rc);
15363
15364 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15365 * execution engines about whether hyper BPs and such are pending. */
15366 uint32_t const uDr7 = pCtx->dr[7];
15367 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15368 && X86_DR7_ANY_RW_IO(uDr7)
15369 && (pCtx->cr4 & X86_CR4_DE))
15370 || DBGFBpIsHwIoArmed(pVM)))
15371 {
15372 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15373
15374 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15375 VMMRZCallRing3Disable(pVCpu);
15376 HM_DISABLE_PREEMPT(pVCpu);
15377
15378 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15379
15380 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15381 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15382 {
15383 /* Raise #DB. */
15384 if (fIsGuestDbgActive)
15385 ASMSetDR6(pCtx->dr[6]);
15386 if (pCtx->dr[7] != uDr7)
15387 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15388
15389 hmR0VmxSetPendingXcptDB(pVCpu);
15390 }
15391 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15392 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15393 else if ( rcStrict2 != VINF_SUCCESS
15394 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15395 rcStrict = rcStrict2;
15396 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15397
15398 HM_RESTORE_PREEMPT();
15399 VMMRZCallRing3Enable(pVCpu);
15400 }
15401 }
15402
15403#ifdef VBOX_STRICT
15404 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15405 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15406 Assert(!fIOWrite);
15407 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15408 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15409 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15410 Assert(fIOWrite);
15411 else
15412 {
15413# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15414 * statuses, that the VMM device and some others may return. See
15415 * IOM_SUCCESS() for guidance. */
15416 AssertMsg( RT_FAILURE(rcStrict)
15417 || rcStrict == VINF_SUCCESS
15418 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15419 || rcStrict == VINF_EM_DBG_BREAKPOINT
15420 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15421 || rcStrict == VINF_EM_RAW_TO_R3
15422 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15423# endif
15424 }
15425#endif
15426 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15427 }
15428 else
15429 {
15430 /*
15431 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15432 */
15433 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15434 AssertRCReturn(rc2, rc2);
15435 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15436 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15437 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15438 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15439 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15440 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15441
15442 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15443 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15444
15445 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15446 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15447 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15448 }
15449 return rcStrict;
15450}
15451
15452
15453/**
15454 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15455 * VM-exit.
15456 */
15457HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15458{
15459 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15460
15461 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15462 hmR0VmxReadExitQualVmcs(pVmxTransient);
15463 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15464 {
15465 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15466 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15467 {
15468 uint32_t uErrCode;
15469 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15470 {
15471 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15472 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15473 }
15474 else
15475 uErrCode = 0;
15476
15477 RTGCUINTPTR GCPtrFaultAddress;
15478 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15479 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15480 else
15481 GCPtrFaultAddress = 0;
15482
15483 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15484
15485 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15486 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15487
15488 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15489 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15490 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15491 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15492 }
15493 }
15494
15495 /* Fall back to the interpreter to emulate the task-switch. */
15496 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15497 return VERR_EM_INTERPRETER;
15498}
15499
15500
15501/**
15502 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15503 */
15504HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15505{
15506 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15507
15508 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15509 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15510 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15511 AssertRC(rc);
15512 return VINF_EM_DBG_STEPPED;
15513}
15514
15515
15516/**
15517 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15518 */
15519HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15520{
15521 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15522 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15523
15524 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15525 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15526 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15527 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15528 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15529
15530 /*
15531 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15532 */
15533 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15534 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15535 {
15536 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15537 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15538 {
15539 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15540 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15541 }
15542 }
15543 else
15544 {
15545 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15546 return rcStrict;
15547 }
15548
15549 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15550 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15551 hmR0VmxReadExitQualVmcs(pVmxTransient);
15552 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15553 AssertRCReturn(rc, rc);
15554
15555 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15556 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15557 switch (uAccessType)
15558 {
15559 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15560 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15561 {
15562 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15563 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15564 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15565
15566 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15567 GCPhys &= PAGE_BASE_GC_MASK;
15568 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15569 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15570 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15571
15572 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
15573 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
15574 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15575 if ( rcStrict == VINF_SUCCESS
15576 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15577 || rcStrict == VERR_PAGE_NOT_PRESENT)
15578 {
15579 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15580 | HM_CHANGED_GUEST_APIC_TPR);
15581 rcStrict = VINF_SUCCESS;
15582 }
15583 break;
15584 }
15585
15586 default:
15587 {
15588 Log4Func(("uAccessType=%#x\n", uAccessType));
15589 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15590 break;
15591 }
15592 }
15593
15594 if (rcStrict != VINF_SUCCESS)
15595 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15596 return rcStrict;
15597}
15598
15599
15600/**
15601 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15602 * VM-exit.
15603 */
15604HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15605{
15606 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15607 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15608
15609 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15610 if (!pVmxTransient->fIsNestedGuest)
15611 {
15612 /* We should -not- get this VM-exit if the guest's debug registers were active. */
15613 if (pVmxTransient->fWasGuestDebugStateActive)
15614 {
15615 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
15616 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15617 }
15618
15619 if ( !pVCpu->hm.s.fSingleInstruction
15620 && !pVmxTransient->fWasHyperDebugStateActive)
15621 {
15622 Assert(!DBGFIsStepping(pVCpu));
15623 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
15624
15625 /* Don't intercept MOV DRx any more. */
15626 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
15627 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15628 AssertRC(rc);
15629
15630 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
15631 VMMRZCallRing3Disable(pVCpu);
15632 HM_DISABLE_PREEMPT(pVCpu);
15633
15634 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
15635 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
15636 Assert(CPUMIsGuestDebugStateActive(pVCpu));
15637
15638 HM_RESTORE_PREEMPT();
15639 VMMRZCallRing3Enable(pVCpu);
15640
15641#ifdef VBOX_WITH_STATISTICS
15642 hmR0VmxReadExitQualVmcs(pVmxTransient);
15643 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15644 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15645 else
15646 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15647#endif
15648 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
15649 return VINF_SUCCESS;
15650 }
15651 }
15652
15653 /*
15654 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
15655 * The EFER MSR is always up-to-date.
15656 * Update the segment registers and DR7 from the CPU.
15657 */
15658 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15659 hmR0VmxReadExitQualVmcs(pVmxTransient);
15660 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
15661 AssertRCReturn(rc, rc);
15662 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
15663
15664 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15665 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15666 {
15667 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15668 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
15669 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
15670 if (RT_SUCCESS(rc))
15671 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
15672 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15673 }
15674 else
15675 {
15676 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15677 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
15678 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
15679 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15680 }
15681
15682 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
15683 if (RT_SUCCESS(rc))
15684 {
15685 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15686 AssertRCReturn(rc2, rc2);
15687 return VINF_SUCCESS;
15688 }
15689 return rc;
15690}
15691
15692
15693/**
15694 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
15695 * Conditional VM-exit.
15696 */
15697HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15698{
15699 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15700 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15701
15702 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15703 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15704 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15705 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15706 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15707
15708 /*
15709 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15710 */
15711 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15712 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15713 {
15714 /*
15715 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
15716 * instruction emulation to inject the original event. Otherwise, injecting the original event
15717 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
15718 */
15719 if (!pVCpu->hm.s.Event.fPending)
15720 { /* likely */ }
15721 else
15722 {
15723 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15724#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15725 /** @todo NSTVMX: Think about how this should be handled. */
15726 if (pVmxTransient->fIsNestedGuest)
15727 return VERR_VMX_IPE_3;
15728#endif
15729 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15730 }
15731 }
15732 else
15733 {
15734 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15735 return rcStrict;
15736 }
15737
15738 /*
15739 * Get sufficient state and update the exit history entry.
15740 */
15741 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15742 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15743 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15744 AssertRCReturn(rc, rc);
15745
15746 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15747 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15748 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
15749 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15750 if (!pExitRec)
15751 {
15752 /*
15753 * If we succeed, resume guest execution.
15754 * If we fail in interpreting the instruction because we couldn't get the guest physical address
15755 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
15756 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
15757 * weird case. See @bugref{6043}.
15758 */
15759 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15760 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15761/** @todo bird: We can probably just go straight to IOM here and assume that
15762 * it's MMIO, then fall back on PGM if that hunch didn't work out so
15763 * well. However, we need to address that aliasing workarounds that
15764 * PGMR0Trap0eHandlerNPMisconfig implements. So, some care is needed.
15765 *
15766 * Might also be interesting to see if we can get this done more or
15767 * less locklessly inside IOM. Need to consider the lookup table
15768 * updating and use a bit more carefully first (or do all updates via
15769 * rendezvous) */
15770 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
15771 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
15772 if ( rcStrict == VINF_SUCCESS
15773 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15774 || rcStrict == VERR_PAGE_NOT_PRESENT)
15775 {
15776 /* Successfully handled MMIO operation. */
15777 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15778 | HM_CHANGED_GUEST_APIC_TPR);
15779 rcStrict = VINF_SUCCESS;
15780 }
15781 }
15782 else
15783 {
15784 /*
15785 * Frequent exit or something needing probing. Call EMHistoryExec.
15786 */
15787 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
15788 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
15789
15790 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15791 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15792
15793 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15794 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15795 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15796 }
15797 return rcStrict;
15798}
15799
15800
15801/**
15802 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
15803 * VM-exit.
15804 */
15805HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15806{
15807 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15808 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15809
15810 hmR0VmxReadExitQualVmcs(pVmxTransient);
15811 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15812 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15813 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15814 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15815 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15816
15817 /*
15818 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15819 */
15820 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15821 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15822 {
15823 /*
15824 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
15825 * we shall resolve the nested #PF and re-inject the original event.
15826 */
15827 if (pVCpu->hm.s.Event.fPending)
15828 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
15829 }
15830 else
15831 {
15832 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15833 return rcStrict;
15834 }
15835
15836 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15837 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15838 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15839 AssertRCReturn(rc, rc);
15840
15841 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15842 uint64_t const uExitQual = pVmxTransient->uExitQual;
15843 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
15844
15845 RTGCUINT uErrorCode = 0;
15846 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
15847 uErrorCode |= X86_TRAP_PF_ID;
15848 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
15849 uErrorCode |= X86_TRAP_PF_RW;
15850 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
15851 uErrorCode |= X86_TRAP_PF_P;
15852
15853 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15854 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15855 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
15856
15857 /*
15858 * Handle the pagefault trap for the nested shadow table.
15859 */
15860 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
15861 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
15862 TRPMResetTrap(pVCpu);
15863
15864 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
15865 if ( rcStrict == VINF_SUCCESS
15866 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15867 || rcStrict == VERR_PAGE_NOT_PRESENT)
15868 {
15869 /* Successfully synced our nested page tables. */
15870 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
15871 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
15872 return VINF_SUCCESS;
15873 }
15874
15875 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15876 return rcStrict;
15877}
15878
15879
15880#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15881/**
15882 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
15883 */
15884HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15885{
15886 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15887
15888 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15889 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15890 hmR0VmxReadExitQualVmcs(pVmxTransient);
15891 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15892 | CPUMCTX_EXTRN_HWVIRT
15893 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15894 AssertRCReturn(rc, rc);
15895
15896 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15897
15898 VMXVEXITINFO ExitInfo;
15899 RT_ZERO(ExitInfo);
15900 ExitInfo.uReason = pVmxTransient->uExitReason;
15901 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15902 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15903 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15904 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15905
15906 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
15907 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15908 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15909 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15910 {
15911 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15912 rcStrict = VINF_SUCCESS;
15913 }
15914 return rcStrict;
15915}
15916
15917
15918/**
15919 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
15920 */
15921HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15922{
15923 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15924
15925 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
15926 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15927 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15928 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15929 AssertRCReturn(rc, rc);
15930
15931 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15932
15933 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15934 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
15935 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15936 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15937 {
15938 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15939 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15940 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15941 }
15942 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15943 return rcStrict;
15944}
15945
15946
15947/**
15948 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
15949 */
15950HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15951{
15952 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15953
15954 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15955 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15956 hmR0VmxReadExitQualVmcs(pVmxTransient);
15957 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15958 | CPUMCTX_EXTRN_HWVIRT
15959 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15960 AssertRCReturn(rc, rc);
15961
15962 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15963
15964 VMXVEXITINFO ExitInfo;
15965 RT_ZERO(ExitInfo);
15966 ExitInfo.uReason = pVmxTransient->uExitReason;
15967 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15968 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15969 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15970 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15971
15972 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
15973 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15974 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15975 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15976 {
15977 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15978 rcStrict = VINF_SUCCESS;
15979 }
15980 return rcStrict;
15981}
15982
15983
15984/**
15985 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
15986 */
15987HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15988{
15989 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15990
15991 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15992 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15993 hmR0VmxReadExitQualVmcs(pVmxTransient);
15994 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15995 | CPUMCTX_EXTRN_HWVIRT
15996 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15997 AssertRCReturn(rc, rc);
15998
15999 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16000
16001 VMXVEXITINFO ExitInfo;
16002 RT_ZERO(ExitInfo);
16003 ExitInfo.uReason = pVmxTransient->uExitReason;
16004 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16005 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16006 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16007 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16008
16009 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16010 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16011 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16012 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16013 {
16014 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16015 rcStrict = VINF_SUCCESS;
16016 }
16017 return rcStrict;
16018}
16019
16020
16021/**
16022 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16023 */
16024HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16025{
16026 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16027
16028 /*
16029 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16030 * thus might not need to import the shadow VMCS state, it's safer just in case
16031 * code elsewhere dares look at unsynced VMCS fields.
16032 */
16033 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16034 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16035 hmR0VmxReadExitQualVmcs(pVmxTransient);
16036 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16037 | CPUMCTX_EXTRN_HWVIRT
16038 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16039 AssertRCReturn(rc, rc);
16040
16041 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16042
16043 VMXVEXITINFO ExitInfo;
16044 RT_ZERO(ExitInfo);
16045 ExitInfo.uReason = pVmxTransient->uExitReason;
16046 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16047 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16048 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16049 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16050 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16051
16052 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16053 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16054 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16055 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16056 {
16057 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16058 rcStrict = VINF_SUCCESS;
16059 }
16060 return rcStrict;
16061}
16062
16063
16064/**
16065 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16066 */
16067HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16068{
16069 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16070
16071 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16072 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16073 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16074 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16075 AssertRCReturn(rc, rc);
16076
16077 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16078
16079 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16080 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16081 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16082 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16083 {
16084 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16085 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16086 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16087 }
16088 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16089 return rcStrict;
16090}
16091
16092
16093/**
16094 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16095 */
16096HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16097{
16098 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16099
16100 /*
16101 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16102 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16103 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16104 */
16105 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16106 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16107 hmR0VmxReadExitQualVmcs(pVmxTransient);
16108 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16109 | CPUMCTX_EXTRN_HWVIRT
16110 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16111 AssertRCReturn(rc, rc);
16112
16113 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16114
16115 VMXVEXITINFO ExitInfo;
16116 RT_ZERO(ExitInfo);
16117 ExitInfo.uReason = pVmxTransient->uExitReason;
16118 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16119 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16120 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16121 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16122 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16123
16124 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16125 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16126 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16127 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16128 {
16129 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16130 rcStrict = VINF_SUCCESS;
16131 }
16132 return rcStrict;
16133}
16134
16135
16136/**
16137 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16138 */
16139HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16140{
16141 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16142
16143 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16144 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16145 | CPUMCTX_EXTRN_HWVIRT
16146 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16147 AssertRCReturn(rc, rc);
16148
16149 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16150
16151 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16152 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16153 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16154 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16155 {
16156 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16157 rcStrict = VINF_SUCCESS;
16158 }
16159 return rcStrict;
16160}
16161
16162
16163/**
16164 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16165 */
16166HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16167{
16168 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16169
16170 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16171 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16172 hmR0VmxReadExitQualVmcs(pVmxTransient);
16173 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16174 | CPUMCTX_EXTRN_HWVIRT
16175 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16176 AssertRCReturn(rc, rc);
16177
16178 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16179
16180 VMXVEXITINFO ExitInfo;
16181 RT_ZERO(ExitInfo);
16182 ExitInfo.uReason = pVmxTransient->uExitReason;
16183 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16184 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16185 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16186 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16187
16188 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16189 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16190 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16191 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16192 {
16193 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16194 rcStrict = VINF_SUCCESS;
16195 }
16196 return rcStrict;
16197}
16198
16199
16200/**
16201 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16202 */
16203HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16204{
16205 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16206
16207 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16208 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16209 hmR0VmxReadExitQualVmcs(pVmxTransient);
16210 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16211 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16212 AssertRCReturn(rc, rc);
16213
16214 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16215
16216 VMXVEXITINFO ExitInfo;
16217 RT_ZERO(ExitInfo);
16218 ExitInfo.uReason = pVmxTransient->uExitReason;
16219 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16220 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16221 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16222 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16223
16224 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16225 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16226 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16227 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16228 {
16229 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16230 rcStrict = VINF_SUCCESS;
16231 }
16232 return rcStrict;
16233}
16234#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16235/** @} */
16236
16237
16238#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16239/** @name Nested-guest VM-exit handlers.
16240 * @{
16241 */
16242/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16243/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16244/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16245
16246/**
16247 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16248 * Conditional VM-exit.
16249 */
16250HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16251{
16252 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16253
16254 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16255
16256 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16257 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16258 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16259
16260 switch (uExitIntType)
16261 {
16262 /*
16263 * Physical NMIs:
16264 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16265 */
16266 case VMX_EXIT_INT_INFO_TYPE_NMI:
16267 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16268
16269 /*
16270 * Hardware exceptions,
16271 * Software exceptions,
16272 * Privileged software exceptions:
16273 * Figure out if the exception must be delivered to the guest or the nested-guest.
16274 */
16275 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16276 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16277 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16278 {
16279 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16280 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16281 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16282 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16283
16284 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16285 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16286 pVmxTransient->uExitIntErrorCode);
16287 if (fIntercept)
16288 {
16289 /* Exit qualification is required for debug and page-fault exceptions. */
16290 hmR0VmxReadExitQualVmcs(pVmxTransient);
16291
16292 /*
16293 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16294 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16295 * length. However, if delivery of a software interrupt, software exception or privileged
16296 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16297 */
16298 VMXVEXITINFO ExitInfo;
16299 RT_ZERO(ExitInfo);
16300 ExitInfo.uReason = pVmxTransient->uExitReason;
16301 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16302 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16303
16304 VMXVEXITEVENTINFO ExitEventInfo;
16305 RT_ZERO(ExitEventInfo);
16306 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16307 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16308 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16309 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16310
16311#ifdef DEBUG_ramshankar
16312 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16313 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16314 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16315 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16316 {
16317 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16318 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16319 }
16320#endif
16321 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16322 }
16323
16324 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16325 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16326 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16327 }
16328
16329 /*
16330 * Software interrupts:
16331 * VM-exits cannot be caused by software interrupts.
16332 *
16333 * External interrupts:
16334 * This should only happen when "acknowledge external interrupts on VM-exit"
16335 * control is set. However, we never set this when executing a guest or
16336 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16337 * the guest.
16338 */
16339 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16340 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16341 default:
16342 {
16343 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16344 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16345 }
16346 }
16347}
16348
16349
16350/**
16351 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16352 * Unconditional VM-exit.
16353 */
16354HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16355{
16356 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16357 return IEMExecVmxVmexitTripleFault(pVCpu);
16358}
16359
16360
16361/**
16362 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16363 */
16364HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16365{
16366 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16367
16368 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16369 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16370 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16371}
16372
16373
16374/**
16375 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16376 */
16377HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16378{
16379 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16380
16381 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16382 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16383 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16384}
16385
16386
16387/**
16388 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16389 * Unconditional VM-exit.
16390 */
16391HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16392{
16393 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16394
16395 hmR0VmxReadExitQualVmcs(pVmxTransient);
16396 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16397 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16398 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16399
16400 VMXVEXITINFO ExitInfo;
16401 RT_ZERO(ExitInfo);
16402 ExitInfo.uReason = pVmxTransient->uExitReason;
16403 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16404 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16405
16406 VMXVEXITEVENTINFO ExitEventInfo;
16407 RT_ZERO(ExitEventInfo);
16408 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16409 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16410 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16411}
16412
16413
16414/**
16415 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16416 */
16417HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16418{
16419 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16420
16421 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16422 {
16423 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16424 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16425 }
16426 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16427}
16428
16429
16430/**
16431 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16432 */
16433HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16434{
16435 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16436
16437 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16438 {
16439 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16440 hmR0VmxReadExitQualVmcs(pVmxTransient);
16441
16442 VMXVEXITINFO ExitInfo;
16443 RT_ZERO(ExitInfo);
16444 ExitInfo.uReason = pVmxTransient->uExitReason;
16445 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16446 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16447 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16448 }
16449 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16450}
16451
16452
16453/**
16454 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16455 */
16456HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16457{
16458 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16459
16460 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16461 {
16462 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16463 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16464 }
16465 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16466}
16467
16468
16469/**
16470 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16471 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16472 */
16473HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16474{
16475 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16476
16477 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16478 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16479
16480 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16481
16482 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16483 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16484 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16485
16486 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16487 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16488 u64VmcsField &= UINT64_C(0xffffffff);
16489
16490 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16491 {
16492 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16493 hmR0VmxReadExitQualVmcs(pVmxTransient);
16494
16495 VMXVEXITINFO ExitInfo;
16496 RT_ZERO(ExitInfo);
16497 ExitInfo.uReason = pVmxTransient->uExitReason;
16498 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16499 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16500 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16501 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16502 }
16503
16504 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16505 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16506 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16507}
16508
16509
16510/**
16511 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16512 */
16513HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16514{
16515 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16516
16517 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16518 {
16519 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16520 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16521 }
16522
16523 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16524}
16525
16526
16527/**
16528 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16529 * Conditional VM-exit.
16530 */
16531HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16532{
16533 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16534
16535 hmR0VmxReadExitQualVmcs(pVmxTransient);
16536 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16537
16538 VBOXSTRICTRC rcStrict;
16539 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16540 switch (uAccessType)
16541 {
16542 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16543 {
16544 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16545 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16546 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16547 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16548
16549 bool fIntercept;
16550 switch (iCrReg)
16551 {
16552 case 0:
16553 case 4:
16554 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(&pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16555 break;
16556
16557 case 3:
16558 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16559 break;
16560
16561 case 8:
16562 fIntercept = CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16563 break;
16564
16565 default:
16566 fIntercept = false;
16567 break;
16568 }
16569 if (fIntercept)
16570 {
16571 VMXVEXITINFO ExitInfo;
16572 RT_ZERO(ExitInfo);
16573 ExitInfo.uReason = pVmxTransient->uExitReason;
16574 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16575 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16576 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16577 }
16578 else
16579 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16580 break;
16581 }
16582
16583 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16584 {
16585 /*
16586 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16587 * CR2 reads do not cause a VM-exit.
16588 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16589 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16590 */
16591 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16592 if ( iCrReg == 3
16593 || iCrReg == 8)
16594 {
16595 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16596 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16597 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16598 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uIntercept))
16599 {
16600 VMXVEXITINFO ExitInfo;
16601 RT_ZERO(ExitInfo);
16602 ExitInfo.uReason = pVmxTransient->uExitReason;
16603 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16604 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16605 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16606 }
16607 else
16608 {
16609 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16610 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16611 }
16612 }
16613 else
16614 {
16615 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
16616 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
16617 }
16618 break;
16619 }
16620
16621 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
16622 {
16623 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
16624 Assert(pVmcsNstGst);
16625 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
16626 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
16627 if ( (uGstHostMask & X86_CR0_TS)
16628 && (uReadShadow & X86_CR0_TS))
16629 {
16630 VMXVEXITINFO ExitInfo;
16631 RT_ZERO(ExitInfo);
16632 ExitInfo.uReason = pVmxTransient->uExitReason;
16633 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16634 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16635 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16636 }
16637 else
16638 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
16639 break;
16640 }
16641
16642 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
16643 {
16644 RTGCPTR GCPtrEffDst;
16645 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
16646 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
16647 if (fMemOperand)
16648 {
16649 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16650 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
16651 }
16652 else
16653 GCPtrEffDst = NIL_RTGCPTR;
16654
16655 if (CPUMIsGuestVmxLmswInterceptSet(&pVCpu->cpum.GstCtx, uNewMsw))
16656 {
16657 VMXVEXITINFO ExitInfo;
16658 RT_ZERO(ExitInfo);
16659 ExitInfo.uReason = pVmxTransient->uExitReason;
16660 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16661 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
16662 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16663 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16664 }
16665 else
16666 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
16667 break;
16668 }
16669
16670 default:
16671 {
16672 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
16673 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
16674 }
16675 }
16676
16677 if (rcStrict == VINF_IEM_RAISED_XCPT)
16678 {
16679 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16680 rcStrict = VINF_SUCCESS;
16681 }
16682 return rcStrict;
16683}
16684
16685
16686/**
16687 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
16688 * Conditional VM-exit.
16689 */
16690HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16691{
16692 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16693
16694 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
16695 {
16696 hmR0VmxReadExitQualVmcs(pVmxTransient);
16697 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16698
16699 VMXVEXITINFO ExitInfo;
16700 RT_ZERO(ExitInfo);
16701 ExitInfo.uReason = pVmxTransient->uExitReason;
16702 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16703 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16704 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16705 }
16706 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
16707}
16708
16709
16710/**
16711 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
16712 * Conditional VM-exit.
16713 */
16714HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16715{
16716 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16717
16718 hmR0VmxReadExitQualVmcs(pVmxTransient);
16719
16720 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16721 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16722 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16723
16724 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16725 uint8_t const cbAccess = s_aIOSizes[uIOSize];
16726 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
16727 {
16728 /*
16729 * IN/OUT instruction:
16730 * - Provides VM-exit instruction length.
16731 *
16732 * INS/OUTS instruction:
16733 * - Provides VM-exit instruction length.
16734 * - Provides Guest-linear address.
16735 * - Optionally provides VM-exit instruction info (depends on CPU feature).
16736 */
16737 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16738 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16739
16740 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
16741 pVmxTransient->ExitInstrInfo.u = 0;
16742 pVmxTransient->uGuestLinearAddr = 0;
16743
16744 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
16745 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
16746 if (fIOString)
16747 {
16748 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16749 if (fVmxInsOutsInfo)
16750 {
16751 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
16752 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16753 }
16754 }
16755
16756 VMXVEXITINFO ExitInfo;
16757 RT_ZERO(ExitInfo);
16758 ExitInfo.uReason = pVmxTransient->uExitReason;
16759 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16760 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16761 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16762 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
16763 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16764 }
16765 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
16766}
16767
16768
16769/**
16770 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
16771 */
16772HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16773{
16774 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16775
16776 uint32_t fMsrpm;
16777 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16778 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16779 else
16780 fMsrpm = VMXMSRPM_EXIT_RD;
16781
16782 if (fMsrpm & VMXMSRPM_EXIT_RD)
16783 {
16784 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16785 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16786 }
16787 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
16788}
16789
16790
16791/**
16792 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
16793 */
16794HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16795{
16796 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16797
16798 uint32_t fMsrpm;
16799 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16800 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16801 else
16802 fMsrpm = VMXMSRPM_EXIT_WR;
16803
16804 if (fMsrpm & VMXMSRPM_EXIT_WR)
16805 {
16806 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16807 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16808 }
16809 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
16810}
16811
16812
16813/**
16814 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
16815 */
16816HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16817{
16818 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16819
16820 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
16821 {
16822 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16823 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16824 }
16825 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
16826}
16827
16828
16829/**
16830 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
16831 * VM-exit.
16832 */
16833HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16834{
16835 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16836
16837 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
16838 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
16839 VMXVEXITINFO ExitInfo;
16840 RT_ZERO(ExitInfo);
16841 ExitInfo.uReason = pVmxTransient->uExitReason;
16842 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
16843 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
16844}
16845
16846
16847/**
16848 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
16849 */
16850HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16851{
16852 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16853
16854 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
16855 {
16856 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16857 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16858 }
16859 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
16860}
16861
16862
16863/**
16864 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
16865 */
16866HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16867{
16868 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16869
16870 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
16871 * PAUSE when executing a nested-guest? If it does not, we would not need
16872 * to check for the intercepts here. Just call VM-exit... */
16873
16874 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
16875 if ( CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
16876 || CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
16877 {
16878 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16879 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16880 }
16881 return hmR0VmxExitPause(pVCpu, pVmxTransient);
16882}
16883
16884
16885/**
16886 * Nested-guest VM-exit handler for when the TPR value is lowered below the
16887 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
16888 */
16889HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16890{
16891 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16892
16893 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
16894 {
16895 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
16896 VMXVEXITINFO ExitInfo;
16897 RT_ZERO(ExitInfo);
16898 ExitInfo.uReason = pVmxTransient->uExitReason;
16899 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
16900 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
16901 }
16902 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
16903}
16904
16905
16906/**
16907 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
16908 * VM-exit.
16909 */
16910HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16911{
16912 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16913
16914 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16915 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16916 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16917 hmR0VmxReadExitQualVmcs(pVmxTransient);
16918
16919 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
16920
16921 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
16922 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
16923
16924 VMXVEXITINFO ExitInfo;
16925 RT_ZERO(ExitInfo);
16926 ExitInfo.uReason = pVmxTransient->uExitReason;
16927 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16928 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16929
16930 VMXVEXITEVENTINFO ExitEventInfo;
16931 RT_ZERO(ExitEventInfo);
16932 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16933 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16934 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
16935}
16936
16937
16938/**
16939 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
16940 * Conditional VM-exit.
16941 */
16942HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16943{
16944 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16945
16946 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
16947 hmR0VmxReadExitQualVmcs(pVmxTransient);
16948 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16949}
16950
16951
16952/**
16953 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
16954 * Conditional VM-exit.
16955 */
16956HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16957{
16958 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16959
16960 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
16961 hmR0VmxReadExitQualVmcs(pVmxTransient);
16962 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16963}
16964
16965
16966/**
16967 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
16968 */
16969HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16970{
16971 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16972
16973 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16974 {
16975 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
16976 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16977 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16978 }
16979 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
16980}
16981
16982
16983/**
16984 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
16985 */
16986HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16987{
16988 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16989
16990 if (CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
16991 {
16992 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16993 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16994 }
16995 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
16996}
16997
16998
16999/**
17000 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17001 */
17002HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17003{
17004 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17005
17006 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17007 {
17008 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17009 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17010 hmR0VmxReadExitQualVmcs(pVmxTransient);
17011 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17012
17013 VMXVEXITINFO ExitInfo;
17014 RT_ZERO(ExitInfo);
17015 ExitInfo.uReason = pVmxTransient->uExitReason;
17016 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17017 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17018 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17019 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17020 }
17021 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17022}
17023
17024
17025/**
17026 * Nested-guest VM-exit handler for invalid-guest state
17027 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17028 */
17029HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17030{
17031 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17032
17033 /*
17034 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17035 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17036 * Handle it like it's in an invalid guest state of the outer guest.
17037 *
17038 * When the fast path is implemented, this should be changed to cause the corresponding
17039 * nested-guest VM-exit.
17040 */
17041 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17042}
17043
17044
17045/**
17046 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17047 * and only provide the instruction length.
17048 *
17049 * Unconditional VM-exit.
17050 */
17051HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17052{
17053 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17054
17055#ifdef VBOX_STRICT
17056 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17057 switch (pVmxTransient->uExitReason)
17058 {
17059 case VMX_EXIT_ENCLS:
17060 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17061 break;
17062
17063 case VMX_EXIT_VMFUNC:
17064 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_VMFUNC));
17065 break;
17066 }
17067#endif
17068
17069 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17070 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17071}
17072
17073
17074/**
17075 * Nested-guest VM-exit handler for instructions that provide instruction length as
17076 * well as more information.
17077 *
17078 * Unconditional VM-exit.
17079 */
17080HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17081{
17082 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17083
17084#ifdef VBOX_STRICT
17085 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17086 switch (pVmxTransient->uExitReason)
17087 {
17088 case VMX_EXIT_GDTR_IDTR_ACCESS:
17089 case VMX_EXIT_LDTR_TR_ACCESS:
17090 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17091 break;
17092
17093 case VMX_EXIT_RDRAND:
17094 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17095 break;
17096
17097 case VMX_EXIT_RDSEED:
17098 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17099 break;
17100
17101 case VMX_EXIT_XSAVES:
17102 case VMX_EXIT_XRSTORS:
17103 /** @todo NSTVMX: Verify XSS-bitmap. */
17104 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17105 break;
17106
17107 case VMX_EXIT_UMWAIT:
17108 case VMX_EXIT_TPAUSE:
17109 Assert(CPUMIsGuestVmxProcCtlsSet(pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17110 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17111 break;
17112 }
17113#endif
17114
17115 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17116 hmR0VmxReadExitQualVmcs(pVmxTransient);
17117 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17118
17119 VMXVEXITINFO ExitInfo;
17120 RT_ZERO(ExitInfo);
17121 ExitInfo.uReason = pVmxTransient->uExitReason;
17122 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17123 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17124 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17125 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17126}
17127
17128/** @} */
17129#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17130
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