VirtualBox

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

Last change on this file since 87559 was 87558, checked in by vboxsync, 4 years ago

VMM/HMVMX: Moved/copy last branch stuff from HM::vmxUse to HMR0PERVM::vmx. bugref:9217

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 732.6 KB
Line 
1/* $Id: HMVMXR0.cpp 87558 2021-02-03 11:21:28Z vboxsync $ */
2/** @file
3 * HM VMX (Intel VT-x) - Host Context Ring-0.
4 */
5
6/*
7 * Copyright (C) 2012-2020 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)->hmr0.s.idEnteredCpu == RTMpCpuId(), \
165 ("Illegal migration! Entered on CPU %u Current %u\n", \
166 (a_pVCpu)->hmr0.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 DECLCALLBACKTYPE(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
693#ifdef VBOX_STRICT
694static const uint32_t g_aVmcsSegBase[] =
695{
696 VMX_VMCS_GUEST_ES_BASE,
697 VMX_VMCS_GUEST_CS_BASE,
698 VMX_VMCS_GUEST_SS_BASE,
699 VMX_VMCS_GUEST_DS_BASE,
700 VMX_VMCS_GUEST_FS_BASE,
701 VMX_VMCS_GUEST_GS_BASE
702};
703static const uint32_t g_aVmcsSegSel[] =
704{
705 VMX_VMCS16_GUEST_ES_SEL,
706 VMX_VMCS16_GUEST_CS_SEL,
707 VMX_VMCS16_GUEST_SS_SEL,
708 VMX_VMCS16_GUEST_DS_SEL,
709 VMX_VMCS16_GUEST_FS_SEL,
710 VMX_VMCS16_GUEST_GS_SEL
711};
712static const uint32_t g_aVmcsSegLimit[] =
713{
714 VMX_VMCS32_GUEST_ES_LIMIT,
715 VMX_VMCS32_GUEST_CS_LIMIT,
716 VMX_VMCS32_GUEST_SS_LIMIT,
717 VMX_VMCS32_GUEST_DS_LIMIT,
718 VMX_VMCS32_GUEST_FS_LIMIT,
719 VMX_VMCS32_GUEST_GS_LIMIT
720};
721static const uint32_t g_aVmcsSegAttr[] =
722{
723 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
724 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
725 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
726 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
727 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
728 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
729};
730AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
731AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
732AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
733AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
734#endif /* VBOX_STRICT */
735
736#ifdef HMVMX_USE_FUNCTION_TABLE
737/**
738 * VMX_EXIT dispatch table.
739 */
740static const struct CLANG11NOTHROWWEIRDNESS { PFNVMXEXITHANDLER pfn; } g_aVMExitHandlers[VMX_EXIT_MAX + 1] =
741{
742 /* 0 VMX_EXIT_XCPT_OR_NMI */ { hmR0VmxExitXcptOrNmi },
743 /* 1 VMX_EXIT_EXT_INT */ { hmR0VmxExitExtInt },
744 /* 2 VMX_EXIT_TRIPLE_FAULT */ { hmR0VmxExitTripleFault },
745 /* 3 VMX_EXIT_INIT_SIGNAL */ { hmR0VmxExitErrUnexpected },
746 /* 4 VMX_EXIT_SIPI */ { hmR0VmxExitErrUnexpected },
747 /* 5 VMX_EXIT_IO_SMI */ { hmR0VmxExitErrUnexpected },
748 /* 6 VMX_EXIT_SMI */ { hmR0VmxExitErrUnexpected },
749 /* 7 VMX_EXIT_INT_WINDOW */ { hmR0VmxExitIntWindow },
750 /* 8 VMX_EXIT_NMI_WINDOW */ { hmR0VmxExitNmiWindow },
751 /* 9 VMX_EXIT_TASK_SWITCH */ { hmR0VmxExitTaskSwitch },
752 /* 10 VMX_EXIT_CPUID */ { hmR0VmxExitCpuid },
753 /* 11 VMX_EXIT_GETSEC */ { hmR0VmxExitGetsec },
754 /* 12 VMX_EXIT_HLT */ { hmR0VmxExitHlt },
755 /* 13 VMX_EXIT_INVD */ { hmR0VmxExitInvd },
756 /* 14 VMX_EXIT_INVLPG */ { hmR0VmxExitInvlpg },
757 /* 15 VMX_EXIT_RDPMC */ { hmR0VmxExitRdpmc },
758 /* 16 VMX_EXIT_RDTSC */ { hmR0VmxExitRdtsc },
759 /* 17 VMX_EXIT_RSM */ { hmR0VmxExitErrUnexpected },
760 /* 18 VMX_EXIT_VMCALL */ { hmR0VmxExitVmcall },
761#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
762 /* 19 VMX_EXIT_VMCLEAR */ { hmR0VmxExitVmclear },
763 /* 20 VMX_EXIT_VMLAUNCH */ { hmR0VmxExitVmlaunch },
764 /* 21 VMX_EXIT_VMPTRLD */ { hmR0VmxExitVmptrld },
765 /* 22 VMX_EXIT_VMPTRST */ { hmR0VmxExitVmptrst },
766 /* 23 VMX_EXIT_VMREAD */ { hmR0VmxExitVmread },
767 /* 24 VMX_EXIT_VMRESUME */ { hmR0VmxExitVmresume },
768 /* 25 VMX_EXIT_VMWRITE */ { hmR0VmxExitVmwrite },
769 /* 26 VMX_EXIT_VMXOFF */ { hmR0VmxExitVmxoff },
770 /* 27 VMX_EXIT_VMXON */ { hmR0VmxExitVmxon },
771#else
772 /* 19 VMX_EXIT_VMCLEAR */ { hmR0VmxExitSetPendingXcptUD },
773 /* 20 VMX_EXIT_VMLAUNCH */ { hmR0VmxExitSetPendingXcptUD },
774 /* 21 VMX_EXIT_VMPTRLD */ { hmR0VmxExitSetPendingXcptUD },
775 /* 22 VMX_EXIT_VMPTRST */ { hmR0VmxExitSetPendingXcptUD },
776 /* 23 VMX_EXIT_VMREAD */ { hmR0VmxExitSetPendingXcptUD },
777 /* 24 VMX_EXIT_VMRESUME */ { hmR0VmxExitSetPendingXcptUD },
778 /* 25 VMX_EXIT_VMWRITE */ { hmR0VmxExitSetPendingXcptUD },
779 /* 26 VMX_EXIT_VMXOFF */ { hmR0VmxExitSetPendingXcptUD },
780 /* 27 VMX_EXIT_VMXON */ { hmR0VmxExitSetPendingXcptUD },
781#endif
782 /* 28 VMX_EXIT_MOV_CRX */ { hmR0VmxExitMovCRx },
783 /* 29 VMX_EXIT_MOV_DRX */ { hmR0VmxExitMovDRx },
784 /* 30 VMX_EXIT_IO_INSTR */ { hmR0VmxExitIoInstr },
785 /* 31 VMX_EXIT_RDMSR */ { hmR0VmxExitRdmsr },
786 /* 32 VMX_EXIT_WRMSR */ { hmR0VmxExitWrmsr },
787 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ { hmR0VmxExitErrInvalidGuestState },
788 /* 34 VMX_EXIT_ERR_MSR_LOAD */ { hmR0VmxExitErrUnexpected },
789 /* 35 UNDEFINED */ { hmR0VmxExitErrUnexpected },
790 /* 36 VMX_EXIT_MWAIT */ { hmR0VmxExitMwait },
791 /* 37 VMX_EXIT_MTF */ { hmR0VmxExitMtf },
792 /* 38 UNDEFINED */ { hmR0VmxExitErrUnexpected },
793 /* 39 VMX_EXIT_MONITOR */ { hmR0VmxExitMonitor },
794 /* 40 VMX_EXIT_PAUSE */ { hmR0VmxExitPause },
795 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ { hmR0VmxExitErrUnexpected },
796 /* 42 UNDEFINED */ { hmR0VmxExitErrUnexpected },
797 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ { hmR0VmxExitTprBelowThreshold },
798 /* 44 VMX_EXIT_APIC_ACCESS */ { hmR0VmxExitApicAccess },
799 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ { hmR0VmxExitErrUnexpected },
800 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ { hmR0VmxExitErrUnexpected },
801 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ { hmR0VmxExitErrUnexpected },
802 /* 48 VMX_EXIT_EPT_VIOLATION */ { hmR0VmxExitEptViolation },
803 /* 49 VMX_EXIT_EPT_MISCONFIG */ { hmR0VmxExitEptMisconfig },
804 /* 50 VMX_EXIT_INVEPT */ { hmR0VmxExitSetPendingXcptUD },
805 /* 51 VMX_EXIT_RDTSCP */ { hmR0VmxExitRdtscp },
806 /* 52 VMX_EXIT_PREEMPT_TIMER */ { hmR0VmxExitPreemptTimer },
807#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
808 /* 53 VMX_EXIT_INVVPID */ { hmR0VmxExitInvvpid },
809#else
810 /* 53 VMX_EXIT_INVVPID */ { hmR0VmxExitSetPendingXcptUD },
811#endif
812 /* 54 VMX_EXIT_WBINVD */ { hmR0VmxExitWbinvd },
813 /* 55 VMX_EXIT_XSETBV */ { hmR0VmxExitXsetbv },
814 /* 56 VMX_EXIT_APIC_WRITE */ { hmR0VmxExitErrUnexpected },
815 /* 57 VMX_EXIT_RDRAND */ { hmR0VmxExitErrUnexpected },
816 /* 58 VMX_EXIT_INVPCID */ { hmR0VmxExitInvpcid },
817 /* 59 VMX_EXIT_VMFUNC */ { hmR0VmxExitErrUnexpected },
818 /* 60 VMX_EXIT_ENCLS */ { hmR0VmxExitErrUnexpected },
819 /* 61 VMX_EXIT_RDSEED */ { hmR0VmxExitErrUnexpected },
820 /* 62 VMX_EXIT_PML_FULL */ { hmR0VmxExitErrUnexpected },
821 /* 63 VMX_EXIT_XSAVES */ { hmR0VmxExitErrUnexpected },
822 /* 64 VMX_EXIT_XRSTORS */ { hmR0VmxExitErrUnexpected },
823 /* 65 UNDEFINED */ { hmR0VmxExitErrUnexpected },
824 /* 66 VMX_EXIT_SPP_EVENT */ { hmR0VmxExitErrUnexpected },
825 /* 67 VMX_EXIT_UMWAIT */ { hmR0VmxExitErrUnexpected },
826 /* 68 VMX_EXIT_TPAUSE */ { hmR0VmxExitErrUnexpected },
827};
828#endif /* HMVMX_USE_FUNCTION_TABLE */
829
830#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
831static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
832{
833 /* 0 */ "(Not Used)",
834 /* 1 */ "VMCALL executed in VMX root operation.",
835 /* 2 */ "VMCLEAR with invalid physical address.",
836 /* 3 */ "VMCLEAR with VMXON pointer.",
837 /* 4 */ "VMLAUNCH with non-clear VMCS.",
838 /* 5 */ "VMRESUME with non-launched VMCS.",
839 /* 6 */ "VMRESUME after VMXOFF",
840 /* 7 */ "VM-entry with invalid control fields.",
841 /* 8 */ "VM-entry with invalid host state fields.",
842 /* 9 */ "VMPTRLD with invalid physical address.",
843 /* 10 */ "VMPTRLD with VMXON pointer.",
844 /* 11 */ "VMPTRLD with incorrect revision identifier.",
845 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
846 /* 13 */ "VMWRITE to read-only VMCS component.",
847 /* 14 */ "(Not Used)",
848 /* 15 */ "VMXON executed in VMX root operation.",
849 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
850 /* 17 */ "VM-entry with non-launched executing VMCS.",
851 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
852 /* 19 */ "VMCALL with non-clear VMCS.",
853 /* 20 */ "VMCALL with invalid VM-exit control fields.",
854 /* 21 */ "(Not Used)",
855 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
856 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
857 /* 24 */ "VMCALL with invalid SMM-monitor features.",
858 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
859 /* 26 */ "VM-entry with events blocked by MOV SS.",
860 /* 27 */ "(Not Used)",
861 /* 28 */ "Invalid operand to INVEPT/INVVPID."
862};
863#endif /* VBOX_STRICT && LOG_ENABLED */
864
865
866/**
867 * Checks if the given MSR is part of the lastbranch-from-IP MSR stack.
868 * @returns @c true if it's part of LBR stack, @c false otherwise.
869 *
870 * @param pVM The cross context VM structure.
871 * @param idMsr The MSR.
872 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
873 * Optional, can be NULL.
874 *
875 * @remarks Must only be called when LBR is enabled.
876 */
877DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchFromMsr(PCVMCC pVM, uint32_t idMsr, uint32_t *pidxMsr)
878{
879 Assert(pVM->hmr0.s.vmx.fLbr);
880 Assert(pVM->hmr0.s.vmx.idLbrFromIpMsrFirst);
881 uint32_t const cLbrStack = pVM->hmr0.s.vmx.idLbrFromIpMsrLast - pVM->hmr0.s.vmx.idLbrFromIpMsrFirst + 1;
882 uint32_t const idxMsr = idMsr - pVM->hmr0.s.vmx.idLbrFromIpMsrFirst;
883 if (idxMsr < cLbrStack)
884 {
885 if (pidxMsr)
886 *pidxMsr = idxMsr;
887 return true;
888 }
889 return false;
890}
891
892
893/**
894 * Checks if the given MSR is part of the lastbranch-to-IP MSR stack.
895 * @returns @c true if it's part of LBR stack, @c false otherwise.
896 *
897 * @param pVM The cross context VM structure.
898 * @param idMsr The MSR.
899 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
900 * Optional, can be NULL.
901 *
902 * @remarks Must only be called when LBR is enabled and when lastbranch-to-IP MSRs
903 * are supported by the CPU (see hmR0VmxSetupLbrMsrRange).
904 */
905DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchToMsr(PCVMCC pVM, uint32_t idMsr, uint32_t *pidxMsr)
906{
907 Assert(pVM->hmr0.s.vmx.fLbr);
908 if (pVM->hmr0.s.vmx.idLbrToIpMsrFirst)
909 {
910 uint32_t const cLbrStack = pVM->hmr0.s.vmx.idLbrToIpMsrLast - pVM->hmr0.s.vmx.idLbrToIpMsrFirst + 1;
911 uint32_t const idxMsr = idMsr - pVM->hmr0.s.vmx.idLbrToIpMsrFirst;
912 if (idxMsr < cLbrStack)
913 {
914 if (pidxMsr)
915 *pidxMsr = idxMsr;
916 return true;
917 }
918 }
919 return false;
920}
921
922
923/**
924 * Gets the CR0 guest/host mask.
925 *
926 * These bits typically does not change through the lifetime of a VM. Any bit set in
927 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
928 * by the guest.
929 *
930 * @returns The CR0 guest/host mask.
931 * @param pVCpu The cross context virtual CPU structure.
932 */
933static uint64_t hmR0VmxGetFixedCr0Mask(PCVMCPUCC pVCpu)
934{
935 /*
936 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
937 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
938 *
939 * Furthermore, modifications to any bits that are reserved/unspecified currently
940 * by the Intel spec. must also cause a VM-exit. This prevents unpredictable behavior
941 * when future CPUs specify and use currently reserved/unspecified bits.
942 */
943 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
944 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
945 * and @bugref{6944}. */
946 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
947 return ( X86_CR0_PE
948 | X86_CR0_NE
949 | (pVM->hmr0.s.fNestedPaging ? 0 : X86_CR0_WP)
950 | X86_CR0_PG
951 | VMX_EXIT_HOST_CR0_IGNORE_MASK);
952}
953
954
955/**
956 * Gets the CR4 guest/host mask.
957 *
958 * These bits typically does not change through the lifetime of a VM. Any bit set in
959 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
960 * by the guest.
961 *
962 * @returns The CR4 guest/host mask.
963 * @param pVCpu The cross context virtual CPU structure.
964 */
965static uint64_t hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
966{
967 /*
968 * We construct a mask of all CR4 bits that the guest can modify without causing
969 * a VM-exit. Then invert this mask to obtain all CR4 bits that should cause
970 * a VM-exit when the guest attempts to modify them when executing using
971 * hardware-assisted VMX.
972 *
973 * When a feature is not exposed to the guest (and may be present on the host),
974 * we want to intercept guest modifications to the bit so we can emulate proper
975 * behavior (e.g., #GP).
976 *
977 * Furthermore, only modifications to those bits that don't require immediate
978 * emulation is allowed. For e.g., PCIDE is excluded because the behavior
979 * depends on CR3 which might not always be the guest value while executing
980 * using hardware-assisted VMX.
981 */
982 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
983 bool const fFsGsBase = pVM->cpum.ro.GuestFeatures.fFsGsBase;
984 bool const fXSaveRstor = pVM->cpum.ro.GuestFeatures.fXSaveRstor;
985 bool const fFxSaveRstor = pVM->cpum.ro.GuestFeatures.fFxSaveRstor;
986
987 /*
988 * Paranoia.
989 * Ensure features exposed to the guest are present on the host.
990 */
991 Assert(!fFsGsBase || pVM->cpum.ro.HostFeatures.fFsGsBase);
992 Assert(!fXSaveRstor || pVM->cpum.ro.HostFeatures.fXSaveRstor);
993 Assert(!fFxSaveRstor || pVM->cpum.ro.HostFeatures.fFxSaveRstor);
994
995 uint64_t const fGstMask = ( X86_CR4_PVI
996 | X86_CR4_TSD
997 | X86_CR4_DE
998 | X86_CR4_MCE
999 | X86_CR4_PCE
1000 | X86_CR4_OSXMMEEXCPT
1001 | (fFsGsBase ? X86_CR4_FSGSBASE : 0)
1002 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
1003 | (fFxSaveRstor ? X86_CR4_OSFXSR : 0));
1004 return ~fGstMask;
1005}
1006
1007
1008/**
1009 * Gets the active (in use) VMCS info. object for the specified VCPU.
1010 *
1011 * This is either the guest or nested-guest VMCS info. and need not necessarily
1012 * pertain to the "current" VMCS (in the VMX definition of the term). For instance,
1013 * if the VM-entry failed due to an invalid-guest state, we may have "cleared" the
1014 * current VMCS while returning to ring-3. However, the VMCS info. object for that
1015 * VMCS would still be active and returned here so that we could dump the VMCS
1016 * fields to ring-3 for diagnostics. This function is thus only used to
1017 * distinguish between the nested-guest or guest VMCS.
1018 *
1019 * @returns The active VMCS information.
1020 * @param pVCpu The cross context virtual CPU structure.
1021 *
1022 * @thread EMT.
1023 * @remarks This function may be called with preemption or interrupts disabled!
1024 */
1025DECLINLINE(PVMXVMCSINFO) hmGetVmxActiveVmcsInfo(PVMCPUCC pVCpu)
1026{
1027 if (!pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
1028 return &pVCpu->hmr0.s.vmx.VmcsInfo;
1029 return &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1030}
1031
1032
1033/**
1034 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
1035 * area.
1036 *
1037 * @returns @c true if it's different, @c false otherwise.
1038 * @param pVmcsInfo The VMCS info. object.
1039 */
1040DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
1041{
1042 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
1043 && pVmcsInfo->pvGuestMsrStore);
1044}
1045
1046
1047/**
1048 * Sets the given Processor-based VM-execution controls.
1049 *
1050 * @param pVmxTransient The VMX-transient structure.
1051 * @param uProcCtls The Processor-based VM-execution controls to set.
1052 */
1053static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1054{
1055 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1056 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
1057 {
1058 pVmcsInfo->u32ProcCtls |= uProcCtls;
1059 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1060 AssertRC(rc);
1061 }
1062}
1063
1064
1065/**
1066 * Removes the given Processor-based VM-execution controls.
1067 *
1068 * @param pVCpu The cross context virtual CPU structure.
1069 * @param pVmxTransient The VMX-transient structure.
1070 * @param uProcCtls The Processor-based VM-execution controls to remove.
1071 *
1072 * @remarks When executing a nested-guest, this will not remove any of the specified
1073 * controls if the nested hypervisor has set any one of them.
1074 */
1075static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1076{
1077 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1078 if (pVmcsInfo->u32ProcCtls & uProcCtls)
1079 {
1080#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1081 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
1082 ? true
1083 : !CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uProcCtls);
1084#else
1085 NOREF(pVCpu);
1086 bool const fRemoveCtls = true;
1087#endif
1088 if (fRemoveCtls)
1089 {
1090 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
1091 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1092 AssertRC(rc);
1093 }
1094 }
1095}
1096
1097
1098/**
1099 * Sets the TSC offset for the current VMCS.
1100 *
1101 * @param uTscOffset The TSC offset to set.
1102 * @param pVmcsInfo The VMCS info. object.
1103 */
1104static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
1105{
1106 if (pVmcsInfo->u64TscOffset != uTscOffset)
1107 {
1108 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
1109 AssertRC(rc);
1110 pVmcsInfo->u64TscOffset = uTscOffset;
1111 }
1112}
1113
1114
1115/**
1116 * Adds one or more exceptions to the exception bitmap and commits it to the current
1117 * VMCS.
1118 *
1119 * @param pVmxTransient The VMX-transient structure.
1120 * @param uXcptMask The exception(s) to add.
1121 */
1122static void hmR0VmxAddXcptInterceptMask(PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1123{
1124 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1125 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1126 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1127 {
1128 uXcptBitmap |= uXcptMask;
1129 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1130 AssertRC(rc);
1131 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1132 }
1133}
1134
1135
1136/**
1137 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1138 *
1139 * @param pVmxTransient The VMX-transient structure.
1140 * @param uXcpt The exception to add.
1141 */
1142static void hmR0VmxAddXcptIntercept(PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1143{
1144 Assert(uXcpt <= X86_XCPT_LAST);
1145 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1146}
1147
1148
1149/**
1150 * Remove one or more exceptions from the exception bitmap and commits it to the
1151 * current VMCS.
1152 *
1153 * This takes care of not removing the exception intercept if a nested-guest
1154 * requires the exception to be intercepted.
1155 *
1156 * @returns VBox status code.
1157 * @param pVCpu The cross context virtual CPU structure.
1158 * @param pVmxTransient The VMX-transient structure.
1159 * @param uXcptMask The exception(s) to remove.
1160 */
1161static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1162{
1163 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1164 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1165 if (u32XcptBitmap & uXcptMask)
1166 {
1167#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1168 if (!pVmxTransient->fIsNestedGuest)
1169 { /* likely */ }
1170 else
1171 {
1172 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1173 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1174 }
1175#endif
1176#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1177 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1178 | RT_BIT(X86_XCPT_DE)
1179 | RT_BIT(X86_XCPT_NM)
1180 | RT_BIT(X86_XCPT_TS)
1181 | RT_BIT(X86_XCPT_UD)
1182 | RT_BIT(X86_XCPT_NP)
1183 | RT_BIT(X86_XCPT_SS)
1184 | RT_BIT(X86_XCPT_GP)
1185 | RT_BIT(X86_XCPT_PF)
1186 | RT_BIT(X86_XCPT_MF));
1187#elif defined(HMVMX_ALWAYS_TRAP_PF)
1188 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1189#endif
1190 if (uXcptMask)
1191 {
1192 /* Validate we are not removing any essential exception intercepts. */
1193 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1194 NOREF(pVCpu);
1195 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1196 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1197
1198 /* Remove it from the exception bitmap. */
1199 u32XcptBitmap &= ~uXcptMask;
1200
1201 /* Commit and update the cache if necessary. */
1202 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1203 {
1204 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1205 AssertRC(rc);
1206 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1207 }
1208 }
1209 }
1210 return VINF_SUCCESS;
1211}
1212
1213
1214/**
1215 * Remove an exceptions from the exception bitmap and commits it to the current
1216 * VMCS.
1217 *
1218 * @returns VBox status code.
1219 * @param pVCpu The cross context virtual CPU structure.
1220 * @param pVmxTransient The VMX-transient structure.
1221 * @param uXcpt The exception to remove.
1222 */
1223static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1224{
1225 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1226}
1227
1228
1229/**
1230 * Loads the VMCS specified by the VMCS info. object.
1231 *
1232 * @returns VBox status code.
1233 * @param pVmcsInfo The VMCS info. object.
1234 *
1235 * @remarks Can be called with interrupts disabled.
1236 */
1237static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1238{
1239 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1240 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1241
1242 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1243 if (RT_SUCCESS(rc))
1244 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1245 return rc;
1246}
1247
1248
1249/**
1250 * Clears the VMCS specified by the VMCS info. object.
1251 *
1252 * @returns VBox status code.
1253 * @param pVmcsInfo The VMCS info. object.
1254 *
1255 * @remarks Can be called with interrupts disabled.
1256 */
1257static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1258{
1259 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1260 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1261
1262 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1263 if (RT_SUCCESS(rc))
1264 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1265 return rc;
1266}
1267
1268
1269#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1270/**
1271 * Loads the shadow VMCS specified by the VMCS info. object.
1272 *
1273 * @returns VBox status code.
1274 * @param pVmcsInfo The VMCS info. object.
1275 *
1276 * @remarks Can be called with interrupts disabled.
1277 */
1278static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1279{
1280 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1281 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1282
1283 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1284 if (RT_SUCCESS(rc))
1285 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1286 return rc;
1287}
1288
1289
1290/**
1291 * Clears the shadow VMCS specified by the VMCS info. object.
1292 *
1293 * @returns VBox status code.
1294 * @param pVmcsInfo The VMCS info. object.
1295 *
1296 * @remarks Can be called with interrupts disabled.
1297 */
1298static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1299{
1300 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1301 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1302
1303 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1304 if (RT_SUCCESS(rc))
1305 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1306 return rc;
1307}
1308
1309
1310/**
1311 * Switches from and to the specified VMCSes.
1312 *
1313 * @returns VBox status code.
1314 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1315 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1316 *
1317 * @remarks Called with interrupts disabled.
1318 */
1319static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1320{
1321 /*
1322 * Clear the VMCS we are switching out if it has not already been cleared.
1323 * This will sync any CPU internal data back to the VMCS.
1324 */
1325 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1326 {
1327 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1328 if (RT_SUCCESS(rc))
1329 {
1330 /*
1331 * The shadow VMCS, if any, would not be active at this point since we
1332 * would have cleared it while importing the virtual hardware-virtualization
1333 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1334 * clear the shadow VMCS here, just assert for safety.
1335 */
1336 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1337 }
1338 else
1339 return rc;
1340 }
1341
1342 /*
1343 * Clear the VMCS we are switching to if it has not already been cleared.
1344 * This will initialize the VMCS launch state to "clear" required for loading it.
1345 *
1346 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1347 */
1348 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1349 {
1350 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1351 if (RT_SUCCESS(rc))
1352 { /* likely */ }
1353 else
1354 return rc;
1355 }
1356
1357 /*
1358 * Finally, load the VMCS we are switching to.
1359 */
1360 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1361}
1362
1363
1364/**
1365 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1366 * caller.
1367 *
1368 * @returns VBox status code.
1369 * @param pVCpu The cross context virtual CPU structure.
1370 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1371 * true) or guest VMCS (pass false).
1372 */
1373static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1374{
1375 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1376 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1377
1378 PVMXVMCSINFO pVmcsInfoFrom;
1379 PVMXVMCSINFO pVmcsInfoTo;
1380 if (fSwitchToNstGstVmcs)
1381 {
1382 pVmcsInfoFrom = &pVCpu->hmr0.s.vmx.VmcsInfo;
1383 pVmcsInfoTo = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1384 }
1385 else
1386 {
1387 pVmcsInfoFrom = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1388 pVmcsInfoTo = &pVCpu->hmr0.s.vmx.VmcsInfo;
1389 }
1390
1391 /*
1392 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1393 * preemption hook code path acquires the current VMCS.
1394 */
1395 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1396
1397 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1398 if (RT_SUCCESS(rc))
1399 {
1400 pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1401 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcsCopyForRing3 = fSwitchToNstGstVmcs;
1402
1403 /*
1404 * If we are switching to a VMCS that was executed on a different host CPU or was
1405 * never executed before, flag that we need to export the host state before executing
1406 * guest/nested-guest code using hardware-assisted VMX.
1407 *
1408 * This could probably be done in a preemptible context since the preemption hook
1409 * will flag the necessary change in host context. However, since preemption is
1410 * already disabled and to avoid making assumptions about host specific code in
1411 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1412 * disabled.
1413 */
1414 if (pVmcsInfoTo->idHostCpuState == RTMpCpuId())
1415 { /* likely */ }
1416 else
1417 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1418
1419 ASMSetFlags(fEFlags);
1420
1421 /*
1422 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1423 * flag that we need to update the host MSR values there. Even if we decide in the
1424 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1425 * if its content differs, we would have to update the host MSRs anyway.
1426 */
1427 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
1428 }
1429 else
1430 ASMSetFlags(fEFlags);
1431 return rc;
1432}
1433#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1434
1435
1436/**
1437 * Updates the VM's last error record.
1438 *
1439 * If there was a VMX instruction error, reads the error data from the VMCS and
1440 * updates VCPU's last error record as well.
1441 *
1442 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1443 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1444 * VERR_VMX_INVALID_VMCS_FIELD.
1445 * @param rc The error code.
1446 */
1447static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1448{
1449 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1450 || rc == VERR_VMX_UNABLE_TO_START_VM)
1451 {
1452 AssertPtrReturnVoid(pVCpu);
1453 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1454 }
1455 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1456}
1457
1458
1459#ifdef VBOX_STRICT
1460/**
1461 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1462 * transient structure.
1463 *
1464 * @param pVmxTransient The VMX-transient structure.
1465 */
1466DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1467{
1468 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1469 AssertRC(rc);
1470}
1471
1472
1473/**
1474 * Reads the VM-entry exception error code field from the VMCS into
1475 * the VMX transient structure.
1476 *
1477 * @param pVmxTransient The VMX-transient structure.
1478 */
1479DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1480{
1481 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1482 AssertRC(rc);
1483}
1484
1485
1486/**
1487 * Reads the VM-entry exception error code field from the VMCS into
1488 * the VMX transient structure.
1489 *
1490 * @param pVmxTransient The VMX-transient structure.
1491 */
1492DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1493{
1494 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1495 AssertRC(rc);
1496}
1497#endif /* VBOX_STRICT */
1498
1499
1500/**
1501 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1502 * transient structure.
1503 *
1504 * @param pVmxTransient The VMX-transient structure.
1505 */
1506DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1507{
1508 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1509 {
1510 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1511 AssertRC(rc);
1512 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1513 }
1514}
1515
1516
1517/**
1518 * Reads the VM-exit interruption error code from the VMCS into the VMX
1519 * transient structure.
1520 *
1521 * @param pVmxTransient The VMX-transient structure.
1522 */
1523DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1524{
1525 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1526 {
1527 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1528 AssertRC(rc);
1529 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1530 }
1531}
1532
1533
1534/**
1535 * Reads the VM-exit instruction length field from the VMCS into the VMX
1536 * transient structure.
1537 *
1538 * @param pVmxTransient The VMX-transient structure.
1539 */
1540DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1541{
1542 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1543 {
1544 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1545 AssertRC(rc);
1546 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1547 }
1548}
1549
1550
1551/**
1552 * Reads the VM-exit instruction-information field from the VMCS into
1553 * the VMX transient structure.
1554 *
1555 * @param pVmxTransient The VMX-transient structure.
1556 */
1557DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1558{
1559 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1560 {
1561 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1562 AssertRC(rc);
1563 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1564 }
1565}
1566
1567
1568/**
1569 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1570 *
1571 * @param pVmxTransient The VMX-transient structure.
1572 */
1573DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1574{
1575 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1576 {
1577 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1578 AssertRC(rc);
1579 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1580 }
1581}
1582
1583
1584/**
1585 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1586 *
1587 * @param pVmxTransient The VMX-transient structure.
1588 */
1589DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1590{
1591 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1592 {
1593 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1594 AssertRC(rc);
1595 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1596 }
1597}
1598
1599
1600/**
1601 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1602 *
1603 * @param pVmxTransient The VMX-transient structure.
1604 */
1605DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1606{
1607 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1608 {
1609 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1610 AssertRC(rc);
1611 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1612 }
1613}
1614
1615#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1616/**
1617 * Reads the Guest pending-debug exceptions from the VMCS into the VMX transient
1618 * structure.
1619 *
1620 * @param pVmxTransient The VMX-transient structure.
1621 */
1622DECLINLINE(void) hmR0VmxReadGuestPendingDbgXctps(PVMXTRANSIENT pVmxTransient)
1623{
1624 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PENDING_DBG_XCPTS))
1625 {
1626 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &pVmxTransient->uGuestPendingDbgXcpts);
1627 AssertRC(rc);
1628 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PENDING_DBG_XCPTS;
1629 }
1630}
1631#endif
1632
1633/**
1634 * Reads the IDT-vectoring information field from the VMCS into the VMX
1635 * transient structure.
1636 *
1637 * @param pVmxTransient The VMX-transient structure.
1638 *
1639 * @remarks No-long-jump zone!!!
1640 */
1641DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1642{
1643 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1644 {
1645 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1646 AssertRC(rc);
1647 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1648 }
1649}
1650
1651
1652/**
1653 * Reads the IDT-vectoring error code from the VMCS into the VMX
1654 * transient structure.
1655 *
1656 * @param pVmxTransient The VMX-transient structure.
1657 */
1658DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1659{
1660 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1661 {
1662 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1663 AssertRC(rc);
1664 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1665 }
1666}
1667
1668#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1669/**
1670 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1671 *
1672 * @param pVmxTransient The VMX-transient structure.
1673 */
1674static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1675{
1676 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1677 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1678 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1679 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1680 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1681 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1682 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1683 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1684 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1685 AssertRC(rc);
1686 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1687 | HMVMX_READ_EXIT_INSTR_LEN
1688 | HMVMX_READ_EXIT_INSTR_INFO
1689 | HMVMX_READ_IDT_VECTORING_INFO
1690 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1691 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1692 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1693 | HMVMX_READ_GUEST_LINEAR_ADDR
1694 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1695}
1696#endif
1697
1698/**
1699 * Enters VMX root mode operation on the current CPU.
1700 *
1701 * @returns VBox status code.
1702 * @param pHostCpu The HM physical-CPU structure.
1703 * @param pVM The cross context VM structure. Can be
1704 * NULL, after a resume.
1705 * @param HCPhysCpuPage Physical address of the VMXON region.
1706 * @param pvCpuPage Pointer to the VMXON region.
1707 */
1708static int hmR0VmxEnterRootMode(PHMPHYSCPU pHostCpu, PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1709{
1710 Assert(pHostCpu);
1711 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1712 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1713 Assert(pvCpuPage);
1714 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1715
1716 if (pVM)
1717 {
1718 /* Write the VMCS revision identifier to the VMXON region. */
1719 *(uint32_t *)pvCpuPage = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
1720 }
1721
1722 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1723 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1724
1725 /* Enable the VMX bit in CR4 if necessary. */
1726 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1727
1728 /* Record whether VMXE was already prior to us enabling it above. */
1729 pHostCpu->fVmxeAlreadyEnabled = RT_BOOL(uOldCr4 & X86_CR4_VMXE);
1730
1731 /* Enter VMX root mode. */
1732 int rc = VMXEnable(HCPhysCpuPage);
1733 if (RT_FAILURE(rc))
1734 {
1735 /* Restore CR4.VMXE if it was not set prior to our attempt to set it above. */
1736 if (!pHostCpu->fVmxeAlreadyEnabled)
1737 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1738
1739 if (pVM)
1740 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1741 }
1742
1743 /* Restore interrupts. */
1744 ASMSetFlags(fEFlags);
1745 return rc;
1746}
1747
1748
1749/**
1750 * Exits VMX root mode operation on the current CPU.
1751 *
1752 * @returns VBox status code.
1753 * @param pHostCpu The HM physical-CPU structure.
1754 */
1755static int hmR0VmxLeaveRootMode(PHMPHYSCPU pHostCpu)
1756{
1757 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1758
1759 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1760 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1761
1762 /* If we're for some reason not in VMX root mode, then don't leave it. */
1763 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1764
1765 int rc;
1766 if (uHostCr4 & X86_CR4_VMXE)
1767 {
1768 /* Exit VMX root mode and clear the VMX bit in CR4. */
1769 VMXDisable();
1770
1771 /* Clear CR4.VMXE only if it was clear prior to use setting it. */
1772 if (!pHostCpu->fVmxeAlreadyEnabled)
1773 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1774
1775 rc = VINF_SUCCESS;
1776 }
1777 else
1778 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1779
1780 /* Restore interrupts. */
1781 ASMSetFlags(fEFlags);
1782 return rc;
1783}
1784
1785
1786/**
1787 * Allocates pages specified as specified by an array of VMX page allocation info
1788 * objects.
1789 *
1790 * The pages contents are zero'd after allocation.
1791 *
1792 * @returns VBox status code.
1793 * @param phMemObj Where to return the handle to the allocation.
1794 * @param paAllocInfo The pointer to the first element of the VMX
1795 * page-allocation info object array.
1796 * @param cEntries The number of elements in the @a paAllocInfo array.
1797 */
1798static int hmR0VmxPagesAllocZ(PRTR0MEMOBJ phMemObj, PVMXPAGEALLOCINFO paAllocInfo, uint32_t cEntries)
1799{
1800 *phMemObj = NIL_RTR0MEMOBJ;
1801
1802 /* Figure out how many pages to allocate. */
1803 uint32_t cPages = 0;
1804 for (uint32_t iPage = 0; iPage < cEntries; iPage++)
1805 cPages += !!paAllocInfo[iPage].fValid;
1806
1807 /* Allocate the pages. */
1808 if (cPages)
1809 {
1810 size_t const cbPages = cPages << PAGE_SHIFT;
1811 int rc = RTR0MemObjAllocPage(phMemObj, cbPages, false /* fExecutable */);
1812 if (RT_FAILURE(rc))
1813 return rc;
1814
1815 /* Zero the contents and assign each page to the corresponding VMX page-allocation entry. */
1816 void *pvFirstPage = RTR0MemObjAddress(*phMemObj);
1817 RT_BZERO(pvFirstPage, cbPages);
1818
1819 uint32_t iPage = 0;
1820 for (uint32_t i = 0; i < cEntries; i++)
1821 if (paAllocInfo[i].fValid)
1822 {
1823 RTHCPHYS const HCPhysPage = RTR0MemObjGetPagePhysAddr(*phMemObj, iPage);
1824 void *pvPage = (void *)((uintptr_t)pvFirstPage + (iPage << X86_PAGE_4K_SHIFT));
1825 Assert(HCPhysPage && HCPhysPage != NIL_RTHCPHYS);
1826 AssertPtr(pvPage);
1827
1828 Assert(paAllocInfo[iPage].pHCPhys);
1829 Assert(paAllocInfo[iPage].ppVirt);
1830 *paAllocInfo[iPage].pHCPhys = HCPhysPage;
1831 *paAllocInfo[iPage].ppVirt = pvPage;
1832
1833 /* Move to next page. */
1834 ++iPage;
1835 }
1836
1837 /* Make sure all valid (requested) pages have been assigned. */
1838 Assert(iPage == cPages);
1839 }
1840 return VINF_SUCCESS;
1841}
1842
1843
1844/**
1845 * Frees pages allocated using hmR0VmxPagesAllocZ.
1846 *
1847 * @param phMemObj Pointer to the memory object handle. Will be set to
1848 * NIL.
1849 */
1850DECL_FORCE_INLINE(void) hmR0VmxPagesFree(PRTR0MEMOBJ phMemObj)
1851{
1852 /* We can cleanup wholesale since it's all one allocation. */
1853 if (*phMemObj != NIL_RTR0MEMOBJ)
1854 {
1855 RTR0MemObjFree(*phMemObj, true /* fFreeMappings */);
1856 *phMemObj = NIL_RTR0MEMOBJ;
1857 }
1858}
1859
1860
1861/**
1862 * Initializes a VMCS info. object.
1863 *
1864 * @param pVmcsInfo The VMCS info. object.
1865 * @param pVmcsInfoShared The VMCS info. object shared with ring-3.
1866 */
1867static void hmR0VmxVmcsInfoInit(PVMXVMCSINFO pVmcsInfo, PVMXVMCSINFOSHARED pVmcsInfoShared)
1868{
1869 RT_ZERO(*pVmcsInfo);
1870 RT_ZERO(*pVmcsInfoShared);
1871
1872 pVmcsInfo->pShared = pVmcsInfoShared;
1873 Assert(pVmcsInfo->hMemObj == NIL_RTR0MEMOBJ);
1874 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1875 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1876 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1877 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1878 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1879 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1880 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1881 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1882 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1883 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
1884 pVmcsInfo->idHostCpuExec = NIL_RTCPUID;
1885}
1886
1887
1888/**
1889 * Frees the VT-x structures for a VMCS info. object.
1890 *
1891 * @param pVmcsInfo The VMCS info. object.
1892 * @param pVmcsInfoShared The VMCS info. object shared with ring-3.
1893 */
1894static void hmR0VmxVmcsInfoFree(PVMXVMCSINFO pVmcsInfo, PVMXVMCSINFOSHARED pVmcsInfoShared)
1895{
1896 hmR0VmxPagesFree(&pVmcsInfo->hMemObj);
1897 hmR0VmxVmcsInfoInit(pVmcsInfo, pVmcsInfoShared);
1898}
1899
1900
1901/**
1902 * Allocates the VT-x structures for a VMCS info. object.
1903 *
1904 * @returns VBox status code.
1905 * @param pVCpu The cross context virtual CPU structure.
1906 * @param pVmcsInfo The VMCS info. object.
1907 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1908 *
1909 * @remarks The caller is expected to take care of any and all allocation failures.
1910 * This function will not perform any cleanup for failures half-way
1911 * through.
1912 */
1913static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1914{
1915 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1916
1917 bool const fMsrBitmaps = RT_BOOL(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS);
1918 bool const fShadowVmcs = !fIsNstGstVmcs ? pVM->hmr0.s.vmx.fUseVmcsShadowing : pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing;
1919 Assert(!pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing); /* VMCS shadowing is not yet exposed to the guest. */
1920 VMXPAGEALLOCINFO aAllocInfo[] =
1921 {
1922 { true, 0 /* Unused */, &pVmcsInfo->HCPhysVmcs, &pVmcsInfo->pvVmcs },
1923 { true, 0 /* Unused */, &pVmcsInfo->HCPhysGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad },
1924 { true, 0 /* Unused */, &pVmcsInfo->HCPhysHostMsrLoad, &pVmcsInfo->pvHostMsrLoad },
1925 { fMsrBitmaps, 0 /* Unused */, &pVmcsInfo->HCPhysMsrBitmap, &pVmcsInfo->pvMsrBitmap },
1926 { fShadowVmcs, 0 /* Unused */, &pVmcsInfo->HCPhysShadowVmcs, &pVmcsInfo->pvShadowVmcs },
1927 };
1928
1929 int rc = hmR0VmxPagesAllocZ(&pVmcsInfo->hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1930 if (RT_FAILURE(rc))
1931 return rc;
1932
1933 /*
1934 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1935 * Because they contain a symmetric list of guest MSRs to load on VM-entry and store on VM-exit.
1936 */
1937 AssertCompile(RT_ELEMENTS(aAllocInfo) > 0);
1938 Assert(pVmcsInfo->HCPhysGuestMsrLoad != NIL_RTHCPHYS);
1939 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1940 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1941
1942 /*
1943 * Get the virtual-APIC page rather than allocating them again.
1944 */
1945 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1946 {
1947 if (!fIsNstGstVmcs)
1948 {
1949 if (PDMHasApic(pVM))
1950 {
1951 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1952 if (RT_FAILURE(rc))
1953 return rc;
1954 Assert(pVmcsInfo->pbVirtApic);
1955 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1956 }
1957 }
1958 else
1959 {
1960 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(&pVCpu->cpum.GstCtx, &pVmcsInfo->HCPhysVirtApic);
1961 Assert(pVmcsInfo->pbVirtApic);
1962 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1963 }
1964 }
1965
1966 return VINF_SUCCESS;
1967}
1968
1969
1970/**
1971 * Free all VT-x structures for the VM.
1972 *
1973 * @returns IPRT status code.
1974 * @param pVM The cross context VM structure.
1975 */
1976static void hmR0VmxStructsFree(PVMCC pVM)
1977{
1978 hmR0VmxPagesFree(&pVM->hmr0.s.vmx.hMemObj);
1979#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1980 if (pVM->hmr0.s.vmx.fUseVmcsShadowing)
1981 {
1982 RTMemFree(pVM->hmr0.s.vmx.paShadowVmcsFields);
1983 pVM->hmr0.s.vmx.paShadowVmcsFields = NULL;
1984 RTMemFree(pVM->hmr0.s.vmx.paShadowVmcsRoFields);
1985 pVM->hmr0.s.vmx.paShadowVmcsRoFields = NULL;
1986 }
1987#endif
1988
1989 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1990 {
1991 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1992 hmR0VmxVmcsInfoFree(&pVCpu->hmr0.s.vmx.VmcsInfo, &pVCpu->hm.s.vmx.VmcsInfo);
1993#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1994 if (pVM->cpum.ro.GuestFeatures.fVmx)
1995 hmR0VmxVmcsInfoFree(&pVCpu->hmr0.s.vmx.VmcsInfoNstGst, &pVCpu->hm.s.vmx.VmcsInfoNstGst);
1996#endif
1997 }
1998}
1999
2000
2001/**
2002 * Allocate all VT-x structures for the VM.
2003 *
2004 * @returns IPRT status code.
2005 * @param pVM The cross context VM structure.
2006 *
2007 * @remarks This functions will cleanup on memory allocation failures.
2008 */
2009static int hmR0VmxStructsAlloc(PVMCC pVM)
2010{
2011 /*
2012 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
2013 * The VMCS size cannot be more than 4096 bytes.
2014 *
2015 * See Intel spec. Appendix A.1 "Basic VMX Information".
2016 */
2017 uint32_t const cbVmcs = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
2018 if (cbVmcs <= X86_PAGE_4K_SIZE)
2019 { /* likely */ }
2020 else
2021 {
2022 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
2023 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2024 }
2025
2026 /*
2027 * Allocate per-VM VT-x structures.
2028 */
2029 bool const fVirtApicAccess = RT_BOOL(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
2030 bool const fUseVmcsShadowing = pVM->hmr0.s.vmx.fUseVmcsShadowing;
2031 VMXPAGEALLOCINFO aAllocInfo[] =
2032 {
2033 { fVirtApicAccess, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysApicAccess, (PRTR0PTR)&pVM->hmr0.s.vmx.pbApicAccess },
2034 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysVmreadBitmap, &pVM->hmr0.s.vmx.pvVmreadBitmap },
2035 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysVmwriteBitmap, &pVM->hmr0.s.vmx.pvVmwriteBitmap },
2036#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2037 { true, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysScratch, (PRTR0PTR)&pVM->hmr0.s.vmx.pbScratch },
2038#endif
2039 };
2040
2041 int rc = hmR0VmxPagesAllocZ(&pVM->hmr0.s.vmx.hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
2042 if (RT_SUCCESS(rc))
2043 {
2044#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2045 /* Allocate the shadow VMCS-fields array. */
2046 if (fUseVmcsShadowing)
2047 {
2048 Assert(!pVM->hmr0.s.vmx.cShadowVmcsFields);
2049 Assert(!pVM->hmr0.s.vmx.cShadowVmcsRoFields);
2050 pVM->hmr0.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2051 pVM->hmr0.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2052 if (!pVM->hmr0.s.vmx.paShadowVmcsFields || !pVM->hmr0.s.vmx.paShadowVmcsRoFields)
2053 rc = VERR_NO_MEMORY;
2054 }
2055#endif
2056
2057 /*
2058 * Allocate per-VCPU VT-x structures.
2059 */
2060 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus && RT_SUCCESS(rc); idCpu++)
2061 {
2062 /* Allocate the guest VMCS structures. */
2063 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2064 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
2065
2066#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2067 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
2068 if (pVM->cpum.ro.GuestFeatures.fVmx && RT_SUCCESS(rc))
2069 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
2070#endif
2071 }
2072 if (RT_SUCCESS(rc))
2073 return VINF_SUCCESS;
2074 }
2075 hmR0VmxStructsFree(pVM);
2076 return rc;
2077}
2078
2079
2080/**
2081 * Pre-initializes non-zero fields in VMX structures that will be allocated.
2082 *
2083 * @param pVM The cross context VM structure.
2084 */
2085static void hmR0VmxStructsInit(PVMCC pVM)
2086{
2087 /* Paranoia. */
2088 Assert(pVM->hmr0.s.vmx.pbApicAccess == NULL);
2089#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2090 Assert(pVM->hmr0.s.vmx.pbScratch == NULL);
2091#endif
2092
2093 /*
2094 * Initialize members up-front so we can cleanup en masse on allocation failures.
2095 */
2096#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2097 pVM->hmr0.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
2098#endif
2099 pVM->hmr0.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
2100 pVM->hmr0.s.vmx.HCPhysVmreadBitmap = NIL_RTHCPHYS;
2101 pVM->hmr0.s.vmx.HCPhysVmwriteBitmap = NIL_RTHCPHYS;
2102 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2103 {
2104 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2105 hmR0VmxVmcsInfoInit(&pVCpu->hmr0.s.vmx.VmcsInfo, &pVCpu->hm.s.vmx.VmcsInfo);
2106 hmR0VmxVmcsInfoInit(&pVCpu->hmr0.s.vmx.VmcsInfoNstGst, &pVCpu->hm.s.vmx.VmcsInfoNstGst);
2107 }
2108}
2109
2110#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2111/**
2112 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2113 *
2114 * @returns @c true if the MSR is intercepted, @c false otherwise.
2115 * @param pvMsrBitmap The MSR bitmap.
2116 * @param offMsr The MSR byte offset.
2117 * @param iBit The bit offset from the byte offset.
2118 */
2119DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2120{
2121 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2122 Assert(pbMsrBitmap);
2123 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2124 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2125}
2126#endif
2127
2128/**
2129 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2130 *
2131 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2132 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2133 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2134 * the read/write access of this MSR.
2135 *
2136 * @param pVCpu The cross context virtual CPU structure.
2137 * @param pVmcsInfo The VMCS info. object.
2138 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2139 * @param idMsr The MSR value.
2140 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2141 * include both a read -and- a write permission!
2142 *
2143 * @sa CPUMGetVmxMsrPermission.
2144 * @remarks Can be called with interrupts disabled.
2145 */
2146static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2147{
2148 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2149 Assert(pbMsrBitmap);
2150 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2151
2152 /*
2153 * MSR-bitmap Layout:
2154 * Byte index MSR range Interpreted as
2155 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2156 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2157 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2158 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2159 *
2160 * A bit corresponding to an MSR within the above range causes a VM-exit
2161 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2162 * the MSR range, it always cause a VM-exit.
2163 *
2164 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2165 */
2166 uint16_t const offBitmapRead = 0;
2167 uint16_t const offBitmapWrite = 0x800;
2168 uint16_t offMsr;
2169 int32_t iBit;
2170 if (idMsr <= UINT32_C(0x00001fff))
2171 {
2172 offMsr = 0;
2173 iBit = idMsr;
2174 }
2175 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2176 {
2177 offMsr = 0x400;
2178 iBit = idMsr - UINT32_C(0xc0000000);
2179 }
2180 else
2181 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2182
2183 /*
2184 * Set the MSR read permission.
2185 */
2186 uint16_t const offMsrRead = offBitmapRead + offMsr;
2187 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2188 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2189 {
2190#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2191 bool const fClear = !fIsNstGstVmcs ? true
2192 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2193#else
2194 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2195 bool const fClear = true;
2196#endif
2197 if (fClear)
2198 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2199 }
2200 else
2201 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2202
2203 /*
2204 * Set the MSR write permission.
2205 */
2206 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2207 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2208 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2209 {
2210#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2211 bool const fClear = !fIsNstGstVmcs ? true
2212 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2213#else
2214 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2215 bool const fClear = true;
2216#endif
2217 if (fClear)
2218 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2219 }
2220 else
2221 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2222}
2223
2224
2225/**
2226 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2227 * area.
2228 *
2229 * @returns VBox status code.
2230 * @param pVCpu The cross context virtual CPU structure.
2231 * @param pVmcsInfo The VMCS info. object.
2232 * @param cMsrs The number of MSRs.
2233 */
2234static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2235{
2236 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2237 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc);
2238 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2239 {
2240 /* Commit the MSR counts to the VMCS and update the cache. */
2241 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2242 {
2243 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2244 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2245 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2246 pVmcsInfo->cEntryMsrLoad = cMsrs;
2247 pVmcsInfo->cExitMsrStore = cMsrs;
2248 pVmcsInfo->cExitMsrLoad = cMsrs;
2249 }
2250 return VINF_SUCCESS;
2251 }
2252
2253 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2254 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2255 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2256}
2257
2258
2259/**
2260 * Adds a new (or updates the value of an existing) guest/host MSR
2261 * pair to be swapped during the world-switch as part of the
2262 * auto-load/store MSR area in the VMCS.
2263 *
2264 * @returns VBox status code.
2265 * @param pVCpu The cross context virtual CPU structure.
2266 * @param pVmxTransient The VMX-transient structure.
2267 * @param idMsr The MSR.
2268 * @param uGuestMsrValue Value of the guest MSR.
2269 * @param fSetReadWrite Whether to set the guest read/write access of this
2270 * MSR (thus not causing a VM-exit).
2271 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2272 * necessary.
2273 */
2274static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2275 bool fSetReadWrite, bool fUpdateHostMsr)
2276{
2277 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2278 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2279 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2280 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2281 uint32_t i;
2282
2283 /* Paranoia. */
2284 Assert(pGuestMsrLoad);
2285
2286 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGuestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2287
2288 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2289 for (i = 0; i < cMsrs; i++)
2290 {
2291 if (pGuestMsrLoad[i].u32Msr == idMsr)
2292 break;
2293 }
2294
2295 bool fAdded = false;
2296 if (i == cMsrs)
2297 {
2298 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2299 ++cMsrs;
2300 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2301 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2302
2303 /* Set the guest to read/write this MSR without causing VM-exits. */
2304 if ( fSetReadWrite
2305 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2306 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2307
2308 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2309 fAdded = true;
2310 }
2311
2312 /* Update the MSR value for the newly added or already existing MSR. */
2313 pGuestMsrLoad[i].u32Msr = idMsr;
2314 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2315
2316 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2317 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2318 {
2319 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2320 pGuestMsrStore[i].u32Msr = idMsr;
2321 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2322 }
2323
2324 /* Update the corresponding slot in the host MSR area. */
2325 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2326 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2327 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2328 pHostMsr[i].u32Msr = idMsr;
2329
2330 /*
2331 * Only if the caller requests to update the host MSR value AND we've newly added the
2332 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2333 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2334 *
2335 * We do this for performance reasons since reading MSRs may be quite expensive.
2336 */
2337 if (fAdded)
2338 {
2339 if (fUpdateHostMsr)
2340 {
2341 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2342 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2343 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2344 }
2345 else
2346 {
2347 /* Someone else can do the work. */
2348 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
2349 }
2350 }
2351 return VINF_SUCCESS;
2352}
2353
2354
2355/**
2356 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2357 * auto-load/store MSR area in the VMCS.
2358 *
2359 * @returns VBox status code.
2360 * @param pVCpu The cross context virtual CPU structure.
2361 * @param pVmxTransient The VMX-transient structure.
2362 * @param idMsr The MSR.
2363 */
2364static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2365{
2366 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2367 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2368 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2369 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2370
2371 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2372
2373 for (uint32_t i = 0; i < cMsrs; i++)
2374 {
2375 /* Find the MSR. */
2376 if (pGuestMsrLoad[i].u32Msr == idMsr)
2377 {
2378 /*
2379 * If it's the last MSR, we only need to reduce the MSR count.
2380 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2381 */
2382 if (i < cMsrs - 1)
2383 {
2384 /* Remove it from the VM-entry MSR-load area. */
2385 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2386 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2387
2388 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2389 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2390 {
2391 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2392 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2393 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2394 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2395 }
2396
2397 /* Remove it from the VM-exit MSR-load area. */
2398 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2399 Assert(pHostMsr[i].u32Msr == idMsr);
2400 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2401 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2402 }
2403
2404 /* Reduce the count to reflect the removed MSR and bail. */
2405 --cMsrs;
2406 break;
2407 }
2408 }
2409
2410 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2411 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2412 {
2413 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2414 AssertRCReturn(rc, rc);
2415
2416 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2417 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2418 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2419
2420 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2421 return VINF_SUCCESS;
2422 }
2423
2424 return VERR_NOT_FOUND;
2425}
2426
2427
2428/**
2429 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2430 *
2431 * @returns @c true if found, @c false otherwise.
2432 * @param pVmcsInfo The VMCS info. object.
2433 * @param idMsr The MSR to find.
2434 */
2435static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2436{
2437 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2438 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2439 Assert(pMsrs);
2440 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2441 for (uint32_t i = 0; i < cMsrs; i++)
2442 {
2443 if (pMsrs[i].u32Msr == idMsr)
2444 return true;
2445 }
2446 return false;
2447}
2448
2449
2450/**
2451 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2452 *
2453 * @param pVCpu The cross context virtual CPU structure.
2454 * @param pVmcsInfo The VMCS info. object.
2455 *
2456 * @remarks No-long-jump zone!!!
2457 */
2458static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2459{
2460 RT_NOREF(pVCpu);
2461 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2462
2463 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2464 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2465 Assert(pHostMsrLoad);
2466 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2467 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2468 for (uint32_t i = 0; i < cMsrs; i++)
2469 {
2470 /*
2471 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2472 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2473 */
2474 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2475 pHostMsrLoad[i].u64Value = g_uHmVmxHostMsrEfer;
2476 else
2477 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2478 }
2479}
2480
2481
2482/**
2483 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2484 * perform lazy restoration of the host MSRs while leaving VT-x.
2485 *
2486 * @param pVCpu The cross context virtual CPU structure.
2487 *
2488 * @remarks No-long-jump zone!!!
2489 */
2490static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2491{
2492 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2493
2494 /*
2495 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2496 */
2497 if (!(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2498 {
2499 Assert(!(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2500 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2501 {
2502 pVCpu->hmr0.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2503 pVCpu->hmr0.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2504 pVCpu->hmr0.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2505 pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2506 }
2507 pVCpu->hmr0.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2508 }
2509}
2510
2511
2512/**
2513 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2514 * lazily while leaving VT-x.
2515 *
2516 * @returns true if it does, false otherwise.
2517 * @param pVCpu The cross context virtual CPU structure.
2518 * @param idMsr The MSR to check.
2519 */
2520static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2521{
2522 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2523 {
2524 switch (idMsr)
2525 {
2526 case MSR_K8_LSTAR:
2527 case MSR_K6_STAR:
2528 case MSR_K8_SF_MASK:
2529 case MSR_K8_KERNEL_GS_BASE:
2530 return true;
2531 }
2532 }
2533 return false;
2534}
2535
2536
2537/**
2538 * Loads a set of guests MSRs to allow read/passthru to the guest.
2539 *
2540 * The name of this function is slightly confusing. This function does NOT
2541 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2542 * common prefix for functions dealing with "lazy restoration" of the shared
2543 * MSRs.
2544 *
2545 * @param pVCpu The cross context virtual CPU structure.
2546 *
2547 * @remarks No-long-jump zone!!!
2548 */
2549static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2550{
2551 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2552 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2553
2554 Assert(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2555 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2556 {
2557 /*
2558 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2559 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2560 * we can skip a few MSR writes.
2561 *
2562 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2563 * guest MSR values in the guest-CPU context might be different to what's currently
2564 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2565 * CPU, see @bugref{8728}.
2566 */
2567 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2568 if ( !(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2569 && pCtx->msrKERNELGSBASE == pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase
2570 && pCtx->msrLSTAR == pVCpu->hmr0.s.vmx.u64HostMsrLStar
2571 && pCtx->msrSTAR == pVCpu->hmr0.s.vmx.u64HostMsrStar
2572 && pCtx->msrSFMASK == pVCpu->hmr0.s.vmx.u64HostMsrSfMask)
2573 {
2574#ifdef VBOX_STRICT
2575 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2576 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2577 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2578 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2579#endif
2580 }
2581 else
2582 {
2583 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2584 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2585 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2586 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2587 }
2588 }
2589 pVCpu->hmr0.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2590}
2591
2592
2593/**
2594 * Performs lazy restoration of the set of host MSRs if they were previously
2595 * loaded with guest MSR values.
2596 *
2597 * @param pVCpu The cross context virtual CPU structure.
2598 *
2599 * @remarks No-long-jump zone!!!
2600 * @remarks The guest MSRs should have been saved back into the guest-CPU
2601 * context by hmR0VmxImportGuestState()!!!
2602 */
2603static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2604{
2605 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2606 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2607
2608 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2609 {
2610 Assert(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2611 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2612 {
2613 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hmr0.s.vmx.u64HostMsrLStar);
2614 ASMWrMsr(MSR_K6_STAR, pVCpu->hmr0.s.vmx.u64HostMsrStar);
2615 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hmr0.s.vmx.u64HostMsrSfMask);
2616 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase);
2617 }
2618 }
2619 pVCpu->hmr0.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2620}
2621
2622
2623/**
2624 * Verifies that our cached values of the VMCS fields are all consistent with
2625 * what's actually present in the VMCS.
2626 *
2627 * @returns VBox status code.
2628 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2629 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2630 * VMCS content. HMCPU error-field is
2631 * updated, see VMX_VCI_XXX.
2632 * @param pVCpu The cross context virtual CPU structure.
2633 * @param pVmcsInfo The VMCS info. object.
2634 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2635 */
2636static int hmR0VmxCheckCachedVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2637{
2638 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2639
2640 uint32_t u32Val;
2641 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2642 AssertRC(rc);
2643 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2644 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2645 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2646 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2647
2648 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2649 AssertRC(rc);
2650 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2651 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2652 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2653 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2654
2655 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2656 AssertRC(rc);
2657 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2658 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2659 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2660 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2661
2662 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2663 AssertRC(rc);
2664 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2665 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2666 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2667 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2668
2669 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2670 {
2671 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2672 AssertRC(rc);
2673 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2674 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2675 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2676 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2677 }
2678
2679 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2680 AssertRC(rc);
2681 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2682 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2683 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2684 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2685
2686 uint64_t u64Val;
2687 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2688 AssertRC(rc);
2689 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2690 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2691 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2692 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2693
2694 NOREF(pcszVmcs);
2695 return VINF_SUCCESS;
2696}
2697
2698#ifdef VBOX_STRICT
2699
2700/**
2701 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2702 *
2703 * @param pVCpu The cross context virtual CPU structure.
2704 * @param pVmcsInfo The VMCS info. object.
2705 */
2706static void hmR0VmxCheckHostEferMsr(PCVMXVMCSINFO pVmcsInfo)
2707{
2708 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2709
2710 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2711 {
2712 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2713 uint64_t const uHostEferMsrCache = g_uHmVmxHostMsrEfer;
2714 uint64_t uVmcsEferMsrVmcs;
2715 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2716 AssertRC(rc);
2717
2718 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2719 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2720 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2721 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2722 }
2723}
2724
2725
2726/**
2727 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2728 * VMCS are correct.
2729 *
2730 * @param pVCpu The cross context virtual CPU structure.
2731 * @param pVmcsInfo The VMCS info. object.
2732 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2733 */
2734static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2735{
2736 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2737
2738 /* Read the various MSR-area counts from the VMCS. */
2739 uint32_t cEntryLoadMsrs;
2740 uint32_t cExitStoreMsrs;
2741 uint32_t cExitLoadMsrs;
2742 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2743 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2744 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2745
2746 /* Verify all the MSR counts are the same. */
2747 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2748 Assert(cExitStoreMsrs == cExitLoadMsrs);
2749 uint32_t const cMsrs = cExitLoadMsrs;
2750
2751 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2752 Assert(cMsrs < VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc));
2753
2754 /* Verify the MSR counts are within the allocated page size. */
2755 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2756
2757 /* Verify the relevant contents of the MSR areas match. */
2758 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2759 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2760 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2761 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2762 for (uint32_t i = 0; i < cMsrs; i++)
2763 {
2764 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2765 if (fSeparateExitMsrStorePage)
2766 {
2767 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2768 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2769 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2770 }
2771
2772 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2773 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2774 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2775
2776 uint64_t const u64HostMsr = ASMRdMsr(pHostMsrLoad->u32Msr);
2777 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64HostMsr,
2778 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2779 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64HostMsr, cMsrs));
2780
2781 /* Verify that cached host EFER MSR matches what's loaded on the CPU. */
2782 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2783 AssertMsgReturnVoid(!fIsEferMsr || u64HostMsr == g_uHmVmxHostMsrEfer,
2784 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n", g_uHmVmxHostMsrEfer, u64HostMsr, cMsrs));
2785
2786 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2787 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2788 {
2789 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2790 if (fIsEferMsr)
2791 {
2792 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2793 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2794 }
2795 else
2796 {
2797 /* Verify LBR MSRs (used only for debugging) are intercepted. We don't passthru these MSRs to the guest yet. */
2798 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
2799 if ( pVM->hmr0.s.vmx.fLbr
2800 && ( hmR0VmxIsLbrBranchFromMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2801 || hmR0VmxIsLbrBranchToMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2802 || pGuestMsrLoad->u32Msr == pVM->hmr0.s.vmx.idLbrTosMsr))
2803 {
2804 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_EXIT_RD_WR,
2805 ("u32Msr=%#RX32 cMsrs=%u Passthru read/write for LBR MSRs!\n",
2806 pGuestMsrLoad->u32Msr, cMsrs));
2807 }
2808 else if (!fIsNstGstVmcs)
2809 {
2810 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_ALLOW_RD_WR,
2811 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2812 }
2813 else
2814 {
2815 /*
2816 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2817 * execute a nested-guest with MSR passthrough.
2818 *
2819 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2820 * allow passthrough too.
2821 */
2822 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2823 Assert(pvMsrBitmapNstGst);
2824 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2825 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2826 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2827 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2828 }
2829 }
2830 }
2831
2832 /* Move to the next MSR. */
2833 pHostMsrLoad++;
2834 pGuestMsrLoad++;
2835 pGuestMsrStore++;
2836 }
2837}
2838
2839#endif /* VBOX_STRICT */
2840
2841/**
2842 * Flushes the TLB using EPT.
2843 *
2844 * @returns VBox status code.
2845 * @param pVCpu The cross context virtual CPU structure of the calling
2846 * EMT. Can be NULL depending on @a enmTlbFlush.
2847 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2848 * enmTlbFlush.
2849 * @param enmTlbFlush Type of flush.
2850 *
2851 * @remarks Caller is responsible for making sure this function is called only
2852 * when NestedPaging is supported and providing @a enmTlbFlush that is
2853 * supported by the CPU.
2854 * @remarks Can be called with interrupts disabled.
2855 */
2856static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2857{
2858 uint64_t au64Descriptor[2];
2859 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2860 au64Descriptor[0] = 0;
2861 else
2862 {
2863 Assert(pVCpu);
2864 Assert(pVmcsInfo);
2865 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2866 }
2867 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2868
2869 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2870 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2871
2872 if ( RT_SUCCESS(rc)
2873 && pVCpu)
2874 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2875}
2876
2877
2878/**
2879 * Flushes the TLB using VPID.
2880 *
2881 * @returns VBox status code.
2882 * @param pVCpu The cross context virtual CPU structure of the calling
2883 * EMT. Can be NULL depending on @a enmTlbFlush.
2884 * @param enmTlbFlush Type of flush.
2885 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2886 * on @a enmTlbFlush).
2887 *
2888 * @remarks Can be called with interrupts disabled.
2889 */
2890static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2891{
2892 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid);
2893
2894 uint64_t au64Descriptor[2];
2895 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2896 {
2897 au64Descriptor[0] = 0;
2898 au64Descriptor[1] = 0;
2899 }
2900 else
2901 {
2902 AssertPtr(pVCpu);
2903 AssertMsg(pVCpu->hmr0.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hmr0.s.uCurrentAsid));
2904 AssertMsg(pVCpu->hmr0.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hmr0.s.uCurrentAsid));
2905 au64Descriptor[0] = pVCpu->hmr0.s.uCurrentAsid;
2906 au64Descriptor[1] = GCPtr;
2907 }
2908
2909 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2910 AssertMsg(rc == VINF_SUCCESS,
2911 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hmr0.s.uCurrentAsid : 0, GCPtr, rc));
2912
2913 if ( RT_SUCCESS(rc)
2914 && pVCpu)
2915 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2916 NOREF(rc);
2917}
2918
2919
2920/**
2921 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2922 * otherwise there is nothing really to invalidate.
2923 *
2924 * @returns VBox status code.
2925 * @param pVCpu The cross context virtual CPU structure.
2926 * @param GCVirt Guest virtual address of the page to invalidate.
2927 */
2928VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2929{
2930 AssertPtr(pVCpu);
2931 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2932
2933 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2934 {
2935 /*
2936 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2937 * the EPT case. See @bugref{6043} and @bugref{6177}.
2938 *
2939 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2940 * as this function maybe called in a loop with individual addresses.
2941 */
2942 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2943 if (pVM->hmr0.s.vmx.fVpid)
2944 {
2945 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
2946 {
2947 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2948 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2949 }
2950 else
2951 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2952 }
2953 else if (pVM->hmr0.s.fNestedPaging)
2954 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2955 }
2956
2957 return VINF_SUCCESS;
2958}
2959
2960
2961/**
2962 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2963 * case where neither EPT nor VPID is supported by the CPU.
2964 *
2965 * @param pHostCpu The HM physical-CPU structure.
2966 * @param pVCpu The cross context virtual CPU structure.
2967 *
2968 * @remarks Called with interrupts disabled.
2969 */
2970static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2971{
2972 AssertPtr(pVCpu);
2973 AssertPtr(pHostCpu);
2974
2975 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2976
2977 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2978 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
2979 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2980 pVCpu->hmr0.s.fForceTLBFlush = false;
2981 return;
2982}
2983
2984
2985/**
2986 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2987 *
2988 * @param pHostCpu The HM physical-CPU structure.
2989 * @param pVCpu The cross context virtual CPU structure.
2990 * @param pVmcsInfo The VMCS info. object.
2991 *
2992 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2993 * nomenclature. The reason is, to avoid confusion in compare statements
2994 * since the host-CPU copies are named "ASID".
2995 *
2996 * @remarks Called with interrupts disabled.
2997 */
2998static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2999{
3000#ifdef VBOX_WITH_STATISTICS
3001 bool fTlbFlushed = false;
3002# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
3003# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
3004 if (!fTlbFlushed) \
3005 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
3006 } while (0)
3007#else
3008# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
3009# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
3010#endif
3011
3012 AssertPtr(pVCpu);
3013 AssertPtr(pHostCpu);
3014 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3015
3016 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3017 AssertMsg(pVM->hmr0.s.fNestedPaging && pVM->hmr0.s.vmx.fVpid,
3018 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
3019 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hmr0.s.fNestedPaging, pVM->hmr0.s.vmx.fVpid));
3020
3021 /*
3022 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
3023 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3024 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3025 * cannot reuse the current ASID anymore.
3026 */
3027 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3028 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3029 {
3030 ++pHostCpu->uCurrentAsid;
3031 if (pHostCpu->uCurrentAsid >= g_uHmMaxAsid)
3032 {
3033 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
3034 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3035 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3036 }
3037
3038 pVCpu->hmr0.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3039 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3040 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3041
3042 /*
3043 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
3044 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
3045 */
3046 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3047 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3048 HMVMX_SET_TAGGED_TLB_FLUSHED();
3049 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
3050 }
3051 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
3052 {
3053 /*
3054 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
3055 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
3056 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
3057 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
3058 * mappings, see @bugref{6568}.
3059 *
3060 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
3061 */
3062 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3063 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3064 HMVMX_SET_TAGGED_TLB_FLUSHED();
3065 }
3066 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3067 {
3068 /*
3069 * The nested-guest specifies its own guest-physical address to use as the APIC-access
3070 * address which requires flushing the TLB of EPT cached structures.
3071 *
3072 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
3073 */
3074 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3075 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3076 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3077 HMVMX_SET_TAGGED_TLB_FLUSHED();
3078 }
3079
3080
3081 pVCpu->hmr0.s.fForceTLBFlush = false;
3082 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
3083
3084 Assert(pVCpu->hmr0.s.idLastCpu == pHostCpu->idCpu);
3085 Assert(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes);
3086 AssertMsg(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3087 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hmr0.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3088 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < g_uHmMaxAsid,
3089 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3090 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hmr0.s.idLastCpu, pVCpu->hmr0.s.cTlbFlushes));
3091 AssertMsg(pVCpu->hmr0.s.uCurrentAsid >= 1 && pVCpu->hmr0.s.uCurrentAsid < g_uHmMaxAsid,
3092 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hmr0.s.uCurrentAsid));
3093
3094 /* Update VMCS with the VPID. */
3095 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hmr0.s.uCurrentAsid);
3096 AssertRC(rc);
3097
3098#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3099}
3100
3101
3102/**
3103 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3104 *
3105 * @param pHostCpu The HM physical-CPU structure.
3106 * @param pVCpu The cross context virtual CPU structure.
3107 * @param pVmcsInfo The VMCS info. object.
3108 *
3109 * @remarks Called with interrupts disabled.
3110 */
3111static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3112{
3113 AssertPtr(pVCpu);
3114 AssertPtr(pHostCpu);
3115 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3116 AssertMsg(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3117 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3118
3119 /*
3120 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3121 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3122 */
3123 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3124 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3125 {
3126 pVCpu->hmr0.s.fForceTLBFlush = true;
3127 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3128 }
3129
3130 /* Check for explicit TLB flushes. */
3131 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3132 {
3133 pVCpu->hmr0.s.fForceTLBFlush = true;
3134 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3135 }
3136
3137 /* Check for TLB flushes while switching to/from a nested-guest. */
3138 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3139 {
3140 pVCpu->hmr0.s.fForceTLBFlush = true;
3141 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3142 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3143 }
3144
3145 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3146 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3147
3148 if (pVCpu->hmr0.s.fForceTLBFlush)
3149 {
3150 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.enmTlbFlushEpt);
3151 pVCpu->hmr0.s.fForceTLBFlush = false;
3152 }
3153}
3154
3155
3156/**
3157 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3158 *
3159 * @param pHostCpu The HM physical-CPU structure.
3160 * @param pVCpu The cross context virtual CPU structure.
3161 *
3162 * @remarks Called with interrupts disabled.
3163 */
3164static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3165{
3166 AssertPtr(pVCpu);
3167 AssertPtr(pHostCpu);
3168 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3169 AssertMsg(pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3170 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3171
3172 /*
3173 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3174 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3175 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3176 * cannot reuse the current ASID anymore.
3177 */
3178 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3179 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3180 {
3181 pVCpu->hmr0.s.fForceTLBFlush = true;
3182 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3183 }
3184
3185 /* Check for explicit TLB flushes. */
3186 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3187 {
3188 /*
3189 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3190 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3191 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3192 * include fExplicitFlush's too) - an obscure corner case.
3193 */
3194 pVCpu->hmr0.s.fForceTLBFlush = true;
3195 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3196 }
3197
3198 /* Check for TLB flushes while switching to/from a nested-guest. */
3199 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3200 {
3201 pVCpu->hmr0.s.fForceTLBFlush = true;
3202 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3203 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3204 }
3205
3206 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3207 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3208 if (pVCpu->hmr0.s.fForceTLBFlush)
3209 {
3210 ++pHostCpu->uCurrentAsid;
3211 if (pHostCpu->uCurrentAsid >= g_uHmMaxAsid)
3212 {
3213 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3214 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3215 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3216 }
3217
3218 pVCpu->hmr0.s.fForceTLBFlush = false;
3219 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3220 pVCpu->hmr0.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3221 if (pHostCpu->fFlushAsidBeforeUse)
3222 {
3223 if (pVM->hmr0.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3224 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3225 else if (pVM->hmr0.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3226 {
3227 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3228 pHostCpu->fFlushAsidBeforeUse = false;
3229 }
3230 else
3231 {
3232 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3233 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3234 }
3235 }
3236 }
3237
3238 AssertMsg(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3239 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hmr0.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3240 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < g_uHmMaxAsid,
3241 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3242 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hmr0.s.idLastCpu, pVCpu->hmr0.s.cTlbFlushes));
3243 AssertMsg(pVCpu->hmr0.s.uCurrentAsid >= 1 && pVCpu->hmr0.s.uCurrentAsid < g_uHmMaxAsid,
3244 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hmr0.s.uCurrentAsid));
3245
3246 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hmr0.s.uCurrentAsid);
3247 AssertRC(rc);
3248}
3249
3250
3251/**
3252 * Flushes the guest TLB entry based on CPU capabilities.
3253 *
3254 * @param pHostCpu The HM physical-CPU structure.
3255 * @param pVCpu The cross context virtual CPU structure.
3256 * @param pVmcsInfo The VMCS info. object.
3257 *
3258 * @remarks Called with interrupts disabled.
3259 */
3260static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3261{
3262#ifdef HMVMX_ALWAYS_FLUSH_TLB
3263 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3264#endif
3265 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3266 switch (pVM->hmr0.s.vmx.enmTlbFlushType)
3267 {
3268 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3269 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3270 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3271 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3272 default:
3273 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3274 break;
3275 }
3276 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3277}
3278
3279
3280/**
3281 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3282 * TLB entries from the host TLB before VM-entry.
3283 *
3284 * @returns VBox status code.
3285 * @param pVM The cross context VM structure.
3286 */
3287static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3288{
3289 /*
3290 * Determine optimal flush type for nested paging.
3291 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3292 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3293 */
3294 if (pVM->hmr0.s.fNestedPaging)
3295 {
3296 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3297 {
3298 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3299 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3300 else if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3301 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3302 else
3303 {
3304 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3305 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3306 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3307 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3308 }
3309
3310 /* Make sure the write-back cacheable memory type for EPT is supported. */
3311 if (RT_UNLIKELY(!(g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3312 {
3313 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3314 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3315 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3316 }
3317
3318 /* EPT requires a page-walk length of 4. */
3319 if (RT_UNLIKELY(!(g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3320 {
3321 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3322 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3323 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3324 }
3325 }
3326 else
3327 {
3328 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3329 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3330 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3331 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3332 }
3333 }
3334
3335 /*
3336 * Determine optimal flush type for VPID.
3337 */
3338 if (pVM->hmr0.s.vmx.fVpid)
3339 {
3340 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3341 {
3342 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3343 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3344 else if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3345 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3346 else
3347 {
3348 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3349 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3350 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3351 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3352 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3353 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3354 pVM->hm.s.vmx.fVpidForRing3 = pVM->hmr0.s.vmx.fVpid = false;
3355 }
3356 }
3357 else
3358 {
3359 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3360 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3361 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3362 pVM->hm.s.vmx.fVpidForRing3 = pVM->hmr0.s.vmx.fVpid = false;
3363 }
3364 }
3365
3366 /*
3367 * Setup the handler for flushing tagged-TLBs.
3368 */
3369 if (pVM->hmr0.s.fNestedPaging && pVM->hmr0.s.vmx.fVpid)
3370 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3371 else if (pVM->hmr0.s.fNestedPaging)
3372 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3373 else if (pVM->hmr0.s.vmx.fVpid)
3374 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3375 else
3376 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3377
3378
3379 /*
3380 * Copy out the result to ring-3.
3381 */
3382 pVM->hm.s.vmx.fVpidForRing3 = pVM->hmr0.s.vmx.fVpid;
3383 pVM->hm.s.vmx.enmTlbFlushTypeForRing3 = pVM->hmr0.s.vmx.enmTlbFlushType;
3384 pVM->hm.s.vmx.enmTlbFlushEptForRing3 = pVM->hmr0.s.vmx.enmTlbFlushEpt;
3385 pVM->hm.s.vmx.enmTlbFlushVpidForRing3 = pVM->hmr0.s.vmx.enmTlbFlushVpid;
3386 return VINF_SUCCESS;
3387}
3388
3389
3390/**
3391 * Sets up the LBR MSR ranges based on the host CPU.
3392 *
3393 * @returns VBox status code.
3394 * @param pVM The cross context VM structure.
3395 */
3396static int hmR0VmxSetupLbrMsrRange(PVMCC pVM)
3397{
3398 Assert(pVM->hmr0.s.vmx.fLbr);
3399 uint32_t idLbrFromIpMsrFirst;
3400 uint32_t idLbrFromIpMsrLast;
3401 uint32_t idLbrToIpMsrFirst;
3402 uint32_t idLbrToIpMsrLast;
3403 uint32_t idLbrTosMsr;
3404
3405 /*
3406 * Determine the LBR MSRs supported for this host CPU family and model.
3407 *
3408 * See Intel spec. 17.4.8 "LBR Stack".
3409 * See Intel "Model-Specific Registers" spec.
3410 */
3411 uint32_t const uFamilyModel = (pVM->cpum.ro.HostFeatures.uFamily << 8)
3412 | pVM->cpum.ro.HostFeatures.uModel;
3413 switch (uFamilyModel)
3414 {
3415 case 0x0f01: case 0x0f02:
3416 idLbrFromIpMsrFirst = MSR_P4_LASTBRANCH_0;
3417 idLbrFromIpMsrLast = MSR_P4_LASTBRANCH_3;
3418 idLbrToIpMsrFirst = 0x0;
3419 idLbrToIpMsrLast = 0x0;
3420 idLbrTosMsr = MSR_P4_LASTBRANCH_TOS;
3421 break;
3422
3423 case 0x065c: case 0x065f: case 0x064e: case 0x065e: case 0x068e:
3424 case 0x069e: case 0x0655: case 0x0666: case 0x067a: case 0x0667:
3425 case 0x066a: case 0x066c: case 0x067d: case 0x067e:
3426 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3427 idLbrFromIpMsrLast = MSR_LASTBRANCH_31_FROM_IP;
3428 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3429 idLbrToIpMsrLast = MSR_LASTBRANCH_31_TO_IP;
3430 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3431 break;
3432
3433 case 0x063d: case 0x0647: case 0x064f: case 0x0656: case 0x063c:
3434 case 0x0645: case 0x0646: case 0x063f: case 0x062a: case 0x062d:
3435 case 0x063a: case 0x063e: case 0x061a: case 0x061e: case 0x061f:
3436 case 0x062e: case 0x0625: case 0x062c: case 0x062f:
3437 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3438 idLbrFromIpMsrLast = MSR_LASTBRANCH_15_FROM_IP;
3439 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3440 idLbrToIpMsrLast = MSR_LASTBRANCH_15_TO_IP;
3441 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3442 break;
3443
3444 case 0x0617: case 0x061d: case 0x060f:
3445 idLbrFromIpMsrFirst = MSR_CORE2_LASTBRANCH_0_FROM_IP;
3446 idLbrFromIpMsrLast = MSR_CORE2_LASTBRANCH_3_FROM_IP;
3447 idLbrToIpMsrFirst = MSR_CORE2_LASTBRANCH_0_TO_IP;
3448 idLbrToIpMsrLast = MSR_CORE2_LASTBRANCH_3_TO_IP;
3449 idLbrTosMsr = MSR_CORE2_LASTBRANCH_TOS;
3450 break;
3451
3452 /* Atom and related microarchitectures we don't care about:
3453 case 0x0637: case 0x064a: case 0x064c: case 0x064d: case 0x065a:
3454 case 0x065d: case 0x061c: case 0x0626: case 0x0627: case 0x0635:
3455 case 0x0636: */
3456 /* All other CPUs: */
3457 default:
3458 {
3459 LogRelFunc(("Could not determine LBR stack size for the CPU model %#x\n", uFamilyModel));
3460 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_UNKNOWN;
3461 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3462 }
3463 }
3464
3465 /*
3466 * Validate.
3467 */
3468 uint32_t const cLbrStack = idLbrFromIpMsrLast - idLbrFromIpMsrFirst + 1;
3469 PCVMCPU pVCpu0 = VMCC_GET_CPU_0(pVM);
3470 AssertCompile( RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr)
3471 == RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrToIpMsr));
3472 if (cLbrStack > RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr))
3473 {
3474 LogRelFunc(("LBR stack size of the CPU (%u) exceeds our buffer size\n", cLbrStack));
3475 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_OVERFLOW;
3476 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3477 }
3478 NOREF(pVCpu0);
3479
3480 /*
3481 * Update the LBR info. to the VM struct. for use later.
3482 */
3483 pVM->hmr0.s.vmx.idLbrTosMsr = idLbrTosMsr;
3484
3485 pVM->hm.s.vmx.idLbrFromIpMsrFirstForRing3 = pVM->hmr0.s.vmx.idLbrFromIpMsrFirst = idLbrFromIpMsrFirst;
3486 pVM->hm.s.vmx.idLbrFromIpMsrLastForRing3 = pVM->hmr0.s.vmx.idLbrFromIpMsrLast = idLbrFromIpMsrLast;
3487
3488 pVM->hm.s.vmx.idLbrToIpMsrFirstForRing3 = pVM->hmr0.s.vmx.idLbrToIpMsrFirst = idLbrToIpMsrFirst;
3489 pVM->hm.s.vmx.idLbrToIpMsrLastForRing3 = pVM->hmr0.s.vmx.idLbrToIpMsrLast = idLbrToIpMsrLast;
3490 return VINF_SUCCESS;
3491}
3492
3493
3494#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3495/**
3496 * Sets up the shadow VMCS fields arrays.
3497 *
3498 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3499 * executing the guest.
3500 *
3501 * @returns VBox status code.
3502 * @param pVM The cross context VM structure.
3503 */
3504static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3505{
3506 /*
3507 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3508 * when the host does not support it.
3509 */
3510 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3511 if ( !fGstVmwriteAll
3512 || (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL))
3513 { /* likely. */ }
3514 else
3515 {
3516 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3517 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3518 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3519 }
3520
3521 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3522 uint32_t cRwFields = 0;
3523 uint32_t cRoFields = 0;
3524 for (uint32_t i = 0; i < cVmcsFields; i++)
3525 {
3526 VMXVMCSFIELD VmcsField;
3527 VmcsField.u = g_aVmcsFields[i];
3528
3529 /*
3530 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3531 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3532 * in the shadow VMCS fields array as they would be redundant.
3533 *
3534 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3535 * we must not include it in the shadow VMCS fields array. Guests attempting to
3536 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3537 * the required behavior.
3538 */
3539 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3540 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3541 {
3542 /*
3543 * Read-only fields are placed in a separate array so that while syncing shadow
3544 * VMCS fields later (which is more performance critical) we can avoid branches.
3545 *
3546 * However, if the guest can write to all fields (including read-only fields),
3547 * we treat it a as read/write field. Otherwise, writing to these fields would
3548 * cause a VMWRITE instruction error while syncing the shadow VMCS.
3549 */
3550 if ( fGstVmwriteAll
3551 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3552 pVM->hmr0.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3553 else
3554 pVM->hmr0.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3555 }
3556 }
3557
3558 /* Update the counts. */
3559 pVM->hmr0.s.vmx.cShadowVmcsFields = cRwFields;
3560 pVM->hmr0.s.vmx.cShadowVmcsRoFields = cRoFields;
3561 return VINF_SUCCESS;
3562}
3563
3564
3565/**
3566 * Sets up the VMREAD and VMWRITE bitmaps.
3567 *
3568 * @param pVM The cross context VM structure.
3569 */
3570static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3571{
3572 /*
3573 * By default, ensure guest attempts to access any VMCS fields cause VM-exits.
3574 */
3575 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3576 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hmr0.s.vmx.pvVmreadBitmap;
3577 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hmr0.s.vmx.pvVmwriteBitmap;
3578 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3579 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3580
3581 /*
3582 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3583 * VMREAD and VMWRITE bitmaps.
3584 */
3585 {
3586 uint32_t const *paShadowVmcsFields = pVM->hmr0.s.vmx.paShadowVmcsFields;
3587 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
3588 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3589 {
3590 uint32_t const uVmcsField = paShadowVmcsFields[i];
3591 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3592 Assert(uVmcsField >> 3 < cbBitmap);
3593 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3594 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3595 }
3596 }
3597
3598 /*
3599 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3600 * if the host supports VMWRITE to all supported VMCS fields.
3601 */
3602 if (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL)
3603 {
3604 uint32_t const *paShadowVmcsRoFields = pVM->hmr0.s.vmx.paShadowVmcsRoFields;
3605 uint32_t const cShadowVmcsRoFields = pVM->hmr0.s.vmx.cShadowVmcsRoFields;
3606 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3607 {
3608 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3609 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3610 Assert(uVmcsField >> 3 < cbBitmap);
3611 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3612 }
3613 }
3614}
3615#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3616
3617
3618/**
3619 * Sets up the virtual-APIC page address for the VMCS.
3620 *
3621 * @param pVmcsInfo The VMCS info. object.
3622 */
3623DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3624{
3625 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3626 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3627 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3628 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3629 AssertRC(rc);
3630}
3631
3632
3633/**
3634 * Sets up the MSR-bitmap address for the VMCS.
3635 *
3636 * @param pVmcsInfo The VMCS info. object.
3637 */
3638DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3639{
3640 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3641 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3642 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3643 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3644 AssertRC(rc);
3645}
3646
3647
3648/**
3649 * Sets up the APIC-access page address for the VMCS.
3650 *
3651 * @param pVCpu The cross context virtual CPU structure.
3652 */
3653DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3654{
3655 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysApicAccess;
3656 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3657 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3658 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3659 AssertRC(rc);
3660}
3661
3662
3663#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3664/**
3665 * Sets up the VMREAD bitmap address for the VMCS.
3666 *
3667 * @param pVCpu The cross context virtual CPU structure.
3668 */
3669DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3670{
3671 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysVmreadBitmap;
3672 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3673 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3674 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3675 AssertRC(rc);
3676}
3677
3678
3679/**
3680 * Sets up the VMWRITE bitmap address for the VMCS.
3681 *
3682 * @param pVCpu The cross context virtual CPU structure.
3683 */
3684DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3685{
3686 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysVmwriteBitmap;
3687 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3688 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3689 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3690 AssertRC(rc);
3691}
3692#endif
3693
3694
3695/**
3696 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3697 * in the VMCS.
3698 *
3699 * @returns VBox status code.
3700 * @param pVmcsInfo The VMCS info. object.
3701 */
3702DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3703{
3704 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3705 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3706 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3707
3708 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3709 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3710 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3711
3712 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3713 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3714 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3715
3716 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3717 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3718 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3719 return VINF_SUCCESS;
3720}
3721
3722
3723/**
3724 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3725 *
3726 * @param pVCpu The cross context virtual CPU structure.
3727 * @param pVmcsInfo The VMCS info. object.
3728 */
3729static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3730{
3731 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3732
3733 /*
3734 * By default, ensure guest attempts to access any MSR cause VM-exits.
3735 * This shall later be relaxed for specific MSRs as necessary.
3736 *
3737 * Note: For nested-guests, the entire bitmap will be merged prior to
3738 * executing the nested-guest using hardware-assisted VMX and hence there
3739 * is no need to perform this operation. See hmR0VmxMergeMsrBitmapNested.
3740 */
3741 Assert(pVmcsInfo->pvMsrBitmap);
3742 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
3743
3744 /*
3745 * The guest can access the following MSRs (read, write) without causing
3746 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3747 */
3748 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3749 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3750 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3751 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3752 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3753 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3754
3755 /*
3756 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3757 * associated with then. We never need to intercept access (writes need to be
3758 * executed without causing a VM-exit, reads will #GP fault anyway).
3759 *
3760 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3761 * read/write them. We swap the the guest/host MSR value using the
3762 * auto-load/store MSR area.
3763 */
3764 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3765 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3766 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3767 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3768 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3769 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3770
3771 /*
3772 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3773 * required for 64-bit guests.
3774 */
3775 if (pVM->hmr0.s.fAllow64BitGuests)
3776 {
3777 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3778 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3779 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3780 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3781 }
3782
3783 /*
3784 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3785 */
3786#ifdef VBOX_STRICT
3787 Assert(pVmcsInfo->pvMsrBitmap);
3788 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3789 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3790#endif
3791}
3792
3793
3794/**
3795 * Sets up pin-based VM-execution controls in the VMCS.
3796 *
3797 * @returns VBox status code.
3798 * @param pVCpu The cross context virtual CPU structure.
3799 * @param pVmcsInfo The VMCS info. object.
3800 */
3801static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3802{
3803 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3804 uint32_t fVal = g_HmMsrs.u.vmx.PinCtls.n.allowed0; /* Bits set here must always be set. */
3805 uint32_t const fZap = g_HmMsrs.u.vmx.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3806
3807 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3808 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3809
3810 if (g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3811 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3812
3813 /* Enable the VMX-preemption timer. */
3814 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
3815 {
3816 Assert(g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3817 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3818 }
3819
3820#if 0
3821 /* Enable posted-interrupt processing. */
3822 if (pVM->hm.s.fPostedIntrs)
3823 {
3824 Assert(g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3825 Assert(g_HmMsrs.u.vmx.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3826 fVal |= VMX_PIN_CTLS_POSTED_INT;
3827 }
3828#endif
3829
3830 if ((fVal & fZap) != fVal)
3831 {
3832 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3833 g_HmMsrs.u.vmx.PinCtls.n.allowed0, fVal, fZap));
3834 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3835 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3836 }
3837
3838 /* Commit it to the VMCS and update our cache. */
3839 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3840 AssertRC(rc);
3841 pVmcsInfo->u32PinCtls = fVal;
3842
3843 return VINF_SUCCESS;
3844}
3845
3846
3847/**
3848 * Sets up secondary processor-based VM-execution controls in the VMCS.
3849 *
3850 * @returns VBox status code.
3851 * @param pVCpu The cross context virtual CPU structure.
3852 * @param pVmcsInfo The VMCS info. object.
3853 */
3854static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3855{
3856 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3857 uint32_t fVal = g_HmMsrs.u.vmx.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3858 uint32_t const fZap = g_HmMsrs.u.vmx.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3859
3860 /* WBINVD causes a VM-exit. */
3861 if (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3862 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3863
3864 /* Enable EPT (aka nested-paging). */
3865 if (pVM->hmr0.s.fNestedPaging)
3866 fVal |= VMX_PROC_CTLS2_EPT;
3867
3868 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3869 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3870 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3871 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3872 fVal |= VMX_PROC_CTLS2_INVPCID;
3873
3874 /* Enable VPID. */
3875 if (pVM->hmr0.s.vmx.fVpid)
3876 fVal |= VMX_PROC_CTLS2_VPID;
3877
3878 /* Enable unrestricted guest execution. */
3879 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
3880 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3881
3882#if 0
3883 if (pVM->hm.s.fVirtApicRegs)
3884 {
3885 /* Enable APIC-register virtualization. */
3886 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3887 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3888
3889 /* Enable virtual-interrupt delivery. */
3890 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3891 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3892 }
3893#endif
3894
3895 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3896 where the TPR shadow resides. */
3897 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3898 * done dynamically. */
3899 if (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3900 {
3901 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3902 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3903 }
3904
3905 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3906 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3907 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3908 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3909 fVal |= VMX_PROC_CTLS2_RDTSCP;
3910
3911 /* Enable Pause-Loop exiting. */
3912 if ( (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3913 && pVM->hm.s.vmx.cPleGapTicks
3914 && pVM->hm.s.vmx.cPleWindowTicks)
3915 {
3916 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3917
3918 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3919 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3920 }
3921
3922 if ((fVal & fZap) != fVal)
3923 {
3924 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3925 g_HmMsrs.u.vmx.ProcCtls2.n.allowed0, fVal, fZap));
3926 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3927 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3928 }
3929
3930 /* Commit it to the VMCS and update our cache. */
3931 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3932 AssertRC(rc);
3933 pVmcsInfo->u32ProcCtls2 = fVal;
3934
3935 return VINF_SUCCESS;
3936}
3937
3938
3939/**
3940 * Sets up processor-based VM-execution controls in the VMCS.
3941 *
3942 * @returns VBox status code.
3943 * @param pVCpu The cross context virtual CPU structure.
3944 * @param pVmcsInfo The VMCS info. object.
3945 */
3946static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3947{
3948 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3949 uint32_t fVal = g_HmMsrs.u.vmx.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3950 uint32_t const fZap = g_HmMsrs.u.vmx.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3951
3952 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3953 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3954 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3955 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3956 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3957 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3958 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3959
3960 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3961 if ( !(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3962 || (g_HmMsrs.u.vmx.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3963 {
3964 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3965 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3966 }
3967
3968 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3969 if (!pVM->hmr0.s.fNestedPaging)
3970 {
3971 Assert(!pVM->hmr0.s.vmx.fUnrestrictedGuest);
3972 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3973 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3974 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3975 }
3976
3977 /* Use TPR shadowing if supported by the CPU. */
3978 if ( PDMHasApic(pVM)
3979 && (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
3980 {
3981 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3982 /* CR8 writes cause a VM-exit based on TPR threshold. */
3983 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3984 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3985 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3986 }
3987 else
3988 {
3989 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3990 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3991 if (pVM->hmr0.s.fAllow64BitGuests)
3992 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3993 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3994 }
3995
3996 /* Use MSR-bitmaps if supported by the CPU. */
3997 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3998 {
3999 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
4000 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4001 }
4002
4003 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
4004 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
4005 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
4006
4007 if ((fVal & fZap) != fVal)
4008 {
4009 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4010 g_HmMsrs.u.vmx.ProcCtls.n.allowed0, fVal, fZap));
4011 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
4012 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4013 }
4014
4015 /* Commit it to the VMCS and update our cache. */
4016 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
4017 AssertRC(rc);
4018 pVmcsInfo->u32ProcCtls = fVal;
4019
4020 /* Set up MSR permissions that don't change through the lifetime of the VM. */
4021 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4022 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
4023
4024 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
4025 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
4026 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
4027
4028 /* Sanity check, should not really happen. */
4029 if (RT_LIKELY(!pVM->hmr0.s.vmx.fUnrestrictedGuest))
4030 { /* likely */ }
4031 else
4032 {
4033 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
4034 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4035 }
4036
4037 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
4038 return VINF_SUCCESS;
4039}
4040
4041
4042/**
4043 * Sets up miscellaneous (everything other than Pin, Processor and secondary
4044 * Processor-based VM-execution) control fields in the VMCS.
4045 *
4046 * @returns VBox status code.
4047 * @param pVCpu The cross context virtual CPU structure.
4048 * @param pVmcsInfo The VMCS info. object.
4049 */
4050static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4051{
4052#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4053 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUseVmcsShadowing)
4054 {
4055 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
4056 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
4057 }
4058#endif
4059
4060 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4061 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4062 AssertRC(rc);
4063
4064 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4065 if (RT_SUCCESS(rc))
4066 {
4067 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
4068 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
4069
4070 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
4071 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
4072
4073 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
4074 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
4075
4076 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fLbr)
4077 {
4078 rc = VMXWriteVmcsNw(VMX_VMCS64_GUEST_DEBUGCTL_FULL, MSR_IA32_DEBUGCTL_LBR);
4079 AssertRC(rc);
4080 }
4081 return VINF_SUCCESS;
4082 }
4083 else
4084 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
4085 return rc;
4086}
4087
4088
4089/**
4090 * Sets up the initial exception bitmap in the VMCS based on static conditions.
4091 *
4092 * We shall setup those exception intercepts that don't change during the
4093 * lifetime of the VM here. The rest are done dynamically while loading the
4094 * guest state.
4095 *
4096 * @param pVCpu The cross context virtual CPU structure.
4097 * @param pVmcsInfo The VMCS info. object.
4098 */
4099static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4100{
4101 /*
4102 * The following exceptions are always intercepted:
4103 *
4104 * #AC - To prevent the guest from hanging the CPU.
4105 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
4106 * recursive #DBs can cause a CPU hang.
4107 * #PF - To sync our shadow page tables when nested-paging is not used.
4108 */
4109 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging;
4110 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
4111 | RT_BIT(X86_XCPT_DB)
4112 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
4113
4114 /* Commit it to the VMCS. */
4115 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
4116 AssertRC(rc);
4117
4118 /* Update our cache of the exception bitmap. */
4119 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
4120}
4121
4122
4123#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4124/**
4125 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
4126 *
4127 * @returns VBox status code.
4128 * @param pVmcsInfo The VMCS info. object.
4129 */
4130static int hmR0VmxSetupVmcsCtlsNested(PVMXVMCSINFO pVmcsInfo)
4131{
4132 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4133 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4134 AssertRC(rc);
4135
4136 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4137 if (RT_SUCCESS(rc))
4138 {
4139 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4140 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4141
4142 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
4143 Assert(!pVmcsInfo->u64Cr0Mask);
4144 Assert(!pVmcsInfo->u64Cr4Mask);
4145 return VINF_SUCCESS;
4146 }
4147 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
4148 return rc;
4149}
4150#endif
4151
4152
4153/**
4154 * Sets pfnStartVm to the best suited variant.
4155 *
4156 * This must be called whenever anything changes relative to the hmR0VmXStartVm
4157 * variant selection:
4158 * - pVCpu->hm.s.fLoadSaveGuestXcr0
4159 * - HM_WSF_IBPB_ENTRY in pVCpu->hmr0.s.fWorldSwitcher
4160 * - HM_WSF_IBPB_EXIT in pVCpu->hmr0.s.fWorldSwitcher
4161 * - Perhaps: CPUMIsGuestFPUStateActive() (windows only)
4162 * - Perhaps: CPUMCTX.fXStateMask (windows only)
4163 *
4164 * We currently ASSUME that neither HM_WSF_IBPB_ENTRY nor HM_WSF_IBPB_EXIT
4165 * cannot be changed at runtime.
4166 */
4167static void hmR0VmxUpdateStartVmFunction(PVMCPUCC pVCpu)
4168{
4169 static const struct CLANGWORKAROUND { PFNHMVMXSTARTVM pfn; } s_aHmR0VmxStartVmFunctions[] =
4170 {
4171 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4172 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4173 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4174 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4175 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4176 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4177 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4178 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4179 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4180 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4181 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4182 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4183 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4184 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4185 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4186 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4187 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4188 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4189 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4190 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4191 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4192 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4193 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4194 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4195 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4196 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4197 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4198 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4199 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4200 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4201 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4202 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4203 };
4204 uintptr_t const idx = (pVCpu->hmr0.s.fLoadSaveGuestXcr0 ? 1 : 0)
4205 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_IBPB_ENTRY ? 2 : 0)
4206 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_L1D_ENTRY ? 4 : 0)
4207 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_MDS_ENTRY ? 8 : 0)
4208 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_IBPB_EXIT ? 16 : 0);
4209 PFNHMVMXSTARTVM const pfnStartVm = s_aHmR0VmxStartVmFunctions[idx].pfn;
4210 if (pVCpu->hmr0.s.vmx.pfnStartVm != pfnStartVm)
4211 pVCpu->hmr0.s.vmx.pfnStartVm = pfnStartVm;
4212}
4213
4214
4215/**
4216 * Selector FNHMSVMVMRUN implementation.
4217 */
4218static DECLCALLBACK(int) hmR0VmxStartVmSelector(PVMXVMCSINFO pVmcsInfo, PVMCPUCC pVCpu, bool fResume)
4219{
4220 hmR0VmxUpdateStartVmFunction(pVCpu);
4221 return pVCpu->hmr0.s.vmx.pfnStartVm(pVmcsInfo, pVCpu, fResume);
4222}
4223
4224
4225/**
4226 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
4227 * VMX.
4228 *
4229 * @returns VBox status code.
4230 * @param pVCpu The cross context virtual CPU structure.
4231 * @param pVmcsInfo The VMCS info. object.
4232 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
4233 */
4234static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
4235{
4236 Assert(pVmcsInfo->pvVmcs);
4237 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4238
4239 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
4240 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
4241 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
4242
4243 LogFlowFunc(("\n"));
4244
4245 /*
4246 * Initialize the VMCS using VMCLEAR before loading the VMCS.
4247 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
4248 */
4249 int rc = hmR0VmxClearVmcs(pVmcsInfo);
4250 if (RT_SUCCESS(rc))
4251 {
4252 rc = hmR0VmxLoadVmcs(pVmcsInfo);
4253 if (RT_SUCCESS(rc))
4254 {
4255 /*
4256 * Initialize the hardware-assisted VMX execution handler for guest and nested-guest VMCS.
4257 * The host is always 64-bit since we no longer support 32-bit hosts.
4258 * Currently we have just a single handler for all guest modes as well, see @bugref{6208#c73}.
4259 */
4260 if (!fIsNstGstVmcs)
4261 {
4262 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
4263 if (RT_SUCCESS(rc))
4264 {
4265 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
4266 if (RT_SUCCESS(rc))
4267 {
4268 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
4269 if (RT_SUCCESS(rc))
4270 {
4271 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4272#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4273 /*
4274 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4275 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4276 * making it fit for use when VMCS shadowing is later enabled.
4277 */
4278 if (pVmcsInfo->pvShadowVmcs)
4279 {
4280 VMXVMCSREVID VmcsRevId;
4281 VmcsRevId.u = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
4282 VmcsRevId.n.fIsShadowVmcs = 1;
4283 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4284 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4285 if (RT_SUCCESS(rc))
4286 { /* likely */ }
4287 else
4288 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4289 }
4290#endif
4291 }
4292 else
4293 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4294 }
4295 else
4296 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4297 }
4298 else
4299 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4300 }
4301 else
4302 {
4303#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4304 rc = hmR0VmxSetupVmcsCtlsNested(pVmcsInfo);
4305 if (RT_SUCCESS(rc))
4306 { /* likely */ }
4307 else
4308 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4309#else
4310 AssertFailed();
4311#endif
4312 }
4313 }
4314 else
4315 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4316 }
4317 else
4318 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4319
4320 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4321 if (RT_SUCCESS(rc))
4322 {
4323 rc = hmR0VmxClearVmcs(pVmcsInfo);
4324 if (RT_SUCCESS(rc))
4325 { /* likely */ }
4326 else
4327 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4328 }
4329
4330 /*
4331 * Update the last-error record both for failures and success, so we
4332 * can propagate the status code back to ring-3 for diagnostics.
4333 */
4334 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4335 NOREF(pszVmcs);
4336 return rc;
4337}
4338
4339
4340/**
4341 * Does global VT-x initialization (called during module initialization).
4342 *
4343 * @returns VBox status code.
4344 */
4345VMMR0DECL(int) VMXR0GlobalInit(void)
4346{
4347#ifdef HMVMX_USE_FUNCTION_TABLE
4348 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_aVMExitHandlers));
4349# ifdef VBOX_STRICT
4350 for (unsigned i = 0; i < RT_ELEMENTS(g_aVMExitHandlers); i++)
4351 Assert(g_aVMExitHandlers[i].pfn);
4352# endif
4353#endif
4354 return VINF_SUCCESS;
4355}
4356
4357
4358/**
4359 * Does global VT-x termination (called during module termination).
4360 */
4361VMMR0DECL(void) VMXR0GlobalTerm()
4362{
4363 /* Nothing to do currently. */
4364}
4365
4366
4367/**
4368 * Sets up and activates VT-x on the current CPU.
4369 *
4370 * @returns VBox status code.
4371 * @param pHostCpu The HM physical-CPU structure.
4372 * @param pVM The cross context VM structure. Can be
4373 * NULL after a host resume operation.
4374 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4375 * fEnabledByHost is @c true).
4376 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4377 * @a fEnabledByHost is @c true).
4378 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4379 * enable VT-x on the host.
4380 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4381 */
4382VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4383 PCSUPHWVIRTMSRS pHwvirtMsrs)
4384{
4385 AssertPtr(pHostCpu);
4386 AssertPtr(pHwvirtMsrs);
4387 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4388
4389 /* Enable VT-x if it's not already enabled by the host. */
4390 if (!fEnabledByHost)
4391 {
4392 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4393 if (RT_FAILURE(rc))
4394 return rc;
4395 }
4396
4397 /*
4398 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4399 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4400 * invalidated when flushing by VPID.
4401 */
4402 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4403 {
4404 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4405 pHostCpu->fFlushAsidBeforeUse = false;
4406 }
4407 else
4408 pHostCpu->fFlushAsidBeforeUse = true;
4409
4410 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4411 ++pHostCpu->cTlbFlushes;
4412
4413 return VINF_SUCCESS;
4414}
4415
4416
4417/**
4418 * Deactivates VT-x on the current CPU.
4419 *
4420 * @returns VBox status code.
4421 * @param pHostCpu The HM physical-CPU structure.
4422 * @param pvCpuPage Pointer to the VMXON region.
4423 * @param HCPhysCpuPage Physical address of the VMXON region.
4424 *
4425 * @remarks This function should never be called when SUPR0EnableVTx() or
4426 * similar was used to enable VT-x on the host.
4427 */
4428VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4429{
4430 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4431
4432 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4433 return hmR0VmxLeaveRootMode(pHostCpu);
4434}
4435
4436
4437/**
4438 * Does per-VM VT-x initialization.
4439 *
4440 * @returns VBox status code.
4441 * @param pVM The cross context VM structure.
4442 */
4443VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4444{
4445 AssertPtr(pVM);
4446 LogFlowFunc(("pVM=%p\n", pVM));
4447
4448 hmR0VmxStructsInit(pVM);
4449 int rc = hmR0VmxStructsAlloc(pVM);
4450 if (RT_FAILURE(rc))
4451 {
4452 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4453 return rc;
4454 }
4455
4456 /* Setup the crash dump page. */
4457#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4458 strcpy((char *)pVM->hmr0.s.vmx.pbScratch, "SCRATCH Magic");
4459 *(uint64_t *)(pVM->hmr0.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
4460#endif
4461 return VINF_SUCCESS;
4462}
4463
4464
4465/**
4466 * Does per-VM VT-x termination.
4467 *
4468 * @returns VBox status code.
4469 * @param pVM The cross context VM structure.
4470 */
4471VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4472{
4473 AssertPtr(pVM);
4474 LogFlowFunc(("pVM=%p\n", pVM));
4475
4476#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4477 if (pVM->hmr0.s.vmx.pbScratch)
4478 RT_BZERO(pVM->hmr0.s.vmx.pbScratch, X86_PAGE_4K_SIZE);
4479#endif
4480 hmR0VmxStructsFree(pVM);
4481 return VINF_SUCCESS;
4482}
4483
4484
4485/**
4486 * Sets up the VM for execution using hardware-assisted VMX.
4487 * This function is only called once per-VM during initialization.
4488 *
4489 * @returns VBox status code.
4490 * @param pVM The cross context VM structure.
4491 */
4492VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4493{
4494 AssertPtr(pVM);
4495 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4496
4497 LogFlowFunc(("pVM=%p\n", pVM));
4498
4499 /*
4500 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4501 * without causing a #GP.
4502 */
4503 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4504 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4505 { /* likely */ }
4506 else
4507 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4508
4509 /*
4510 * Check that nested paging is supported if enabled and copy over the flag to the
4511 * ring-0 only structure.
4512 */
4513 bool const fNestedPaging = pVM->hm.s.fNestedPagingCfg;
4514 AssertReturn( !fNestedPaging
4515 || (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_EPT), /** @todo use a ring-0 copy of ProcCtls2.n.allowed1 */
4516 VERR_INCOMPATIBLE_CONFIG);
4517 pVM->hmr0.s.fNestedPaging = fNestedPaging;
4518 pVM->hmr0.s.fAllow64BitGuests = pVM->hm.s.fAllow64BitGuestsCfg;
4519
4520 /*
4521 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4522 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4523 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4524 */
4525 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuestCfg;
4526 AssertReturn( !fUnrestrictedGuest
4527 || ( (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_UNRESTRICTED_GUEST)
4528 && fNestedPaging),
4529 VERR_INCOMPATIBLE_CONFIG);
4530 if ( !fUnrestrictedGuest
4531 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4532 || !pVM->hm.s.vmx.pRealModeTSS))
4533 {
4534 LogRelFunc(("Invalid real-on-v86 state.\n"));
4535 return VERR_INTERNAL_ERROR;
4536 }
4537 pVM->hmr0.s.vmx.fUnrestrictedGuest = fUnrestrictedGuest;
4538
4539 /* Initialize these always, see hmR3InitFinalizeR0().*/
4540 pVM->hm.s.vmx.enmTlbFlushEptForRing3 = pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4541 pVM->hm.s.vmx.enmTlbFlushVpidForRing3 = pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4542
4543 /* Setup the tagged-TLB flush handlers. */
4544 int rc = hmR0VmxSetupTaggedTlb(pVM);
4545 if (RT_FAILURE(rc))
4546 {
4547 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4548 return rc;
4549 }
4550
4551 /* Determine LBR capabilities. */
4552 pVM->hmr0.s.vmx.fLbr = pVM->hm.s.vmx.fLbrCfg;
4553 if (pVM->hmr0.s.vmx.fLbr)
4554 {
4555 rc = hmR0VmxSetupLbrMsrRange(pVM);
4556 if (RT_FAILURE(rc))
4557 {
4558 LogRelFunc(("Failed to setup LBR MSR range. rc=%Rrc\n", rc));
4559 return rc;
4560 }
4561 }
4562
4563#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4564 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4565 if (pVM->hmr0.s.vmx.fUseVmcsShadowing)
4566 {
4567 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4568 if (RT_SUCCESS(rc))
4569 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4570 else
4571 {
4572 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4573 return rc;
4574 }
4575 }
4576#endif
4577
4578 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4579 {
4580 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4581 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4582
4583 pVCpu->hmr0.s.vmx.pfnStartVm = hmR0VmxStartVmSelector;
4584
4585 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4586 if (RT_SUCCESS(rc))
4587 {
4588#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4589 if (pVM->cpum.ro.GuestFeatures.fVmx)
4590 {
4591 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4592 if (RT_SUCCESS(rc))
4593 { /* likely */ }
4594 else
4595 {
4596 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4597 return rc;
4598 }
4599 }
4600#endif
4601 }
4602 else
4603 {
4604 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4605 return rc;
4606 }
4607 }
4608
4609 return VINF_SUCCESS;
4610}
4611
4612
4613/**
4614 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4615 * the VMCS.
4616 * @returns CR4 for passing along to hmR0VmxExportHostSegmentRegs.
4617 */
4618static uint64_t hmR0VmxExportHostControlRegs(void)
4619{
4620 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4621 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4622 uint64_t uHostCr4 = ASMGetCR4();
4623 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, uHostCr4); AssertRC(rc);
4624 return uHostCr4;
4625}
4626
4627
4628/**
4629 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4630 * the host-state area in the VMCS.
4631 *
4632 * @returns VBox status code.
4633 * @param pVCpu The cross context virtual CPU structure.
4634 * @param uHostCr4 The host CR4 value.
4635 */
4636static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu, uint64_t uHostCr4)
4637{
4638 /*
4639 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4640 * will be messed up. We should -not- save the messed up state without restoring
4641 * the original host-state, see @bugref{7240}.
4642 *
4643 * This apparently can happen (most likely the FPU changes), deal with it rather than
4644 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4645 */
4646 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
4647 {
4648 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hmr0.s.vmx.fRestoreHostFlags,
4649 pVCpu->idCpu));
4650 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
4651 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
4652 }
4653
4654 /*
4655 * Get all the host info.
4656 * ASSUME it is safe to use rdfsbase and friends if the CR4.FSGSBASE bit is set
4657 * without also checking the cpuid bit.
4658 */
4659 uint32_t fRestoreHostFlags;
4660#if RT_INLINE_ASM_EXTERNAL
4661 if (uHostCr4 & X86_CR4_FSGSBASE)
4662 {
4663 hmR0VmxExportHostSegmentRegsAsmHlp(&pVCpu->hmr0.s.vmx.RestoreHost, true /*fHaveFsGsBase*/);
4664 fRestoreHostFlags = VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE;
4665 }
4666 else
4667 {
4668 hmR0VmxExportHostSegmentRegsAsmHlp(&pVCpu->hmr0.s.vmx.RestoreHost, false /*fHaveFsGsBase*/);
4669 fRestoreHostFlags = 0;
4670 }
4671 RTSEL uSelES = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelES;
4672 RTSEL uSelDS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelDS;
4673 RTSEL uSelFS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelFS;
4674 RTSEL uSelGS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelGS;
4675#else
4676 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR = ASMGetTR();
4677 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS = ASMGetSS();
4678 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS = ASMGetCS();
4679 ASMGetGDTR((PRTGDTR)&pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr);
4680 ASMGetIDTR((PRTIDTR)&pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr);
4681 if (uHostCr4 & X86_CR4_FSGSBASE)
4682 {
4683 pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase = ASMGetFSBase();
4684 pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase = ASMGetGSBase();
4685 fRestoreHostFlags = VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE;
4686 }
4687 else
4688 {
4689 pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase = ASMRdMsr(MSR_K8_FS_BASE);
4690 pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase = ASMRdMsr(MSR_K8_GS_BASE);
4691 fRestoreHostFlags = 0;
4692 }
4693 RTSEL uSelES, uSelDS, uSelFS, uSelGS;
4694 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelDS = uSelDS = ASMGetDS();
4695 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelES = uSelES = ASMGetES();
4696 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelFS = uSelFS = ASMGetFS();
4697 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelGS = uSelGS = ASMGetGS();
4698#endif
4699
4700 /*
4701 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4702 * gain VM-entry and restore them before we get preempted.
4703 *
4704 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4705 */
4706 RTSEL const uSelAll = uSelFS | uSelGS | uSelES | uSelDS;
4707 if (uSelAll & (X86_SEL_RPL | X86_SEL_LDT))
4708 {
4709 if (!(uSelAll & X86_SEL_LDT))
4710 {
4711#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_uVmcsVar) \
4712 do { \
4713 (a_uVmcsVar) = pVCpu->hmr0.s.vmx.RestoreHost.uHostSel##a_Seg; \
4714 if ((a_uVmcsVar) & X86_SEL_RPL) \
4715 { \
4716 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4717 (a_uVmcsVar) = 0; \
4718 } \
4719 } while (0)
4720 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4721 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4722 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4723 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4724#undef VMXLOCAL_ADJUST_HOST_SEG
4725 }
4726 else
4727 {
4728#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_uVmcsVar) \
4729 do { \
4730 (a_uVmcsVar) = pVCpu->hmr0.s.vmx.RestoreHost.uHostSel##a_Seg; \
4731 if ((a_uVmcsVar) & (X86_SEL_RPL | X86_SEL_LDT)) \
4732 { \
4733 if (!((a_uVmcsVar) & X86_SEL_LDT)) \
4734 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4735 else \
4736 { \
4737 uint32_t const fAttr = ASMGetSegAttr(a_uVmcsVar); \
4738 if ((fAttr & X86_DESC_P) && fAttr != UINT32_MAX) \
4739 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4740 } \
4741 (a_uVmcsVar) = 0; \
4742 } \
4743 } while (0)
4744 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4745 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4746 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4747 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4748#undef VMXLOCAL_ADJUST_HOST_SEG
4749 }
4750 }
4751
4752 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4753 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR & X86_SEL_LDT)); Assert(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR);
4754 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS & X86_SEL_LDT)); Assert(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS);
4755 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS & X86_SEL_LDT));
4756 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4757 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4758 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4759 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4760
4761 /*
4762 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4763 * them to the maximum limit (0xffff) on every VM-exit.
4764 */
4765 if (pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb != 0xffff)
4766 fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4767
4768 /*
4769 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4770 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4771 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4772 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4773 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4774 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4775 * at 0xffff on hosts where we are sure it won't cause trouble.
4776 */
4777#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4778 if (pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.cb < 0x0fff)
4779#else
4780 if (pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.cb != 0xffff)
4781#endif
4782 fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4783
4784 /*
4785 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4786 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4787 * RPL should be too in most cases.
4788 */
4789 RTSEL const uSelTR = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR;
4790 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb,
4791 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb),
4792 VERR_VMX_INVALID_HOST_STATE);
4793
4794 PCX86DESCHC pDesc = (PCX86DESCHC)(pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.uAddr + (uSelTR & X86_SEL_MASK));
4795 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4796
4797 /*
4798 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4799 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4800 * restoration if the host has something else. Task switching is not supported in 64-bit
4801 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4802 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4803 *
4804 * [1] See Intel spec. 3.5 "System Descriptor Types".
4805 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4806 */
4807 Assert(pDesc->System.u4Type == 11);
4808 if ( pDesc->System.u16LimitLow != 0x67
4809 || pDesc->System.u4LimitHigh)
4810 {
4811 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4812
4813 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4814 if (g_fHmHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4815 fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4816 if (g_fHmHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4817 {
4818 /* The GDT is read-only but the writable GDT is available. */
4819 fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4820 pVCpu->hmr0.s.vmx.RestoreHost.HostGdtrRw.cb = pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb;
4821 int rc = SUPR0GetCurrentGdtRw(&pVCpu->hmr0.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4822 AssertRCReturn(rc, rc);
4823 }
4824 }
4825
4826 pVCpu->hmr0.s.vmx.fRestoreHostFlags = fRestoreHostFlags;
4827
4828 /*
4829 * Do all the VMCS updates in one block to assist nested virtualization.
4830 */
4831 int rc;
4832 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS); AssertRC(rc);
4833 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS); AssertRC(rc);
4834 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4835 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4836 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4837 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4838 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR); AssertRC(rc);
4839 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.uAddr); AssertRC(rc);
4840 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.uAddr); AssertRC(rc);
4841 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase); AssertRC(rc);
4842 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase); AssertRC(rc);
4843 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase); AssertRC(rc);
4844
4845 return VINF_SUCCESS;
4846}
4847
4848
4849/**
4850 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4851 * host-state area of the VMCS.
4852 *
4853 * These MSRs will be automatically restored on the host after every successful
4854 * VM-exit.
4855 *
4856 * @param pVCpu The cross context virtual CPU structure.
4857 *
4858 * @remarks No-long-jump zone!!!
4859 */
4860static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4861{
4862 AssertPtr(pVCpu);
4863
4864 /*
4865 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4866 * rather than swapping them on every VM-entry.
4867 */
4868 hmR0VmxLazySaveHostMsrs(pVCpu);
4869
4870 /*
4871 * Host Sysenter MSRs.
4872 */
4873 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4874 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4875 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4876
4877 /*
4878 * Host EFER MSR.
4879 *
4880 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4881 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4882 */
4883 if (g_fHmVmxSupportsVmcsEfer)
4884 {
4885 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, g_uHmVmxHostMsrEfer);
4886 AssertRC(rc);
4887 }
4888
4889 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4890 * hmR0VmxExportGuestEntryExitCtls(). */
4891}
4892
4893
4894/**
4895 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4896 *
4897 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4898 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4899 *
4900 * @returns true if we need to load guest EFER, false otherwise.
4901 * @param pVCpu The cross context virtual CPU structure.
4902 * @param pVmxTransient The VMX-transient structure.
4903 *
4904 * @remarks Requires EFER, CR4.
4905 * @remarks No-long-jump zone!!!
4906 */
4907static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4908{
4909#ifdef HMVMX_ALWAYS_SWAP_EFER
4910 RT_NOREF2(pVCpu, pVmxTransient);
4911 return true;
4912#else
4913 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4914 uint64_t const u64HostEfer = g_uHmVmxHostMsrEfer;
4915 uint64_t const u64GuestEfer = pCtx->msrEFER;
4916
4917# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4918 /*
4919 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4920 * the nested-guest.
4921 */
4922 if ( pVmxTransient->fIsNestedGuest
4923 && ( CPUMIsGuestVmxEntryCtlsSet(pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4924 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4925 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4926 return true;
4927# else
4928 RT_NOREF(pVmxTransient);
4929#endif
4930
4931 /*
4932 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4933 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4934 */
4935 if ( CPUMIsGuestInLongModeEx(pCtx)
4936 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4937 return true;
4938
4939 /*
4940 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4941 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4942 *
4943 * See Intel spec. 4.5 "IA-32e Paging".
4944 * See Intel spec. 4.1.1 "Three Paging Modes".
4945 *
4946 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4947 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4948 */
4949 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4950 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4951 if ( (pCtx->cr4 & X86_CR4_PAE)
4952 && (pCtx->cr0 & X86_CR0_PG))
4953 {
4954 /*
4955 * If nested paging is not used, verify that the guest paging mode matches the
4956 * shadow paging mode which is/will be placed in the VMCS (which is what will
4957 * actually be used while executing the guest and not the CR4 shadow value).
4958 */
4959 AssertMsg( pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging
4960 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4961 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4962 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4963 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX,
4964 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4965 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4966 {
4967 /* Verify that the host is NX capable. */
4968 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4969 return true;
4970 }
4971 }
4972
4973 return false;
4974#endif
4975}
4976
4977
4978/**
4979 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4980 * VMCS.
4981 *
4982 * This is typically required when the guest changes paging mode.
4983 *
4984 * @returns VBox status code.
4985 * @param pVCpu The cross context virtual CPU structure.
4986 * @param pVmxTransient The VMX-transient structure.
4987 *
4988 * @remarks Requires EFER.
4989 * @remarks No-long-jump zone!!!
4990 */
4991static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4992{
4993 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4994 {
4995 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4996 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4997
4998 /*
4999 * VM-entry controls.
5000 */
5001 {
5002 uint32_t fVal = g_HmMsrs.u.vmx.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5003 uint32_t const fZap = g_HmMsrs.u.vmx.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5004
5005 /*
5006 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
5007 * The first VT-x capable CPUs only supported the 1-setting of this bit.
5008 *
5009 * For nested-guests, this is a mandatory VM-entry control. It's also
5010 * required because we do not want to leak host bits to the nested-guest.
5011 */
5012 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
5013
5014 /*
5015 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
5016 *
5017 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
5018 * required to get the nested-guest working with hardware-assisted VMX execution.
5019 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
5020 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
5021 * here rather than while merging the guest VMCS controls.
5022 */
5023 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
5024 {
5025 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
5026 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
5027 }
5028 else
5029 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
5030
5031 /*
5032 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
5033 *
5034 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
5035 * regardless of whether the nested-guest VMCS specifies it because we are free to
5036 * load whatever MSRs we require and we do not need to modify the guest visible copy
5037 * of the VM-entry MSR load area.
5038 */
5039 if ( g_fHmVmxSupportsVmcsEfer
5040 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
5041 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
5042 else
5043 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
5044
5045 /*
5046 * The following should -not- be set (since we're not in SMM mode):
5047 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
5048 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
5049 */
5050
5051 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
5052 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
5053
5054 if ((fVal & fZap) == fVal)
5055 { /* likely */ }
5056 else
5057 {
5058 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
5059 g_HmMsrs.u.vmx.EntryCtls.n.allowed0, fVal, fZap));
5060 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
5061 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5062 }
5063
5064 /* Commit it to the VMCS. */
5065 if (pVmcsInfo->u32EntryCtls != fVal)
5066 {
5067 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
5068 AssertRC(rc);
5069 pVmcsInfo->u32EntryCtls = fVal;
5070 }
5071 }
5072
5073 /*
5074 * VM-exit controls.
5075 */
5076 {
5077 uint32_t fVal = g_HmMsrs.u.vmx.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5078 uint32_t const fZap = g_HmMsrs.u.vmx.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5079
5080 /*
5081 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
5082 * supported the 1-setting of this bit.
5083 *
5084 * For nested-guests, we set the "save debug controls" as the converse
5085 * "load debug controls" is mandatory for nested-guests anyway.
5086 */
5087 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
5088
5089 /*
5090 * Set the host long mode active (EFER.LMA) bit (which Intel calls
5091 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
5092 * host EFER.LMA and EFER.LME bit to this value. See assertion in
5093 * hmR0VmxExportHostMsrs().
5094 *
5095 * For nested-guests, we always set this bit as we do not support 32-bit
5096 * hosts.
5097 */
5098 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5099
5100 /*
5101 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
5102 *
5103 * For nested-guests, we should use the "save IA32_EFER" control if we also
5104 * used the "load IA32_EFER" control while exporting VM-entry controls.
5105 */
5106 if ( g_fHmVmxSupportsVmcsEfer
5107 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
5108 {
5109 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
5110 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
5111 }
5112
5113 /*
5114 * Enable saving of the VMX-preemption timer value on VM-exit.
5115 * For nested-guests, currently not exposed/used.
5116 */
5117 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
5118 {
5119 Assert(g_HmMsrs.u.vmx.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER);
5120 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
5121 }
5122
5123 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
5124 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
5125
5126 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5127 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5128 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5129
5130 if ((fVal & fZap) == fVal)
5131 { /* likely */ }
5132 else
5133 {
5134 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5135 g_HmMsrs.u.vmx.ExitCtls.n.allowed0, fVal, fZap));
5136 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5137 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5138 }
5139
5140 /* Commit it to the VMCS. */
5141 if (pVmcsInfo->u32ExitCtls != fVal)
5142 {
5143 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5144 AssertRC(rc);
5145 pVmcsInfo->u32ExitCtls = fVal;
5146 }
5147 }
5148
5149 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5150 }
5151 return VINF_SUCCESS;
5152}
5153
5154
5155/**
5156 * Sets the TPR threshold in the VMCS.
5157 *
5158 * @param pVmcsInfo The VMCS info. object.
5159 * @param u32TprThreshold The TPR threshold (task-priority class only).
5160 */
5161DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5162{
5163 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5164 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5165 RT_NOREF(pVmcsInfo);
5166 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5167 AssertRC(rc);
5168}
5169
5170
5171/**
5172 * Exports the guest APIC TPR state into the VMCS.
5173 *
5174 * @param pVCpu The cross context virtual CPU structure.
5175 * @param pVmxTransient The VMX-transient structure.
5176 *
5177 * @remarks No-long-jump zone!!!
5178 */
5179static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5180{
5181 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5182 {
5183 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5184
5185 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5186 if (!pVmxTransient->fIsNestedGuest)
5187 {
5188 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5189 && APICIsEnabled(pVCpu))
5190 {
5191 /*
5192 * Setup TPR shadowing.
5193 */
5194 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5195 {
5196 bool fPendingIntr = false;
5197 uint8_t u8Tpr = 0;
5198 uint8_t u8PendingIntr = 0;
5199 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5200 AssertRC(rc);
5201
5202 /*
5203 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5204 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5205 * priority of the pending interrupt so we can deliver the interrupt. If there
5206 * are no interrupts pending, set threshold to 0 to not cause any
5207 * TPR-below-threshold VM-exits.
5208 */
5209 uint32_t u32TprThreshold = 0;
5210 if (fPendingIntr)
5211 {
5212 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5213 (which is the Task-Priority Class). */
5214 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5215 const uint8_t u8TprPriority = u8Tpr >> 4;
5216 if (u8PendingPriority <= u8TprPriority)
5217 u32TprThreshold = u8PendingPriority;
5218 }
5219
5220 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
5221 }
5222 }
5223 }
5224 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5225 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5226 }
5227}
5228
5229
5230/**
5231 * Gets the guest interruptibility-state and updates related force-flags.
5232 *
5233 * @returns Guest's interruptibility-state.
5234 * @param pVCpu The cross context virtual CPU structure.
5235 *
5236 * @remarks No-long-jump zone!!!
5237 */
5238static uint32_t hmR0VmxGetGuestIntrStateAndUpdateFFs(PVMCPUCC pVCpu)
5239{
5240 /*
5241 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5242 */
5243 uint32_t fIntrState = 0;
5244 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5245 {
5246 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
5247 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
5248
5249 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5250 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5251 {
5252 if (pCtx->eflags.Bits.u1IF)
5253 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5254 else
5255 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5256 }
5257 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5258 {
5259 /*
5260 * We can clear the inhibit force flag as even if we go back to the recompiler
5261 * without executing guest code in VT-x, the flag's condition to be cleared is
5262 * met and thus the cleared state is correct.
5263 */
5264 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5265 }
5266 }
5267
5268 /*
5269 * Check if we should inhibit NMI delivery.
5270 */
5271 if (CPUMIsGuestNmiBlocking(pVCpu))
5272 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5273
5274 /*
5275 * Validate.
5276 */
5277#ifdef VBOX_STRICT
5278 /* We don't support block-by-SMI yet.*/
5279 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
5280
5281 /* Block-by-STI must not be set when interrupts are disabled. */
5282 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
5283 {
5284 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5285 Assert(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_IF);
5286 }
5287#endif
5288
5289 return fIntrState;
5290}
5291
5292
5293/**
5294 * Exports the exception intercepts required for guest execution in the VMCS.
5295 *
5296 * @param pVCpu The cross context virtual CPU structure.
5297 * @param pVmxTransient The VMX-transient structure.
5298 *
5299 * @remarks No-long-jump zone!!!
5300 */
5301static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5302{
5303 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5304 {
5305 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5306 if ( !pVmxTransient->fIsNestedGuest
5307 && pVCpu->hm.s.fGIMTrapXcptUD)
5308 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5309 else
5310 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5311
5312 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5313 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5314 }
5315}
5316
5317
5318/**
5319 * Exports the guest's RIP into the guest-state area in the VMCS.
5320 *
5321 * @param pVCpu The cross context virtual CPU structure.
5322 *
5323 * @remarks No-long-jump zone!!!
5324 */
5325static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5326{
5327 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5328 {
5329 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5330
5331 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5332 AssertRC(rc);
5333
5334 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5335 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5336 }
5337}
5338
5339
5340/**
5341 * Exports the guest's RSP into the guest-state area in the VMCS.
5342 *
5343 * @param pVCpu The cross context virtual CPU structure.
5344 *
5345 * @remarks No-long-jump zone!!!
5346 */
5347static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5348{
5349 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5350 {
5351 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5352
5353 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5354 AssertRC(rc);
5355
5356 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5357 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5358 }
5359}
5360
5361
5362/**
5363 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5364 *
5365 * @param pVCpu The cross context virtual CPU structure.
5366 * @param pVmxTransient The VMX-transient structure.
5367 *
5368 * @remarks No-long-jump zone!!!
5369 */
5370static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5371{
5372 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5373 {
5374 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5375
5376 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5377 Let us assert it as such and use 32-bit VMWRITE. */
5378 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5379 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5380 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5381 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5382
5383 /*
5384 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5385 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5386 * can run the real-mode guest code under Virtual 8086 mode.
5387 */
5388 PVMXVMCSINFOSHARED pVmcsInfo = pVmxTransient->pVmcsInfo->pShared;
5389 if (pVmcsInfo->RealMode.fRealOnV86Active)
5390 {
5391 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5392 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5393 Assert(!pVmxTransient->fIsNestedGuest);
5394 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5395 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5396 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5397 }
5398
5399 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5400 AssertRC(rc);
5401
5402 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5403 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5404 }
5405}
5406
5407
5408#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5409/**
5410 * Copies the nested-guest VMCS to the shadow VMCS.
5411 *
5412 * @returns VBox status code.
5413 * @param pVCpu The cross context virtual CPU structure.
5414 * @param pVmcsInfo The VMCS info. object.
5415 *
5416 * @remarks No-long-jump zone!!!
5417 */
5418static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5419{
5420 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5421 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5422
5423 /*
5424 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5425 * current VMCS, as we may try saving guest lazy MSRs.
5426 *
5427 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5428 * calling the import VMCS code which is currently performing the guest MSR reads
5429 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5430 * and the rest of the VMX leave session machinery.
5431 */
5432 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5433
5434 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5435 if (RT_SUCCESS(rc))
5436 {
5437 /*
5438 * Copy all guest read/write VMCS fields.
5439 *
5440 * We don't check for VMWRITE failures here for performance reasons and
5441 * because they are not expected to fail, barring irrecoverable conditions
5442 * like hardware errors.
5443 */
5444 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
5445 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5446 {
5447 uint64_t u64Val;
5448 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsFields[i];
5449 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5450 VMXWriteVmcs64(uVmcsField, u64Val);
5451 }
5452
5453 /*
5454 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5455 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5456 */
5457 if (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL)
5458 {
5459 uint32_t const cShadowVmcsRoFields = pVM->hmr0.s.vmx.cShadowVmcsRoFields;
5460 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5461 {
5462 uint64_t u64Val;
5463 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsRoFields[i];
5464 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5465 VMXWriteVmcs64(uVmcsField, u64Val);
5466 }
5467 }
5468
5469 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5470 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5471 }
5472
5473 ASMSetFlags(fEFlags);
5474 return rc;
5475}
5476
5477
5478/**
5479 * Copies the shadow VMCS to the nested-guest VMCS.
5480 *
5481 * @returns VBox status code.
5482 * @param pVCpu The cross context virtual CPU structure.
5483 * @param pVmcsInfo The VMCS info. object.
5484 *
5485 * @remarks Called with interrupts disabled.
5486 */
5487static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5488{
5489 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5490 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5491 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5492
5493 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5494 if (RT_SUCCESS(rc))
5495 {
5496 /*
5497 * Copy guest read/write fields from the shadow VMCS.
5498 * Guest read-only fields cannot be modified, so no need to copy them.
5499 *
5500 * We don't check for VMREAD failures here for performance reasons and
5501 * because they are not expected to fail, barring irrecoverable conditions
5502 * like hardware errors.
5503 */
5504 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
5505 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5506 {
5507 uint64_t u64Val;
5508 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsFields[i];
5509 VMXReadVmcs64(uVmcsField, &u64Val);
5510 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5511 }
5512
5513 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5514 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5515 }
5516 return rc;
5517}
5518
5519
5520/**
5521 * Enables VMCS shadowing for the given VMCS info. object.
5522 *
5523 * @param pVmcsInfo The VMCS info. object.
5524 *
5525 * @remarks No-long-jump zone!!!
5526 */
5527static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5528{
5529 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5530 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5531 {
5532 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5533 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5534 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5535 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5536 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5537 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5538 Log4Func(("Enabled\n"));
5539 }
5540}
5541
5542
5543/**
5544 * Disables VMCS shadowing for the given VMCS info. object.
5545 *
5546 * @param pVmcsInfo The VMCS info. object.
5547 *
5548 * @remarks No-long-jump zone!!!
5549 */
5550static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5551{
5552 /*
5553 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5554 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5555 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5556 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5557 *
5558 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5559 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5560 */
5561 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5562 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5563 {
5564 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5565 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5566 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5567 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5568 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5569 Log4Func(("Disabled\n"));
5570 }
5571}
5572#endif
5573
5574
5575/**
5576 * Exports the guest hardware-virtualization state.
5577 *
5578 * @returns VBox status code.
5579 * @param pVCpu The cross context virtual CPU structure.
5580 * @param pVmxTransient The VMX-transient structure.
5581 *
5582 * @remarks No-long-jump zone!!!
5583 */
5584static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5585{
5586 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5587 {
5588#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5589 /*
5590 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5591 * VMCS shadowing.
5592 */
5593 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUseVmcsShadowing)
5594 {
5595 /*
5596 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5597 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5598 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5599 *
5600 * We check for VMX root mode here in case the guest executes VMXOFF without
5601 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5602 * not clear the current VMCS pointer.
5603 */
5604 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5605 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5606 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5607 && CPUMIsGuestVmxCurrentVmcsValid(&pVCpu->cpum.GstCtx))
5608 {
5609 /* Paranoia. */
5610 Assert(!pVmxTransient->fIsNestedGuest);
5611
5612 /*
5613 * For performance reasons, also check if the nested hypervisor's current VMCS
5614 * was newly loaded or modified before copying it to the shadow VMCS.
5615 */
5616 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5617 {
5618 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5619 AssertRCReturn(rc, rc);
5620 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5621 }
5622 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5623 }
5624 else
5625 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5626 }
5627#else
5628 NOREF(pVmxTransient);
5629#endif
5630 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5631 }
5632 return VINF_SUCCESS;
5633}
5634
5635
5636/**
5637 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5638 *
5639 * The guest FPU state is always pre-loaded hence we don't need to bother about
5640 * sharing FPU related CR0 bits between the guest and host.
5641 *
5642 * @returns VBox status code.
5643 * @param pVCpu The cross context virtual CPU structure.
5644 * @param pVmxTransient The VMX-transient structure.
5645 *
5646 * @remarks No-long-jump zone!!!
5647 */
5648static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5649{
5650 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5651 {
5652 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5653 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5654
5655 uint64_t fSetCr0 = g_HmMsrs.u.vmx.u64Cr0Fixed0;
5656 uint64_t const fZapCr0 = g_HmMsrs.u.vmx.u64Cr0Fixed1;
5657 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
5658 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5659 else
5660 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5661
5662 if (!pVmxTransient->fIsNestedGuest)
5663 {
5664 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5665 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5666 uint64_t const u64ShadowCr0 = u64GuestCr0;
5667 Assert(!RT_HI_U32(u64GuestCr0));
5668
5669 /*
5670 * Setup VT-x's view of the guest CR0.
5671 */
5672 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5673 if (pVM->hmr0.s.fNestedPaging)
5674 {
5675 if (CPUMIsGuestPagingEnabled(pVCpu))
5676 {
5677 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5678 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5679 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5680 }
5681 else
5682 {
5683 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5684 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5685 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5686 }
5687
5688 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5689 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
5690 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5691 }
5692 else
5693 {
5694 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5695 u64GuestCr0 |= X86_CR0_WP;
5696 }
5697
5698 /*
5699 * Guest FPU bits.
5700 *
5701 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5702 * using CR0.TS.
5703 *
5704 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5705 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5706 */
5707 u64GuestCr0 |= X86_CR0_NE;
5708
5709 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5710 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5711
5712 /*
5713 * Update exception intercepts.
5714 */
5715 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5716 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
5717 {
5718 Assert(PDMVmmDevHeapIsEnabled(pVM));
5719 Assert(pVM->hm.s.vmx.pRealModeTSS);
5720 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5721 }
5722 else
5723 {
5724 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5725 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5726 if (fInterceptMF)
5727 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5728 }
5729
5730 /* Additional intercepts for debugging, define these yourself explicitly. */
5731#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5732 uXcptBitmap |= 0
5733 | RT_BIT(X86_XCPT_BP)
5734 | RT_BIT(X86_XCPT_DE)
5735 | RT_BIT(X86_XCPT_NM)
5736 | RT_BIT(X86_XCPT_TS)
5737 | RT_BIT(X86_XCPT_UD)
5738 | RT_BIT(X86_XCPT_NP)
5739 | RT_BIT(X86_XCPT_SS)
5740 | RT_BIT(X86_XCPT_GP)
5741 | RT_BIT(X86_XCPT_PF)
5742 | RT_BIT(X86_XCPT_MF)
5743 ;
5744#elif defined(HMVMX_ALWAYS_TRAP_PF)
5745 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5746#endif
5747 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5748 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5749 Assert(pVM->hmr0.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5750
5751 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5752 u64GuestCr0 |= fSetCr0;
5753 u64GuestCr0 &= fZapCr0;
5754 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5755
5756 /* Commit the CR0 and related fields to the guest VMCS. */
5757 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5758 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5759 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5760 {
5761 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5762 AssertRC(rc);
5763 }
5764 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5765 {
5766 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5767 AssertRC(rc);
5768 }
5769
5770 /* Update our caches. */
5771 pVmcsInfo->u32ProcCtls = uProcCtls;
5772 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5773
5774 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5775 }
5776 else
5777 {
5778 /*
5779 * With nested-guests, we may have extended the guest/host mask here since we
5780 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5781 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5782 * originally supplied. We must copy those bits from the nested-guest CR0 into
5783 * the nested-guest CR0 read-shadow.
5784 */
5785 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5786 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5787 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(&pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5788 Assert(!RT_HI_U32(u64GuestCr0));
5789 Assert(u64GuestCr0 & X86_CR0_NE);
5790
5791 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5792 u64GuestCr0 |= fSetCr0;
5793 u64GuestCr0 &= fZapCr0;
5794 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5795
5796 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5797 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5798 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5799
5800 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5801 }
5802
5803 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5804 }
5805
5806 return VINF_SUCCESS;
5807}
5808
5809
5810/**
5811 * Exports the guest control registers (CR3, CR4) into the guest-state area
5812 * in the VMCS.
5813 *
5814 * @returns VBox strict status code.
5815 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5816 * without unrestricted guest access and the VMMDev is not presently
5817 * mapped (e.g. EFI32).
5818 *
5819 * @param pVCpu The cross context virtual CPU structure.
5820 * @param pVmxTransient The VMX-transient structure.
5821 *
5822 * @remarks No-long-jump zone!!!
5823 */
5824static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5825{
5826 int rc = VINF_SUCCESS;
5827 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5828
5829 /*
5830 * Guest CR2.
5831 * It's always loaded in the assembler code. Nothing to do here.
5832 */
5833
5834 /*
5835 * Guest CR3.
5836 */
5837 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5838 {
5839 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5840
5841 if (pVM->hmr0.s.fNestedPaging)
5842 {
5843 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5844 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5845
5846 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5847 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5848 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5849 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5850
5851 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5852 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5853 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5854
5855 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5856 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5857 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5858 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5859 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5860 || (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5861 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5862
5863 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5864 AssertRC(rc);
5865
5866 uint64_t u64GuestCr3;
5867 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5868 if ( pVM->hmr0.s.vmx.fUnrestrictedGuest
5869 || CPUMIsGuestPagingEnabledEx(pCtx))
5870 {
5871 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5872 if (CPUMIsGuestInPAEModeEx(pCtx))
5873 {
5874 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5875 AssertRC(rc);
5876 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5877 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5878 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5879 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5880 }
5881
5882 /*
5883 * The guest's view of its CR3 is unblemished with nested paging when the
5884 * guest is using paging or we have unrestricted guest execution to handle
5885 * the guest when it's not using paging.
5886 */
5887 u64GuestCr3 = pCtx->cr3;
5888 }
5889 else
5890 {
5891 /*
5892 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5893 * thinks it accesses physical memory directly, we use our identity-mapped
5894 * page table to map guest-linear to guest-physical addresses. EPT takes care
5895 * of translating it to host-physical addresses.
5896 */
5897 RTGCPHYS GCPhys;
5898 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5899
5900 /* We obtain it here every time as the guest could have relocated this PCI region. */
5901 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5902 if (RT_SUCCESS(rc))
5903 { /* likely */ }
5904 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5905 {
5906 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5907 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5908 }
5909 else
5910 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5911
5912 u64GuestCr3 = GCPhys;
5913 }
5914
5915 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5916 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5917 AssertRC(rc);
5918 }
5919 else
5920 {
5921 Assert(!pVmxTransient->fIsNestedGuest);
5922 /* Non-nested paging case, just use the hypervisor's CR3. */
5923 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5924
5925 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5926 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5927 AssertRC(rc);
5928 }
5929
5930 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5931 }
5932
5933 /*
5934 * Guest CR4.
5935 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5936 */
5937 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5938 {
5939 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5940 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5941
5942 uint64_t const fSetCr4 = g_HmMsrs.u.vmx.u64Cr4Fixed0;
5943 uint64_t const fZapCr4 = g_HmMsrs.u.vmx.u64Cr4Fixed1;
5944
5945 /*
5946 * With nested-guests, we may have extended the guest/host mask here (since we
5947 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5948 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5949 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5950 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5951 */
5952 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5953 uint64_t u64GuestCr4 = pCtx->cr4;
5954 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5955 ? pCtx->cr4
5956 : CPUMGetGuestVmxMaskedCr4(pCtx, pVmcsInfo->u64Cr4Mask);
5957 Assert(!RT_HI_U32(u64GuestCr4));
5958
5959 /*
5960 * Setup VT-x's view of the guest CR4.
5961 *
5962 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5963 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5964 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5965 *
5966 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5967 */
5968 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
5969 {
5970 Assert(pVM->hm.s.vmx.pRealModeTSS);
5971 Assert(PDMVmmDevHeapIsEnabled(pVM));
5972 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5973 }
5974
5975 if (pVM->hmr0.s.fNestedPaging)
5976 {
5977 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5978 && !pVM->hmr0.s.vmx.fUnrestrictedGuest)
5979 {
5980 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5981 u64GuestCr4 |= X86_CR4_PSE;
5982 /* Our identity mapping is a 32-bit page directory. */
5983 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5984 }
5985 /* else use guest CR4.*/
5986 }
5987 else
5988 {
5989 Assert(!pVmxTransient->fIsNestedGuest);
5990
5991 /*
5992 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5993 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5994 */
5995 switch (pVCpu->hm.s.enmShadowMode)
5996 {
5997 case PGMMODE_REAL: /* Real-mode. */
5998 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5999 case PGMMODE_32_BIT: /* 32-bit paging. */
6000 {
6001 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
6002 break;
6003 }
6004
6005 case PGMMODE_PAE: /* PAE paging. */
6006 case PGMMODE_PAE_NX: /* PAE paging with NX. */
6007 {
6008 u64GuestCr4 |= X86_CR4_PAE;
6009 break;
6010 }
6011
6012 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
6013 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
6014 {
6015#ifdef VBOX_WITH_64_BITS_GUESTS
6016 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
6017 Assert(u64GuestCr4 & X86_CR4_PAE);
6018 break;
6019#endif
6020 }
6021 default:
6022 AssertFailed();
6023 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6024 }
6025 }
6026
6027 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
6028 u64GuestCr4 |= fSetCr4;
6029 u64GuestCr4 &= fZapCr4;
6030
6031 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
6032 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
6033 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
6034
6035 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
6036 bool const fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
6037 if (fLoadSaveGuestXcr0 != pVCpu->hmr0.s.fLoadSaveGuestXcr0)
6038 {
6039 pVCpu->hmr0.s.fLoadSaveGuestXcr0 = fLoadSaveGuestXcr0;
6040 hmR0VmxUpdateStartVmFunction(pVCpu);
6041 }
6042
6043 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
6044
6045 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
6046 }
6047 return rc;
6048}
6049
6050
6051/**
6052 * Exports the guest debug registers into the guest-state area in the VMCS.
6053 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
6054 *
6055 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
6056 *
6057 * @returns VBox status code.
6058 * @param pVCpu The cross context virtual CPU structure.
6059 * @param pVmxTransient The VMX-transient structure.
6060 *
6061 * @remarks No-long-jump zone!!!
6062 */
6063static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6064{
6065 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
6066
6067 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
6068 * stepping. */
6069 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6070 if (pVmxTransient->fIsNestedGuest)
6071 {
6072 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
6073 AssertRC(rc);
6074
6075 /* Always intercept Mov DRx accesses for the nested-guest for now. */
6076 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6077 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
6078 AssertRC(rc);
6079 return VINF_SUCCESS;
6080 }
6081
6082#ifdef VBOX_STRICT
6083 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
6084 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
6085 {
6086 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
6087 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
6088 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
6089 }
6090#endif
6091
6092 bool fSteppingDB = false;
6093 bool fInterceptMovDRx = false;
6094 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6095 if (pVCpu->hm.s.fSingleInstruction)
6096 {
6097 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
6098 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
6099 {
6100 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
6101 Assert(fSteppingDB == false);
6102 }
6103 else
6104 {
6105 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
6106 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
6107 pVCpu->hmr0.s.fClearTrapFlag = true;
6108 fSteppingDB = true;
6109 }
6110 }
6111
6112 uint64_t u64GuestDr7;
6113 if ( fSteppingDB
6114 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
6115 {
6116 /*
6117 * Use the combined guest and host DRx values found in the hypervisor register set
6118 * because the hypervisor debugger has breakpoints active or someone is single stepping
6119 * on the host side without a monitor trap flag.
6120 *
6121 * Note! DBGF expects a clean DR6 state before executing guest code.
6122 */
6123 if (!CPUMIsHyperDebugStateActive(pVCpu))
6124 {
6125 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6126 Assert(CPUMIsHyperDebugStateActive(pVCpu));
6127 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
6128 }
6129
6130 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6131 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
6132 pVCpu->hmr0.s.fUsingHyperDR7 = true;
6133 fInterceptMovDRx = true;
6134 }
6135 else
6136 {
6137 /*
6138 * If the guest has enabled debug registers, we need to load them prior to
6139 * executing guest code so they'll trigger at the right time.
6140 */
6141 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
6142 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6143 {
6144 if (!CPUMIsGuestDebugStateActive(pVCpu))
6145 {
6146 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6147 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6148 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6149 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6150 }
6151 Assert(!fInterceptMovDRx);
6152 }
6153 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6154 {
6155 /*
6156 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6157 * must intercept #DB in order to maintain a correct DR6 guest value, and
6158 * because we need to intercept it to prevent nested #DBs from hanging the
6159 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6160 */
6161 fInterceptMovDRx = true;
6162 }
6163
6164 /* Update DR7 with the actual guest value. */
6165 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6166 pVCpu->hmr0.s.fUsingHyperDR7 = false;
6167 }
6168
6169 if (fInterceptMovDRx)
6170 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6171 else
6172 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6173
6174 /*
6175 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6176 * monitor-trap flag and update our cache.
6177 */
6178 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6179 {
6180 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6181 AssertRC(rc);
6182 pVmcsInfo->u32ProcCtls = uProcCtls;
6183 }
6184
6185 /*
6186 * Update guest DR7.
6187 */
6188 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
6189 AssertRC(rc);
6190
6191 /*
6192 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6193 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6194 *
6195 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6196 */
6197 if (fSteppingDB)
6198 {
6199 Assert(pVCpu->hm.s.fSingleInstruction);
6200 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6201
6202 uint32_t fIntrState = 0;
6203 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6204 AssertRC(rc);
6205
6206 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6207 {
6208 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6209 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6210 AssertRC(rc);
6211 }
6212 }
6213
6214 return VINF_SUCCESS;
6215}
6216
6217
6218#ifdef VBOX_STRICT
6219/**
6220 * Strict function to validate segment registers.
6221 *
6222 * @param pVCpu The cross context virtual CPU structure.
6223 * @param pVmcsInfo The VMCS info. object.
6224 *
6225 * @remarks Will import guest CR0 on strict builds during validation of
6226 * segments.
6227 */
6228static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
6229{
6230 /*
6231 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6232 *
6233 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6234 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6235 * unusable bit and doesn't change the guest-context value.
6236 */
6237 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6238 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6239 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6240 if ( !pVM->hmr0.s.vmx.fUnrestrictedGuest
6241 && ( !CPUMIsGuestInRealModeEx(pCtx)
6242 && !CPUMIsGuestInV86ModeEx(pCtx)))
6243 {
6244 /* Protected mode checks */
6245 /* CS */
6246 Assert(pCtx->cs.Attr.n.u1Present);
6247 Assert(!(pCtx->cs.Attr.u & 0xf00));
6248 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6249 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6250 || !(pCtx->cs.Attr.n.u1Granularity));
6251 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6252 || (pCtx->cs.Attr.n.u1Granularity));
6253 /* CS cannot be loaded with NULL in protected mode. */
6254 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6255 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6256 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6257 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6258 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6259 else
6260 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6261 /* SS */
6262 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6263 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6264 if ( !(pCtx->cr0 & X86_CR0_PE)
6265 || pCtx->cs.Attr.n.u4Type == 3)
6266 {
6267 Assert(!pCtx->ss.Attr.n.u2Dpl);
6268 }
6269 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6270 {
6271 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6272 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6273 Assert(pCtx->ss.Attr.n.u1Present);
6274 Assert(!(pCtx->ss.Attr.u & 0xf00));
6275 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6276 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6277 || !(pCtx->ss.Attr.n.u1Granularity));
6278 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6279 || (pCtx->ss.Attr.n.u1Granularity));
6280 }
6281 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6282 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6283 {
6284 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6285 Assert(pCtx->ds.Attr.n.u1Present);
6286 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6287 Assert(!(pCtx->ds.Attr.u & 0xf00));
6288 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6289 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6290 || !(pCtx->ds.Attr.n.u1Granularity));
6291 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6292 || (pCtx->ds.Attr.n.u1Granularity));
6293 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6294 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6295 }
6296 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6297 {
6298 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6299 Assert(pCtx->es.Attr.n.u1Present);
6300 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6301 Assert(!(pCtx->es.Attr.u & 0xf00));
6302 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6303 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6304 || !(pCtx->es.Attr.n.u1Granularity));
6305 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6306 || (pCtx->es.Attr.n.u1Granularity));
6307 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6308 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6309 }
6310 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6311 {
6312 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6313 Assert(pCtx->fs.Attr.n.u1Present);
6314 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6315 Assert(!(pCtx->fs.Attr.u & 0xf00));
6316 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6317 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6318 || !(pCtx->fs.Attr.n.u1Granularity));
6319 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6320 || (pCtx->fs.Attr.n.u1Granularity));
6321 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6322 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6323 }
6324 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6325 {
6326 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6327 Assert(pCtx->gs.Attr.n.u1Present);
6328 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6329 Assert(!(pCtx->gs.Attr.u & 0xf00));
6330 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6331 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6332 || !(pCtx->gs.Attr.n.u1Granularity));
6333 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6334 || (pCtx->gs.Attr.n.u1Granularity));
6335 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6336 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6337 }
6338 /* 64-bit capable CPUs. */
6339 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6340 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6341 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6342 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6343 }
6344 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6345 || ( CPUMIsGuestInRealModeEx(pCtx)
6346 && !pVM->hmr0.s.vmx.fUnrestrictedGuest))
6347 {
6348 /* Real and v86 mode checks. */
6349 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6350 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6351 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
6352 {
6353 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6354 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6355 }
6356 else
6357 {
6358 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6359 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6360 }
6361
6362 /* CS */
6363 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6364 Assert(pCtx->cs.u32Limit == 0xffff);
6365 Assert(u32CSAttr == 0xf3);
6366 /* SS */
6367 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6368 Assert(pCtx->ss.u32Limit == 0xffff);
6369 Assert(u32SSAttr == 0xf3);
6370 /* DS */
6371 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6372 Assert(pCtx->ds.u32Limit == 0xffff);
6373 Assert(u32DSAttr == 0xf3);
6374 /* ES */
6375 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6376 Assert(pCtx->es.u32Limit == 0xffff);
6377 Assert(u32ESAttr == 0xf3);
6378 /* FS */
6379 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6380 Assert(pCtx->fs.u32Limit == 0xffff);
6381 Assert(u32FSAttr == 0xf3);
6382 /* GS */
6383 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6384 Assert(pCtx->gs.u32Limit == 0xffff);
6385 Assert(u32GSAttr == 0xf3);
6386 /* 64-bit capable CPUs. */
6387 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6388 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6389 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6390 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6391 }
6392}
6393#endif /* VBOX_STRICT */
6394
6395
6396/**
6397 * Exports a guest segment register into the guest-state area in the VMCS.
6398 *
6399 * @returns VBox status code.
6400 * @param pVCpu The cross context virtual CPU structure.
6401 * @param pVmcsInfo The VMCS info. object.
6402 * @param iSegReg The segment register number (X86_SREG_XXX).
6403 * @param pSelReg Pointer to the segment selector.
6404 *
6405 * @remarks No-long-jump zone!!!
6406 */
6407static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint32_t iSegReg, PCCPUMSELREG pSelReg)
6408{
6409 Assert(iSegReg < X86_SREG_COUNT);
6410
6411 uint32_t u32Access = pSelReg->Attr.u;
6412 if (!pVmcsInfo->pShared->RealMode.fRealOnV86Active)
6413 {
6414 /*
6415 * The way to differentiate between whether this is really a null selector or was just
6416 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6417 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6418 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6419 * NULL selectors loaded in protected-mode have their attribute as 0.
6420 */
6421 if (u32Access)
6422 { }
6423 else
6424 u32Access = X86DESCATTR_UNUSABLE;
6425 }
6426 else
6427 {
6428 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6429 u32Access = 0xf3;
6430 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6431 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6432 RT_NOREF_PV(pVCpu);
6433 }
6434
6435 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6436 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6437 ("Access bit not set for usable segment. %.2s sel=%#x attr %#x\n", "ESCSSSDSFSGS" + iSegReg * 2, pSelReg, pSelReg->Attr.u));
6438
6439 /*
6440 * Commit it to the VMCS.
6441 */
6442 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]);
6443 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]);
6444 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
6445 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]);
6446 int rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), pSelReg->Sel); AssertRC(rc);
6447 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), pSelReg->u32Limit); AssertRC(rc);
6448 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), pSelReg->u64Base); AssertRC(rc);
6449 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), u32Access); AssertRC(rc);
6450 return VINF_SUCCESS;
6451}
6452
6453
6454/**
6455 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6456 * area in the VMCS.
6457 *
6458 * @returns VBox status code.
6459 * @param pVCpu The cross context virtual CPU structure.
6460 * @param pVmxTransient The VMX-transient structure.
6461 *
6462 * @remarks Will import guest CR0 on strict builds during validation of
6463 * segments.
6464 * @remarks No-long-jump zone!!!
6465 */
6466static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6467{
6468 int rc = VERR_INTERNAL_ERROR_5;
6469 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6470 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6471 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6472 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
6473
6474 /*
6475 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6476 */
6477 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6478 {
6479 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6480 {
6481 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6482 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6483 pVmcsInfoShared->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6484 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6485 AssertRC(rc);
6486 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6487 }
6488
6489 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6490 {
6491 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6492 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6493 pVmcsInfoShared->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6494 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6495 AssertRC(rc);
6496 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6497 }
6498
6499 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6500 {
6501 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6502 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6503 pVmcsInfoShared->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6504 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6505 AssertRC(rc);
6506 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6507 }
6508
6509 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6510 {
6511 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6512 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6513 pVmcsInfoShared->RealMode.AttrES.u = pCtx->es.Attr.u;
6514 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6515 AssertRC(rc);
6516 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6517 }
6518
6519 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6520 {
6521 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6522 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6523 pVmcsInfoShared->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6524 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6525 AssertRC(rc);
6526 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6527 }
6528
6529 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6530 {
6531 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6532 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6533 pVmcsInfoShared->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6534 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6535 AssertRC(rc);
6536 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6537 }
6538
6539#ifdef VBOX_STRICT
6540 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6541#endif
6542 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6543 pCtx->cs.Attr.u));
6544 }
6545
6546 /*
6547 * Guest TR.
6548 */
6549 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6550 {
6551 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6552
6553 /*
6554 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6555 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6556 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6557 */
6558 uint16_t u16Sel;
6559 uint32_t u32Limit;
6560 uint64_t u64Base;
6561 uint32_t u32AccessRights;
6562 if (!pVmcsInfoShared->RealMode.fRealOnV86Active)
6563 {
6564 u16Sel = pCtx->tr.Sel;
6565 u32Limit = pCtx->tr.u32Limit;
6566 u64Base = pCtx->tr.u64Base;
6567 u32AccessRights = pCtx->tr.Attr.u;
6568 }
6569 else
6570 {
6571 Assert(!pVmxTransient->fIsNestedGuest);
6572 Assert(pVM->hm.s.vmx.pRealModeTSS);
6573 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6574
6575 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6576 RTGCPHYS GCPhys;
6577 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6578 AssertRCReturn(rc, rc);
6579
6580 X86DESCATTR DescAttr;
6581 DescAttr.u = 0;
6582 DescAttr.n.u1Present = 1;
6583 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6584
6585 u16Sel = 0;
6586 u32Limit = HM_VTX_TSS_SIZE;
6587 u64Base = GCPhys;
6588 u32AccessRights = DescAttr.u;
6589 }
6590
6591 /* Validate. */
6592 Assert(!(u16Sel & RT_BIT(2)));
6593 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6594 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6595 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6596 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6597 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6598 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6599 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6600 Assert( (u32Limit & 0xfff) == 0xfff
6601 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6602 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6603 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6604
6605 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6606 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6607 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6608 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6609
6610 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6611 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6612 }
6613
6614 /*
6615 * Guest GDTR.
6616 */
6617 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6618 {
6619 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6620
6621 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6622 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6623
6624 /* Validate. */
6625 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6626
6627 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6628 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6629 }
6630
6631 /*
6632 * Guest LDTR.
6633 */
6634 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6635 {
6636 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6637
6638 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6639 uint32_t u32Access;
6640 if ( !pVmxTransient->fIsNestedGuest
6641 && !pCtx->ldtr.Attr.u)
6642 u32Access = X86DESCATTR_UNUSABLE;
6643 else
6644 u32Access = pCtx->ldtr.Attr.u;
6645
6646 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6647 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6648 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6649 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6650
6651 /* Validate. */
6652 if (!(u32Access & X86DESCATTR_UNUSABLE))
6653 {
6654 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6655 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6656 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6657 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6658 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6659 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6660 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6661 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6662 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6663 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6664 }
6665
6666 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6667 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6668 }
6669
6670 /*
6671 * Guest IDTR.
6672 */
6673 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6674 {
6675 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6676
6677 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6678 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6679
6680 /* Validate. */
6681 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6682
6683 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6684 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6685 }
6686
6687 return VINF_SUCCESS;
6688}
6689
6690
6691/**
6692 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6693 * areas.
6694 *
6695 * These MSRs will automatically be loaded to the host CPU on every successful
6696 * VM-entry and stored from the host CPU on every successful VM-exit.
6697 *
6698 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6699 * actual host MSR values are not- updated here for performance reasons. See
6700 * hmR0VmxExportHostMsrs().
6701 *
6702 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6703 *
6704 * @returns VBox status code.
6705 * @param pVCpu The cross context virtual CPU structure.
6706 * @param pVmxTransient The VMX-transient structure.
6707 *
6708 * @remarks No-long-jump zone!!!
6709 */
6710static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6711{
6712 AssertPtr(pVCpu);
6713 AssertPtr(pVmxTransient);
6714
6715 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6716 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6717
6718 /*
6719 * MSRs that we use the auto-load/store MSR area in the VMCS.
6720 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6721 * nothing to do here. The host MSR values are updated when it's safe in
6722 * hmR0VmxLazySaveHostMsrs().
6723 *
6724 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6725 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6726 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6727 * for any MSR that are not part of the lazy MSRs so we do not need to place
6728 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6729 */
6730 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6731 {
6732 /* No auto-load/store MSRs currently. */
6733 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6734 }
6735
6736 /*
6737 * Guest Sysenter MSRs.
6738 */
6739 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6740 {
6741 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6742
6743 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6744 {
6745 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6746 AssertRC(rc);
6747 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6748 }
6749
6750 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6751 {
6752 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6753 AssertRC(rc);
6754 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6755 }
6756
6757 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6758 {
6759 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6760 AssertRC(rc);
6761 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6762 }
6763 }
6764
6765 /*
6766 * Guest/host EFER MSR.
6767 */
6768 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6769 {
6770 /* Whether we are using the VMCS to swap the EFER MSR must have been
6771 determined earlier while exporting VM-entry/VM-exit controls. */
6772 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6773 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6774
6775 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6776 {
6777 /*
6778 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6779 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6780 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6781 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6782 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6783 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6784 * during VM-entry.
6785 */
6786 uint64_t uGuestEferMsr = pCtx->msrEFER;
6787 if (!pVM->hmr0.s.vmx.fUnrestrictedGuest)
6788 {
6789 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6790 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6791 else
6792 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6793 }
6794
6795 /*
6796 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6797 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6798 */
6799 if (g_fHmVmxSupportsVmcsEfer)
6800 {
6801 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6802 AssertRC(rc);
6803 }
6804 else
6805 {
6806 /*
6807 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6808 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6809 */
6810 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6811 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6812 AssertRCReturn(rc, rc);
6813 }
6814
6815 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6816 }
6817 else if (!g_fHmVmxSupportsVmcsEfer)
6818 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6819
6820 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6821 }
6822
6823 /*
6824 * Other MSRs.
6825 */
6826 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6827 {
6828 /* Speculation Control (R/W). */
6829 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6830 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6831 {
6832 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6833 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6834 AssertRCReturn(rc, rc);
6835 }
6836
6837 /* Last Branch Record. */
6838 if (pVM->hmr0.s.vmx.fLbr)
6839 {
6840 PVMXVMCSINFOSHARED const pVmcsInfoShared = pVmxTransient->pVmcsInfo->pShared;
6841 uint32_t const idFromIpMsrStart = pVM->hmr0.s.vmx.idLbrFromIpMsrFirst;
6842 uint32_t const idToIpMsrStart = pVM->hmr0.s.vmx.idLbrToIpMsrFirst;
6843 uint32_t const cLbrStack = pVM->hmr0.s.vmx.idLbrFromIpMsrLast - pVM->hmr0.s.vmx.idLbrFromIpMsrFirst + 1;
6844 Assert(cLbrStack <= 32);
6845 for (uint32_t i = 0; i < cLbrStack; i++)
6846 {
6847 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idFromIpMsrStart + i,
6848 pVmcsInfoShared->au64LbrFromIpMsr[i],
6849 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6850 AssertRCReturn(rc, rc);
6851
6852 /* Some CPUs don't have a Branch-To-IP MSR (P4 and related Xeons). */
6853 if (idToIpMsrStart != 0)
6854 {
6855 rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idToIpMsrStart + i,
6856 pVmcsInfoShared->au64LbrToIpMsr[i],
6857 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6858 AssertRCReturn(rc, rc);
6859 }
6860 }
6861
6862 /* Add LBR top-of-stack MSR (which contains the index to the most recent record). */
6863 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, pVM->hmr0.s.vmx.idLbrTosMsr,
6864 pVmcsInfoShared->u64LbrTosMsr, false /* fSetReadWrite */,
6865 false /* fUpdateHostMsr */);
6866 AssertRCReturn(rc, rc);
6867 }
6868
6869 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6870 }
6871
6872 return VINF_SUCCESS;
6873}
6874
6875
6876/**
6877 * Wrapper for running the guest code in VT-x.
6878 *
6879 * @returns VBox status code, no informational status codes.
6880 * @param pVCpu The cross context virtual CPU structure.
6881 * @param pVmxTransient The VMX-transient structure.
6882 *
6883 * @remarks No-long-jump zone!!!
6884 */
6885DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6886{
6887 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6888 pVCpu->cpum.GstCtx.fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6889
6890 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6891 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6892#ifdef VBOX_WITH_STATISTICS
6893 if (fResumeVM)
6894 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxVmResume);
6895 else
6896 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxVmLaunch);
6897#endif
6898 int rc = pVCpu->hmr0.s.vmx.pfnStartVm(pVmcsInfo, pVCpu, fResumeVM);
6899 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6900 return rc;
6901}
6902
6903
6904/**
6905 * Reports world-switch error and dumps some useful debug info.
6906 *
6907 * @param pVCpu The cross context virtual CPU structure.
6908 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6909 * @param pVmxTransient The VMX-transient structure (only
6910 * exitReason updated).
6911 */
6912static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6913{
6914 Assert(pVCpu);
6915 Assert(pVmxTransient);
6916 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6917
6918 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6919 switch (rcVMRun)
6920 {
6921 case VERR_VMX_INVALID_VMXON_PTR:
6922 AssertFailed();
6923 break;
6924 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6925 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6926 {
6927 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6928 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6929 AssertRC(rc);
6930 hmR0VmxReadExitQualVmcs(pVmxTransient);
6931
6932 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hmr0.s.idEnteredCpu;
6933 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6934 Cannot do it here as we may have been long preempted. */
6935
6936#ifdef VBOX_STRICT
6937 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6938 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6939 pVmxTransient->uExitReason));
6940 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6941 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6942 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6943 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6944 else
6945 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6946 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6947 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6948
6949 static struct
6950 {
6951 /** Name of the field to log. */
6952 const char *pszName;
6953 /** The VMCS field. */
6954 uint32_t uVmcsField;
6955 /** Whether host support of this field needs to be checked. */
6956 bool fCheckSupport;
6957 } const s_aVmcsFields[] =
6958 {
6959 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6960 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6961 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6962 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6963 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6964 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6965 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6966 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6967 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6968 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6969 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6970 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6971 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6972 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6973 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6974 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6975 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6976 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6977 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6978 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6979 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6980 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6981 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6982 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6983 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6984 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6985 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6986 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6987 /* The order of selector fields below are fixed! */
6988 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6989 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6990 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6991 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6992 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6993 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6994 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6995 /* End of ordered selector fields. */
6996 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6997 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6998 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6999 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
7000 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
7001 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
7002 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
7003 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
7004 };
7005
7006 RTGDTR HostGdtr;
7007 ASMGetGDTR(&HostGdtr);
7008
7009 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
7010 for (uint32_t i = 0; i < cVmcsFields; i++)
7011 {
7012 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
7013
7014 bool fSupported;
7015 if (!s_aVmcsFields[i].fCheckSupport)
7016 fSupported = true;
7017 else
7018 {
7019 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7020 switch (uVmcsField)
7021 {
7022 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hmr0.s.fNestedPaging; break;
7023 case VMX_VMCS16_VPID: fSupported = pVM->hmr0.s.vmx.fVpid; break;
7024 case VMX_VMCS32_CTRL_PROC_EXEC2:
7025 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
7026 break;
7027 default:
7028 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
7029 }
7030 }
7031
7032 if (fSupported)
7033 {
7034 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
7035 switch (uWidth)
7036 {
7037 case VMX_VMCSFIELD_WIDTH_16BIT:
7038 {
7039 uint16_t u16Val;
7040 rc = VMXReadVmcs16(uVmcsField, &u16Val);
7041 AssertRC(rc);
7042 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
7043
7044 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
7045 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
7046 {
7047 if (u16Val < HostGdtr.cbGdt)
7048 {
7049 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
7050 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
7051 "Host FS", "Host GS", "Host TR" };
7052 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
7053 Assert(idxSel < RT_ELEMENTS(s_apszSel));
7054 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
7055 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
7056 }
7057 else
7058 Log4((" Selector value exceeds GDT limit!\n"));
7059 }
7060 break;
7061 }
7062
7063 case VMX_VMCSFIELD_WIDTH_32BIT:
7064 {
7065 uint32_t u32Val;
7066 rc = VMXReadVmcs32(uVmcsField, &u32Val);
7067 AssertRC(rc);
7068 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
7069 break;
7070 }
7071
7072 case VMX_VMCSFIELD_WIDTH_64BIT:
7073 case VMX_VMCSFIELD_WIDTH_NATURAL:
7074 {
7075 uint64_t u64Val;
7076 rc = VMXReadVmcs64(uVmcsField, &u64Val);
7077 AssertRC(rc);
7078 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
7079 break;
7080 }
7081 }
7082 }
7083 }
7084
7085 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
7086 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
7087 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
7088 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
7089 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
7090 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
7091#endif /* VBOX_STRICT */
7092 break;
7093 }
7094
7095 default:
7096 /* Impossible */
7097 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
7098 break;
7099 }
7100}
7101
7102
7103/**
7104 * Sets up the usage of TSC-offsetting and updates the VMCS.
7105 *
7106 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
7107 * VMX-preemption timer.
7108 *
7109 * @returns VBox status code.
7110 * @param pVCpu The cross context virtual CPU structure.
7111 * @param pVmxTransient The VMX-transient structure.
7112 *
7113 * @remarks No-long-jump zone!!!
7114 */
7115static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
7116{
7117 bool fOffsettedTsc;
7118 bool fParavirtTsc;
7119 uint64_t uTscOffset;
7120 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7121 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7122
7123 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
7124 {
7125 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
7126
7127 /* Make sure the returned values have sane upper and lower boundaries. */
7128 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7129 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
7130 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
7131 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7132
7133 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7134 * preemption timers here. We probably need to clamp the preemption timer,
7135 * after converting the timer value to the host. */
7136 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7137 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7138 AssertRC(rc);
7139 }
7140 else
7141 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7142
7143 if (fParavirtTsc)
7144 {
7145 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7146 information before every VM-entry, hence disable it for performance sake. */
7147#if 0
7148 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7149 AssertRC(rc);
7150#endif
7151 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7152 }
7153
7154 if ( fOffsettedTsc
7155 && RT_LIKELY(!pVCpu->hmr0.s.fDebugWantRdTscExit))
7156 {
7157 if (pVmxTransient->fIsNestedGuest)
7158 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7159 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
7160 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7161 }
7162 else
7163 {
7164 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7165 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7166 }
7167}
7168
7169
7170/**
7171 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7172 * VM-exit interruption info type.
7173 *
7174 * @returns The IEM exception flags.
7175 * @param uVector The event vector.
7176 * @param uVmxEventType The VMX event type.
7177 *
7178 * @remarks This function currently only constructs flags required for
7179 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7180 * and CR2 aspects of an exception are not included).
7181 */
7182static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7183{
7184 uint32_t fIemXcptFlags;
7185 switch (uVmxEventType)
7186 {
7187 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7188 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7189 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7190 break;
7191
7192 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7193 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7194 break;
7195
7196 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7197 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7198 break;
7199
7200 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7201 {
7202 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7203 if (uVector == X86_XCPT_BP)
7204 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7205 else if (uVector == X86_XCPT_OF)
7206 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7207 else
7208 {
7209 fIemXcptFlags = 0;
7210 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7211 }
7212 break;
7213 }
7214
7215 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7216 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7217 break;
7218
7219 default:
7220 fIemXcptFlags = 0;
7221 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7222 break;
7223 }
7224 return fIemXcptFlags;
7225}
7226
7227
7228/**
7229 * Sets an event as a pending event to be injected into the guest.
7230 *
7231 * @param pVCpu The cross context virtual CPU structure.
7232 * @param u32IntInfo The VM-entry interruption-information field.
7233 * @param cbInstr The VM-entry instruction length in bytes (for
7234 * software interrupts, exceptions and privileged
7235 * software exceptions).
7236 * @param u32ErrCode The VM-entry exception error code.
7237 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7238 * page-fault.
7239 */
7240DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7241 RTGCUINTPTR GCPtrFaultAddress)
7242{
7243 Assert(!pVCpu->hm.s.Event.fPending);
7244 pVCpu->hm.s.Event.fPending = true;
7245 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7246 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7247 pVCpu->hm.s.Event.cbInstr = cbInstr;
7248 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7249}
7250
7251
7252/**
7253 * Sets an external interrupt as pending-for-injection into the VM.
7254 *
7255 * @param pVCpu The cross context virtual CPU structure.
7256 * @param u8Interrupt The external interrupt vector.
7257 */
7258DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
7259{
7260 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7261 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7262 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7263 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7264 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7265}
7266
7267
7268/**
7269 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7270 *
7271 * @param pVCpu The cross context virtual CPU structure.
7272 */
7273DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
7274{
7275 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7276 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7277 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7278 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7279 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7280}
7281
7282
7283/**
7284 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7285 *
7286 * @param pVCpu The cross context virtual CPU structure.
7287 */
7288DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
7289{
7290 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7291 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7292 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7293 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7294 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7295}
7296
7297
7298/**
7299 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7300 *
7301 * @param pVCpu The cross context virtual CPU structure.
7302 */
7303DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
7304{
7305 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7306 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7307 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7308 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7309 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7310}
7311
7312
7313/**
7314 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7315 *
7316 * @param pVCpu The cross context virtual CPU structure.
7317 */
7318DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
7319{
7320 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7321 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7322 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7323 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7324 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7325}
7326
7327
7328#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7329/**
7330 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7331 *
7332 * @param pVCpu The cross context virtual CPU structure.
7333 * @param u32ErrCode The error code for the general-protection exception.
7334 */
7335DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7336{
7337 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7338 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7339 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7340 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7341 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7342}
7343
7344
7345/**
7346 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7347 *
7348 * @param pVCpu The cross context virtual CPU structure.
7349 * @param u32ErrCode The error code for the stack exception.
7350 */
7351DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7352{
7353 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7354 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7355 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7356 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7357 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7358}
7359#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7360
7361
7362/**
7363 * Fixes up attributes for the specified segment register.
7364 *
7365 * @param pVCpu The cross context virtual CPU structure.
7366 * @param pSelReg The segment register that needs fixing.
7367 * @param pszRegName The register name (for logging and assertions).
7368 */
7369static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, const char *pszRegName)
7370{
7371 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7372
7373 /*
7374 * If VT-x marks the segment as unusable, most other bits remain undefined:
7375 * - For CS the L, D and G bits have meaning.
7376 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7377 * - For the remaining data segments no bits are defined.
7378 *
7379 * The present bit and the unusable bit has been observed to be set at the
7380 * same time (the selector was supposed to be invalid as we started executing
7381 * a V8086 interrupt in ring-0).
7382 *
7383 * What should be important for the rest of the VBox code, is that the P bit is
7384 * cleared. Some of the other VBox code recognizes the unusable bit, but
7385 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7386 * safe side here, we'll strip off P and other bits we don't care about. If
7387 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7388 *
7389 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7390 */
7391#ifdef VBOX_STRICT
7392 uint32_t const uAttr = pSelReg->Attr.u;
7393#endif
7394
7395 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7396 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7397 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7398
7399#ifdef VBOX_STRICT
7400 VMMRZCallRing3Disable(pVCpu);
7401 Log4Func(("Unusable %s: sel=%#x attr=%#x -> %#x\n", pszRegName, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7402# ifdef DEBUG_bird
7403 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7404 ("%s: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7405 pszRegName, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7406# endif
7407 VMMRZCallRing3Enable(pVCpu);
7408 NOREF(uAttr);
7409#endif
7410 RT_NOREF2(pVCpu, pszRegName);
7411}
7412
7413
7414/**
7415 * Imports a guest segment register from the current VMCS into the guest-CPU
7416 * context.
7417 *
7418 * @param pVCpu The cross context virtual CPU structure.
7419 * @param iSegReg The segment register number (X86_SREG_XXX).
7420 *
7421 * @remarks Called with interrupts and/or preemption disabled.
7422 */
7423static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint32_t iSegReg)
7424{
7425 Assert(iSegReg < X86_SREG_COUNT);
7426 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]);
7427 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]);
7428 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
7429 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]);
7430
7431 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7432
7433 uint16_t u16Sel;
7434 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), &u16Sel); AssertRC(rc);
7435 pSelReg->Sel = u16Sel;
7436 pSelReg->ValidSel = u16Sel;
7437
7438 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), &pSelReg->u32Limit); AssertRC(rc);
7439 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), &pSelReg->u64Base); AssertRC(rc);
7440
7441 uint32_t u32Attr;
7442 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), &u32Attr); AssertRC(rc);
7443 pSelReg->Attr.u = u32Attr;
7444 if (u32Attr & X86DESCATTR_UNUSABLE)
7445 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, "ES\0CS\0SS\0DS\0FS\0GS" + iSegReg * 3);
7446
7447 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7448}
7449
7450
7451/**
7452 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7453 *
7454 * @param pVCpu The cross context virtual CPU structure.
7455 *
7456 * @remarks Called with interrupts and/or preemption disabled.
7457 */
7458static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7459{
7460 uint16_t u16Sel;
7461 uint64_t u64Base;
7462 uint32_t u32Limit, u32Attr;
7463 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7464 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7465 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7466 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7467
7468 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7469 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7470 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7471 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7472 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7473 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7474 if (u32Attr & X86DESCATTR_UNUSABLE)
7475 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, "LDTR");
7476}
7477
7478
7479/**
7480 * Imports the guest TR from the current VMCS into the guest-CPU context.
7481 *
7482 * @param pVCpu The cross context virtual CPU structure.
7483 *
7484 * @remarks Called with interrupts and/or preemption disabled.
7485 */
7486static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7487{
7488 uint16_t u16Sel;
7489 uint64_t u64Base;
7490 uint32_t u32Limit, u32Attr;
7491 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7492 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7493 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7494 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7495
7496 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7497 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7498 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7499 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7500 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7501 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7502 /* TR is the only selector that can never be unusable. */
7503 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7504}
7505
7506
7507/**
7508 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7509 *
7510 * @param pVCpu The cross context virtual CPU structure.
7511 *
7512 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7513 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7514 * instead!!!
7515 */
7516static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7517{
7518 uint64_t u64Val;
7519 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7520 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7521 {
7522 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7523 AssertRC(rc);
7524
7525 pCtx->rip = u64Val;
7526 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7527 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7528 }
7529}
7530
7531
7532/**
7533 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7534 *
7535 * @param pVCpu The cross context virtual CPU structure.
7536 * @param pVmcsInfo The VMCS info. object.
7537 *
7538 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7539 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7540 * instead!!!
7541 */
7542static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7543{
7544 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7545 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7546 {
7547 uint64_t u64Val;
7548 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7549 AssertRC(rc);
7550
7551 pCtx->rflags.u64 = u64Val;
7552 PCVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7553 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
7554 {
7555 pCtx->eflags.Bits.u1VM = 0;
7556 pCtx->eflags.Bits.u2IOPL = pVmcsInfoShared->RealMode.Eflags.Bits.u2IOPL;
7557 }
7558 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7559 }
7560}
7561
7562
7563/**
7564 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7565 * context.
7566 *
7567 * @param pVCpu The cross context virtual CPU structure.
7568 * @param pVmcsInfo The VMCS info. object.
7569 *
7570 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7571 * do not log!
7572 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7573 * instead!!!
7574 */
7575static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7576{
7577 uint32_t u32Val;
7578 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7579 if (!u32Val)
7580 {
7581 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7582 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7583 CPUMSetGuestNmiBlocking(pVCpu, false);
7584 }
7585 else
7586 {
7587 /*
7588 * We must import RIP here to set our EM interrupt-inhibited state.
7589 * We also import RFLAGS as our code that evaluates pending interrupts
7590 * before VM-entry requires it.
7591 */
7592 hmR0VmxImportGuestRip(pVCpu);
7593 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7594
7595 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7596 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7597 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7598 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7599
7600 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7601 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7602 }
7603}
7604
7605
7606/**
7607 * Worker for VMXR0ImportStateOnDemand.
7608 *
7609 * @returns VBox status code.
7610 * @param pVCpu The cross context virtual CPU structure.
7611 * @param pVmcsInfo The VMCS info. object.
7612 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7613 */
7614static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7615{
7616 int rc = VINF_SUCCESS;
7617 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7618 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7619 uint32_t u32Val;
7620
7621 /*
7622 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7623 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7624 * neither are other host platforms.
7625 *
7626 * Committing this temporarily as it prevents BSOD.
7627 *
7628 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7629 */
7630#ifdef RT_OS_WINDOWS
7631 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7632 return VERR_HM_IPE_1;
7633#endif
7634
7635 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7636
7637 /*
7638 * We disable interrupts to make the updating of the state and in particular
7639 * the fExtrn modification atomic wrt to preemption hooks.
7640 */
7641 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7642
7643 fWhat &= pCtx->fExtrn;
7644 if (fWhat)
7645 {
7646 do
7647 {
7648 if (fWhat & CPUMCTX_EXTRN_RIP)
7649 hmR0VmxImportGuestRip(pVCpu);
7650
7651 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7652 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7653
7654 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7655 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7656
7657 if (fWhat & CPUMCTX_EXTRN_RSP)
7658 {
7659 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7660 AssertRC(rc);
7661 }
7662
7663 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7664 {
7665 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7666 bool const fRealOnV86Active = pVmcsInfoShared->RealMode.fRealOnV86Active;
7667 if (fWhat & CPUMCTX_EXTRN_CS)
7668 {
7669 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7670 hmR0VmxImportGuestRip(pVCpu);
7671 if (fRealOnV86Active)
7672 pCtx->cs.Attr.u = pVmcsInfoShared->RealMode.AttrCS.u;
7673 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7674 }
7675 if (fWhat & CPUMCTX_EXTRN_SS)
7676 {
7677 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7678 if (fRealOnV86Active)
7679 pCtx->ss.Attr.u = pVmcsInfoShared->RealMode.AttrSS.u;
7680 }
7681 if (fWhat & CPUMCTX_EXTRN_DS)
7682 {
7683 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7684 if (fRealOnV86Active)
7685 pCtx->ds.Attr.u = pVmcsInfoShared->RealMode.AttrDS.u;
7686 }
7687 if (fWhat & CPUMCTX_EXTRN_ES)
7688 {
7689 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7690 if (fRealOnV86Active)
7691 pCtx->es.Attr.u = pVmcsInfoShared->RealMode.AttrES.u;
7692 }
7693 if (fWhat & CPUMCTX_EXTRN_FS)
7694 {
7695 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7696 if (fRealOnV86Active)
7697 pCtx->fs.Attr.u = pVmcsInfoShared->RealMode.AttrFS.u;
7698 }
7699 if (fWhat & CPUMCTX_EXTRN_GS)
7700 {
7701 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7702 if (fRealOnV86Active)
7703 pCtx->gs.Attr.u = pVmcsInfoShared->RealMode.AttrGS.u;
7704 }
7705 }
7706
7707 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7708 {
7709 if (fWhat & CPUMCTX_EXTRN_LDTR)
7710 hmR0VmxImportGuestLdtr(pVCpu);
7711
7712 if (fWhat & CPUMCTX_EXTRN_GDTR)
7713 {
7714 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7715 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7716 pCtx->gdtr.cbGdt = u32Val;
7717 }
7718
7719 /* Guest IDTR. */
7720 if (fWhat & CPUMCTX_EXTRN_IDTR)
7721 {
7722 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7723 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7724 pCtx->idtr.cbIdt = u32Val;
7725 }
7726
7727 /* Guest TR. */
7728 if (fWhat & CPUMCTX_EXTRN_TR)
7729 {
7730 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7731 don't need to import that one. */
7732 if (!pVmcsInfo->pShared->RealMode.fRealOnV86Active)
7733 hmR0VmxImportGuestTr(pVCpu);
7734 }
7735 }
7736
7737 if (fWhat & CPUMCTX_EXTRN_DR7)
7738 {
7739 if (!pVCpu->hmr0.s.fUsingHyperDR7)
7740 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7741 }
7742
7743 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7744 {
7745 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7746 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7747 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7748 pCtx->SysEnter.cs = u32Val;
7749 }
7750
7751 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7752 {
7753 if ( pVM->hmr0.s.fAllow64BitGuests
7754 && (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7755 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7756 }
7757
7758 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7759 {
7760 if ( pVM->hmr0.s.fAllow64BitGuests
7761 && (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7762 {
7763 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7764 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7765 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7766 }
7767 }
7768
7769 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7770 {
7771 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7772 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7773 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7774 Assert(pMsrs);
7775 Assert(cMsrs <= VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc));
7776 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7777 for (uint32_t i = 0; i < cMsrs; i++)
7778 {
7779 uint32_t const idMsr = pMsrs[i].u32Msr;
7780 switch (idMsr)
7781 {
7782 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7783 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7784 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7785 default:
7786 {
7787 uint32_t idxLbrMsr;
7788 if (pVM->hmr0.s.vmx.fLbr)
7789 {
7790 if (hmR0VmxIsLbrBranchFromMsr(pVM, idMsr, &idxLbrMsr))
7791 {
7792 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfoShared->au64LbrFromIpMsr));
7793 pVmcsInfoShared->au64LbrFromIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7794 break;
7795 }
7796 if (hmR0VmxIsLbrBranchToMsr(pVM, idMsr, &idxLbrMsr))
7797 {
7798 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfoShared->au64LbrFromIpMsr));
7799 pVmcsInfoShared->au64LbrToIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7800 break;
7801 }
7802 if (idMsr == pVM->hmr0.s.vmx.idLbrTosMsr)
7803 {
7804 pVmcsInfoShared->u64LbrTosMsr = pMsrs[i].u64Value;
7805 break;
7806 }
7807 /* Fallthru (no break) */
7808 }
7809 pCtx->fExtrn = 0;
7810 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7811 ASMSetFlags(fEFlags);
7812 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7813 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7814 }
7815 }
7816 }
7817 }
7818
7819 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7820 {
7821 if (fWhat & CPUMCTX_EXTRN_CR0)
7822 {
7823 uint64_t u64Cr0;
7824 uint64_t u64Shadow;
7825 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7826 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7827#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7828 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7829 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7830#else
7831 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7832 {
7833 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7834 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7835 }
7836 else
7837 {
7838 /*
7839 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7840 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7841 * re-construct CR0. See @bugref{9180#c95} for details.
7842 */
7843 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
7844 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7845 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7846 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7847 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7848 }
7849#endif
7850 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7851 CPUMSetGuestCR0(pVCpu, u64Cr0);
7852 VMMRZCallRing3Enable(pVCpu);
7853 }
7854
7855 if (fWhat & CPUMCTX_EXTRN_CR4)
7856 {
7857 uint64_t u64Cr4;
7858 uint64_t u64Shadow;
7859 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7860 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7861#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7862 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7863 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7864#else
7865 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7866 {
7867 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7868 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7869 }
7870 else
7871 {
7872 /*
7873 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7874 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7875 * re-construct CR4. See @bugref{9180#c95} for details.
7876 */
7877 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
7878 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7879 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7880 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7881 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7882 }
7883#endif
7884 pCtx->cr4 = u64Cr4;
7885 }
7886
7887 if (fWhat & CPUMCTX_EXTRN_CR3)
7888 {
7889 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7890 if ( pVM->hmr0.s.vmx.fUnrestrictedGuest
7891 || ( pVM->hmr0.s.fNestedPaging
7892 && CPUMIsGuestPagingEnabledEx(pCtx)))
7893 {
7894 uint64_t u64Cr3;
7895 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7896 if (pCtx->cr3 != u64Cr3)
7897 {
7898 pCtx->cr3 = u64Cr3;
7899 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7900 }
7901
7902 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7903 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7904 if (CPUMIsGuestInPAEModeEx(pCtx))
7905 {
7906 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7907 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7908 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7909 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7910 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7911 }
7912 }
7913 }
7914 }
7915
7916#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7917 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7918 {
7919 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7920 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7921 {
7922 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7923 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7924 if (RT_SUCCESS(rc))
7925 { /* likely */ }
7926 else
7927 break;
7928 }
7929 }
7930#endif
7931 } while (0);
7932
7933 if (RT_SUCCESS(rc))
7934 {
7935 /* Update fExtrn. */
7936 pCtx->fExtrn &= ~fWhat;
7937
7938 /* If everything has been imported, clear the HM keeper bit. */
7939 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7940 {
7941 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7942 Assert(!pCtx->fExtrn);
7943 }
7944 }
7945 }
7946 else
7947 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7948
7949 /*
7950 * Restore interrupts.
7951 */
7952 ASMSetFlags(fEFlags);
7953
7954 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7955
7956 if (RT_SUCCESS(rc))
7957 { /* likely */ }
7958 else
7959 return rc;
7960
7961 /*
7962 * Honor any pending CR3 updates.
7963 *
7964 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7965 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7966 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7967 *
7968 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7969 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7970 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7971 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7972 *
7973 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7974 */
7975 if (VMMRZCallRing3IsEnabled(pVCpu))
7976 {
7977 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7978 {
7979 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7980 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7981 }
7982
7983 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7984 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7985
7986 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7987 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7988 }
7989
7990 return VINF_SUCCESS;
7991}
7992
7993
7994/**
7995 * Saves the guest state from the VMCS into the guest-CPU context.
7996 *
7997 * @returns VBox status code.
7998 * @param pVCpu The cross context virtual CPU structure.
7999 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
8000 */
8001VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
8002{
8003 AssertPtr(pVCpu);
8004 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8005 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
8006}
8007
8008
8009/**
8010 * Check per-VM and per-VCPU force flag actions that require us to go back to
8011 * ring-3 for one reason or another.
8012 *
8013 * @returns Strict VBox status code (i.e. informational status codes too)
8014 * @retval VINF_SUCCESS if we don't have any actions that require going back to
8015 * ring-3.
8016 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
8017 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
8018 * interrupts)
8019 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
8020 * all EMTs to be in ring-3.
8021 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
8022 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
8023 * to the EM loop.
8024 *
8025 * @param pVCpu The cross context virtual CPU structure.
8026 * @param pVmxTransient The VMX-transient structure.
8027 * @param fStepping Whether we are single-stepping the guest using the
8028 * hypervisor debugger.
8029 *
8030 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
8031 * is no longer in VMX non-root mode.
8032 */
8033static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, bool fStepping)
8034{
8035 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8036
8037 /*
8038 * Update pending interrupts into the APIC's IRR.
8039 */
8040 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
8041 APICUpdatePendingInterrupts(pVCpu);
8042
8043 /*
8044 * Anything pending? Should be more likely than not if we're doing a good job.
8045 */
8046 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8047 if ( !fStepping
8048 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
8049 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
8050 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
8051 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
8052 return VINF_SUCCESS;
8053
8054 /* Pending PGM C3 sync. */
8055 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
8056 {
8057 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8058 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
8059 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
8060 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
8061 if (rcStrict != VINF_SUCCESS)
8062 {
8063 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
8064 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
8065 return rcStrict;
8066 }
8067 }
8068
8069 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
8070 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
8071 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
8072 {
8073 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
8074 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
8075 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
8076 return rc;
8077 }
8078
8079 /* Pending VM request packets, such as hardware interrupts. */
8080 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
8081 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
8082 {
8083 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
8084 Log4Func(("Pending VM request forcing us back to ring-3\n"));
8085 return VINF_EM_PENDING_REQUEST;
8086 }
8087
8088 /* Pending PGM pool flushes. */
8089 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
8090 {
8091 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
8092 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
8093 return VINF_PGM_POOL_FLUSH_PENDING;
8094 }
8095
8096 /* Pending DMA requests. */
8097 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
8098 {
8099 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
8100 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
8101 return VINF_EM_RAW_TO_R3;
8102 }
8103
8104#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8105 /*
8106 * Pending nested-guest events.
8107 *
8108 * Please note the priority of these events are specified and important.
8109 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
8110 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
8111 */
8112 if (pVmxTransient->fIsNestedGuest)
8113 {
8114 /* Pending nested-guest APIC-write. */
8115 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
8116 {
8117 Log4Func(("Pending nested-guest APIC-write\n"));
8118 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
8119 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8120 return rcStrict;
8121 }
8122
8123 /* Pending nested-guest monitor-trap flag (MTF). */
8124 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
8125 {
8126 Log4Func(("Pending nested-guest MTF\n"));
8127 VBOXSTRICTRC rcStrict = IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */);
8128 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8129 return rcStrict;
8130 }
8131
8132 /* Pending nested-guest VMX-preemption timer expired. */
8133 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
8134 {
8135 Log4Func(("Pending nested-guest MTF\n"));
8136 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitPreemptTimer(pVCpu);
8137 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8138 return rcStrict;
8139 }
8140 }
8141#else
8142 NOREF(pVmxTransient);
8143#endif
8144
8145 return VINF_SUCCESS;
8146}
8147
8148
8149/**
8150 * Converts any TRPM trap into a pending HM event. This is typically used when
8151 * entering from ring-3 (not longjmp returns).
8152 *
8153 * @param pVCpu The cross context virtual CPU structure.
8154 */
8155static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
8156{
8157 Assert(TRPMHasTrap(pVCpu));
8158 Assert(!pVCpu->hm.s.Event.fPending);
8159
8160 uint8_t uVector;
8161 TRPMEVENT enmTrpmEvent;
8162 uint32_t uErrCode;
8163 RTGCUINTPTR GCPtrFaultAddress;
8164 uint8_t cbInstr;
8165 bool fIcebp;
8166
8167 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
8168 AssertRC(rc);
8169
8170 uint32_t u32IntInfo;
8171 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8172 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
8173
8174 rc = TRPMResetTrap(pVCpu);
8175 AssertRC(rc);
8176 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8177 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8178
8179 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8180}
8181
8182
8183/**
8184 * Converts the pending HM event into a TRPM trap.
8185 *
8186 * @param pVCpu The cross context virtual CPU structure.
8187 */
8188static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
8189{
8190 Assert(pVCpu->hm.s.Event.fPending);
8191
8192 /* If a trap was already pending, we did something wrong! */
8193 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8194
8195 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8196 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8197 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8198
8199 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8200
8201 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8202 AssertRC(rc);
8203
8204 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8205 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8206
8207 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8208 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8209 else
8210 {
8211 uint8_t const uVectorType = VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo);
8212 switch (uVectorType)
8213 {
8214 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
8215 TRPMSetTrapDueToIcebp(pVCpu);
8216 RT_FALL_THRU();
8217 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
8218 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
8219 {
8220 AssertMsg( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
8221 || ( uVector == X86_XCPT_BP /* INT3 */
8222 || uVector == X86_XCPT_OF /* INTO */
8223 || uVector == X86_XCPT_DB /* INT1 (ICEBP) */),
8224 ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uVectorType));
8225 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8226 break;
8227 }
8228 }
8229 }
8230
8231 /* We're now done converting the pending event. */
8232 pVCpu->hm.s.Event.fPending = false;
8233}
8234
8235
8236/**
8237 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8238 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8239 *
8240 * @param pVmcsInfo The VMCS info. object.
8241 */
8242static void hmR0VmxSetIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8243{
8244 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8245 {
8246 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8247 {
8248 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8249 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8250 AssertRC(rc);
8251 }
8252 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8253}
8254
8255
8256/**
8257 * Clears the interrupt-window exiting control in the VMCS.
8258 *
8259 * @param pVmcsInfo The VMCS info. object.
8260 */
8261DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8262{
8263 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8264 {
8265 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8266 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8267 AssertRC(rc);
8268 }
8269}
8270
8271
8272/**
8273 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8274 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8275 *
8276 * @param pVmcsInfo The VMCS info. object.
8277 */
8278static void hmR0VmxSetNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8279{
8280 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8281 {
8282 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8283 {
8284 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8285 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8286 AssertRC(rc);
8287 Log4Func(("Setup NMI-window exiting\n"));
8288 }
8289 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8290}
8291
8292
8293/**
8294 * Clears the NMI-window exiting control in the VMCS.
8295 *
8296 * @param pVmcsInfo The VMCS info. object.
8297 */
8298DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8299{
8300 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8301 {
8302 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8303 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8304 AssertRC(rc);
8305 }
8306}
8307
8308
8309/**
8310 * Does the necessary state syncing before returning to ring-3 for any reason
8311 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8312 *
8313 * @returns VBox status code.
8314 * @param pVCpu The cross context virtual CPU structure.
8315 * @param fImportState Whether to import the guest state from the VMCS back
8316 * to the guest-CPU context.
8317 *
8318 * @remarks No-long-jmp zone!!!
8319 */
8320static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
8321{
8322 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8323 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8324
8325 RTCPUID const idCpu = RTMpCpuId();
8326 Log4Func(("HostCpuId=%u\n", idCpu));
8327
8328 /*
8329 * !!! IMPORTANT !!!
8330 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
8331 */
8332
8333 /* Save the guest state if necessary. */
8334 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8335 if (fImportState)
8336 {
8337 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8338 AssertRCReturn(rc, rc);
8339 }
8340
8341 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8342 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8343 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8344
8345 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8346#ifdef VBOX_STRICT
8347 if (CPUMIsHyperDebugStateActive(pVCpu))
8348 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8349#endif
8350 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8351 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
8352 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
8353
8354 /* Restore host-state bits that VT-x only restores partially. */
8355 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
8356 {
8357 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hmr0.s.vmx.fRestoreHostFlags, idCpu));
8358 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
8359 }
8360 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
8361
8362 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8363 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8364 {
8365 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8366 if (!fImportState)
8367 {
8368 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8369 AssertRCReturn(rc, rc);
8370 }
8371 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8372 Assert(!pVCpu->hmr0.s.vmx.fLazyMsrs);
8373 }
8374 else
8375 pVCpu->hmr0.s.vmx.fLazyMsrs = 0;
8376
8377 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8378 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
8379
8380 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8381 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8382 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8383 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8384 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8385 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8386 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8387 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8388 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8389 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8390
8391 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8392
8393 /** @todo This partially defeats the purpose of having preemption hooks.
8394 * The problem is, deregistering the hooks should be moved to a place that
8395 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8396 * context.
8397 */
8398 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8399 AssertRCReturn(rc, rc);
8400
8401#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8402 /*
8403 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8404 * clear a shadow VMCS before allowing that VMCS to become active on another
8405 * logical processor. We may or may not be importing guest state which clears
8406 * it, so cover for it here.
8407 *
8408 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8409 */
8410 if ( pVmcsInfo->pvShadowVmcs
8411 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8412 {
8413 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8414 AssertRCReturn(rc, rc);
8415 }
8416
8417 /*
8418 * Flag that we need to re-export the host state if we switch to this VMCS before
8419 * executing guest or nested-guest code.
8420 */
8421 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8422#endif
8423
8424 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8425 NOREF(idCpu);
8426 return VINF_SUCCESS;
8427}
8428
8429
8430/**
8431 * Leaves the VT-x session.
8432 *
8433 * @returns VBox status code.
8434 * @param pVCpu The cross context virtual CPU structure.
8435 *
8436 * @remarks No-long-jmp zone!!!
8437 */
8438static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8439{
8440 HM_DISABLE_PREEMPT(pVCpu);
8441 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8442 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8443 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8444
8445 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8446 and done this from the VMXR0ThreadCtxCallback(). */
8447 if (!pVCpu->hmr0.s.fLeaveDone)
8448 {
8449 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8450 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8451 pVCpu->hmr0.s.fLeaveDone = true;
8452 }
8453 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8454
8455 /*
8456 * !!! IMPORTANT !!!
8457 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8458 */
8459
8460 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8461 /** @todo Deregistering here means we need to VMCLEAR always
8462 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8463 * for calling VMMR0ThreadCtxHookDisable here! */
8464 VMMR0ThreadCtxHookDisable(pVCpu);
8465
8466 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8467 int rc = HMR0LeaveCpu(pVCpu);
8468 HM_RESTORE_PREEMPT();
8469 return rc;
8470}
8471
8472
8473/**
8474 * Does the necessary state syncing before doing a longjmp to ring-3.
8475 *
8476 * @returns VBox status code.
8477 * @param pVCpu The cross context virtual CPU structure.
8478 *
8479 * @remarks No-long-jmp zone!!!
8480 */
8481DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8482{
8483 return hmR0VmxLeaveSession(pVCpu);
8484}
8485
8486
8487/**
8488 * Take necessary actions before going back to ring-3.
8489 *
8490 * An action requires us to go back to ring-3. This function does the necessary
8491 * steps before we can safely return to ring-3. This is not the same as longjmps
8492 * to ring-3, this is voluntary and prepares the guest so it may continue
8493 * executing outside HM (recompiler/IEM).
8494 *
8495 * @returns VBox status code.
8496 * @param pVCpu The cross context virtual CPU structure.
8497 * @param rcExit The reason for exiting to ring-3. Can be
8498 * VINF_VMM_UNKNOWN_RING3_CALL.
8499 */
8500static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8501{
8502 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8503
8504 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8505 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8506 {
8507 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8508 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8509 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hmr0.s.idEnteredCpu;
8510 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8511 }
8512
8513 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8514 VMMRZCallRing3Disable(pVCpu);
8515 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8516
8517 /*
8518 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8519 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8520 *
8521 * This is because execution may continue from ring-3 and we would need to inject
8522 * the event from there (hence place it back in TRPM).
8523 */
8524 if (pVCpu->hm.s.Event.fPending)
8525 {
8526 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8527 Assert(!pVCpu->hm.s.Event.fPending);
8528
8529 /* Clear the events from the VMCS. */
8530 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc);
8531 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0); AssertRC(rc);
8532 }
8533#ifdef VBOX_STRICT
8534 /*
8535 * We check for rcExit here since for errors like VERR_VMX_UNABLE_TO_START_VM (which are
8536 * fatal), we don't care about verifying duplicate injection of events. Errors like
8537 * VERR_EM_INTERPRET are converted to their VINF_* counterparts -prior- to calling this
8538 * function so those should and will be checked below.
8539 */
8540 else if (RT_SUCCESS(rcExit))
8541 {
8542 /*
8543 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8544 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8545 * occasionally, see @bugref{9180#c42}.
8546 *
8547 * However, if the VM-entry failed, any VM entry-interruption info. field would
8548 * be left unmodified as the event would not have been injected to the guest. In
8549 * such cases, don't assert, we're not going to continue guest execution anyway.
8550 */
8551 uint32_t uExitReason;
8552 uint32_t uEntryIntInfo;
8553 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8554 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8555 AssertRC(rc);
8556 AssertMsg(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo),
8557 ("uExitReason=%#RX32 uEntryIntInfo=%#RX32 rcExit=%d\n", uExitReason, uEntryIntInfo, VBOXSTRICTRC_VAL(rcExit)));
8558 }
8559#endif
8560
8561 /*
8562 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8563 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8564 * (e.g. TPR below threshold).
8565 */
8566 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8567 {
8568 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8569 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8570 }
8571
8572 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8573 and if we're injecting an event we should have a TRPM trap pending. */
8574 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8575#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8576 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8577#endif
8578
8579 /* Save guest state and restore host state bits. */
8580 int rc = hmR0VmxLeaveSession(pVCpu);
8581 AssertRCReturn(rc, rc);
8582 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8583
8584 /* Thread-context hooks are unregistered at this point!!! */
8585 /* Ring-3 callback notifications are unregistered at this point!!! */
8586
8587 /* Sync recompiler state. */
8588 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8589 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8590 | CPUM_CHANGED_LDTR
8591 | CPUM_CHANGED_GDTR
8592 | CPUM_CHANGED_IDTR
8593 | CPUM_CHANGED_TR
8594 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8595 if ( pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging
8596 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8597 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8598
8599 Assert(!pVCpu->hmr0.s.fClearTrapFlag);
8600
8601 /* Update the exit-to-ring 3 reason. */
8602 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8603
8604 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8605 if ( rcExit != VINF_EM_RAW_INTERRUPT
8606 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8607 {
8608 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8609 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8610 }
8611
8612 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8613 VMMRZCallRing3Enable(pVCpu);
8614 return rc;
8615}
8616
8617
8618/**
8619 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8620 * longjump to ring-3 and possibly get preempted.
8621 *
8622 * @returns VBox status code.
8623 * @param pVCpu The cross context virtual CPU structure.
8624 * @param enmOperation The operation causing the ring-3 longjump.
8625 */
8626VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8627{
8628 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8629 {
8630 /*
8631 * !!! IMPORTANT !!!
8632 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8633 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8634 */
8635 VMMRZCallRing3RemoveNotification(pVCpu);
8636 VMMRZCallRing3Disable(pVCpu);
8637 HM_DISABLE_PREEMPT(pVCpu);
8638
8639 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8640 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8641 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8642 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8643
8644 /* Restore host-state bits that VT-x only restores partially. */
8645 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
8646 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
8647 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
8648
8649 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8650 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8651 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8652
8653 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8654 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
8655 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8656
8657 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8658 cleared as part of importing the guest state above. */
8659 hmR0VmxClearVmcs(pVmcsInfo);
8660
8661 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8662 VMMR0ThreadCtxHookDisable(pVCpu);
8663
8664 /* Leave HM context. This takes care of local init (term). */
8665 HMR0LeaveCpu(pVCpu);
8666 HM_RESTORE_PREEMPT();
8667 return VINF_SUCCESS;
8668 }
8669
8670 Assert(pVCpu);
8671 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8672 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8673
8674 VMMRZCallRing3Disable(pVCpu);
8675 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8676
8677 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8678
8679 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8680 AssertRCReturn(rc, rc);
8681
8682 VMMRZCallRing3Enable(pVCpu);
8683 return VINF_SUCCESS;
8684}
8685
8686
8687/**
8688 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8689 * stack.
8690 *
8691 * @returns Strict VBox status code (i.e. informational status codes too).
8692 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8693 * @param pVCpu The cross context virtual CPU structure.
8694 * @param uValue The value to push to the guest stack.
8695 */
8696static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8697{
8698 /*
8699 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8700 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8701 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8702 */
8703 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8704 if (pCtx->sp == 1)
8705 return VINF_EM_RESET;
8706 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8707 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8708 AssertRC(rc);
8709 return rc;
8710}
8711
8712
8713/**
8714 * Injects an event into the guest upon VM-entry by updating the relevant fields
8715 * in the VM-entry area in the VMCS.
8716 *
8717 * @returns Strict VBox status code (i.e. informational status codes too).
8718 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8719 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8720 *
8721 * @param pVCpu The cross context virtual CPU structure.
8722 * @param pVmxTransient The VMX-transient structure.
8723 * @param pEvent The event being injected.
8724 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8725 * will be updated if necessary. This cannot not be NULL.
8726 * @param fStepping Whether we're single-stepping guest execution and should
8727 * return VINF_EM_DBG_STEPPED if the event is injected
8728 * directly (registers modified by us, not by hardware on
8729 * VM-entry).
8730 */
8731static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8732 uint32_t *pfIntrState)
8733{
8734 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8735 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8736 Assert(pfIntrState);
8737
8738 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8739 uint32_t u32IntInfo = pEvent->u64IntInfo;
8740 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8741 uint32_t const cbInstr = pEvent->cbInstr;
8742 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8743 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8744 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8745
8746#ifdef VBOX_STRICT
8747 /*
8748 * Validate the error-code-valid bit for hardware exceptions.
8749 * No error codes for exceptions in real-mode.
8750 *
8751 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8752 */
8753 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8754 && !CPUMIsGuestInRealModeEx(pCtx))
8755 {
8756 switch (uVector)
8757 {
8758 case X86_XCPT_PF:
8759 case X86_XCPT_DF:
8760 case X86_XCPT_TS:
8761 case X86_XCPT_NP:
8762 case X86_XCPT_SS:
8763 case X86_XCPT_GP:
8764 case X86_XCPT_AC:
8765 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8766 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8767 RT_FALL_THRU();
8768 default:
8769 break;
8770 }
8771 }
8772
8773 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8774 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8775 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8776#endif
8777
8778 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8779 || uIntType == VMX_EXIT_INT_INFO_TYPE_NMI
8780 || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT
8781 || uIntType == VMX_EXIT_INT_INFO_TYPE_SW_XCPT)
8782 {
8783 Assert(uVector <= X86_XCPT_LAST);
8784 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_NMI || uVector == X86_XCPT_NMI);
8785 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT || uVector == X86_XCPT_DB);
8786 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedXcptsR0[uVector]);
8787 }
8788 else
8789 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8790
8791 /*
8792 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8793 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8794 * interrupt handler in the (real-mode) guest.
8795 *
8796 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8797 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8798 */
8799 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8800 {
8801 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest)
8802 {
8803 /*
8804 * For CPUs with unrestricted guest execution enabled and with the guest
8805 * in real-mode, we must not set the deliver-error-code bit.
8806 *
8807 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8808 */
8809 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8810 }
8811 else
8812 {
8813 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8814 Assert(PDMVmmDevHeapIsEnabled(pVM));
8815 Assert(pVM->hm.s.vmx.pRealModeTSS);
8816 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8817
8818 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8819 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8820 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8821 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8822 AssertRCReturn(rc2, rc2);
8823
8824 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8825 size_t const cbIdtEntry = sizeof(X86IDTR16);
8826 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8827 {
8828 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8829 if (uVector == X86_XCPT_DF)
8830 return VINF_EM_RESET;
8831
8832 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8833 No error codes for exceptions in real-mode. */
8834 if (uVector == X86_XCPT_GP)
8835 {
8836 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8837 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8838 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8839 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8840 HMEVENT EventXcptDf;
8841 RT_ZERO(EventXcptDf);
8842 EventXcptDf.u64IntInfo = uXcptDfInfo;
8843 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8844 }
8845
8846 /*
8847 * If we're injecting an event with no valid IDT entry, inject a #GP.
8848 * No error codes for exceptions in real-mode.
8849 *
8850 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8851 */
8852 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8853 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8854 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8855 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8856 HMEVENT EventXcptGp;
8857 RT_ZERO(EventXcptGp);
8858 EventXcptGp.u64IntInfo = uXcptGpInfo;
8859 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8860 }
8861
8862 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8863 uint16_t uGuestIp = pCtx->ip;
8864 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8865 {
8866 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8867 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8868 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8869 }
8870 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8871 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8872
8873 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8874 X86IDTR16 IdtEntry;
8875 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8876 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8877 AssertRCReturn(rc2, rc2);
8878
8879 /* Construct the stack frame for the interrupt/exception handler. */
8880 VBOXSTRICTRC rcStrict;
8881 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8882 if (rcStrict == VINF_SUCCESS)
8883 {
8884 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8885 if (rcStrict == VINF_SUCCESS)
8886 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8887 }
8888
8889 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8890 if (rcStrict == VINF_SUCCESS)
8891 {
8892 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8893 pCtx->rip = IdtEntry.offSel;
8894 pCtx->cs.Sel = IdtEntry.uSel;
8895 pCtx->cs.ValidSel = IdtEntry.uSel;
8896 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8897 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8898 && uVector == X86_XCPT_PF)
8899 pCtx->cr2 = GCPtrFault;
8900
8901 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8902 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8903 | HM_CHANGED_GUEST_RSP);
8904
8905 /*
8906 * If we delivered a hardware exception (other than an NMI) and if there was
8907 * block-by-STI in effect, we should clear it.
8908 */
8909 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8910 {
8911 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8912 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8913 Log4Func(("Clearing inhibition due to STI\n"));
8914 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8915 }
8916
8917 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8918 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8919
8920 /*
8921 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8922 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8923 */
8924 pVCpu->hm.s.Event.fPending = false;
8925
8926 /*
8927 * If we eventually support nested-guest execution without unrestricted guest execution,
8928 * we should set fInterceptEvents here.
8929 */
8930 Assert(!pVmxTransient->fIsNestedGuest);
8931
8932 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8933 if (fStepping)
8934 rcStrict = VINF_EM_DBG_STEPPED;
8935 }
8936 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8937 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8938 return rcStrict;
8939 }
8940 }
8941
8942 /*
8943 * Validate.
8944 */
8945 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8946 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8947
8948 /*
8949 * Inject the event into the VMCS.
8950 */
8951 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8952 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8953 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8954 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8955 AssertRC(rc);
8956
8957 /*
8958 * Update guest CR2 if this is a page-fault.
8959 */
8960 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8961 pCtx->cr2 = GCPtrFault;
8962
8963 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8964 return VINF_SUCCESS;
8965}
8966
8967
8968/**
8969 * Evaluates the event to be delivered to the guest and sets it as the pending
8970 * event.
8971 *
8972 * Toggling of interrupt force-flags here is safe since we update TRPM on premature
8973 * exits to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must
8974 * NOT restore these force-flags.
8975 *
8976 * @returns Strict VBox status code (i.e. informational status codes too).
8977 * @param pVCpu The cross context virtual CPU structure.
8978 * @param pVmxTransient The VMX-transient structure.
8979 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8980 */
8981static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8982{
8983 Assert(pfIntrState);
8984 Assert(!TRPMHasTrap(pVCpu));
8985
8986 /*
8987 * Compute/update guest-interruptibility state related FFs.
8988 * The FFs will be used below while evaluating events to be injected.
8989 */
8990 *pfIntrState = hmR0VmxGetGuestIntrStateAndUpdateFFs(pVCpu);
8991
8992 /*
8993 * Evaluate if a new event needs to be injected.
8994 * An event that's already pending has already performed all necessary checks.
8995 */
8996 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8997 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8998 if ( !pVCpu->hm.s.Event.fPending
8999 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
9000 {
9001 /** @todo SMI. SMIs take priority over NMIs. */
9002
9003 /*
9004 * NMIs.
9005 * NMIs take priority over external interrupts.
9006 */
9007 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9008 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
9009 {
9010 /*
9011 * For a guest, the FF always indicates the guest's ability to receive an NMI.
9012 *
9013 * For a nested-guest, the FF always indicates the outer guest's ability to
9014 * receive an NMI while the guest-interruptibility state bit depends on whether
9015 * the nested-hypervisor is using virtual-NMIs.
9016 */
9017 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
9018 {
9019#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9020 if ( fIsNestedGuest
9021 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_NMI_EXIT))
9022 return IEMExecVmxVmexitXcptNmi(pVCpu);
9023#endif
9024 hmR0VmxSetPendingXcptNmi(pVCpu);
9025 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
9026 Log4Func(("NMI pending injection\n"));
9027
9028 /* We've injected the NMI, bail. */
9029 return VINF_SUCCESS;
9030 }
9031 else if (!fIsNestedGuest)
9032 hmR0VmxSetNmiWindowExitVmcs(pVmcsInfo);
9033 }
9034
9035 /*
9036 * External interrupts (PIC/APIC).
9037 * Once PDMGetInterrupt() returns a valid interrupt we -must- deliver it.
9038 * We cannot re-request the interrupt from the controller again.
9039 */
9040 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9041 && !pVCpu->hm.s.fSingleInstruction)
9042 {
9043 Assert(!DBGFIsStepping(pVCpu));
9044 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
9045 AssertRC(rc);
9046
9047 /*
9048 * We must not check EFLAGS directly when executing a nested-guest, use
9049 * CPUMIsGuestPhysIntrEnabled() instead as EFLAGS.IF does not control the blocking of
9050 * external interrupts when "External interrupt exiting" is set. This fixes a nasty
9051 * SMP hang while executing nested-guest VCPUs on spinlocks which aren't rescued by
9052 * other VM-exits (like a preemption timer), see @bugref{9562#c18}.
9053 *
9054 * See Intel spec. 25.4.1 "Event Blocking".
9055 */
9056 if (CPUMIsGuestPhysIntrEnabled(pVCpu))
9057 {
9058#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9059 if ( fIsNestedGuest
9060 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9061 {
9062 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
9063 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
9064 return rcStrict;
9065 }
9066#endif
9067 uint8_t u8Interrupt;
9068 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9069 if (RT_SUCCESS(rc))
9070 {
9071#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9072 if ( fIsNestedGuest
9073 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9074 {
9075 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9076 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
9077 return rcStrict;
9078 }
9079#endif
9080 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9081 Log4Func(("External interrupt (%#x) pending injection\n", u8Interrupt));
9082 }
9083 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9084 {
9085 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9086
9087 if ( !fIsNestedGuest
9088 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9089 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
9090 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
9091
9092 /*
9093 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9094 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9095 * need to re-set this force-flag here.
9096 */
9097 }
9098 else
9099 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9100
9101 /* We've injected the interrupt or taken necessary action, bail. */
9102 return VINF_SUCCESS;
9103 }
9104 if (!fIsNestedGuest)
9105 hmR0VmxSetIntWindowExitVmcs(pVmcsInfo);
9106 }
9107 }
9108 else if (!fIsNestedGuest)
9109 {
9110 /*
9111 * An event is being injected or we are in an interrupt shadow. Check if another event is
9112 * pending. If so, instruct VT-x to cause a VM-exit as soon as the guest is ready to accept
9113 * the pending event.
9114 */
9115 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
9116 hmR0VmxSetNmiWindowExitVmcs(pVmcsInfo);
9117 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9118 && !pVCpu->hm.s.fSingleInstruction)
9119 hmR0VmxSetIntWindowExitVmcs(pVmcsInfo);
9120 }
9121 /* else: for nested-guests, NMI/interrupt-window exiting will be picked up when merging VMCS controls. */
9122
9123 return VINF_SUCCESS;
9124}
9125
9126
9127/**
9128 * Injects any pending events into the guest if the guest is in a state to
9129 * receive them.
9130 *
9131 * @returns Strict VBox status code (i.e. informational status codes too).
9132 * @param pVCpu The cross context virtual CPU structure.
9133 * @param pVmxTransient The VMX-transient structure.
9134 * @param fIntrState The VT-x guest-interruptibility state.
9135 * @param fStepping Whether we are single-stepping the guest using the
9136 * hypervisor debugger and should return
9137 * VINF_EM_DBG_STEPPED if the event was dispatched
9138 * directly.
9139 */
9140static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9141{
9142 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9143 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9144
9145#ifdef VBOX_STRICT
9146 /*
9147 * Verify guest-interruptibility state.
9148 *
9149 * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
9150 * since injecting an event may modify the interruptibility state and we must thus always
9151 * use fIntrState.
9152 */
9153 {
9154 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9155 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9156 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9157 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9158 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9159 Assert(!TRPMHasTrap(pVCpu));
9160 NOREF(fBlockMovSS); NOREF(fBlockSti);
9161 }
9162#endif
9163
9164 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9165 if (pVCpu->hm.s.Event.fPending)
9166 {
9167 /*
9168 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9169 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9170 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9171 *
9172 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9173 */
9174 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9175#ifdef VBOX_STRICT
9176 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9177 {
9178 Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9179 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9180 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9181 }
9182 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9183 {
9184 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
9185 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9186 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9187 }
9188#endif
9189 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9190 uIntType));
9191
9192 /*
9193 * Inject the event and get any changes to the guest-interruptibility state.
9194 *
9195 * The guest-interruptibility state may need to be updated if we inject the event
9196 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9197 */
9198 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9199 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9200
9201 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9202 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9203 else
9204 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9205 }
9206
9207 /*
9208 * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
9209 * is an interrupt shadow (block-by-STI or block-by-MOV SS).
9210 */
9211 if ( (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9212 && !pVmxTransient->fIsNestedGuest)
9213 {
9214 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
9215
9216 if (!pVCpu->hm.s.fSingleInstruction)
9217 {
9218 /*
9219 * Set or clear the BS bit depending on whether the trap flag is active or not. We need
9220 * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
9221 */
9222 Assert(!DBGFIsStepping(pVCpu));
9223 uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
9224 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
9225 AssertRC(rc);
9226 }
9227 else
9228 {
9229 /*
9230 * We must not deliver a debug exception when single-stepping over STI/Mov-SS in the
9231 * hypervisor debugger using EFLAGS.TF but rather clear interrupt inhibition. However,
9232 * we take care of this case in hmR0VmxExportSharedDebugState and also the case if
9233 * we use MTF, so just make sure it's called before executing guest-code.
9234 */
9235 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR_MASK);
9236 }
9237 }
9238 /* else: for nested-guest currently handling while merging controls. */
9239
9240 /*
9241 * Finally, update the guest-interruptibility state.
9242 *
9243 * This is required for the real-on-v86 software interrupt injection, for
9244 * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
9245 */
9246 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9247 AssertRC(rc);
9248
9249 /*
9250 * There's no need to clear the VM-entry interruption-information field here if we're not
9251 * injecting anything. VT-x clears the valid bit on every VM-exit.
9252 *
9253 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9254 */
9255
9256 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9257 return rcStrict;
9258}
9259
9260
9261/**
9262 * Enters the VT-x session.
9263 *
9264 * @returns VBox status code.
9265 * @param pVCpu The cross context virtual CPU structure.
9266 */
9267VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
9268{
9269 AssertPtr(pVCpu);
9270 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9271 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9272
9273 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9274 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9275 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9276
9277#ifdef VBOX_STRICT
9278 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9279 RTCCUINTREG uHostCr4 = ASMGetCR4();
9280 if (!(uHostCr4 & X86_CR4_VMXE))
9281 {
9282 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9283 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9284 }
9285#endif
9286
9287 /*
9288 * Load the appropriate VMCS as the current and active one.
9289 */
9290 PVMXVMCSINFO pVmcsInfo;
9291 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9292 if (!fInNestedGuestMode)
9293 pVmcsInfo = &pVCpu->hmr0.s.vmx.VmcsInfo;
9294 else
9295 pVmcsInfo = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
9296 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9297 if (RT_SUCCESS(rc))
9298 {
9299 pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9300 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcsCopyForRing3 = fInNestedGuestMode;
9301 pVCpu->hmr0.s.fLeaveDone = false;
9302 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9303
9304 /*
9305 * Do the EMT scheduled L1D flush here if needed.
9306 */
9307 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9308 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9309 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9310 hmR0MdsClear();
9311 }
9312 return rc;
9313}
9314
9315
9316/**
9317 * The thread-context callback (only on platforms which support it).
9318 *
9319 * @param enmEvent The thread-context event.
9320 * @param pVCpu The cross context virtual CPU structure.
9321 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9322 * @thread EMT(pVCpu)
9323 */
9324VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
9325{
9326 AssertPtr(pVCpu);
9327 RT_NOREF1(fGlobalInit);
9328
9329 switch (enmEvent)
9330 {
9331 case RTTHREADCTXEVENT_OUT:
9332 {
9333 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9334 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9335 VMCPU_ASSERT_EMT(pVCpu);
9336
9337 /* No longjmps (logger flushes, locks) in this fragile context. */
9338 VMMRZCallRing3Disable(pVCpu);
9339 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9340
9341 /* Restore host-state (FPU, debug etc.) */
9342 if (!pVCpu->hmr0.s.fLeaveDone)
9343 {
9344 /*
9345 * Do -not- import the guest-state here as we might already be in the middle of importing
9346 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9347 */
9348 hmR0VmxLeave(pVCpu, false /* fImportState */);
9349 pVCpu->hmr0.s.fLeaveDone = true;
9350 }
9351
9352 /* Leave HM context, takes care of local init (term). */
9353 int rc = HMR0LeaveCpu(pVCpu);
9354 AssertRC(rc);
9355
9356 /* Restore longjmp state. */
9357 VMMRZCallRing3Enable(pVCpu);
9358 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9359 break;
9360 }
9361
9362 case RTTHREADCTXEVENT_IN:
9363 {
9364 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9365 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9366 VMCPU_ASSERT_EMT(pVCpu);
9367
9368 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9369 VMMRZCallRing3Disable(pVCpu);
9370 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9371
9372 /* Initialize the bare minimum state required for HM. This takes care of
9373 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9374 int rc = hmR0EnterCpu(pVCpu);
9375 AssertRC(rc);
9376 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9377 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9378
9379 /* Load the active VMCS as the current one. */
9380 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9381 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9382 AssertRC(rc);
9383 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9384 pVCpu->hmr0.s.fLeaveDone = false;
9385
9386 /* Do the EMT scheduled L1D flush if needed. */
9387 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9388 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9389
9390 /* Restore longjmp state. */
9391 VMMRZCallRing3Enable(pVCpu);
9392 break;
9393 }
9394
9395 default:
9396 break;
9397 }
9398}
9399
9400
9401/**
9402 * Exports the host state into the VMCS host-state area.
9403 * Sets up the VM-exit MSR-load area.
9404 *
9405 * The CPU state will be loaded from these fields on every successful VM-exit.
9406 *
9407 * @returns VBox status code.
9408 * @param pVCpu The cross context virtual CPU structure.
9409 *
9410 * @remarks No-long-jump zone!!!
9411 */
9412static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
9413{
9414 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9415
9416 int rc = VINF_SUCCESS;
9417 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9418 {
9419 uint64_t uHostCr4 = hmR0VmxExportHostControlRegs();
9420
9421 rc = hmR0VmxExportHostSegmentRegs(pVCpu, uHostCr4);
9422 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9423
9424 hmR0VmxExportHostMsrs(pVCpu);
9425
9426 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9427 }
9428 return rc;
9429}
9430
9431
9432/**
9433 * Saves the host state in the VMCS host-state.
9434 *
9435 * @returns VBox status code.
9436 * @param pVCpu The cross context virtual CPU structure.
9437 *
9438 * @remarks No-long-jump zone!!!
9439 */
9440VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
9441{
9442 AssertPtr(pVCpu);
9443 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9444
9445 /*
9446 * Export the host state here while entering HM context.
9447 * When thread-context hooks are used, we might get preempted and have to re-save the host
9448 * state but most of the time we won't be, so do it here before we disable interrupts.
9449 */
9450 return hmR0VmxExportHostState(pVCpu);
9451}
9452
9453
9454/**
9455 * Exports the guest state into the VMCS guest-state area.
9456 *
9457 * The will typically be done before VM-entry when the guest-CPU state and the
9458 * VMCS state may potentially be out of sync.
9459 *
9460 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9461 * VM-entry controls.
9462 * Sets up the appropriate VMX non-root function to execute guest code based on
9463 * the guest CPU mode.
9464 *
9465 * @returns VBox strict status code.
9466 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9467 * without unrestricted guest execution and the VMMDev is not presently
9468 * mapped (e.g. EFI32).
9469 *
9470 * @param pVCpu The cross context virtual CPU structure.
9471 * @param pVmxTransient The VMX-transient structure.
9472 *
9473 * @remarks No-long-jump zone!!!
9474 */
9475static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9476{
9477 AssertPtr(pVCpu);
9478 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9479 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9480
9481 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9482
9483 /*
9484 * Determine real-on-v86 mode.
9485 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9486 */
9487 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmxTransient->pVmcsInfo->pShared;
9488 if ( pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest
9489 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9490 pVmcsInfoShared->RealMode.fRealOnV86Active = false;
9491 else
9492 {
9493 Assert(!pVmxTransient->fIsNestedGuest);
9494 pVmcsInfoShared->RealMode.fRealOnV86Active = true;
9495 }
9496
9497 /*
9498 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9499 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9500 */
9501 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9502 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9503
9504 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9505 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9506
9507 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9508 if (rcStrict == VINF_SUCCESS)
9509 { /* likely */ }
9510 else
9511 {
9512 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9513 return rcStrict;
9514 }
9515
9516 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9517 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9518
9519 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9520 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9521
9522 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9523 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9524 hmR0VmxExportGuestRip(pVCpu);
9525 hmR0VmxExportGuestRsp(pVCpu);
9526 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9527
9528 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9529 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9530
9531 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9532 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9533 | HM_CHANGED_GUEST_CR2
9534 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9535 | HM_CHANGED_GUEST_X87
9536 | HM_CHANGED_GUEST_SSE_AVX
9537 | HM_CHANGED_GUEST_OTHER_XSAVE
9538 | HM_CHANGED_GUEST_XCRx
9539 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9540 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9541 | HM_CHANGED_GUEST_TSC_AUX
9542 | HM_CHANGED_GUEST_OTHER_MSRS
9543 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9544
9545 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9546 return rc;
9547}
9548
9549
9550/**
9551 * Exports the state shared between the host and guest into the VMCS.
9552 *
9553 * @param pVCpu The cross context virtual CPU structure.
9554 * @param pVmxTransient The VMX-transient structure.
9555 *
9556 * @remarks No-long-jump zone!!!
9557 */
9558static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9559{
9560 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9561 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9562
9563 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9564 {
9565 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9566 AssertRC(rc);
9567 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9568
9569 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9570 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9571 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9572 }
9573
9574 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9575 {
9576 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9577 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9578 }
9579
9580 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9581 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9582}
9583
9584
9585/**
9586 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9587 *
9588 * @returns Strict VBox status code (i.e. informational status codes too).
9589 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9590 * without unrestricted guest execution and the VMMDev is not presently
9591 * mapped (e.g. EFI32).
9592 *
9593 * @param pVCpu The cross context virtual CPU structure.
9594 * @param pVmxTransient The VMX-transient structure.
9595 *
9596 * @remarks No-long-jump zone!!!
9597 */
9598static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9599{
9600 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9601 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9602 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9603
9604#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9605 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9606#endif
9607
9608 /*
9609 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9610 * changes. First try to export only these without going through all other changed-flag checks.
9611 */
9612 VBOXSTRICTRC rcStrict;
9613 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9614 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9615 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9616
9617 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9618 if ( (fCtxChanged & fMinimalMask)
9619 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9620 {
9621 hmR0VmxExportGuestRip(pVCpu);
9622 hmR0VmxExportGuestRsp(pVCpu);
9623 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9624 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9625 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9626 }
9627 /* If anything else also changed, go through the full export routine and export as required. */
9628 else if (fCtxChanged & fCtxMask)
9629 {
9630 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9631 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9632 { /* likely */}
9633 else
9634 {
9635 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9636 VBOXSTRICTRC_VAL(rcStrict)));
9637 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9638 return rcStrict;
9639 }
9640 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9641 }
9642 /* Nothing changed, nothing to load here. */
9643 else
9644 rcStrict = VINF_SUCCESS;
9645
9646#ifdef VBOX_STRICT
9647 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9648 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9649 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9650#endif
9651 return rcStrict;
9652}
9653
9654
9655/**
9656 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9657 * and update error record fields accordingly.
9658 *
9659 * @returns VMX_IGS_* error codes.
9660 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9661 * wrong with the guest state.
9662 *
9663 * @param pVCpu The cross context virtual CPU structure.
9664 * @param pVmcsInfo The VMCS info. object.
9665 *
9666 * @remarks This function assumes our cache of the VMCS controls
9667 * are valid, i.e. hmR0VmxCheckCachedVmcsCtls() succeeded.
9668 */
9669static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9670{
9671#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9672#define HMVMX_CHECK_BREAK(expr, err) do { \
9673 if (!(expr)) { uError = (err); break; } \
9674 } while (0)
9675
9676 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9677 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9678 uint32_t uError = VMX_IGS_ERROR;
9679 uint32_t u32IntrState = 0;
9680 bool const fUnrestrictedGuest = pVM->hmr0.s.vmx.fUnrestrictedGuest;
9681 do
9682 {
9683 int rc;
9684
9685 /*
9686 * Guest-interruptibility state.
9687 *
9688 * Read this first so that any check that fails prior to those that actually
9689 * require the guest-interruptibility state would still reflect the correct
9690 * VMCS value and avoids causing further confusion.
9691 */
9692 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9693 AssertRC(rc);
9694
9695 uint32_t u32Val;
9696 uint64_t u64Val;
9697
9698 /*
9699 * CR0.
9700 */
9701 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9702 uint64_t fSetCr0 = (g_HmMsrs.u.vmx.u64Cr0Fixed0 & g_HmMsrs.u.vmx.u64Cr0Fixed1);
9703 uint64_t const fZapCr0 = (g_HmMsrs.u.vmx.u64Cr0Fixed0 | g_HmMsrs.u.vmx.u64Cr0Fixed1);
9704 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9705 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9706 if (fUnrestrictedGuest)
9707 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9708
9709 uint64_t u64GuestCr0;
9710 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9711 AssertRC(rc);
9712 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9713 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9714 if ( !fUnrestrictedGuest
9715 && (u64GuestCr0 & X86_CR0_PG)
9716 && !(u64GuestCr0 & X86_CR0_PE))
9717 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9718
9719 /*
9720 * CR4.
9721 */
9722 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9723 uint64_t const fSetCr4 = (g_HmMsrs.u.vmx.u64Cr4Fixed0 & g_HmMsrs.u.vmx.u64Cr4Fixed1);
9724 uint64_t const fZapCr4 = (g_HmMsrs.u.vmx.u64Cr4Fixed0 | g_HmMsrs.u.vmx.u64Cr4Fixed1);
9725
9726 uint64_t u64GuestCr4;
9727 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9728 AssertRC(rc);
9729 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9730 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9731
9732 /*
9733 * IA32_DEBUGCTL MSR.
9734 */
9735 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9736 AssertRC(rc);
9737 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9738 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9739 {
9740 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9741 }
9742 uint64_t u64DebugCtlMsr = u64Val;
9743
9744#ifdef VBOX_STRICT
9745 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9746 AssertRC(rc);
9747 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9748#endif
9749 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9750
9751 /*
9752 * RIP and RFLAGS.
9753 */
9754 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9755 AssertRC(rc);
9756 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9757 if ( !fLongModeGuest
9758 || !pCtx->cs.Attr.n.u1Long)
9759 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9760 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9761 * must be identical if the "IA-32e mode guest" VM-entry
9762 * control is 1 and CS.L is 1. No check applies if the
9763 * CPU supports 64 linear-address bits. */
9764
9765 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9766 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9767 AssertRC(rc);
9768 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9769 VMX_IGS_RFLAGS_RESERVED);
9770 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9771 uint32_t const u32Eflags = u64Val;
9772
9773 if ( fLongModeGuest
9774 || ( fUnrestrictedGuest
9775 && !(u64GuestCr0 & X86_CR0_PE)))
9776 {
9777 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9778 }
9779
9780 uint32_t u32EntryInfo;
9781 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9782 AssertRC(rc);
9783 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9784 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9785
9786 /*
9787 * 64-bit checks.
9788 */
9789 if (fLongModeGuest)
9790 {
9791 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9792 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9793 }
9794
9795 if ( !fLongModeGuest
9796 && (u64GuestCr4 & X86_CR4_PCIDE))
9797 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9798
9799 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9800 * 51:32 beyond the processor's physical-address width are 0. */
9801
9802 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9803 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9804 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9805
9806 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9807 AssertRC(rc);
9808 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9809
9810 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9811 AssertRC(rc);
9812 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9813
9814 /*
9815 * PERF_GLOBAL MSR.
9816 */
9817 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9818 {
9819 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9820 AssertRC(rc);
9821 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9822 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9823 }
9824
9825 /*
9826 * PAT MSR.
9827 */
9828 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9829 {
9830 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9831 AssertRC(rc);
9832 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9833 for (unsigned i = 0; i < 8; i++)
9834 {
9835 uint8_t u8Val = (u64Val & 0xff);
9836 if ( u8Val != 0 /* UC */
9837 && u8Val != 1 /* WC */
9838 && u8Val != 4 /* WT */
9839 && u8Val != 5 /* WP */
9840 && u8Val != 6 /* WB */
9841 && u8Val != 7 /* UC- */)
9842 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9843 u64Val >>= 8;
9844 }
9845 }
9846
9847 /*
9848 * EFER MSR.
9849 */
9850 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9851 {
9852 Assert(g_fHmVmxSupportsVmcsEfer);
9853 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9854 AssertRC(rc);
9855 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9856 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9857 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9858 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9859 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9860 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9861 * iemVmxVmentryCheckGuestState(). */
9862 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9863 || !(u64GuestCr0 & X86_CR0_PG)
9864 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9865 VMX_IGS_EFER_LMA_LME_MISMATCH);
9866 }
9867
9868 /*
9869 * Segment registers.
9870 */
9871 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9872 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9873 if (!(u32Eflags & X86_EFL_VM))
9874 {
9875 /* CS */
9876 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9877 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9878 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9879 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9880 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9881 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9882 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9883 /* CS cannot be loaded with NULL in protected mode. */
9884 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9885 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9886 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9887 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9888 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9889 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9890 else if (fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9891 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9892 else
9893 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9894
9895 /* SS */
9896 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9897 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9898 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9899 if ( !(pCtx->cr0 & X86_CR0_PE)
9900 || pCtx->cs.Attr.n.u4Type == 3)
9901 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9902
9903 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9904 {
9905 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9906 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9907 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9908 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9909 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9910 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9911 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9912 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9913 }
9914
9915 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9916 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9917 {
9918 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9919 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9920 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9921 || pCtx->ds.Attr.n.u4Type > 11
9922 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9923 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9924 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9925 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9926 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9927 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9928 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9929 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9930 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9931 }
9932 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9933 {
9934 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9935 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9936 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9937 || pCtx->es.Attr.n.u4Type > 11
9938 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9939 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9940 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9941 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9942 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9943 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9944 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9945 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9946 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9947 }
9948 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9949 {
9950 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9951 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9952 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9953 || pCtx->fs.Attr.n.u4Type > 11
9954 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9955 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9956 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9957 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9958 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9959 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9960 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9961 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9962 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9963 }
9964 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9965 {
9966 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9967 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9968 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9969 || pCtx->gs.Attr.n.u4Type > 11
9970 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9971 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9972 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9973 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9974 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9975 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9976 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9977 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9978 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9979 }
9980 /* 64-bit capable CPUs. */
9981 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9982 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9983 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9984 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9985 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9986 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9987 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9988 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9989 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9990 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9991 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9992 }
9993 else
9994 {
9995 /* V86 mode checks. */
9996 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9997 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
9998 {
9999 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
10000 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
10001 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
10002 }
10003 else
10004 {
10005 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
10006 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
10007 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
10008 }
10009
10010 /* CS */
10011 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10012 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10013 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10014 /* SS */
10015 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10016 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10017 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10018 /* DS */
10019 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10020 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10021 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10022 /* ES */
10023 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10024 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10025 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10026 /* FS */
10027 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10028 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10029 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10030 /* GS */
10031 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10032 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10033 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10034 /* 64-bit capable CPUs. */
10035 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10036 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10037 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10038 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10039 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10040 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10041 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10042 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10043 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10044 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10045 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10046 }
10047
10048 /*
10049 * TR.
10050 */
10051 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10052 /* 64-bit capable CPUs. */
10053 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10054 if (fLongModeGuest)
10055 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10056 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10057 else
10058 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10059 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10060 VMX_IGS_TR_ATTR_TYPE_INVALID);
10061 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10062 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10063 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10064 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10065 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10066 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10067 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10068 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10069
10070 /*
10071 * GDTR and IDTR (64-bit capable checks).
10072 */
10073 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10074 AssertRC(rc);
10075 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10076
10077 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10078 AssertRC(rc);
10079 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10080
10081 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10082 AssertRC(rc);
10083 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10084
10085 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10086 AssertRC(rc);
10087 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10088
10089 /*
10090 * Guest Non-Register State.
10091 */
10092 /* Activity State. */
10093 uint32_t u32ActivityState;
10094 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10095 AssertRC(rc);
10096 HMVMX_CHECK_BREAK( !u32ActivityState
10097 || (u32ActivityState & RT_BF_GET(g_HmMsrs.u.vmx.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10098 VMX_IGS_ACTIVITY_STATE_INVALID);
10099 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10100 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10101
10102 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10103 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10104 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10105
10106 /** @todo Activity state and injecting interrupts. Left as a todo since we
10107 * currently don't use activity states but ACTIVE. */
10108
10109 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10110 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10111
10112 /* Guest interruptibility-state. */
10113 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10114 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10115 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10116 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10117 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10118 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10119 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10120 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10121 {
10122 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10123 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10124 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10125 }
10126 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10127 {
10128 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10129 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10130 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10131 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10132 }
10133 /** @todo Assumes the processor is not in SMM. */
10134 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10135 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10136 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10137 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10138 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10139 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10140 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10141 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10142
10143 /* Pending debug exceptions. */
10144 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10145 AssertRC(rc);
10146 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10147 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10148 u32Val = u64Val; /* For pending debug exceptions checks below. */
10149
10150 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10151 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10152 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10153 {
10154 if ( (u32Eflags & X86_EFL_TF)
10155 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10156 {
10157 /* Bit 14 is PendingDebug.BS. */
10158 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10159 }
10160 if ( !(u32Eflags & X86_EFL_TF)
10161 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10162 {
10163 /* Bit 14 is PendingDebug.BS. */
10164 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10165 }
10166 }
10167
10168 /* VMCS link pointer. */
10169 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10170 AssertRC(rc);
10171 if (u64Val != UINT64_C(0xffffffffffffffff))
10172 {
10173 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10174 /** @todo Bits beyond the processor's physical-address width MBZ. */
10175 /** @todo SMM checks. */
10176 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10177 Assert(pVmcsInfo->pvShadowVmcs);
10178 VMXVMCSREVID VmcsRevId;
10179 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10180 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID),
10181 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10182 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10183 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10184 }
10185
10186 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10187 * not using nested paging? */
10188 if ( pVM->hmr0.s.fNestedPaging
10189 && !fLongModeGuest
10190 && CPUMIsGuestInPAEModeEx(pCtx))
10191 {
10192 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10193 AssertRC(rc);
10194 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10195
10196 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10197 AssertRC(rc);
10198 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10199
10200 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10201 AssertRC(rc);
10202 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10203
10204 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10205 AssertRC(rc);
10206 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10207 }
10208
10209 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10210 if (uError == VMX_IGS_ERROR)
10211 uError = VMX_IGS_REASON_NOT_FOUND;
10212 } while (0);
10213
10214 pVCpu->hm.s.u32HMError = uError;
10215 pVCpu->hm.s.vmx.LastError.u32GuestIntrState = u32IntrState;
10216 return uError;
10217
10218#undef HMVMX_ERROR_BREAK
10219#undef HMVMX_CHECK_BREAK
10220}
10221
10222
10223/**
10224 * Map the APIC-access page for virtualizing APIC accesses.
10225 *
10226 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10227 * this not done as part of exporting guest state, see @bugref{8721}.
10228 *
10229 * @returns VBox status code.
10230 * @param pVCpu The cross context virtual CPU structure.
10231 */
10232static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
10233{
10234 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10235 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10236
10237 Assert(PDMHasApic(pVM));
10238 Assert(u64MsrApicBase);
10239
10240 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10241 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10242
10243 /* Unalias the existing mapping. */
10244 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10245 AssertRCReturn(rc, rc);
10246
10247 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10248 Assert(pVM->hmr0.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10249 rc = IOMR0MmioMapMmioHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hmr0.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10250 AssertRCReturn(rc, rc);
10251
10252 /* Update the per-VCPU cache of the APIC base MSR. */
10253 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10254 return VINF_SUCCESS;
10255}
10256
10257
10258/**
10259 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10260 * CPU.
10261 *
10262 * @param idCpu The ID for the CPU the function is called on.
10263 * @param pvUser1 Null, not used.
10264 * @param pvUser2 Null, not used.
10265 */
10266static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10267{
10268 RT_NOREF3(idCpu, pvUser1, pvUser2);
10269 VMXDispatchHostNmi();
10270}
10271
10272
10273/**
10274 * Dispatching an NMI on the host CPU that received it.
10275 *
10276 * @returns VBox status code.
10277 * @param pVCpu The cross context virtual CPU structure.
10278 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10279 * executing when receiving the host NMI in VMX non-root
10280 * operation.
10281 */
10282static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
10283{
10284 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
10285 Assert(idCpu != NIL_RTCPUID);
10286
10287 /*
10288 * We don't want to delay dispatching the NMI any more than we have to. However,
10289 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10290 * after executing guest or nested-guest code for the following reasons:
10291 *
10292 * - We would need to perform VMREADs with interrupts disabled and is orders of
10293 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
10294 * supported by the host hypervisor.
10295 *
10296 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10297 * longer period of time just for handling an edge case like host NMIs which do
10298 * not occur nearly as frequently as other VM-exits.
10299 *
10300 * Let's cover the most likely scenario first. Check if we are on the target CPU
10301 * and dispatch the NMI right away. This should be much faster than calling into
10302 * RTMpOnSpecific() machinery.
10303 */
10304 bool fDispatched = false;
10305 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10306 if (idCpu == RTMpCpuId())
10307 {
10308 VMXDispatchHostNmi();
10309 fDispatched = true;
10310 }
10311 ASMSetFlags(fEFlags);
10312 if (fDispatched)
10313 {
10314 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10315 return VINF_SUCCESS;
10316 }
10317
10318 /*
10319 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10320 * there should be no race or recursion even if we are unlucky enough to be preempted
10321 * (to the target CPU) without dispatching the host NMI above.
10322 */
10323 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10324 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10325}
10326
10327
10328#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10329/**
10330 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10331 * nested-guest using hardware-assisted VMX.
10332 *
10333 * @param pVCpu The cross context virtual CPU structure.
10334 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10335 * @param pVmcsInfoGst The guest VMCS info. object.
10336 */
10337static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10338{
10339 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10340 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10341 Assert(pu64MsrBitmap);
10342
10343 /*
10344 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10345 * MSR that is intercepted by the guest is also intercepted while executing the
10346 * nested-guest using hardware-assisted VMX.
10347 *
10348 * Note! If the nested-guest is not using an MSR bitmap, every MSR must cause a
10349 * nested-guest VM-exit even if the outer guest is not intercepting some
10350 * MSRs. We cannot assume the caller has initialized the nested-guest
10351 * MSR bitmap in this case.
10352 *
10353 * The nested hypervisor may also switch whether it uses MSR bitmaps for
10354 * each of its VM-entry, hence initializing it once per-VM while setting
10355 * up the nested-guest VMCS is not sufficient.
10356 */
10357 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10358 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10359 {
10360 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10361 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10362 Assert(pu64MsrBitmapNstGst);
10363 Assert(pu64MsrBitmapGst);
10364
10365 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10366 for (uint32_t i = 0; i < cFrags; i++)
10367 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10368 }
10369 else
10370 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10371}
10372
10373
10374/**
10375 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10376 * hardware-assisted VMX execution of the nested-guest.
10377 *
10378 * For a guest, we don't modify these controls once we set up the VMCS and hence
10379 * this function is never called.
10380 *
10381 * For nested-guests since the nested hypervisor provides these controls on every
10382 * nested-guest VM-entry and could potentially change them everytime we need to
10383 * merge them before every nested-guest VM-entry.
10384 *
10385 * @returns VBox status code.
10386 * @param pVCpu The cross context virtual CPU structure.
10387 */
10388static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
10389{
10390 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10391 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
10392 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10393 Assert(pVmcsNstGst);
10394
10395 /*
10396 * Merge the controls with the requirements of the guest VMCS.
10397 *
10398 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10399 * VMCS with the features supported by the physical CPU as it's already done by the
10400 * VMLAUNCH/VMRESUME instruction emulation.
10401 *
10402 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10403 * derived from the VMX features supported by the physical CPU.
10404 */
10405
10406 /* Pin-based VM-execution controls. */
10407 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10408
10409 /* Processor-based VM-execution controls. */
10410 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10411 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10412 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10413 | VMX_PROC_CTLS_USE_TPR_SHADOW
10414 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10415
10416 /* Secondary processor-based VM-execution controls. */
10417 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10418 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10419 | VMX_PROC_CTLS2_INVPCID
10420 | VMX_PROC_CTLS2_VMCS_SHADOWING
10421 | VMX_PROC_CTLS2_RDTSCP
10422 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10423 | VMX_PROC_CTLS2_APIC_REG_VIRT
10424 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10425 | VMX_PROC_CTLS2_VMFUNC));
10426
10427 /*
10428 * VM-entry controls:
10429 * These controls contains state that depends on the nested-guest state (primarily
10430 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10431 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
10432 * properly continue executing the nested-guest if the EFER MSR changes but does not
10433 * cause a nested-guest VM-exits.
10434 *
10435 * VM-exit controls:
10436 * These controls specify the host state on return. We cannot use the controls from
10437 * the nested hypervisor state as is as it would contain the guest state rather than
10438 * the host state. Since the host state is subject to change (e.g. preemption, trips
10439 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10440 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10441 *
10442 * VM-entry MSR-load:
10443 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10444 * context by the VMLAUNCH/VMRESUME instruction emulation.
10445 *
10446 * VM-exit MSR-store:
10447 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10448 * back into the VM-exit MSR-store area.
10449 *
10450 * VM-exit MSR-load areas:
10451 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10452 * can entirely ignore what the nested hypervisor wants to load here.
10453 */
10454
10455 /*
10456 * Exception bitmap.
10457 *
10458 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10459 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10460 * code more flexible if intercepting exceptions become more dynamic in the future we do
10461 * it as part of exporting the nested-guest state.
10462 */
10463 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10464
10465 /*
10466 * CR0/CR4 guest/host mask.
10467 *
10468 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10469 * cause VM-exits, so we need to merge them here.
10470 */
10471 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10472 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10473
10474 /*
10475 * Page-fault error-code mask and match.
10476 *
10477 * Although we require unrestricted guest execution (and thereby nested-paging) for
10478 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10479 * normally intercept #PFs, it might intercept them for debugging purposes.
10480 *
10481 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10482 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10483 */
10484 uint32_t u32XcptPFMask;
10485 uint32_t u32XcptPFMatch;
10486 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10487 {
10488 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10489 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10490 }
10491 else
10492 {
10493 u32XcptPFMask = 0;
10494 u32XcptPFMatch = 0;
10495 }
10496
10497 /*
10498 * Pause-Loop exiting.
10499 */
10500 /** @todo r=bird: given that both pVM->hm.s.vmx.cPleGapTicks and
10501 * pVM->hm.s.vmx.cPleWindowTicks defaults to zero, I cannot see how
10502 * this will work... */
10503 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10504 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10505
10506 /*
10507 * Pending debug exceptions.
10508 * Currently just copy whatever the nested-guest provides us.
10509 */
10510 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10511
10512 /*
10513 * I/O Bitmap.
10514 *
10515 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10516 * intercept all I/O port accesses.
10517 */
10518 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10519 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10520
10521 /*
10522 * VMCS shadowing.
10523 *
10524 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10525 * enabled while executing the nested-guest.
10526 */
10527 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10528
10529 /*
10530 * APIC-access page.
10531 */
10532 RTHCPHYS HCPhysApicAccess;
10533 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10534 {
10535 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10536 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10537
10538 /** @todo NSTVMX: This is not really correct but currently is required to make
10539 * things work. We need to re-enable the page handler when we fallback to
10540 * IEM execution of the nested-guest! */
10541 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10542
10543 void *pvPage;
10544 PGMPAGEMAPLOCK PgLockApicAccess;
10545 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10546 if (RT_SUCCESS(rc))
10547 {
10548 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10549 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10550
10551 /** @todo Handle proper releasing of page-mapping lock later. */
10552 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10553 }
10554 else
10555 return rc;
10556 }
10557 else
10558 HCPhysApicAccess = 0;
10559
10560 /*
10561 * Virtual-APIC page and TPR threshold.
10562 */
10563 RTHCPHYS HCPhysVirtApic;
10564 uint32_t u32TprThreshold;
10565 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10566 {
10567 Assert(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10568 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10569
10570 void *pvPage;
10571 PGMPAGEMAPLOCK PgLockVirtApic;
10572 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10573 if (RT_SUCCESS(rc))
10574 {
10575 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10576 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10577
10578 /** @todo Handle proper releasing of page-mapping lock later. */
10579 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10580 }
10581 else
10582 return rc;
10583
10584 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10585 }
10586 else
10587 {
10588 HCPhysVirtApic = 0;
10589 u32TprThreshold = 0;
10590
10591 /*
10592 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10593 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10594 * be taken care of by EPT/shadow paging.
10595 */
10596 if (pVM->hmr0.s.fAllow64BitGuests)
10597 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10598 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10599 }
10600
10601 /*
10602 * Validate basic assumptions.
10603 */
10604 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
10605 Assert(pVM->hmr0.s.vmx.fUnrestrictedGuest);
10606 Assert(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10607 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10608
10609 /*
10610 * Commit it to the nested-guest VMCS.
10611 */
10612 int rc = VINF_SUCCESS;
10613 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10614 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10615 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10616 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10617 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10618 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10619 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10620 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10621 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10622 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10623 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10624 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10625 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10626 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10627 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10628 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10629 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10630 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10631 {
10632 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10633 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10634 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10635 }
10636 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10637 {
10638 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10639 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10640 }
10641 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10642 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10643 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10644 AssertRC(rc);
10645
10646 /*
10647 * Update the nested-guest VMCS cache.
10648 */
10649 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10650 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10651 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10652 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10653 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10654 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10655 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10656 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10657 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10658
10659 /*
10660 * We need to flush the TLB if we are switching the APIC-access page address.
10661 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10662 */
10663 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10664 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10665
10666 /*
10667 * MSR bitmap.
10668 *
10669 * The MSR bitmap address has already been initialized while setting up the nested-guest
10670 * VMCS, here we need to merge the MSR bitmaps.
10671 */
10672 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10673 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10674
10675 return VINF_SUCCESS;
10676}
10677#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10678
10679
10680/**
10681 * Does the preparations before executing guest code in VT-x.
10682 *
10683 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10684 * recompiler/IEM. We must be cautious what we do here regarding committing
10685 * guest-state information into the VMCS assuming we assuredly execute the
10686 * guest in VT-x mode.
10687 *
10688 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10689 * the common-state (TRPM/forceflags), we must undo those changes so that the
10690 * recompiler/IEM can (and should) use them when it resumes guest execution.
10691 * Otherwise such operations must be done when we can no longer exit to ring-3.
10692 *
10693 * @returns Strict VBox status code (i.e. informational status codes too).
10694 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10695 * have been disabled.
10696 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10697 * pending events).
10698 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10699 * double-fault into the guest.
10700 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10701 * dispatched directly.
10702 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10703 *
10704 * @param pVCpu The cross context virtual CPU structure.
10705 * @param pVmxTransient The VMX-transient structure.
10706 * @param fStepping Whether we are single-stepping the guest in the
10707 * hypervisor debugger. Makes us ignore some of the reasons
10708 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10709 * if event dispatching took place.
10710 */
10711static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10712{
10713 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10714
10715 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10716
10717#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10718 if (pVmxTransient->fIsNestedGuest)
10719 {
10720 RT_NOREF2(pVCpu, fStepping);
10721 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10722 return VINF_EM_RESCHEDULE_REM;
10723 }
10724#endif
10725
10726 /*
10727 * Check and process force flag actions, some of which might require us to go back to ring-3.
10728 */
10729 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, pVmxTransient, fStepping);
10730 if (rcStrict == VINF_SUCCESS)
10731 {
10732 /* FFs don't get set all the time. */
10733#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10734 if ( pVmxTransient->fIsNestedGuest
10735 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10736 {
10737 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10738 return VINF_VMX_VMEXIT;
10739 }
10740#endif
10741 }
10742 else
10743 return rcStrict;
10744
10745 /*
10746 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10747 */
10748 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10749 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10750 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10751 && PDMHasApic(pVM))
10752 {
10753 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10754 AssertRCReturn(rc, rc);
10755 }
10756
10757#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10758 /*
10759 * Merge guest VMCS controls with the nested-guest VMCS controls.
10760 *
10761 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10762 * saved state), we should be okay with merging controls as we initialize the
10763 * guest VMCS controls as part of VM setup phase.
10764 */
10765 if ( pVmxTransient->fIsNestedGuest
10766 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10767 {
10768 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10769 AssertRCReturn(rc, rc);
10770 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10771 }
10772#endif
10773
10774 /*
10775 * Evaluate events to be injected into the guest.
10776 *
10777 * Events in TRPM can be injected without inspecting the guest state.
10778 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10779 * guest to cause a VM-exit the next time they are ready to receive the event.
10780 *
10781 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10782 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10783 * subject to interecption. Otherwise, we should have checked and injected them
10784 * manually elsewhere (IEM).
10785 */
10786 if (TRPMHasTrap(pVCpu))
10787 {
10788 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10789 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10790 }
10791
10792 uint32_t fIntrState;
10793 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10794
10795#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10796 /*
10797 * While evaluating pending events if something failed (unlikely) or if we were
10798 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10799 */
10800 if (rcStrict != VINF_SUCCESS)
10801 return rcStrict;
10802 if ( pVmxTransient->fIsNestedGuest
10803 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10804 {
10805 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10806 return VINF_VMX_VMEXIT;
10807 }
10808#else
10809 Assert(rcStrict == VINF_SUCCESS);
10810#endif
10811
10812 /*
10813 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10814 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10815 * also result in triple-faulting the VM.
10816 *
10817 * With nested-guests, the above does not apply since unrestricted guest execution is a
10818 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10819 */
10820 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10821 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10822 { /* likely */ }
10823 else
10824 {
10825 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10826 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10827 return rcStrict;
10828 }
10829
10830 /*
10831 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10832 * import CR3 themselves. We will need to update them here, as even as late as the above
10833 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10834 * the below force flags to be set.
10835 */
10836 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10837 {
10838 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10839 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10840 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10841 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10842 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10843 }
10844 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10845 {
10846 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10847 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10848 }
10849
10850#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10851 /* Paranoia. */
10852 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10853#endif
10854
10855 /*
10856 * No longjmps to ring-3 from this point on!!!
10857 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10858 * This also disables flushing of the R0-logger instance (if any).
10859 */
10860 VMMRZCallRing3Disable(pVCpu);
10861
10862 /*
10863 * Export the guest state bits.
10864 *
10865 * We cannot perform longjmps while loading the guest state because we do not preserve the
10866 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10867 * CPU migration.
10868 *
10869 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10870 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10871 */
10872 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10873 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10874 { /* likely */ }
10875 else
10876 {
10877 VMMRZCallRing3Enable(pVCpu);
10878 return rcStrict;
10879 }
10880
10881 /*
10882 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10883 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10884 * preemption disabled for a while. Since this is purely to aid the
10885 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10886 * disable interrupt on NT.
10887 *
10888 * We need to check for force-flags that could've possible been altered since we last
10889 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10890 * see @bugref{6398}).
10891 *
10892 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10893 * to ring-3 before executing guest code.
10894 */
10895 pVmxTransient->fEFlags = ASMIntDisableFlags();
10896
10897 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10898 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10899 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10900 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10901 {
10902 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10903 {
10904#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10905 /*
10906 * If we are executing a nested-guest make sure that we should intercept subsequent
10907 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10908 * the VM-exit instruction emulation happy.
10909 */
10910 if (pVmxTransient->fIsNestedGuest)
10911 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10912#endif
10913
10914 /*
10915 * We've injected any pending events. This is really the point of no return (to ring-3).
10916 *
10917 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10918 * returns from this function, so do -not- enable them here.
10919 */
10920 pVCpu->hm.s.Event.fPending = false;
10921 return VINF_SUCCESS;
10922 }
10923
10924 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10925 rcStrict = VINF_EM_RAW_INTERRUPT;
10926 }
10927 else
10928 {
10929 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10930 rcStrict = VINF_EM_RAW_TO_R3;
10931 }
10932
10933 ASMSetFlags(pVmxTransient->fEFlags);
10934 VMMRZCallRing3Enable(pVCpu);
10935
10936 return rcStrict;
10937}
10938
10939
10940/**
10941 * Final preparations before executing guest code using hardware-assisted VMX.
10942 *
10943 * We can no longer get preempted to a different host CPU and there are no returns
10944 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10945 * failures), this function is not intended to fail sans unrecoverable hardware
10946 * errors.
10947 *
10948 * @param pVCpu The cross context virtual CPU structure.
10949 * @param pVmxTransient The VMX-transient structure.
10950 *
10951 * @remarks Called with preemption disabled.
10952 * @remarks No-long-jump zone!!!
10953 */
10954static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10955{
10956 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10957 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10958 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10959 Assert(!pVCpu->hm.s.Event.fPending);
10960
10961 /*
10962 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10963 */
10964 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10965 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10966
10967 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10968 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10969 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10970 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10971
10972 if (!CPUMIsGuestFPUStateActive(pVCpu))
10973 {
10974 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10975 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10976 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10977 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10978 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10979 }
10980
10981 /*
10982 * Re-export the host state bits as we may've been preempted (only happens when
10983 * thread-context hooks are used or when the VM start function changes) or if
10984 * the host CR0 is modified while loading the guest FPU state above.
10985 *
10986 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10987 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10988 * see @bugref{8432}.
10989 *
10990 * This may also happen when switching to/from a nested-guest VMCS without leaving
10991 * ring-0.
10992 */
10993 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10994 {
10995 hmR0VmxExportHostState(pVCpu);
10996 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10997 }
10998 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10999
11000 /*
11001 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
11002 */
11003 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
11004 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
11005 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
11006
11007 /*
11008 * Store status of the shared guest/host debug state at the time of VM-entry.
11009 */
11010 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
11011 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11012
11013 /*
11014 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11015 * more than one conditional check. The post-run side of our code shall determine
11016 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11017 */
11018 if (pVmcsInfo->pbVirtApic)
11019 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11020
11021 /*
11022 * Update the host MSRs values in the VM-exit MSR-load area.
11023 */
11024 if (!pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs)
11025 {
11026 if (pVmcsInfo->cExitMsrLoad > 0)
11027 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11028 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = true;
11029 }
11030
11031 /*
11032 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11033 * VMX-preemption timer based on the next virtual sync clock deadline.
11034 */
11035 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11036 || idCurrentCpu != pVCpu->hmr0.s.idLastCpu)
11037 {
11038 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
11039 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11040 }
11041
11042 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11043 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11044 if (!fIsRdtscIntercepted)
11045 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11046 else
11047 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11048
11049 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11050 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11051 Assert(idCurrentCpu == pVCpu->hmr0.s.idLastCpu);
11052 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
11053 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
11054 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
11055
11056 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11057
11058 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11059 as we're about to start executing the guest. */
11060
11061 /*
11062 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11063 *
11064 * This is done this late as updating the TSC offsetting/preemption timer above
11065 * figures out if we can skip intercepting RDTSCP by calculating the number of
11066 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11067 */
11068 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11069 && !fIsRdtscIntercepted)
11070 {
11071 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11072
11073 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11074 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11075 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11076 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11077 AssertRC(rc);
11078 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11079 pVmxTransient->fRemoveTscAuxMsr = true;
11080 }
11081
11082#ifdef VBOX_STRICT
11083 Assert(pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs);
11084 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11085 hmR0VmxCheckHostEferMsr(pVmcsInfo);
11086 AssertRC(hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11087#endif
11088
11089#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11090 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11091 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11092 * see @bugref{9180#c54}. */
11093 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11094 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11095 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11096#endif
11097}
11098
11099
11100/**
11101 * First C routine invoked after running guest code using hardware-assisted VMX.
11102 *
11103 * @param pVCpu The cross context virtual CPU structure.
11104 * @param pVmxTransient The VMX-transient structure.
11105 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11106 *
11107 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11108 *
11109 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11110 * unconditionally when it is safe to do so.
11111 */
11112static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11113{
11114 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
11115
11116 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11117 ASMAtomicIncU32(&pVCpu->hmr0.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11118 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11119 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11120 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11121 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11122
11123 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11124 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11125 {
11126 uint64_t uGstTsc;
11127 if (!pVmxTransient->fIsNestedGuest)
11128 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11129 else
11130 {
11131 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11132 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11133 }
11134 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11135 }
11136
11137 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11138 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
11139 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11140
11141 pVCpu->hmr0.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11142 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11143#ifdef VBOX_STRICT
11144 hmR0VmxCheckHostEferMsr(pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11145#endif
11146 Assert(!ASMIntAreEnabled());
11147 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11148 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11149
11150#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11151 /*
11152 * Clean all the VMCS fields in the transient structure before reading
11153 * anything from the VMCS.
11154 */
11155 pVmxTransient->uExitReason = 0;
11156 pVmxTransient->uExitIntErrorCode = 0;
11157 pVmxTransient->uExitQual = 0;
11158 pVmxTransient->uGuestLinearAddr = 0;
11159 pVmxTransient->uExitIntInfo = 0;
11160 pVmxTransient->cbExitInstr = 0;
11161 pVmxTransient->ExitInstrInfo.u = 0;
11162 pVmxTransient->uEntryIntInfo = 0;
11163 pVmxTransient->uEntryXcptErrorCode = 0;
11164 pVmxTransient->cbEntryInstr = 0;
11165 pVmxTransient->uIdtVectoringInfo = 0;
11166 pVmxTransient->uIdtVectoringErrorCode = 0;
11167#endif
11168
11169 /*
11170 * Save the basic VM-exit reason and check if the VM-entry failed.
11171 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11172 */
11173 uint32_t uExitReason;
11174 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11175 AssertRC(rc);
11176 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11177 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11178
11179 /*
11180 * Log the VM-exit before logging anything else as otherwise it might be a
11181 * tad confusing what happens before and after the world-switch.
11182 */
11183 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11184
11185 /*
11186 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11187 * bitmap permissions, if it was added before VM-entry.
11188 */
11189 if (pVmxTransient->fRemoveTscAuxMsr)
11190 {
11191 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11192 pVmxTransient->fRemoveTscAuxMsr = false;
11193 }
11194
11195 /*
11196 * Check if VMLAUNCH/VMRESUME succeeded.
11197 * If this failed, we cause a guru meditation and cease further execution.
11198 *
11199 * However, if we are executing a nested-guest we might fail if we use the
11200 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11201 */
11202 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11203 {
11204 /*
11205 * Update the VM-exit history array here even if the VM-entry failed due to:
11206 * - Invalid guest state.
11207 * - MSR loading.
11208 * - Machine-check event.
11209 *
11210 * In any of the above cases we will still have a "valid" VM-exit reason
11211 * despite @a fVMEntryFailed being false.
11212 *
11213 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11214 *
11215 * Note! We don't have CS or RIP at this point. Will probably address that later
11216 * by amending the history entry added here.
11217 */
11218 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11219 UINT64_MAX, uHostTsc);
11220
11221 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11222 {
11223 VMMRZCallRing3Enable(pVCpu);
11224
11225 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11226 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11227
11228#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
11229 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
11230#endif
11231
11232 /*
11233 * Import the guest-interruptibility state always as we need it while evaluating
11234 * injecting events on re-entry.
11235 *
11236 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11237 * checking for real-mode while exporting the state because all bits that cause
11238 * mode changes wrt CR0 are intercepted.
11239 */
11240 uint64_t const fImportMask = CPUMCTX_EXTRN_HM_VMX_INT_STATE
11241#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11242 | HMVMX_CPUMCTX_EXTRN_ALL
11243#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11244 | CPUMCTX_EXTRN_RFLAGS
11245#endif
11246 ;
11247 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImportMask);
11248 AssertRC(rc);
11249
11250 /*
11251 * Sync the TPR shadow with our APIC state.
11252 */
11253 if ( !pVmxTransient->fIsNestedGuest
11254 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
11255 {
11256 Assert(pVmcsInfo->pbVirtApic);
11257 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11258 {
11259 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11260 AssertRC(rc);
11261 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11262 }
11263 }
11264
11265 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11266 return;
11267 }
11268 }
11269#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11270 else if (pVmxTransient->fIsNestedGuest)
11271 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11272#endif
11273 else
11274 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11275
11276 VMMRZCallRing3Enable(pVCpu);
11277}
11278
11279
11280/**
11281 * Runs the guest code using hardware-assisted VMX the normal way.
11282 *
11283 * @returns VBox status code.
11284 * @param pVCpu The cross context virtual CPU structure.
11285 * @param pcLoops Pointer to the number of executed loops.
11286 */
11287static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
11288{
11289 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
11290 Assert(pcLoops);
11291 Assert(*pcLoops <= cMaxResumeLoops);
11292 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11293
11294#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11295 /*
11296 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11297 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11298 * guest VMCS while entering the VMX ring-0 session.
11299 */
11300 if (pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
11301 {
11302 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11303 if (RT_SUCCESS(rc))
11304 { /* likely */ }
11305 else
11306 {
11307 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11308 return rc;
11309 }
11310 }
11311#endif
11312
11313 VMXTRANSIENT VmxTransient;
11314 RT_ZERO(VmxTransient);
11315 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11316
11317 /* Paranoia. */
11318 Assert(VmxTransient.pVmcsInfo == &pVCpu->hmr0.s.vmx.VmcsInfo);
11319
11320 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11321 for (;;)
11322 {
11323 Assert(!HMR0SuspendPending());
11324 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11325 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11326
11327 /*
11328 * Preparatory work for running nested-guest code, this may force us to
11329 * return to ring-3.
11330 *
11331 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11332 */
11333 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11334 if (rcStrict != VINF_SUCCESS)
11335 break;
11336
11337 /* Interrupts are disabled at this point! */
11338 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11339 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11340 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11341 /* Interrupts are re-enabled at this point! */
11342
11343 /*
11344 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11345 */
11346 if (RT_SUCCESS(rcRun))
11347 { /* very likely */ }
11348 else
11349 {
11350 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11351 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11352 return rcRun;
11353 }
11354
11355 /*
11356 * Profile the VM-exit.
11357 */
11358 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11359 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11360 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11361 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11362 HMVMX_START_EXIT_DISPATCH_PROF();
11363
11364 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11365
11366 /*
11367 * Handle the VM-exit.
11368 */
11369#ifdef HMVMX_USE_FUNCTION_TABLE
11370 rcStrict = g_aVMExitHandlers[VmxTransient.uExitReason].pfn(pVCpu, &VmxTransient);
11371#else
11372 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11373#endif
11374 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11375 if (rcStrict == VINF_SUCCESS)
11376 {
11377 if (++(*pcLoops) <= cMaxResumeLoops)
11378 continue;
11379 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11380 rcStrict = VINF_EM_RAW_INTERRUPT;
11381 }
11382 break;
11383 }
11384
11385 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11386 return rcStrict;
11387}
11388
11389
11390#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11391/**
11392 * Runs the nested-guest code using hardware-assisted VMX.
11393 *
11394 * @returns VBox status code.
11395 * @param pVCpu The cross context virtual CPU structure.
11396 * @param pcLoops Pointer to the number of executed loops.
11397 *
11398 * @sa hmR0VmxRunGuestCodeNormal.
11399 */
11400static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
11401{
11402 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
11403 Assert(pcLoops);
11404 Assert(*pcLoops <= cMaxResumeLoops);
11405 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11406
11407 /*
11408 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11409 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11410 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11411 */
11412 if (!pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
11413 {
11414 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11415 if (RT_SUCCESS(rc))
11416 { /* likely */ }
11417 else
11418 {
11419 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11420 return rc;
11421 }
11422 }
11423
11424 VMXTRANSIENT VmxTransient;
11425 RT_ZERO(VmxTransient);
11426 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11427 VmxTransient.fIsNestedGuest = true;
11428
11429 /* Paranoia. */
11430 Assert(VmxTransient.pVmcsInfo == &pVCpu->hmr0.s.vmx.VmcsInfoNstGst);
11431
11432 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11433 for (;;)
11434 {
11435 Assert(!HMR0SuspendPending());
11436 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11437 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11438
11439 /*
11440 * Preparatory work for running guest code, this may force us to
11441 * return to ring-3.
11442 *
11443 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11444 */
11445 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11446 if (rcStrict != VINF_SUCCESS)
11447 break;
11448
11449 /* Interrupts are disabled at this point! */
11450 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11451 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11452 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11453 /* Interrupts are re-enabled at this point! */
11454
11455 /*
11456 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11457 */
11458 if (RT_SUCCESS(rcRun))
11459 { /* very likely */ }
11460 else
11461 {
11462 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11463 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11464 return rcRun;
11465 }
11466
11467 /*
11468 * Profile the VM-exit.
11469 */
11470 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11471 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11472 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11473 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11474 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11475 HMVMX_START_EXIT_DISPATCH_PROF();
11476
11477 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11478
11479 /*
11480 * Handle the VM-exit.
11481 */
11482 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11483 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11484 if (rcStrict == VINF_SUCCESS)
11485 {
11486 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11487 {
11488 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11489 rcStrict = VINF_VMX_VMEXIT;
11490 }
11491 else
11492 {
11493 if (++(*pcLoops) <= cMaxResumeLoops)
11494 continue;
11495 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11496 rcStrict = VINF_EM_RAW_INTERRUPT;
11497 }
11498 }
11499 else
11500 Assert(rcStrict != VINF_VMX_VMEXIT);
11501 break;
11502 }
11503
11504 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11505 return rcStrict;
11506}
11507#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11508
11509
11510/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11511 * probes.
11512 *
11513 * The following few functions and associated structure contains the bloat
11514 * necessary for providing detailed debug events and dtrace probes as well as
11515 * reliable host side single stepping. This works on the principle of
11516 * "subclassing" the normal execution loop and workers. We replace the loop
11517 * method completely and override selected helpers to add necessary adjustments
11518 * to their core operation.
11519 *
11520 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11521 * any performance for debug and analysis features.
11522 *
11523 * @{
11524 */
11525
11526/**
11527 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11528 * the debug run loop.
11529 */
11530typedef struct VMXRUNDBGSTATE
11531{
11532 /** The RIP we started executing at. This is for detecting that we stepped. */
11533 uint64_t uRipStart;
11534 /** The CS we started executing with. */
11535 uint16_t uCsStart;
11536
11537 /** Whether we've actually modified the 1st execution control field. */
11538 bool fModifiedProcCtls : 1;
11539 /** Whether we've actually modified the 2nd execution control field. */
11540 bool fModifiedProcCtls2 : 1;
11541 /** Whether we've actually modified the exception bitmap. */
11542 bool fModifiedXcptBitmap : 1;
11543
11544 /** We desire the modified the CR0 mask to be cleared. */
11545 bool fClearCr0Mask : 1;
11546 /** We desire the modified the CR4 mask to be cleared. */
11547 bool fClearCr4Mask : 1;
11548 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11549 uint32_t fCpe1Extra;
11550 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11551 uint32_t fCpe1Unwanted;
11552 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11553 uint32_t fCpe2Extra;
11554 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11555 uint32_t bmXcptExtra;
11556 /** The sequence number of the Dtrace provider settings the state was
11557 * configured against. */
11558 uint32_t uDtraceSettingsSeqNo;
11559 /** VM-exits to check (one bit per VM-exit). */
11560 uint32_t bmExitsToCheck[3];
11561
11562 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11563 uint32_t fProcCtlsInitial;
11564 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11565 uint32_t fProcCtls2Initial;
11566 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11567 uint32_t bmXcptInitial;
11568} VMXRUNDBGSTATE;
11569AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11570typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11571
11572
11573/**
11574 * Initializes the VMXRUNDBGSTATE structure.
11575 *
11576 * @param pVCpu The cross context virtual CPU structure of the
11577 * calling EMT.
11578 * @param pVmxTransient The VMX-transient structure.
11579 * @param pDbgState The debug state to initialize.
11580 */
11581static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11582{
11583 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11584 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11585
11586 pDbgState->fModifiedProcCtls = false;
11587 pDbgState->fModifiedProcCtls2 = false;
11588 pDbgState->fModifiedXcptBitmap = false;
11589 pDbgState->fClearCr0Mask = false;
11590 pDbgState->fClearCr4Mask = false;
11591 pDbgState->fCpe1Extra = 0;
11592 pDbgState->fCpe1Unwanted = 0;
11593 pDbgState->fCpe2Extra = 0;
11594 pDbgState->bmXcptExtra = 0;
11595 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11596 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11597 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11598}
11599
11600
11601/**
11602 * Updates the VMSC fields with changes requested by @a pDbgState.
11603 *
11604 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11605 * immediately before executing guest code, i.e. when interrupts are disabled.
11606 * We don't check status codes here as we cannot easily assert or return in the
11607 * latter case.
11608 *
11609 * @param pVCpu The cross context virtual CPU structure.
11610 * @param pVmxTransient The VMX-transient structure.
11611 * @param pDbgState The debug state.
11612 */
11613static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11614{
11615 /*
11616 * Ensure desired flags in VMCS control fields are set.
11617 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11618 *
11619 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11620 * there should be no stale data in pCtx at this point.
11621 */
11622 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11623 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11624 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11625 {
11626 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11627 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11628 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11629 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11630 pDbgState->fModifiedProcCtls = true;
11631 }
11632
11633 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11634 {
11635 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11636 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11637 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11638 pDbgState->fModifiedProcCtls2 = true;
11639 }
11640
11641 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11642 {
11643 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11644 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11645 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11646 pDbgState->fModifiedXcptBitmap = true;
11647 }
11648
11649 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11650 {
11651 pVmcsInfo->u64Cr0Mask = 0;
11652 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11653 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11654 }
11655
11656 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11657 {
11658 pVmcsInfo->u64Cr4Mask = 0;
11659 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11660 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11661 }
11662
11663 NOREF(pVCpu);
11664}
11665
11666
11667/**
11668 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11669 * re-entry next time around.
11670 *
11671 * @returns Strict VBox status code (i.e. informational status codes too).
11672 * @param pVCpu The cross context virtual CPU structure.
11673 * @param pVmxTransient The VMX-transient structure.
11674 * @param pDbgState The debug state.
11675 * @param rcStrict The return code from executing the guest using single
11676 * stepping.
11677 */
11678static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11679 VBOXSTRICTRC rcStrict)
11680{
11681 /*
11682 * Restore VM-exit control settings as we may not reenter this function the
11683 * next time around.
11684 */
11685 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11686
11687 /* We reload the initial value, trigger what we can of recalculations the
11688 next time around. From the looks of things, that's all that's required atm. */
11689 if (pDbgState->fModifiedProcCtls)
11690 {
11691 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11692 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11693 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11694 AssertRC(rc2);
11695 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11696 }
11697
11698 /* We're currently the only ones messing with this one, so just restore the
11699 cached value and reload the field. */
11700 if ( pDbgState->fModifiedProcCtls2
11701 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11702 {
11703 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11704 AssertRC(rc2);
11705 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11706 }
11707
11708 /* If we've modified the exception bitmap, we restore it and trigger
11709 reloading and partial recalculation the next time around. */
11710 if (pDbgState->fModifiedXcptBitmap)
11711 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11712
11713 return rcStrict;
11714}
11715
11716
11717/**
11718 * Configures VM-exit controls for current DBGF and DTrace settings.
11719 *
11720 * This updates @a pDbgState and the VMCS execution control fields to reflect
11721 * the necessary VM-exits demanded by DBGF and DTrace.
11722 *
11723 * @param pVCpu The cross context virtual CPU structure.
11724 * @param pVmxTransient The VMX-transient structure. May update
11725 * fUpdatedTscOffsettingAndPreemptTimer.
11726 * @param pDbgState The debug state.
11727 */
11728static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11729{
11730 /*
11731 * Take down the dtrace serial number so we can spot changes.
11732 */
11733 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11734 ASMCompilerBarrier();
11735
11736 /*
11737 * We'll rebuild most of the middle block of data members (holding the
11738 * current settings) as we go along here, so start by clearing it all.
11739 */
11740 pDbgState->bmXcptExtra = 0;
11741 pDbgState->fCpe1Extra = 0;
11742 pDbgState->fCpe1Unwanted = 0;
11743 pDbgState->fCpe2Extra = 0;
11744 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11745 pDbgState->bmExitsToCheck[i] = 0;
11746
11747 /*
11748 * Software interrupts (INT XXh) - no idea how to trigger these...
11749 */
11750 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11751 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11752 || VBOXVMM_INT_SOFTWARE_ENABLED())
11753 {
11754 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11755 }
11756
11757 /*
11758 * INT3 breakpoints - triggered by #BP exceptions.
11759 */
11760 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11761 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11762
11763 /*
11764 * Exception bitmap and XCPT events+probes.
11765 */
11766 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11767 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11768 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11769
11770 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11771 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11772 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11773 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11774 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11775 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11776 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11777 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11778 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11779 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11780 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11781 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11782 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11783 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11784 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11785 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11786 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11787 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11788
11789 if (pDbgState->bmXcptExtra)
11790 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11791
11792 /*
11793 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11794 *
11795 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11796 * So, when adding/changing/removing please don't forget to update it.
11797 *
11798 * Some of the macros are picking up local variables to save horizontal space,
11799 * (being able to see it in a table is the lesser evil here).
11800 */
11801#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11802 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11803 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11804#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11805 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11806 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11807 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11808 } else do { } while (0)
11809#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11810 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11811 { \
11812 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11813 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11814 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11815 } else do { } while (0)
11816#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11817 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11818 { \
11819 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11820 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11821 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11822 } else do { } while (0)
11823#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11824 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11825 { \
11826 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11827 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11828 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11829 } else do { } while (0)
11830
11831 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11832 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11833 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11834 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11835 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11836
11837 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11838 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11839 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11840 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11841 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11842 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11843 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11844 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11845 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11846 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11847 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11848 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11849 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11850 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11851 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11852 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11853 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11854 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11855 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11856 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11857 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11858 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11859 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11860 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11861 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11862 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11863 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11864 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11865 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11866 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11867 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11868 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11869 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11870 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11871 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11872 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11873
11874 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11875 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11876 {
11877 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11878 | CPUMCTX_EXTRN_APIC_TPR);
11879 AssertRC(rc);
11880
11881#if 0 /** @todo fix me */
11882 pDbgState->fClearCr0Mask = true;
11883 pDbgState->fClearCr4Mask = true;
11884#endif
11885 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11886 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11887 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11888 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11889 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11890 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11891 require clearing here and in the loop if we start using it. */
11892 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11893 }
11894 else
11895 {
11896 if (pDbgState->fClearCr0Mask)
11897 {
11898 pDbgState->fClearCr0Mask = false;
11899 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11900 }
11901 if (pDbgState->fClearCr4Mask)
11902 {
11903 pDbgState->fClearCr4Mask = false;
11904 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11905 }
11906 }
11907 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11908 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11909
11910 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11911 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11912 {
11913 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11914 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11915 }
11916 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11917 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11918
11919 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11920 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11921 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11922 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11923 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11924 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11925 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11926 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11927#if 0 /** @todo too slow, fix handler. */
11928 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11929#endif
11930 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11931
11932 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11933 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11934 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11935 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11936 {
11937 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11938 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11939 }
11940 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11941 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11942 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11943 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11944
11945 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11946 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11947 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11948 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11949 {
11950 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11951 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11952 }
11953 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11954 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11955 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11956 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11957
11958 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11959 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11960 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11961 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11962 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11963 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11964 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11965 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11966 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11967 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11968 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11969 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11970 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11971 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11972 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11973 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11974 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11975 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11976 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11977 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11978 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11979 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11980
11981#undef IS_EITHER_ENABLED
11982#undef SET_ONLY_XBM_IF_EITHER_EN
11983#undef SET_CPE1_XBM_IF_EITHER_EN
11984#undef SET_CPEU_XBM_IF_EITHER_EN
11985#undef SET_CPE2_XBM_IF_EITHER_EN
11986
11987 /*
11988 * Sanitize the control stuff.
11989 */
11990 pDbgState->fCpe2Extra &= g_HmMsrs.u.vmx.ProcCtls2.n.allowed1;
11991 if (pDbgState->fCpe2Extra)
11992 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11993 pDbgState->fCpe1Extra &= g_HmMsrs.u.vmx.ProcCtls.n.allowed1;
11994 pDbgState->fCpe1Unwanted &= ~g_HmMsrs.u.vmx.ProcCtls.n.allowed0;
11995 if (pVCpu->hmr0.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11996 {
11997 pVCpu->hmr0.s.fDebugWantRdTscExit ^= true;
11998 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11999 }
12000
12001 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
12002 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
12003 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
12004 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
12005}
12006
12007
12008/**
12009 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
12010 * appropriate.
12011 *
12012 * The caller has checked the VM-exit against the
12013 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12014 * already, so we don't have to do that either.
12015 *
12016 * @returns Strict VBox status code (i.e. informational status codes too).
12017 * @param pVCpu The cross context virtual CPU structure.
12018 * @param pVmxTransient The VMX-transient structure.
12019 * @param uExitReason The VM-exit reason.
12020 *
12021 * @remarks The name of this function is displayed by dtrace, so keep it short
12022 * and to the point. No longer than 33 chars long, please.
12023 */
12024static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12025{
12026 /*
12027 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12028 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12029 *
12030 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12031 * does. Must add/change/remove both places. Same ordering, please.
12032 *
12033 * Added/removed events must also be reflected in the next section
12034 * where we dispatch dtrace events.
12035 */
12036 bool fDtrace1 = false;
12037 bool fDtrace2 = false;
12038 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12039 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12040 uint32_t uEventArg = 0;
12041#define SET_EXIT(a_EventSubName) \
12042 do { \
12043 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12044 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12045 } while (0)
12046#define SET_BOTH(a_EventSubName) \
12047 do { \
12048 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12049 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12050 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12051 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12052 } while (0)
12053 switch (uExitReason)
12054 {
12055 case VMX_EXIT_MTF:
12056 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12057
12058 case VMX_EXIT_XCPT_OR_NMI:
12059 {
12060 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12061 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12062 {
12063 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12064 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12065 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12066 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12067 {
12068 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12069 {
12070 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12071 uEventArg = pVmxTransient->uExitIntErrorCode;
12072 }
12073 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12074 switch (enmEvent1)
12075 {
12076 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12077 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12078 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12079 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12080 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12081 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12082 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12083 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12084 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12085 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12086 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12087 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12088 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12089 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12090 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12091 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12092 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12093 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12094 default: break;
12095 }
12096 }
12097 else
12098 AssertFailed();
12099 break;
12100
12101 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12102 uEventArg = idxVector;
12103 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12104 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12105 break;
12106 }
12107 break;
12108 }
12109
12110 case VMX_EXIT_TRIPLE_FAULT:
12111 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12112 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12113 break;
12114 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12115 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12116 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12117 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12118 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12119
12120 /* Instruction specific VM-exits: */
12121 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12122 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12123 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12124 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12125 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12126 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12127 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12128 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12129 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12130 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12131 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12132 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12133 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12134 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12135 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12136 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12137 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12138 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12139 case VMX_EXIT_MOV_CRX:
12140 hmR0VmxReadExitQualVmcs(pVmxTransient);
12141 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12142 SET_BOTH(CRX_READ);
12143 else
12144 SET_BOTH(CRX_WRITE);
12145 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12146 break;
12147 case VMX_EXIT_MOV_DRX:
12148 hmR0VmxReadExitQualVmcs(pVmxTransient);
12149 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12150 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12151 SET_BOTH(DRX_READ);
12152 else
12153 SET_BOTH(DRX_WRITE);
12154 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12155 break;
12156 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12157 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12158 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12159 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12160 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12161 case VMX_EXIT_GDTR_IDTR_ACCESS:
12162 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12163 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12164 {
12165 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12166 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12167 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12168 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12169 }
12170 break;
12171
12172 case VMX_EXIT_LDTR_TR_ACCESS:
12173 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12174 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12175 {
12176 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12177 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12178 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12179 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12180 }
12181 break;
12182
12183 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12184 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12185 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12186 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12187 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12188 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12189 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12190 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12191 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12192 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12193 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12194
12195 /* Events that aren't relevant at this point. */
12196 case VMX_EXIT_EXT_INT:
12197 case VMX_EXIT_INT_WINDOW:
12198 case VMX_EXIT_NMI_WINDOW:
12199 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12200 case VMX_EXIT_PREEMPT_TIMER:
12201 case VMX_EXIT_IO_INSTR:
12202 break;
12203
12204 /* Errors and unexpected events. */
12205 case VMX_EXIT_INIT_SIGNAL:
12206 case VMX_EXIT_SIPI:
12207 case VMX_EXIT_IO_SMI:
12208 case VMX_EXIT_SMI:
12209 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12210 case VMX_EXIT_ERR_MSR_LOAD:
12211 case VMX_EXIT_ERR_MACHINE_CHECK:
12212 case VMX_EXIT_PML_FULL:
12213 case VMX_EXIT_VIRTUALIZED_EOI:
12214 break;
12215
12216 default:
12217 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12218 break;
12219 }
12220#undef SET_BOTH
12221#undef SET_EXIT
12222
12223 /*
12224 * Dtrace tracepoints go first. We do them here at once so we don't
12225 * have to copy the guest state saving and stuff a few dozen times.
12226 * Down side is that we've got to repeat the switch, though this time
12227 * we use enmEvent since the probes are a subset of what DBGF does.
12228 */
12229 if (fDtrace1 || fDtrace2)
12230 {
12231 hmR0VmxReadExitQualVmcs(pVmxTransient);
12232 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12233 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12234 switch (enmEvent1)
12235 {
12236 /** @todo consider which extra parameters would be helpful for each probe. */
12237 case DBGFEVENT_END: break;
12238 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12239 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12240 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12241 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12242 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12243 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12244 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12245 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12246 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12247 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12248 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12249 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12250 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12251 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12252 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12253 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12254 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12255 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12256 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12257 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12258 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12259 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12260 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12261 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12262 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12263 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12264 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12265 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12266 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12267 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12268 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12269 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12270 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12271 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12272 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12273 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12274 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12275 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12276 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12277 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12278 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12279 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12280 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12281 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12282 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12283 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12284 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12285 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12286 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12287 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12288 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12289 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12290 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12291 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12292 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12293 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12294 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12295 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12296 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12297 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12298 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12299 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12300 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12301 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12302 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12303 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12304 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12305 }
12306 switch (enmEvent2)
12307 {
12308 /** @todo consider which extra parameters would be helpful for each probe. */
12309 case DBGFEVENT_END: break;
12310 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12311 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12312 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12313 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12314 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12315 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12316 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12317 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12318 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12319 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12320 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12321 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12322 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12323 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12324 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12325 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12326 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12327 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12328 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12329 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12330 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12331 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12332 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12333 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12334 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12335 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12336 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12337 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12338 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12339 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12340 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12341 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12342 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12343 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12344 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12345 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12346 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12347 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12348 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12349 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12350 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12351 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12352 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12353 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12354 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12355 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12356 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12357 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12358 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12359 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12360 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12361 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12362 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12363 }
12364 }
12365
12366 /*
12367 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12368 * the DBGF call will do a full check).
12369 *
12370 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12371 * Note! If we have to events, we prioritize the first, i.e. the instruction
12372 * one, in order to avoid event nesting.
12373 */
12374 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
12375 if ( enmEvent1 != DBGFEVENT_END
12376 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12377 {
12378 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12379 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12380 if (rcStrict != VINF_SUCCESS)
12381 return rcStrict;
12382 }
12383 else if ( enmEvent2 != DBGFEVENT_END
12384 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12385 {
12386 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12387 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12388 if (rcStrict != VINF_SUCCESS)
12389 return rcStrict;
12390 }
12391
12392 return VINF_SUCCESS;
12393}
12394
12395
12396/**
12397 * Single-stepping VM-exit filtering.
12398 *
12399 * This is preprocessing the VM-exits and deciding whether we've gotten far
12400 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12401 * handling is performed.
12402 *
12403 * @returns Strict VBox status code (i.e. informational status codes too).
12404 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12405 * @param pVmxTransient The VMX-transient structure.
12406 * @param pDbgState The debug state.
12407 */
12408DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12409{
12410 /*
12411 * Expensive (saves context) generic dtrace VM-exit probe.
12412 */
12413 uint32_t const uExitReason = pVmxTransient->uExitReason;
12414 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12415 { /* more likely */ }
12416 else
12417 {
12418 hmR0VmxReadExitQualVmcs(pVmxTransient);
12419 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12420 AssertRC(rc);
12421 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12422 }
12423
12424 /*
12425 * Check for host NMI, just to get that out of the way.
12426 */
12427 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12428 { /* normally likely */ }
12429 else
12430 {
12431 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12432 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12433 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12434 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12435 }
12436
12437 /*
12438 * Check for single stepping event if we're stepping.
12439 */
12440 if (pVCpu->hm.s.fSingleInstruction)
12441 {
12442 switch (uExitReason)
12443 {
12444 case VMX_EXIT_MTF:
12445 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12446
12447 /* Various events: */
12448 case VMX_EXIT_XCPT_OR_NMI:
12449 case VMX_EXIT_EXT_INT:
12450 case VMX_EXIT_TRIPLE_FAULT:
12451 case VMX_EXIT_INT_WINDOW:
12452 case VMX_EXIT_NMI_WINDOW:
12453 case VMX_EXIT_TASK_SWITCH:
12454 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12455 case VMX_EXIT_APIC_ACCESS:
12456 case VMX_EXIT_EPT_VIOLATION:
12457 case VMX_EXIT_EPT_MISCONFIG:
12458 case VMX_EXIT_PREEMPT_TIMER:
12459
12460 /* Instruction specific VM-exits: */
12461 case VMX_EXIT_CPUID:
12462 case VMX_EXIT_GETSEC:
12463 case VMX_EXIT_HLT:
12464 case VMX_EXIT_INVD:
12465 case VMX_EXIT_INVLPG:
12466 case VMX_EXIT_RDPMC:
12467 case VMX_EXIT_RDTSC:
12468 case VMX_EXIT_RSM:
12469 case VMX_EXIT_VMCALL:
12470 case VMX_EXIT_VMCLEAR:
12471 case VMX_EXIT_VMLAUNCH:
12472 case VMX_EXIT_VMPTRLD:
12473 case VMX_EXIT_VMPTRST:
12474 case VMX_EXIT_VMREAD:
12475 case VMX_EXIT_VMRESUME:
12476 case VMX_EXIT_VMWRITE:
12477 case VMX_EXIT_VMXOFF:
12478 case VMX_EXIT_VMXON:
12479 case VMX_EXIT_MOV_CRX:
12480 case VMX_EXIT_MOV_DRX:
12481 case VMX_EXIT_IO_INSTR:
12482 case VMX_EXIT_RDMSR:
12483 case VMX_EXIT_WRMSR:
12484 case VMX_EXIT_MWAIT:
12485 case VMX_EXIT_MONITOR:
12486 case VMX_EXIT_PAUSE:
12487 case VMX_EXIT_GDTR_IDTR_ACCESS:
12488 case VMX_EXIT_LDTR_TR_ACCESS:
12489 case VMX_EXIT_INVEPT:
12490 case VMX_EXIT_RDTSCP:
12491 case VMX_EXIT_INVVPID:
12492 case VMX_EXIT_WBINVD:
12493 case VMX_EXIT_XSETBV:
12494 case VMX_EXIT_RDRAND:
12495 case VMX_EXIT_INVPCID:
12496 case VMX_EXIT_VMFUNC:
12497 case VMX_EXIT_RDSEED:
12498 case VMX_EXIT_XSAVES:
12499 case VMX_EXIT_XRSTORS:
12500 {
12501 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12502 AssertRCReturn(rc, rc);
12503 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12504 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12505 return VINF_EM_DBG_STEPPED;
12506 break;
12507 }
12508
12509 /* Errors and unexpected events: */
12510 case VMX_EXIT_INIT_SIGNAL:
12511 case VMX_EXIT_SIPI:
12512 case VMX_EXIT_IO_SMI:
12513 case VMX_EXIT_SMI:
12514 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12515 case VMX_EXIT_ERR_MSR_LOAD:
12516 case VMX_EXIT_ERR_MACHINE_CHECK:
12517 case VMX_EXIT_PML_FULL:
12518 case VMX_EXIT_VIRTUALIZED_EOI:
12519 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12520 break;
12521
12522 default:
12523 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12524 break;
12525 }
12526 }
12527
12528 /*
12529 * Check for debugger event breakpoints and dtrace probes.
12530 */
12531 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12532 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12533 {
12534 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12535 if (rcStrict != VINF_SUCCESS)
12536 return rcStrict;
12537 }
12538
12539 /*
12540 * Normal processing.
12541 */
12542#ifdef HMVMX_USE_FUNCTION_TABLE
12543 return g_aVMExitHandlers[uExitReason].pfn(pVCpu, pVmxTransient);
12544#else
12545 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12546#endif
12547}
12548
12549
12550/**
12551 * Single steps guest code using hardware-assisted VMX.
12552 *
12553 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12554 * but single-stepping through the hypervisor debugger.
12555 *
12556 * @returns Strict VBox status code (i.e. informational status codes too).
12557 * @param pVCpu The cross context virtual CPU structure.
12558 * @param pcLoops Pointer to the number of executed loops.
12559 *
12560 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12561 */
12562static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12563{
12564 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
12565 Assert(pcLoops);
12566 Assert(*pcLoops <= cMaxResumeLoops);
12567
12568 VMXTRANSIENT VmxTransient;
12569 RT_ZERO(VmxTransient);
12570 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12571
12572 /* Set HMCPU indicators. */
12573 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12574 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12575 pVCpu->hmr0.s.fDebugWantRdTscExit = false;
12576 pVCpu->hmr0.s.fUsingDebugLoop = true;
12577
12578 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12579 VMXRUNDBGSTATE DbgState;
12580 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12581 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12582
12583 /*
12584 * The loop.
12585 */
12586 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12587 for (;;)
12588 {
12589 Assert(!HMR0SuspendPending());
12590 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12591 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12592 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12593
12594 /* Set up VM-execution controls the next two can respond to. */
12595 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12596
12597 /*
12598 * Preparatory work for running guest code, this may force us to
12599 * return to ring-3.
12600 *
12601 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12602 */
12603 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12604 if (rcStrict != VINF_SUCCESS)
12605 break;
12606
12607 /* Interrupts are disabled at this point! */
12608 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12609
12610 /* Override any obnoxious code in the above two calls. */
12611 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12612
12613 /*
12614 * Finally execute the guest.
12615 */
12616 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12617
12618 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12619 /* Interrupts are re-enabled at this point! */
12620
12621 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12622 if (RT_SUCCESS(rcRun))
12623 { /* very likely */ }
12624 else
12625 {
12626 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12627 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12628 return rcRun;
12629 }
12630
12631 /* Profile the VM-exit. */
12632 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12633 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12634 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12635 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12636 HMVMX_START_EXIT_DISPATCH_PROF();
12637
12638 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12639
12640 /*
12641 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12642 */
12643 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12644 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12645 if (rcStrict != VINF_SUCCESS)
12646 break;
12647 if (++(*pcLoops) > cMaxResumeLoops)
12648 {
12649 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12650 rcStrict = VINF_EM_RAW_INTERRUPT;
12651 break;
12652 }
12653
12654 /*
12655 * Stepping: Did the RIP change, if so, consider it a single step.
12656 * Otherwise, make sure one of the TFs gets set.
12657 */
12658 if (fStepping)
12659 {
12660 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12661 AssertRC(rc);
12662 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12663 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12664 {
12665 rcStrict = VINF_EM_DBG_STEPPED;
12666 break;
12667 }
12668 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12669 }
12670
12671 /*
12672 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12673 */
12674 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12675 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12676
12677 /* Restore all controls applied by hmR0VmxPreRunGuestDebugStateApply above. */
12678 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12679 Assert(rcStrict == VINF_SUCCESS);
12680 }
12681
12682 /*
12683 * Clear the X86_EFL_TF if necessary.
12684 */
12685 if (pVCpu->hmr0.s.fClearTrapFlag)
12686 {
12687 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12688 AssertRC(rc);
12689 pVCpu->hmr0.s.fClearTrapFlag = false;
12690 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12691 }
12692 /** @todo there seems to be issues with the resume flag when the monitor trap
12693 * flag is pending without being used. Seen early in bios init when
12694 * accessing APIC page in protected mode. */
12695
12696 /* Restore HMCPU indicators. */
12697 pVCpu->hmr0.s.fUsingDebugLoop = false;
12698 pVCpu->hmr0.s.fDebugWantRdTscExit = false;
12699 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12700
12701 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12702 return rcStrict;
12703}
12704
12705
12706/** @} */
12707
12708
12709/**
12710 * Checks if any expensive dtrace probes are enabled and we should go to the
12711 * debug loop.
12712 *
12713 * @returns true if we should use debug loop, false if not.
12714 */
12715static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12716{
12717 /* It's probably faster to OR the raw 32-bit counter variables together.
12718 Since the variables are in an array and the probes are next to one
12719 another (more or less), we have good locality. So, better read
12720 eight-nine cache lines ever time and only have one conditional, than
12721 128+ conditionals, right? */
12722 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12723 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12724 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12725 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12726 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12727 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12728 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12729 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12730 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12731 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12732 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12733 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12734 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12735 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12736 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12737 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12738 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12739 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12740 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12741 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12742 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12743 ) != 0
12744 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12745 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12746 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12747 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12748 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12749 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12750 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12751 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12752 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12753 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12754 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12755 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12756 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12757 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12758 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12759 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12760 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12761 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12762 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12763 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12764 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12765 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12766 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12767 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12768 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12769 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12770 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12771 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12772 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12773 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12774 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12775 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12776 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12777 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12778 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12779 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12780 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12781 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12782 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12783 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12784 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12785 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12786 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12787 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12788 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12789 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12790 ) != 0
12791 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12792 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12793 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12794 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12795 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12796 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12797 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12798 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12799 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12800 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12801 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12802 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12803 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12804 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12805 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12806 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12807 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12808 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12809 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12810 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12811 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12812 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12813 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12814 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12815 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12816 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12817 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12818 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12819 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12820 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12821 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12822 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12823 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12824 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12825 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12826 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12827 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12828 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12829 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12830 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12831 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12832 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12833 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12834 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12835 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12836 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12837 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12838 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12839 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12840 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12841 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12842 ) != 0;
12843}
12844
12845
12846/**
12847 * Runs the guest using hardware-assisted VMX.
12848 *
12849 * @returns Strict VBox status code (i.e. informational status codes too).
12850 * @param pVCpu The cross context virtual CPU structure.
12851 */
12852VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12853{
12854 AssertPtr(pVCpu);
12855 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12856 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12857 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12858 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12859
12860 VBOXSTRICTRC rcStrict;
12861 uint32_t cLoops = 0;
12862 for (;;)
12863 {
12864#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12865 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12866#else
12867 NOREF(pCtx);
12868 bool const fInNestedGuestMode = false;
12869#endif
12870 if (!fInNestedGuestMode)
12871 {
12872 if ( !pVCpu->hm.s.fUseDebugLoop
12873 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12874 && !DBGFIsStepping(pVCpu)
12875 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12876 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12877 else
12878 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12879 }
12880#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12881 else
12882 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12883
12884 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12885 {
12886 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12887 continue;
12888 }
12889 if (rcStrict == VINF_VMX_VMEXIT)
12890 {
12891 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12892 continue;
12893 }
12894#endif
12895 break;
12896 }
12897
12898 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12899 switch (rcLoop)
12900 {
12901 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12902 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12903 }
12904
12905 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12906 if (RT_FAILURE(rc2))
12907 {
12908 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12909 rcStrict = rc2;
12910 }
12911 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12912 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12913 return rcStrict;
12914}
12915
12916
12917#ifndef HMVMX_USE_FUNCTION_TABLE
12918/**
12919 * Handles a guest VM-exit from hardware-assisted VMX execution.
12920 *
12921 * @returns Strict VBox status code (i.e. informational status codes too).
12922 * @param pVCpu The cross context virtual CPU structure.
12923 * @param pVmxTransient The VMX-transient structure.
12924 */
12925DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12926{
12927#ifdef DEBUG_ramshankar
12928# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12929 do { \
12930 if (a_fSave != 0) \
12931 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12932 VBOXSTRICTRC rcStrict = a_CallExpr; \
12933 if (a_fSave != 0) \
12934 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12935 return rcStrict; \
12936 } while (0)
12937#else
12938# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12939#endif
12940 uint32_t const uExitReason = pVmxTransient->uExitReason;
12941 switch (uExitReason)
12942 {
12943 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12944 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12945 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12946 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12947 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12948 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12949 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12950 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12951 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12952 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12953 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12954 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12955 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12956 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12957 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12958 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12959 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12960 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12961 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12962 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12963 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12964 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12965 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12966 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12967 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12968 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12969 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12970 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12971 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12972 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12973#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12974 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12975 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12976 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12977 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12978 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12979 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12980 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12981 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12982 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12983 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12984 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12985#else
12986 case VMX_EXIT_VMCLEAR:
12987 case VMX_EXIT_VMLAUNCH:
12988 case VMX_EXIT_VMPTRLD:
12989 case VMX_EXIT_VMPTRST:
12990 case VMX_EXIT_VMREAD:
12991 case VMX_EXIT_VMRESUME:
12992 case VMX_EXIT_VMWRITE:
12993 case VMX_EXIT_VMXOFF:
12994 case VMX_EXIT_VMXON:
12995 case VMX_EXIT_INVVPID:
12996 case VMX_EXIT_INVEPT:
12997 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12998#endif
12999
13000 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
13001 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
13002 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
13003
13004 case VMX_EXIT_INIT_SIGNAL:
13005 case VMX_EXIT_SIPI:
13006 case VMX_EXIT_IO_SMI:
13007 case VMX_EXIT_SMI:
13008 case VMX_EXIT_ERR_MSR_LOAD:
13009 case VMX_EXIT_ERR_MACHINE_CHECK:
13010 case VMX_EXIT_PML_FULL:
13011 case VMX_EXIT_VIRTUALIZED_EOI:
13012 case VMX_EXIT_GDTR_IDTR_ACCESS:
13013 case VMX_EXIT_LDTR_TR_ACCESS:
13014 case VMX_EXIT_APIC_WRITE:
13015 case VMX_EXIT_RDRAND:
13016 case VMX_EXIT_RSM:
13017 case VMX_EXIT_VMFUNC:
13018 case VMX_EXIT_ENCLS:
13019 case VMX_EXIT_RDSEED:
13020 case VMX_EXIT_XSAVES:
13021 case VMX_EXIT_XRSTORS:
13022 case VMX_EXIT_UMWAIT:
13023 case VMX_EXIT_TPAUSE:
13024 default:
13025 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13026 }
13027#undef VMEXIT_CALL_RET
13028}
13029#endif /* !HMVMX_USE_FUNCTION_TABLE */
13030
13031
13032#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13033/**
13034 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13035 *
13036 * @returns Strict VBox status code (i.e. informational status codes too).
13037 * @param pVCpu The cross context virtual CPU structure.
13038 * @param pVmxTransient The VMX-transient structure.
13039 */
13040DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13041{
13042 uint32_t const uExitReason = pVmxTransient->uExitReason;
13043 switch (uExitReason)
13044 {
13045 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13046 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13047 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13048 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13049 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13050
13051 /*
13052 * We shouldn't direct host physical interrupts to the nested-guest.
13053 */
13054 case VMX_EXIT_EXT_INT:
13055 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13056
13057 /*
13058 * Instructions that cause VM-exits unconditionally or the condition is
13059 * always is taken solely from the nested hypervisor (meaning if the VM-exit
13060 * happens, it's guaranteed to be a nested-guest VM-exit).
13061 *
13062 * - Provides VM-exit instruction length ONLY.
13063 */
13064 case VMX_EXIT_CPUID: /* Unconditional. */
13065 case VMX_EXIT_VMCALL:
13066 case VMX_EXIT_GETSEC:
13067 case VMX_EXIT_INVD:
13068 case VMX_EXIT_XSETBV:
13069 case VMX_EXIT_VMLAUNCH:
13070 case VMX_EXIT_VMRESUME:
13071 case VMX_EXIT_VMXOFF:
13072 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
13073 case VMX_EXIT_VMFUNC:
13074 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13075
13076 /*
13077 * Instructions that cause VM-exits unconditionally or the condition is
13078 * always is taken solely from the nested hypervisor (meaning if the VM-exit
13079 * happens, it's guaranteed to be a nested-guest VM-exit).
13080 *
13081 * - Provides VM-exit instruction length.
13082 * - Provides VM-exit information.
13083 * - Optionally provides Exit qualification.
13084 *
13085 * Since Exit qualification is 0 for all VM-exits where it is not
13086 * applicable, reading and passing it to the guest should produce
13087 * defined behavior.
13088 *
13089 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13090 */
13091 case VMX_EXIT_INVEPT: /* Unconditional. */
13092 case VMX_EXIT_INVVPID:
13093 case VMX_EXIT_VMCLEAR:
13094 case VMX_EXIT_VMPTRLD:
13095 case VMX_EXIT_VMPTRST:
13096 case VMX_EXIT_VMXON:
13097 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
13098 case VMX_EXIT_LDTR_TR_ACCESS:
13099 case VMX_EXIT_RDRAND:
13100 case VMX_EXIT_RDSEED:
13101 case VMX_EXIT_XSAVES:
13102 case VMX_EXIT_XRSTORS:
13103 case VMX_EXIT_UMWAIT:
13104 case VMX_EXIT_TPAUSE:
13105 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13106
13107 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13108 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13109 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13110 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13111 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13112 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13113 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13114 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13115 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13116 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13117 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13118 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13119 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13120 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13121 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13122 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13123 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13124 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13125 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13126
13127 case VMX_EXIT_PREEMPT_TIMER:
13128 {
13129 /** @todo NSTVMX: Preempt timer. */
13130 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13131 }
13132
13133 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13134 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13135
13136 case VMX_EXIT_VMREAD:
13137 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13138
13139 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13140 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13141
13142 case VMX_EXIT_INIT_SIGNAL:
13143 case VMX_EXIT_SIPI:
13144 case VMX_EXIT_IO_SMI:
13145 case VMX_EXIT_SMI:
13146 case VMX_EXIT_ERR_MSR_LOAD:
13147 case VMX_EXIT_ERR_MACHINE_CHECK:
13148 case VMX_EXIT_PML_FULL:
13149 case VMX_EXIT_RSM:
13150 default:
13151 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13152 }
13153}
13154#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13155
13156
13157/** @name VM-exit helpers.
13158 * @{
13159 */
13160/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13161/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13162/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13163
13164/** Macro for VM-exits called unexpectedly. */
13165#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13166 do { \
13167 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13168 return VERR_VMX_UNEXPECTED_EXIT; \
13169 } while (0)
13170
13171#ifdef VBOX_STRICT
13172/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13173# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13174 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13175
13176# define HMVMX_ASSERT_PREEMPT_CPUID() \
13177 do { \
13178 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13179 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13180 } while (0)
13181
13182# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13183 do { \
13184 AssertPtr((a_pVCpu)); \
13185 AssertPtr((a_pVmxTransient)); \
13186 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13187 Assert((a_pVmxTransient)->pVmcsInfo); \
13188 Assert(ASMIntAreEnabled()); \
13189 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13190 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13191 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13192 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13193 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13194 HMVMX_ASSERT_PREEMPT_CPUID(); \
13195 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13196 } while (0)
13197
13198# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13199 do { \
13200 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13201 Assert((a_pVmxTransient)->fIsNestedGuest); \
13202 } while (0)
13203
13204# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13205 do { \
13206 Log4Func(("\n")); \
13207 } while (0)
13208#else
13209# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13210 do { \
13211 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13212 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13213 } while (0)
13214
13215# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13216 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13217
13218# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13219#endif
13220
13221#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13222/** Macro that does the necessary privilege checks and intercepted VM-exits for
13223 * guests that attempted to execute a VMX instruction. */
13224# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13225 do \
13226 { \
13227 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13228 if (rcStrictTmp == VINF_SUCCESS) \
13229 { /* likely */ } \
13230 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13231 { \
13232 Assert((a_pVCpu)->hm.s.Event.fPending); \
13233 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13234 return VINF_SUCCESS; \
13235 } \
13236 else \
13237 { \
13238 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13239 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13240 } \
13241 } while (0)
13242
13243/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13244# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13245 do \
13246 { \
13247 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13248 (a_pGCPtrEffAddr)); \
13249 if (rcStrictTmp == VINF_SUCCESS) \
13250 { /* likely */ } \
13251 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13252 { \
13253 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13254 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13255 NOREF(uXcptTmp); \
13256 return VINF_SUCCESS; \
13257 } \
13258 else \
13259 { \
13260 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13261 return rcStrictTmp; \
13262 } \
13263 } while (0)
13264#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13265
13266
13267/**
13268 * Advances the guest RIP by the specified number of bytes.
13269 *
13270 * @param pVCpu The cross context virtual CPU structure.
13271 * @param cbInstr Number of bytes to advance the RIP by.
13272 *
13273 * @remarks No-long-jump zone!!!
13274 */
13275DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
13276{
13277 /* Advance the RIP. */
13278 pVCpu->cpum.GstCtx.rip += cbInstr;
13279 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13280
13281 /* Update interrupt inhibition. */
13282 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13283 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13284 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13285}
13286
13287
13288/**
13289 * Advances the guest RIP after reading it from the VMCS.
13290 *
13291 * @returns VBox status code, no informational status codes.
13292 * @param pVCpu The cross context virtual CPU structure.
13293 * @param pVmxTransient The VMX-transient structure.
13294 *
13295 * @remarks No-long-jump zone!!!
13296 */
13297static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13298{
13299 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13300 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13301 AssertRCReturn(rc, rc);
13302
13303 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
13304 return VINF_SUCCESS;
13305}
13306
13307
13308/**
13309 * Handle a condition that occurred while delivering an event through the guest or
13310 * nested-guest IDT.
13311 *
13312 * @returns Strict VBox status code (i.e. informational status codes too).
13313 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13314 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13315 * to continue execution of the guest which will delivery the \#DF.
13316 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13317 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13318 *
13319 * @param pVCpu The cross context virtual CPU structure.
13320 * @param pVmxTransient The VMX-transient structure.
13321 *
13322 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13323 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13324 * is due to an EPT violation, PML full or SPP-related event.
13325 *
13326 * @remarks No-long-jump zone!!!
13327 */
13328static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13329{
13330 Assert(!pVCpu->hm.s.Event.fPending);
13331 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13332 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13333 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13334 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13335 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13336
13337 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13338 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13339 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13340 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13341 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13342 {
13343 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13344 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13345
13346 /*
13347 * If the event was a software interrupt (generated with INT n) or a software exception
13348 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13349 * can handle the VM-exit and continue guest execution which will re-execute the
13350 * instruction rather than re-injecting the exception, as that can cause premature
13351 * trips to ring-3 before injection and involve TRPM which currently has no way of
13352 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13353 * the problem).
13354 */
13355 IEMXCPTRAISE enmRaise;
13356 IEMXCPTRAISEINFO fRaiseInfo;
13357 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13358 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13359 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13360 {
13361 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13362 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13363 }
13364 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13365 {
13366 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13367 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13368 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13369
13370 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13371 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13372
13373 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13374
13375 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13376 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13377 {
13378 pVmxTransient->fVectoringPF = true;
13379 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13380 }
13381 }
13382 else
13383 {
13384 /*
13385 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13386 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13387 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13388 */
13389 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13390 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13391 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13392 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13393 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13394 }
13395
13396 /*
13397 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13398 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13399 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13400 * subsequent VM-entry would fail, see @bugref{7445}.
13401 *
13402 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13403 */
13404 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13405 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13406 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13407 && CPUMIsGuestNmiBlocking(pVCpu))
13408 {
13409 CPUMSetGuestNmiBlocking(pVCpu, false);
13410 }
13411
13412 switch (enmRaise)
13413 {
13414 case IEMXCPTRAISE_CURRENT_XCPT:
13415 {
13416 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13417 Assert(rcStrict == VINF_SUCCESS);
13418 break;
13419 }
13420
13421 case IEMXCPTRAISE_PREV_EVENT:
13422 {
13423 uint32_t u32ErrCode;
13424 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13425 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13426 else
13427 u32ErrCode = 0;
13428
13429 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13430 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13431 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13432 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13433
13434 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13435 pVCpu->hm.s.Event.u32ErrCode));
13436 Assert(rcStrict == VINF_SUCCESS);
13437 break;
13438 }
13439
13440 case IEMXCPTRAISE_REEXEC_INSTR:
13441 Assert(rcStrict == VINF_SUCCESS);
13442 break;
13443
13444 case IEMXCPTRAISE_DOUBLE_FAULT:
13445 {
13446 /*
13447 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13448 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13449 */
13450 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13451 {
13452 pVmxTransient->fVectoringDoublePF = true;
13453 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13454 pVCpu->cpum.GstCtx.cr2));
13455 rcStrict = VINF_SUCCESS;
13456 }
13457 else
13458 {
13459 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13460 hmR0VmxSetPendingXcptDF(pVCpu);
13461 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13462 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13463 rcStrict = VINF_HM_DOUBLE_FAULT;
13464 }
13465 break;
13466 }
13467
13468 case IEMXCPTRAISE_TRIPLE_FAULT:
13469 {
13470 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13471 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13472 rcStrict = VINF_EM_RESET;
13473 break;
13474 }
13475
13476 case IEMXCPTRAISE_CPU_HANG:
13477 {
13478 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13479 rcStrict = VERR_EM_GUEST_CPU_HANG;
13480 break;
13481 }
13482
13483 default:
13484 {
13485 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13486 rcStrict = VERR_VMX_IPE_2;
13487 break;
13488 }
13489 }
13490 }
13491 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13492 && !CPUMIsGuestNmiBlocking(pVCpu))
13493 {
13494 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13495 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13496 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13497 {
13498 /*
13499 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13500 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13501 * that virtual NMIs remain blocked until the IRET execution is completed.
13502 *
13503 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13504 */
13505 CPUMSetGuestNmiBlocking(pVCpu, true);
13506 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13507 }
13508 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13509 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13510 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13511 {
13512 /*
13513 * Execution of IRET caused an EPT violation, page-modification log-full event or
13514 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13515 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13516 * that virtual NMIs remain blocked until the IRET execution is completed.
13517 *
13518 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13519 */
13520 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13521 {
13522 CPUMSetGuestNmiBlocking(pVCpu, true);
13523 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13524 }
13525 }
13526 }
13527
13528 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13529 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13530 return rcStrict;
13531}
13532
13533
13534#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13535/**
13536 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13537 * guest attempting to execute a VMX instruction.
13538 *
13539 * @returns Strict VBox status code (i.e. informational status codes too).
13540 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13541 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13542 *
13543 * @param pVCpu The cross context virtual CPU structure.
13544 * @param uExitReason The VM-exit reason.
13545 *
13546 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13547 * @remarks No-long-jump zone!!!
13548 */
13549static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13550{
13551 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13552 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13553
13554 /*
13555 * The physical CPU would have already checked the CPU mode/code segment.
13556 * We shall just assert here for paranoia.
13557 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13558 */
13559 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13560 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13561 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13562
13563 if (uExitReason == VMX_EXIT_VMXON)
13564 {
13565 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13566
13567 /*
13568 * We check CR4.VMXE because it is required to be always set while in VMX operation
13569 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13570 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13571 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13572 */
13573 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13574 {
13575 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13576 hmR0VmxSetPendingXcptUD(pVCpu);
13577 return VINF_HM_PENDING_XCPT;
13578 }
13579 }
13580 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13581 {
13582 /*
13583 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13584 * (other than VMXON), we need to raise a #UD.
13585 */
13586 Log4Func(("Not in VMX root mode -> #UD\n"));
13587 hmR0VmxSetPendingXcptUD(pVCpu);
13588 return VINF_HM_PENDING_XCPT;
13589 }
13590
13591 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13592 return VINF_SUCCESS;
13593}
13594
13595
13596/**
13597 * Decodes the memory operand of an instruction that caused a VM-exit.
13598 *
13599 * The Exit qualification field provides the displacement field for memory
13600 * operand instructions, if any.
13601 *
13602 * @returns Strict VBox status code (i.e. informational status codes too).
13603 * @retval VINF_SUCCESS if the operand was successfully decoded.
13604 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13605 * operand.
13606 * @param pVCpu The cross context virtual CPU structure.
13607 * @param uExitInstrInfo The VM-exit instruction information field.
13608 * @param enmMemAccess The memory operand's access type (read or write).
13609 * @param GCPtrDisp The instruction displacement field, if any. For
13610 * RIP-relative addressing pass RIP + displacement here.
13611 * @param pGCPtrMem Where to store the effective destination memory address.
13612 *
13613 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13614 * virtual-8086 mode hence skips those checks while verifying if the
13615 * segment is valid.
13616 */
13617static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13618 PRTGCPTR pGCPtrMem)
13619{
13620 Assert(pGCPtrMem);
13621 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13622 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13623 | CPUMCTX_EXTRN_CR0);
13624
13625 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13626 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13627 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13628
13629 VMXEXITINSTRINFO ExitInstrInfo;
13630 ExitInstrInfo.u = uExitInstrInfo;
13631 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13632 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13633 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13634 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13635 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13636 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13637 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13638 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13639 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13640
13641 /*
13642 * Validate instruction information.
13643 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13644 */
13645 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13646 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13647 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13648 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13649 AssertLogRelMsgReturn(fIsMemOperand,
13650 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13651
13652 /*
13653 * Compute the complete effective address.
13654 *
13655 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13656 * See AMD spec. 4.5.2 "Segment Registers".
13657 */
13658 RTGCPTR GCPtrMem = GCPtrDisp;
13659 if (fBaseRegValid)
13660 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13661 if (fIdxRegValid)
13662 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13663
13664 RTGCPTR const GCPtrOff = GCPtrMem;
13665 if ( !fIsLongMode
13666 || iSegReg >= X86_SREG_FS)
13667 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13668 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13669
13670 /*
13671 * Validate effective address.
13672 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13673 */
13674 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13675 Assert(cbAccess > 0);
13676 if (fIsLongMode)
13677 {
13678 if (X86_IS_CANONICAL(GCPtrMem))
13679 {
13680 *pGCPtrMem = GCPtrMem;
13681 return VINF_SUCCESS;
13682 }
13683
13684 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13685 * "Data Limit Checks in 64-bit Mode". */
13686 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13687 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13688 return VINF_HM_PENDING_XCPT;
13689 }
13690
13691 /*
13692 * This is a watered down version of iemMemApplySegment().
13693 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13694 * and segment CPL/DPL checks are skipped.
13695 */
13696 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13697 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13698 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13699
13700 /* Check if the segment is present and usable. */
13701 if ( pSel->Attr.n.u1Present
13702 && !pSel->Attr.n.u1Unusable)
13703 {
13704 Assert(pSel->Attr.n.u1DescType);
13705 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13706 {
13707 /* Check permissions for the data segment. */
13708 if ( enmMemAccess == VMXMEMACCESS_WRITE
13709 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13710 {
13711 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13712 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13713 return VINF_HM_PENDING_XCPT;
13714 }
13715
13716 /* Check limits if it's a normal data segment. */
13717 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13718 {
13719 if ( GCPtrFirst32 > pSel->u32Limit
13720 || GCPtrLast32 > pSel->u32Limit)
13721 {
13722 Log4Func(("Data segment limit exceeded. "
13723 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13724 GCPtrLast32, pSel->u32Limit));
13725 if (iSegReg == X86_SREG_SS)
13726 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13727 else
13728 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13729 return VINF_HM_PENDING_XCPT;
13730 }
13731 }
13732 else
13733 {
13734 /* Check limits if it's an expand-down data segment.
13735 Note! The upper boundary is defined by the B bit, not the G bit! */
13736 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13737 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13738 {
13739 Log4Func(("Expand-down data segment limit exceeded. "
13740 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13741 GCPtrLast32, pSel->u32Limit));
13742 if (iSegReg == X86_SREG_SS)
13743 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13744 else
13745 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13746 return VINF_HM_PENDING_XCPT;
13747 }
13748 }
13749 }
13750 else
13751 {
13752 /* Check permissions for the code segment. */
13753 if ( enmMemAccess == VMXMEMACCESS_WRITE
13754 || ( enmMemAccess == VMXMEMACCESS_READ
13755 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13756 {
13757 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13758 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13759 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13760 return VINF_HM_PENDING_XCPT;
13761 }
13762
13763 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13764 if ( GCPtrFirst32 > pSel->u32Limit
13765 || GCPtrLast32 > pSel->u32Limit)
13766 {
13767 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13768 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13769 if (iSegReg == X86_SREG_SS)
13770 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13771 else
13772 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13773 return VINF_HM_PENDING_XCPT;
13774 }
13775 }
13776 }
13777 else
13778 {
13779 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13780 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13781 return VINF_HM_PENDING_XCPT;
13782 }
13783
13784 *pGCPtrMem = GCPtrMem;
13785 return VINF_SUCCESS;
13786}
13787#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13788
13789
13790/**
13791 * VM-exit helper for LMSW.
13792 */
13793static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13794{
13795 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13796 AssertRCReturn(rc, rc);
13797
13798 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13799 AssertMsg( rcStrict == VINF_SUCCESS
13800 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13801
13802 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13803 if (rcStrict == VINF_IEM_RAISED_XCPT)
13804 {
13805 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13806 rcStrict = VINF_SUCCESS;
13807 }
13808
13809 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13810 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13811 return rcStrict;
13812}
13813
13814
13815/**
13816 * VM-exit helper for CLTS.
13817 */
13818static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13819{
13820 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13821 AssertRCReturn(rc, rc);
13822
13823 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13824 AssertMsg( rcStrict == VINF_SUCCESS
13825 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13826
13827 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13828 if (rcStrict == VINF_IEM_RAISED_XCPT)
13829 {
13830 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13831 rcStrict = VINF_SUCCESS;
13832 }
13833
13834 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13835 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13836 return rcStrict;
13837}
13838
13839
13840/**
13841 * VM-exit helper for MOV from CRx (CRx read).
13842 */
13843static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13844{
13845 Assert(iCrReg < 16);
13846 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13847
13848 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13849 AssertRCReturn(rc, rc);
13850
13851 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13852 AssertMsg( rcStrict == VINF_SUCCESS
13853 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13854
13855 if (iGReg == X86_GREG_xSP)
13856 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13857 else
13858 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13859#ifdef VBOX_WITH_STATISTICS
13860 switch (iCrReg)
13861 {
13862 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13863 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13864 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13865 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13866 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13867 }
13868#endif
13869 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13870 return rcStrict;
13871}
13872
13873
13874/**
13875 * VM-exit helper for MOV to CRx (CRx write).
13876 */
13877static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13878{
13879 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13880 AssertRCReturn(rc, rc);
13881
13882 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13883 AssertMsg( rcStrict == VINF_SUCCESS
13884 || rcStrict == VINF_IEM_RAISED_XCPT
13885 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13886
13887 switch (iCrReg)
13888 {
13889 case 0:
13890 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13891 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13892 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13893 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13894 break;
13895
13896 case 2:
13897 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13898 /* Nothing to do here, CR2 it's not part of the VMCS. */
13899 break;
13900
13901 case 3:
13902 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13903 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13904 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13905 break;
13906
13907 case 4:
13908 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13909 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13910 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13911 pVCpu->cpum.GstCtx.cr4, pVCpu->hmr0.s.fLoadSaveGuestXcr0));
13912 break;
13913
13914 case 8:
13915 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13916 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13917 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13918 break;
13919
13920 default:
13921 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13922 break;
13923 }
13924
13925 if (rcStrict == VINF_IEM_RAISED_XCPT)
13926 {
13927 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13928 rcStrict = VINF_SUCCESS;
13929 }
13930 return rcStrict;
13931}
13932
13933
13934/**
13935 * VM-exit exception handler for \#PF (Page-fault exception).
13936 *
13937 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13938 */
13939static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13940{
13941 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13942 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13943 hmR0VmxReadExitQualVmcs(pVmxTransient);
13944
13945 if (!pVM->hmr0.s.fNestedPaging)
13946 { /* likely */ }
13947 else
13948 {
13949#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13950 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hmr0.s.fUsingDebugLoop);
13951#endif
13952 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13953 if (!pVmxTransient->fVectoringDoublePF)
13954 {
13955 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13956 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13957 }
13958 else
13959 {
13960 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13961 Assert(!pVmxTransient->fIsNestedGuest);
13962 hmR0VmxSetPendingXcptDF(pVCpu);
13963 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13964 }
13965 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13966 return VINF_SUCCESS;
13967 }
13968
13969 Assert(!pVmxTransient->fIsNestedGuest);
13970
13971 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13972 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13973 if (pVmxTransient->fVectoringPF)
13974 {
13975 Assert(pVCpu->hm.s.Event.fPending);
13976 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13977 }
13978
13979 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13980 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13981 AssertRCReturn(rc, rc);
13982
13983 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13984 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13985
13986 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13987 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13988
13989 Log4Func(("#PF: rc=%Rrc\n", rc));
13990 if (rc == VINF_SUCCESS)
13991 {
13992 /*
13993 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13994 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13995 */
13996 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13997 TRPMResetTrap(pVCpu);
13998 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13999 return rc;
14000 }
14001
14002 if (rc == VINF_EM_RAW_GUEST_TRAP)
14003 {
14004 if (!pVmxTransient->fVectoringDoublePF)
14005 {
14006 /* It's a guest page fault and needs to be reflected to the guest. */
14007 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
14008 TRPMResetTrap(pVCpu);
14009 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
14010 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14011 uGstErrorCode, pVmxTransient->uExitQual);
14012 }
14013 else
14014 {
14015 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14016 TRPMResetTrap(pVCpu);
14017 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14018 hmR0VmxSetPendingXcptDF(pVCpu);
14019 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14020 }
14021
14022 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14023 return VINF_SUCCESS;
14024 }
14025
14026 TRPMResetTrap(pVCpu);
14027 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14028 return rc;
14029}
14030
14031
14032/**
14033 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14034 *
14035 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14036 */
14037static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14038{
14039 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14040 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14041
14042 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14043 AssertRCReturn(rc, rc);
14044
14045 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14046 {
14047 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14048 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14049
14050 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14051 * provides VM-exit instruction length. If this causes problem later,
14052 * disassemble the instruction like it's done on AMD-V. */
14053 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14054 AssertRCReturn(rc2, rc2);
14055 return rc;
14056 }
14057
14058 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
14059 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14060 return VINF_SUCCESS;
14061}
14062
14063
14064/**
14065 * VM-exit exception handler for \#BP (Breakpoint exception).
14066 *
14067 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14068 */
14069static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14070{
14071 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14072 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14073
14074 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14075 AssertRCReturn(rc, rc);
14076
14077 if (!pVmxTransient->fIsNestedGuest)
14078 rc = DBGFTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
14079 else
14080 rc = VINF_EM_RAW_GUEST_TRAP;
14081
14082 if (rc == VINF_EM_RAW_GUEST_TRAP)
14083 {
14084 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14085 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14086 rc = VINF_SUCCESS;
14087 }
14088
14089 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
14090 return rc;
14091}
14092
14093
14094/**
14095 * VM-exit exception handler for \#AC (Alignment-check exception).
14096 *
14097 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14098 */
14099static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14100{
14101 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14102 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14103
14104 /* Re-inject it. We'll detect any nesting before getting here. */
14105 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14106 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14107 return VINF_SUCCESS;
14108}
14109
14110
14111/**
14112 * VM-exit exception handler for \#DB (Debug exception).
14113 *
14114 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14115 */
14116static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14117{
14118 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14119 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14120
14121 /*
14122 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14123 */
14124 hmR0VmxReadExitQualVmcs(pVmxTransient);
14125
14126 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14127 uint64_t const uDR6 = X86_DR6_INIT_VAL
14128 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14129 | X86_DR6_BD | X86_DR6_BS));
14130
14131 int rc;
14132 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14133 if (!pVmxTransient->fIsNestedGuest)
14134 {
14135 rc = DBGFTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14136
14137 /*
14138 * Prevents stepping twice over the same instruction when the guest is stepping using
14139 * EFLAGS.TF and the hypervisor debugger is stepping using MTF.
14140 * Testcase: DOSQEMM, break (using "ba x 1") at cs:rip 0x70:0x774 and step (using "t").
14141 */
14142 if ( rc == VINF_EM_DBG_STEPPED
14143 && (pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MONITOR_TRAP_FLAG))
14144 {
14145 Assert(pVCpu->hm.s.fSingleInstruction);
14146 rc = VINF_EM_RAW_GUEST_TRAP;
14147 }
14148 }
14149 else
14150 rc = VINF_EM_RAW_GUEST_TRAP;
14151 Log6Func(("rc=%Rrc\n", rc));
14152 if (rc == VINF_EM_RAW_GUEST_TRAP)
14153 {
14154 /*
14155 * The exception was for the guest. Update DR6, DR7.GD and
14156 * IA32_DEBUGCTL.LBR before forwarding it.
14157 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14158 */
14159 VMMRZCallRing3Disable(pVCpu);
14160 HM_DISABLE_PREEMPT(pVCpu);
14161
14162 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14163 pCtx->dr[6] |= uDR6;
14164 if (CPUMIsGuestDebugStateActive(pVCpu))
14165 ASMSetDR6(pCtx->dr[6]);
14166
14167 HM_RESTORE_PREEMPT();
14168 VMMRZCallRing3Enable(pVCpu);
14169
14170 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14171 AssertRCReturn(rc, rc);
14172
14173 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14174 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
14175
14176 /* Paranoia. */
14177 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
14178 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14179
14180 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
14181 AssertRC(rc);
14182
14183 /*
14184 * Raise #DB in the guest.
14185 *
14186 * It is important to reflect exactly what the VM-exit gave us (preserving the
14187 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14188 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14189 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14190 *
14191 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14192 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14193 */
14194 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14195 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14196 return VINF_SUCCESS;
14197 }
14198
14199 /*
14200 * Not a guest trap, must be a hypervisor related debug event then.
14201 * Update DR6 in case someone is interested in it.
14202 */
14203 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14204 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14205 CPUMSetHyperDR6(pVCpu, uDR6);
14206
14207 return rc;
14208}
14209
14210
14211/**
14212 * Hacks its way around the lovely mesa driver's backdoor accesses.
14213 *
14214 * @sa hmR0SvmHandleMesaDrvGp.
14215 */
14216static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14217{
14218 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14219 RT_NOREF(pCtx);
14220
14221 /* For now we'll just skip the instruction. */
14222 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14223}
14224
14225
14226/**
14227 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14228 * backdoor logging w/o checking what it is running inside.
14229 *
14230 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14231 * backdoor port and magic numbers loaded in registers.
14232 *
14233 * @returns true if it is, false if it isn't.
14234 * @sa hmR0SvmIsMesaDrvGp.
14235 */
14236DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14237{
14238 /* 0xed: IN eAX,dx */
14239 uint8_t abInstr[1];
14240 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
14241 return false;
14242
14243 /* Check that it is #GP(0). */
14244 if (pVmxTransient->uExitIntErrorCode != 0)
14245 return false;
14246
14247 /* Check magic and port. */
14248 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14249 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14250 if (pCtx->rax != UINT32_C(0x564d5868))
14251 return false;
14252 if (pCtx->dx != UINT32_C(0x5658))
14253 return false;
14254
14255 /* Flat ring-3 CS. */
14256 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14257 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14258 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14259 if (pCtx->cs.Attr.n.u2Dpl != 3)
14260 return false;
14261 if (pCtx->cs.u64Base != 0)
14262 return false;
14263
14264 /* Check opcode. */
14265 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14266 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14267 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14268 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14269 if (RT_FAILURE(rc))
14270 return false;
14271 if (abInstr[0] != 0xed)
14272 return false;
14273
14274 return true;
14275}
14276
14277
14278/**
14279 * VM-exit exception handler for \#GP (General-protection exception).
14280 *
14281 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14282 */
14283static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14284{
14285 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14286 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14287
14288 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14289 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14290 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
14291 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
14292 { /* likely */ }
14293 else
14294 {
14295#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14296 Assert(pVCpu->hmr0.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14297#endif
14298 /*
14299 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14300 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14301 */
14302 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14303 AssertRCReturn(rc, rc);
14304 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14305 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14306
14307 if ( pVmxTransient->fIsNestedGuest
14308 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14309 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14310 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14311 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14312 else
14313 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14314 return rc;
14315 }
14316
14317 Assert(CPUMIsGuestInRealModeEx(pCtx));
14318 Assert(!pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest);
14319 Assert(!pVmxTransient->fIsNestedGuest);
14320
14321 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14322 AssertRCReturn(rc, rc);
14323
14324 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14325 if (rcStrict == VINF_SUCCESS)
14326 {
14327 if (!CPUMIsGuestInRealModeEx(pCtx))
14328 {
14329 /*
14330 * The guest is no longer in real-mode, check if we can continue executing the
14331 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14332 */
14333 pVmcsInfoShared->RealMode.fRealOnV86Active = false;
14334 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
14335 {
14336 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14337 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14338 }
14339 else
14340 {
14341 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14342 rcStrict = VINF_EM_RESCHEDULE;
14343 }
14344 }
14345 else
14346 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14347 }
14348 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14349 {
14350 rcStrict = VINF_SUCCESS;
14351 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14352 }
14353 return VBOXSTRICTRC_VAL(rcStrict);
14354}
14355
14356
14357/**
14358 * VM-exit exception handler wrapper for all other exceptions that are not handled
14359 * by a specific handler.
14360 *
14361 * This simply re-injects the exception back into the VM without any special
14362 * processing.
14363 *
14364 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14365 */
14366static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14367{
14368 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14369
14370#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14371 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14372 AssertMsg(pVCpu->hmr0.s.fUsingDebugLoop || pVmcsInfo->pShared->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14373 ("uVector=%#x u32XcptBitmap=%#X32\n",
14374 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14375 NOREF(pVmcsInfo);
14376#endif
14377
14378 /*
14379 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14380 * would have been handled while checking exits due to event delivery.
14381 */
14382 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14383
14384#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14385 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14386 AssertRCReturn(rc, rc);
14387 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14388#endif
14389
14390#ifdef VBOX_WITH_STATISTICS
14391 switch (uVector)
14392 {
14393 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14394 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14395 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14396 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14397 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14398 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14399 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14400 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14401 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14402 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14403 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14404 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14405 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14406 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14407 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14408 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14409 default:
14410 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14411 break;
14412 }
14413#endif
14414
14415 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14416 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14417 NOREF(uVector);
14418
14419 /* Re-inject the original exception into the guest. */
14420 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14421 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14422 return VINF_SUCCESS;
14423}
14424
14425
14426/**
14427 * VM-exit exception handler for all exceptions (except NMIs!).
14428 *
14429 * @remarks This may be called for both guests and nested-guests. Take care to not
14430 * make assumptions and avoid doing anything that is not relevant when
14431 * executing a nested-guest (e.g., Mesa driver hacks).
14432 */
14433static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14434{
14435 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14436
14437 /*
14438 * If this VM-exit occurred while delivering an event through the guest IDT, take
14439 * action based on the return code and additional hints (e.g. for page-faults)
14440 * that will be updated in the VMX transient structure.
14441 */
14442 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14443 if (rcStrict == VINF_SUCCESS)
14444 {
14445 /*
14446 * If an exception caused a VM-exit due to delivery of an event, the original
14447 * event may have to be re-injected into the guest. We shall reinject it and
14448 * continue guest execution. However, page-fault is a complicated case and
14449 * needs additional processing done in hmR0VmxExitXcptPF().
14450 */
14451 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14452 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14453 if ( !pVCpu->hm.s.Event.fPending
14454 || uVector == X86_XCPT_PF)
14455 {
14456 switch (uVector)
14457 {
14458 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14459 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14460 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14461 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14462 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14463 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14464 default:
14465 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14466 }
14467 }
14468 /* else: inject pending event before resuming guest execution. */
14469 }
14470 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14471 {
14472 Assert(pVCpu->hm.s.Event.fPending);
14473 rcStrict = VINF_SUCCESS;
14474 }
14475
14476 return rcStrict;
14477}
14478/** @} */
14479
14480
14481/** @name VM-exit handlers.
14482 * @{
14483 */
14484/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14485/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14486/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14487
14488/**
14489 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14490 */
14491HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14492{
14493 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14494 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14495 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14496 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14497 return VINF_SUCCESS;
14498 return VINF_EM_RAW_INTERRUPT;
14499}
14500
14501
14502/**
14503 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14504 * VM-exit.
14505 */
14506HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14507{
14508 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14509 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14510
14511 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14512
14513 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14514 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14515 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14516
14517 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14518 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14519 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14520 NOREF(pVmcsInfo);
14521
14522 VBOXSTRICTRC rcStrict;
14523 switch (uExitIntType)
14524 {
14525 /*
14526 * Host physical NMIs:
14527 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14528 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14529 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14530 *
14531 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14532 * See Intel spec. 27.5.5 "Updating Non-Register State".
14533 */
14534 case VMX_EXIT_INT_INFO_TYPE_NMI:
14535 {
14536 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14537 break;
14538 }
14539
14540 /*
14541 * Privileged software exceptions (#DB from ICEBP),
14542 * Software exceptions (#BP and #OF),
14543 * Hardware exceptions:
14544 * Process the required exceptions and resume guest execution if possible.
14545 */
14546 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14547 Assert(uVector == X86_XCPT_DB);
14548 RT_FALL_THRU();
14549 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14550 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14551 RT_FALL_THRU();
14552 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14553 {
14554 NOREF(uVector);
14555 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14556 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14557 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14558 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14559
14560 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14561 break;
14562 }
14563
14564 default:
14565 {
14566 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14567 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14568 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14569 break;
14570 }
14571 }
14572
14573 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14574 return rcStrict;
14575}
14576
14577
14578/**
14579 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14580 */
14581HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14582{
14583 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14584
14585 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14586 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14587 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14588
14589 /* Evaluate and deliver pending events and resume guest execution. */
14590 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14591 return VINF_SUCCESS;
14592}
14593
14594
14595/**
14596 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14597 */
14598HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14599{
14600 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14601
14602 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14603 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14604 {
14605 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14606 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14607 }
14608
14609 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14610
14611 /*
14612 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14613 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14614 */
14615 uint32_t fIntrState;
14616 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14617 AssertRC(rc);
14618 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14619 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14620 {
14621 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14622 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14623
14624 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14625 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14626 AssertRC(rc);
14627 }
14628
14629 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14630 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14631
14632 /* Evaluate and deliver pending events and resume guest execution. */
14633 return VINF_SUCCESS;
14634}
14635
14636
14637/**
14638 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14639 */
14640HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14641{
14642 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14643 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14644}
14645
14646
14647/**
14648 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14649 */
14650HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14651{
14652 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14653 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14654}
14655
14656
14657/**
14658 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14659 */
14660HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14661{
14662 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14663
14664 /*
14665 * Get the state we need and update the exit history entry.
14666 */
14667 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14668 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14669
14670 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14671 AssertRCReturn(rc, rc);
14672
14673 VBOXSTRICTRC rcStrict;
14674 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14675 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14676 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14677 if (!pExitRec)
14678 {
14679 /*
14680 * Regular CPUID instruction execution.
14681 */
14682 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14683 if (rcStrict == VINF_SUCCESS)
14684 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14685 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14686 {
14687 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14688 rcStrict = VINF_SUCCESS;
14689 }
14690 }
14691 else
14692 {
14693 /*
14694 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14695 */
14696 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14697 AssertRCReturn(rc2, rc2);
14698
14699 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14700 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14701
14702 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14703 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14704
14705 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14706 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14707 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14708 }
14709 return rcStrict;
14710}
14711
14712
14713/**
14714 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14715 */
14716HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14717{
14718 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14719
14720 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14721 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14722 AssertRCReturn(rc, rc);
14723
14724 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14725 return VINF_EM_RAW_EMULATE_INSTR;
14726
14727 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14728 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14729}
14730
14731
14732/**
14733 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14734 */
14735HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14736{
14737 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14738
14739 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14740 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14741 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14742 AssertRCReturn(rc, rc);
14743
14744 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14745 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14746 {
14747 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14748 we must reset offsetting on VM-entry. See @bugref{6634}. */
14749 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14750 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14751 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14752 }
14753 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14754 {
14755 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14756 rcStrict = VINF_SUCCESS;
14757 }
14758 return rcStrict;
14759}
14760
14761
14762/**
14763 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14764 */
14765HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14766{
14767 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14768
14769 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14770 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14771 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14772 AssertRCReturn(rc, rc);
14773
14774 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14775 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14776 {
14777 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14778 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14779 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14780 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14781 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14782 }
14783 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14784 {
14785 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14786 rcStrict = VINF_SUCCESS;
14787 }
14788 return rcStrict;
14789}
14790
14791
14792/**
14793 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14794 */
14795HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14796{
14797 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14798
14799 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14800 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14801 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14802 AssertRCReturn(rc, rc);
14803
14804 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14805 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14806 if (RT_LIKELY(rc == VINF_SUCCESS))
14807 {
14808 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14809 Assert(pVmxTransient->cbExitInstr == 2);
14810 }
14811 else
14812 {
14813 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14814 rc = VERR_EM_INTERPRETER;
14815 }
14816 return rc;
14817}
14818
14819
14820/**
14821 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14822 */
14823HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14824{
14825 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14826
14827 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14828 if (EMAreHypercallInstructionsEnabled(pVCpu))
14829 {
14830 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14831 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14832 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14833 AssertRCReturn(rc, rc);
14834
14835 /* Perform the hypercall. */
14836 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14837 if (rcStrict == VINF_SUCCESS)
14838 {
14839 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14840 AssertRCReturn(rc, rc);
14841 }
14842 else
14843 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14844 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14845 || RT_FAILURE(rcStrict));
14846
14847 /* If the hypercall changes anything other than guest's general-purpose registers,
14848 we would need to reload the guest changed bits here before VM-entry. */
14849 }
14850 else
14851 Log4Func(("Hypercalls not enabled\n"));
14852
14853 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14854 if (RT_FAILURE(rcStrict))
14855 {
14856 hmR0VmxSetPendingXcptUD(pVCpu);
14857 rcStrict = VINF_SUCCESS;
14858 }
14859
14860 return rcStrict;
14861}
14862
14863
14864/**
14865 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14866 */
14867HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14868{
14869 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14870 Assert(!pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging || pVCpu->hmr0.s.fUsingDebugLoop);
14871
14872 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14873 hmR0VmxReadExitQualVmcs(pVmxTransient);
14874 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14875 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14876 AssertRCReturn(rc, rc);
14877
14878 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14879
14880 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14881 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14882 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14883 {
14884 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14885 rcStrict = VINF_SUCCESS;
14886 }
14887 else
14888 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14889 VBOXSTRICTRC_VAL(rcStrict)));
14890 return rcStrict;
14891}
14892
14893
14894/**
14895 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14896 */
14897HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14898{
14899 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14900
14901 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14902 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14903 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14904 AssertRCReturn(rc, rc);
14905
14906 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14907 if (rcStrict == VINF_SUCCESS)
14908 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14909 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14910 {
14911 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14912 rcStrict = VINF_SUCCESS;
14913 }
14914
14915 return rcStrict;
14916}
14917
14918
14919/**
14920 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14921 */
14922HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14923{
14924 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14925
14926 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14927 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14928 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14929 AssertRCReturn(rc, rc);
14930
14931 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14932 if (RT_SUCCESS(rcStrict))
14933 {
14934 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14935 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14936 rcStrict = VINF_SUCCESS;
14937 }
14938
14939 return rcStrict;
14940}
14941
14942
14943/**
14944 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14945 * VM-exit.
14946 */
14947HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14948{
14949 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14950 return VINF_EM_RESET;
14951}
14952
14953
14954/**
14955 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14956 */
14957HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14958{
14959 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14960
14961 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14962 AssertRCReturn(rc, rc);
14963
14964 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14965 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14966 rc = VINF_SUCCESS;
14967 else
14968 rc = VINF_EM_HALT;
14969
14970 if (rc != VINF_SUCCESS)
14971 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14972 return rc;
14973}
14974
14975
14976/**
14977 * VM-exit handler for instructions that result in a \#UD exception delivered to
14978 * the guest.
14979 */
14980HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14981{
14982 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14983 hmR0VmxSetPendingXcptUD(pVCpu);
14984 return VINF_SUCCESS;
14985}
14986
14987
14988/**
14989 * VM-exit handler for expiry of the VMX-preemption timer.
14990 */
14991HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14992{
14993 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14994
14995 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14996 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14997
14998 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14999 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15000 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
15001 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
15002 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
15003}
15004
15005
15006/**
15007 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
15008 */
15009HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15010{
15011 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15012
15013 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15014 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15015 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15016 AssertRCReturn(rc, rc);
15017
15018 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
15019 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15020 : HM_CHANGED_RAISED_XCPT_MASK);
15021
15022 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15023 bool const fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15024 if (fLoadSaveGuestXcr0 != pVCpu->hmr0.s.fLoadSaveGuestXcr0)
15025 {
15026 pVCpu->hmr0.s.fLoadSaveGuestXcr0 = fLoadSaveGuestXcr0;
15027 hmR0VmxUpdateStartVmFunction(pVCpu);
15028 }
15029
15030 return rcStrict;
15031}
15032
15033
15034/**
15035 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15036 */
15037HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15038{
15039 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15040
15041 /** @todo Enable the new code after finding a reliably guest test-case. */
15042#if 1
15043 return VERR_EM_INTERPRETER;
15044#else
15045 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15046 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15047 hmR0VmxReadExitQualVmcs(pVmxTransient);
15048 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15049 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15050 AssertRCReturn(rc, rc);
15051
15052 /* Paranoia. Ensure this has a memory operand. */
15053 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
15054
15055 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
15056 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
15057 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
15058 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
15059
15060 RTGCPTR GCPtrDesc;
15061 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
15062
15063 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
15064 GCPtrDesc, uType);
15065 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15066 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15067 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15068 {
15069 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15070 rcStrict = VINF_SUCCESS;
15071 }
15072 return rcStrict;
15073#endif
15074}
15075
15076
15077/**
15078 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15079 * VM-exit.
15080 */
15081HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15082{
15083 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15084 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15085 AssertRCReturn(rc, rc);
15086
15087 rc = hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15088 if (RT_FAILURE(rc))
15089 return rc;
15090
15091 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15092 NOREF(uInvalidReason);
15093
15094#ifdef VBOX_STRICT
15095 uint32_t fIntrState;
15096 uint64_t u64Val;
15097 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15098 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15099 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15100
15101 Log4(("uInvalidReason %u\n", uInvalidReason));
15102 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15103 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15104 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15105
15106 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
15107 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15108 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
15109 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
15110 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
15111 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
15112 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
15113 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
15114 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
15115 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
15116 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
15117 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
15118 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging)
15119 {
15120 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15121 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15122 }
15123 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
15124#endif
15125
15126 return VERR_VMX_INVALID_GUEST_STATE;
15127}
15128
15129/**
15130 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15131 */
15132HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15133{
15134 /*
15135 * Cumulative notes of all recognized but unexpected VM-exits.
15136 *
15137 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
15138 * nested-paging is used.
15139 *
15140 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15141 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15142 * this function (and thereby stop VM execution) for handling such instructions.
15143 *
15144 *
15145 * VMX_EXIT_INIT_SIGNAL:
15146 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15147 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15148 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15149 *
15150 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15151 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15152 * See Intel spec. "23.8 Restrictions on VMX operation".
15153 *
15154 * VMX_EXIT_SIPI:
15155 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15156 * activity state is used. We don't make use of it as our guests don't have direct
15157 * access to the host local APIC.
15158 *
15159 * See Intel spec. 25.3 "Other Causes of VM-exits".
15160 *
15161 * VMX_EXIT_IO_SMI:
15162 * VMX_EXIT_SMI:
15163 * This can only happen if we support dual-monitor treatment of SMI, which can be
15164 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15165 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15166 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15167 *
15168 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15169 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15170 *
15171 * VMX_EXIT_ERR_MSR_LOAD:
15172 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15173 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15174 * execution.
15175 *
15176 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15177 *
15178 * VMX_EXIT_ERR_MACHINE_CHECK:
15179 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15180 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15181 * #MC exception abort class exception is raised. We thus cannot assume a
15182 * reasonable chance of continuing any sort of execution and we bail.
15183 *
15184 * See Intel spec. 15.1 "Machine-check Architecture".
15185 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15186 *
15187 * VMX_EXIT_PML_FULL:
15188 * VMX_EXIT_VIRTUALIZED_EOI:
15189 * VMX_EXIT_APIC_WRITE:
15190 * We do not currently support any of these features and thus they are all unexpected
15191 * VM-exits.
15192 *
15193 * VMX_EXIT_GDTR_IDTR_ACCESS:
15194 * VMX_EXIT_LDTR_TR_ACCESS:
15195 * VMX_EXIT_RDRAND:
15196 * VMX_EXIT_RSM:
15197 * VMX_EXIT_VMFUNC:
15198 * VMX_EXIT_ENCLS:
15199 * VMX_EXIT_RDSEED:
15200 * VMX_EXIT_XSAVES:
15201 * VMX_EXIT_XRSTORS:
15202 * VMX_EXIT_UMWAIT:
15203 * VMX_EXIT_TPAUSE:
15204 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15205 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15206 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15207 *
15208 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15209 */
15210 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15211 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15212 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15213}
15214
15215
15216/**
15217 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15218 */
15219HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15220{
15221 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15222
15223 /** @todo Optimize this: We currently drag in the whole MSR state
15224 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15225 * MSRs required. That would require changes to IEM and possibly CPUM too.
15226 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15227 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15228 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15229 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15230 switch (idMsr)
15231 {
15232 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15233 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15234 }
15235
15236 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15237 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15238 AssertRCReturn(rc, rc);
15239
15240 Log4Func(("ecx=%#RX32\n", idMsr));
15241
15242#ifdef VBOX_STRICT
15243 Assert(!pVmxTransient->fIsNestedGuest);
15244 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15245 {
15246 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15247 && idMsr != MSR_K6_EFER)
15248 {
15249 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15250 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15251 }
15252 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15253 {
15254 Assert(pVmcsInfo->pvMsrBitmap);
15255 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15256 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15257 {
15258 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15259 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15260 }
15261 }
15262 }
15263#endif
15264
15265 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
15266 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15267 if (rcStrict == VINF_SUCCESS)
15268 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15269 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15270 {
15271 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15272 rcStrict = VINF_SUCCESS;
15273 }
15274 else
15275 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ || rcStrict == VINF_EM_TRIPLE_FAULT,
15276 ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15277
15278 return rcStrict;
15279}
15280
15281
15282/**
15283 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15284 */
15285HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15286{
15287 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15288
15289 /** @todo Optimize this: We currently drag in the whole MSR state
15290 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15291 * MSRs required. That would require changes to IEM and possibly CPUM too.
15292 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15293 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15294 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15295
15296 /*
15297 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15298 * Although we don't need to fetch the base as it will be overwritten shortly, while
15299 * loading guest-state we would also load the entire segment register including limit
15300 * and attributes and thus we need to load them here.
15301 */
15302 switch (idMsr)
15303 {
15304 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15305 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15306 }
15307
15308 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15309 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15310 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15311 AssertRCReturn(rc, rc);
15312
15313 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15314
15315 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
15316 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15317
15318 if (rcStrict == VINF_SUCCESS)
15319 {
15320 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15321
15322 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15323 if ( idMsr == MSR_IA32_APICBASE
15324 || ( idMsr >= MSR_IA32_X2APIC_START
15325 && idMsr <= MSR_IA32_X2APIC_END))
15326 {
15327 /*
15328 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15329 * When full APIC register virtualization is implemented we'll have to make
15330 * sure APIC state is saved from the VMCS before IEM changes it.
15331 */
15332 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15333 }
15334 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15335 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15336 else if (idMsr == MSR_K6_EFER)
15337 {
15338 /*
15339 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15340 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15341 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15342 */
15343 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15344 }
15345
15346 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15347 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15348 {
15349 switch (idMsr)
15350 {
15351 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15352 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15353 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15354 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15355 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15356 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15357 default:
15358 {
15359 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15360 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15361 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15362 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15363 break;
15364 }
15365 }
15366 }
15367#ifdef VBOX_STRICT
15368 else
15369 {
15370 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15371 switch (idMsr)
15372 {
15373 case MSR_IA32_SYSENTER_CS:
15374 case MSR_IA32_SYSENTER_EIP:
15375 case MSR_IA32_SYSENTER_ESP:
15376 case MSR_K8_FS_BASE:
15377 case MSR_K8_GS_BASE:
15378 {
15379 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15380 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15381 }
15382
15383 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15384 default:
15385 {
15386 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15387 {
15388 /* EFER MSR writes are always intercepted. */
15389 if (idMsr != MSR_K6_EFER)
15390 {
15391 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15392 idMsr));
15393 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15394 }
15395 }
15396
15397 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15398 {
15399 Assert(pVmcsInfo->pvMsrBitmap);
15400 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15401 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15402 {
15403 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15404 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15405 }
15406 }
15407 break;
15408 }
15409 }
15410 }
15411#endif /* VBOX_STRICT */
15412 }
15413 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15414 {
15415 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15416 rcStrict = VINF_SUCCESS;
15417 }
15418 else
15419 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE || rcStrict == VINF_EM_TRIPLE_FAULT,
15420 ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15421
15422 return rcStrict;
15423}
15424
15425
15426/**
15427 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15428 */
15429HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15430{
15431 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15432
15433 /** @todo The guest has likely hit a contended spinlock. We might want to
15434 * poke a schedule different guest VCPU. */
15435 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15436 if (RT_SUCCESS(rc))
15437 return VINF_EM_RAW_INTERRUPT;
15438
15439 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15440 return rc;
15441}
15442
15443
15444/**
15445 * VM-exit handler for when the TPR value is lowered below the specified
15446 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15447 */
15448HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15449{
15450 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15451 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15452
15453 /*
15454 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15455 * We'll re-evaluate pending interrupts and inject them before the next VM
15456 * entry so we can just continue execution here.
15457 */
15458 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15459 return VINF_SUCCESS;
15460}
15461
15462
15463/**
15464 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15465 * VM-exit.
15466 *
15467 * @retval VINF_SUCCESS when guest execution can continue.
15468 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15469 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15470 * incompatible guest state for VMX execution (real-on-v86 case).
15471 */
15472HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15473{
15474 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15475 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15476
15477 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15478 hmR0VmxReadExitQualVmcs(pVmxTransient);
15479 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15480
15481 VBOXSTRICTRC rcStrict;
15482 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15483 uint64_t const uExitQual = pVmxTransient->uExitQual;
15484 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15485 switch (uAccessType)
15486 {
15487 /*
15488 * MOV to CRx.
15489 */
15490 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15491 {
15492 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15493 AssertRCReturn(rc, rc);
15494
15495 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15496 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15497 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15498 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15499
15500 /*
15501 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15502 * - When nested paging isn't used.
15503 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15504 * - We are executing in the VM debug loop.
15505 */
15506 Assert( iCrReg != 3
15507 || !pVM->hmr0.s.fNestedPaging
15508 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15509 || pVCpu->hmr0.s.fUsingDebugLoop);
15510
15511 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15512 Assert( iCrReg != 8
15513 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15514
15515 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15516 AssertMsg( rcStrict == VINF_SUCCESS
15517 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15518
15519 /*
15520 * This is a kludge for handling switches back to real mode when we try to use
15521 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15522 * deal with special selector values, so we have to return to ring-3 and run
15523 * there till the selector values are V86 mode compatible.
15524 *
15525 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15526 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15527 * this function.
15528 */
15529 if ( iCrReg == 0
15530 && rcStrict == VINF_SUCCESS
15531 && !pVM->hmr0.s.vmx.fUnrestrictedGuest
15532 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15533 && (uOldCr0 & X86_CR0_PE)
15534 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15535 {
15536 /** @todo Check selectors rather than returning all the time. */
15537 Assert(!pVmxTransient->fIsNestedGuest);
15538 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15539 rcStrict = VINF_EM_RESCHEDULE_REM;
15540 }
15541 break;
15542 }
15543
15544 /*
15545 * MOV from CRx.
15546 */
15547 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15548 {
15549 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15550 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15551
15552 /*
15553 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15554 * - When nested paging isn't used.
15555 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15556 * - We are executing in the VM debug loop.
15557 */
15558 Assert( iCrReg != 3
15559 || !pVM->hmr0.s.fNestedPaging
15560 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15561 || pVCpu->hmr0.s.fLeaveDone);
15562
15563 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15564 Assert( iCrReg != 8
15565 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15566
15567 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15568 break;
15569 }
15570
15571 /*
15572 * CLTS (Clear Task-Switch Flag in CR0).
15573 */
15574 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15575 {
15576 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15577 break;
15578 }
15579
15580 /*
15581 * LMSW (Load Machine-Status Word into CR0).
15582 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15583 */
15584 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15585 {
15586 RTGCPTR GCPtrEffDst;
15587 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15588 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15589 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15590 if (fMemOperand)
15591 {
15592 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15593 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15594 }
15595 else
15596 GCPtrEffDst = NIL_RTGCPTR;
15597 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15598 break;
15599 }
15600
15601 default:
15602 {
15603 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15604 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15605 }
15606 }
15607
15608 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15609 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15610 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15611
15612 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15613 NOREF(pVM);
15614 return rcStrict;
15615}
15616
15617
15618/**
15619 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15620 * VM-exit.
15621 */
15622HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15623{
15624 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15625 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15626
15627 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15628 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15629 hmR0VmxReadExitQualVmcs(pVmxTransient);
15630 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15631 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15632 | CPUMCTX_EXTRN_EFER);
15633 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15634 AssertRCReturn(rc, rc);
15635
15636 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15637 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15638 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15639 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15640 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15641 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15642 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15643 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15644
15645 /*
15646 * Update exit history to see if this exit can be optimized.
15647 */
15648 VBOXSTRICTRC rcStrict;
15649 PCEMEXITREC pExitRec = NULL;
15650 if ( !fGstStepping
15651 && !fDbgStepping)
15652 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15653 !fIOString
15654 ? !fIOWrite
15655 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15656 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15657 : !fIOWrite
15658 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15659 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15660 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15661 if (!pExitRec)
15662 {
15663 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15664 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15665
15666 uint32_t const cbValue = s_aIOSizes[uIOSize];
15667 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15668 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15669 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15670 if (fIOString)
15671 {
15672 /*
15673 * INS/OUTS - I/O String instruction.
15674 *
15675 * Use instruction-information if available, otherwise fall back on
15676 * interpreting the instruction.
15677 */
15678 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15679 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15680 bool const fInsOutsInfo = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15681 if (fInsOutsInfo)
15682 {
15683 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15684 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15685 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15686 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15687 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15688 if (fIOWrite)
15689 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15690 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15691 else
15692 {
15693 /*
15694 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15695 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15696 * See Intel Instruction spec. for "INS".
15697 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15698 */
15699 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15700 }
15701 }
15702 else
15703 rcStrict = IEMExecOne(pVCpu);
15704
15705 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15706 fUpdateRipAlready = true;
15707 }
15708 else
15709 {
15710 /*
15711 * IN/OUT - I/O instruction.
15712 */
15713 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15714 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15715 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15716 if (fIOWrite)
15717 {
15718 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15719 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15720 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15721 && !pCtx->eflags.Bits.u1TF)
15722 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15723 }
15724 else
15725 {
15726 uint32_t u32Result = 0;
15727 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15728 if (IOM_SUCCESS(rcStrict))
15729 {
15730 /* Save result of I/O IN instr. in AL/AX/EAX. */
15731 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15732 }
15733 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15734 && !pCtx->eflags.Bits.u1TF)
15735 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15736 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15737 }
15738 }
15739
15740 if (IOM_SUCCESS(rcStrict))
15741 {
15742 if (!fUpdateRipAlready)
15743 {
15744 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15745 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15746 }
15747
15748 /*
15749 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15750 * while booting Fedora 17 64-bit guest.
15751 *
15752 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15753 */
15754 if (fIOString)
15755 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15756
15757 /*
15758 * If any I/O breakpoints are armed, we need to check if one triggered
15759 * and take appropriate action.
15760 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15761 */
15762 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15763 AssertRCReturn(rc, rc);
15764
15765 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15766 * execution engines about whether hyper BPs and such are pending. */
15767 uint32_t const uDr7 = pCtx->dr[7];
15768 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15769 && X86_DR7_ANY_RW_IO(uDr7)
15770 && (pCtx->cr4 & X86_CR4_DE))
15771 || DBGFBpIsHwIoArmed(pVM)))
15772 {
15773 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15774
15775 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15776 VMMRZCallRing3Disable(pVCpu);
15777 HM_DISABLE_PREEMPT(pVCpu);
15778
15779 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15780
15781 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15782 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15783 {
15784 /* Raise #DB. */
15785 if (fIsGuestDbgActive)
15786 ASMSetDR6(pCtx->dr[6]);
15787 if (pCtx->dr[7] != uDr7)
15788 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15789
15790 hmR0VmxSetPendingXcptDB(pVCpu);
15791 }
15792 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15793 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15794 else if ( rcStrict2 != VINF_SUCCESS
15795 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15796 rcStrict = rcStrict2;
15797 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15798
15799 HM_RESTORE_PREEMPT();
15800 VMMRZCallRing3Enable(pVCpu);
15801 }
15802 }
15803
15804#ifdef VBOX_STRICT
15805 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15806 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15807 Assert(!fIOWrite);
15808 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15809 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15810 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15811 Assert(fIOWrite);
15812 else
15813 {
15814# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15815 * statuses, that the VMM device and some others may return. See
15816 * IOM_SUCCESS() for guidance. */
15817 AssertMsg( RT_FAILURE(rcStrict)
15818 || rcStrict == VINF_SUCCESS
15819 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15820 || rcStrict == VINF_EM_DBG_BREAKPOINT
15821 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15822 || rcStrict == VINF_EM_RAW_TO_R3
15823 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15824# endif
15825 }
15826#endif
15827 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15828 }
15829 else
15830 {
15831 /*
15832 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15833 */
15834 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15835 AssertRCReturn(rc2, rc2);
15836 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15837 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15838 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15839 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15840 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15841 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15842
15843 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15844 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15845
15846 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15847 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15848 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15849 }
15850 return rcStrict;
15851}
15852
15853
15854/**
15855 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15856 * VM-exit.
15857 */
15858HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15859{
15860 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15861
15862 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15863 hmR0VmxReadExitQualVmcs(pVmxTransient);
15864 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15865 {
15866 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15867 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15868 {
15869 uint32_t uErrCode;
15870 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15871 {
15872 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15873 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15874 }
15875 else
15876 uErrCode = 0;
15877
15878 RTGCUINTPTR GCPtrFaultAddress;
15879 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15880 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15881 else
15882 GCPtrFaultAddress = 0;
15883
15884 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15885
15886 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15887 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15888
15889 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15890 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15891 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15892 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15893 }
15894 }
15895
15896 /* Fall back to the interpreter to emulate the task-switch. */
15897 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15898 return VERR_EM_INTERPRETER;
15899}
15900
15901
15902/**
15903 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15904 */
15905HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15906{
15907 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15908
15909 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15910 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15911 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15912 AssertRC(rc);
15913 return VINF_EM_DBG_STEPPED;
15914}
15915
15916
15917/**
15918 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15919 */
15920HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15921{
15922 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15923 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15924
15925 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15926 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15927 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15928 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15929 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15930
15931 /*
15932 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15933 */
15934 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15935 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15936 {
15937 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15938 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15939 {
15940 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15941 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15942 }
15943 }
15944 else
15945 {
15946 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15947 return rcStrict;
15948 }
15949
15950 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15951 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15952 hmR0VmxReadExitQualVmcs(pVmxTransient);
15953 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15954 AssertRCReturn(rc, rc);
15955
15956 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15957 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15958 switch (uAccessType)
15959 {
15960 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15961 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15962 {
15963 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15964 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15965 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15966
15967 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15968 GCPhys &= PAGE_BASE_GC_MASK;
15969 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15970 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15971 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15972
15973 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
15974 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
15975 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15976 if ( rcStrict == VINF_SUCCESS
15977 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15978 || rcStrict == VERR_PAGE_NOT_PRESENT)
15979 {
15980 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15981 | HM_CHANGED_GUEST_APIC_TPR);
15982 rcStrict = VINF_SUCCESS;
15983 }
15984 break;
15985 }
15986
15987 default:
15988 {
15989 Log4Func(("uAccessType=%#x\n", uAccessType));
15990 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15991 break;
15992 }
15993 }
15994
15995 if (rcStrict != VINF_SUCCESS)
15996 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15997 return rcStrict;
15998}
15999
16000
16001/**
16002 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
16003 * VM-exit.
16004 */
16005HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16006{
16007 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16008 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16009
16010 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
16011 if (!pVmxTransient->fIsNestedGuest)
16012 {
16013 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16014 if (pVmxTransient->fWasGuestDebugStateActive)
16015 {
16016 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16017 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16018 }
16019
16020 if ( !pVCpu->hm.s.fSingleInstruction
16021 && !pVmxTransient->fWasHyperDebugStateActive)
16022 {
16023 Assert(!DBGFIsStepping(pVCpu));
16024 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16025
16026 /* Don't intercept MOV DRx any more. */
16027 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16028 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16029 AssertRC(rc);
16030
16031 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16032 VMMRZCallRing3Disable(pVCpu);
16033 HM_DISABLE_PREEMPT(pVCpu);
16034
16035 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16036 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16037 Assert(CPUMIsGuestDebugStateActive(pVCpu));
16038
16039 HM_RESTORE_PREEMPT();
16040 VMMRZCallRing3Enable(pVCpu);
16041
16042#ifdef VBOX_WITH_STATISTICS
16043 hmR0VmxReadExitQualVmcs(pVmxTransient);
16044 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16045 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16046 else
16047 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16048#endif
16049 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16050 return VINF_SUCCESS;
16051 }
16052 }
16053
16054 /*
16055 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16056 * The EFER MSR is always up-to-date.
16057 * Update the segment registers and DR7 from the CPU.
16058 */
16059 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16060 hmR0VmxReadExitQualVmcs(pVmxTransient);
16061 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16062 AssertRCReturn(rc, rc);
16063 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16064
16065 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16066 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16067 {
16068 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16069 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16070 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16071 if (RT_SUCCESS(rc))
16072 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16073 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16074 }
16075 else
16076 {
16077 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16078 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16079 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16080 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16081 }
16082
16083 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16084 if (RT_SUCCESS(rc))
16085 {
16086 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16087 AssertRCReturn(rc2, rc2);
16088 return VINF_SUCCESS;
16089 }
16090 return rc;
16091}
16092
16093
16094/**
16095 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16096 * Conditional VM-exit.
16097 */
16098HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16099{
16100 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16101 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16102
16103 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16104 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16105 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16106 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16107 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16108
16109 /*
16110 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16111 */
16112 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16113 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16114 {
16115 /*
16116 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16117 * instruction emulation to inject the original event. Otherwise, injecting the original event
16118 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
16119 */
16120 if (!pVCpu->hm.s.Event.fPending)
16121 { /* likely */ }
16122 else
16123 {
16124 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16125#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16126 /** @todo NSTVMX: Think about how this should be handled. */
16127 if (pVmxTransient->fIsNestedGuest)
16128 return VERR_VMX_IPE_3;
16129#endif
16130 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16131 }
16132 }
16133 else
16134 {
16135 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16136 return rcStrict;
16137 }
16138
16139 /*
16140 * Get sufficient state and update the exit history entry.
16141 */
16142 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16143 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16144 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16145 AssertRCReturn(rc, rc);
16146
16147 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16148 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16149 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16150 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16151 if (!pExitRec)
16152 {
16153 /*
16154 * If we succeed, resume guest execution.
16155 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16156 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16157 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16158 * weird case. See @bugref{6043}.
16159 */
16160 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16161 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16162/** @todo bird: We can probably just go straight to IOM here and assume that
16163 * it's MMIO, then fall back on PGM if that hunch didn't work out so
16164 * well. However, we need to address that aliasing workarounds that
16165 * PGMR0Trap0eHandlerNPMisconfig implements. So, some care is needed.
16166 *
16167 * Might also be interesting to see if we can get this done more or
16168 * less locklessly inside IOM. Need to consider the lookup table
16169 * updating and use a bit more carefully first (or do all updates via
16170 * rendezvous) */
16171 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16172 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16173 if ( rcStrict == VINF_SUCCESS
16174 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16175 || rcStrict == VERR_PAGE_NOT_PRESENT)
16176 {
16177 /* Successfully handled MMIO operation. */
16178 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16179 | HM_CHANGED_GUEST_APIC_TPR);
16180 rcStrict = VINF_SUCCESS;
16181 }
16182 }
16183 else
16184 {
16185 /*
16186 * Frequent exit or something needing probing. Call EMHistoryExec.
16187 */
16188 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16189 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16190
16191 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16192 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16193
16194 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16195 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16196 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16197 }
16198 return rcStrict;
16199}
16200
16201
16202/**
16203 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16204 * VM-exit.
16205 */
16206HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16207{
16208 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16209 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16210
16211 hmR0VmxReadExitQualVmcs(pVmxTransient);
16212 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16213 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16214 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16215 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16216 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16217
16218 /*
16219 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16220 */
16221 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16222 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16223 {
16224 /*
16225 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16226 * we shall resolve the nested #PF and re-inject the original event.
16227 */
16228 if (pVCpu->hm.s.Event.fPending)
16229 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16230 }
16231 else
16232 {
16233 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16234 return rcStrict;
16235 }
16236
16237 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16238 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16239 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16240 AssertRCReturn(rc, rc);
16241
16242 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16243 uint64_t const uExitQual = pVmxTransient->uExitQual;
16244 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16245
16246 RTGCUINT uErrorCode = 0;
16247 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16248 uErrorCode |= X86_TRAP_PF_ID;
16249 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16250 uErrorCode |= X86_TRAP_PF_RW;
16251 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16252 uErrorCode |= X86_TRAP_PF_P;
16253
16254 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16255 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16256 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16257
16258 /*
16259 * Handle the pagefault trap for the nested shadow table.
16260 */
16261 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16262 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16263 TRPMResetTrap(pVCpu);
16264
16265 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16266 if ( rcStrict == VINF_SUCCESS
16267 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16268 || rcStrict == VERR_PAGE_NOT_PRESENT)
16269 {
16270 /* Successfully synced our nested page tables. */
16271 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16272 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16273 return VINF_SUCCESS;
16274 }
16275
16276 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16277 return rcStrict;
16278}
16279
16280
16281#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16282/**
16283 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16284 */
16285HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16286{
16287 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16288
16289 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16290 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16291 hmR0VmxReadExitQualVmcs(pVmxTransient);
16292 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16293 | CPUMCTX_EXTRN_HWVIRT
16294 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16295 AssertRCReturn(rc, rc);
16296
16297 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16298
16299 VMXVEXITINFO ExitInfo;
16300 RT_ZERO(ExitInfo);
16301 ExitInfo.uReason = pVmxTransient->uExitReason;
16302 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16303 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16304 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16305 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16306
16307 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16308 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16309 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16310 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16311 {
16312 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16313 rcStrict = VINF_SUCCESS;
16314 }
16315 return rcStrict;
16316}
16317
16318
16319/**
16320 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16321 */
16322HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16323{
16324 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16325
16326 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16327 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16328 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16329 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16330 AssertRCReturn(rc, rc);
16331
16332 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16333
16334 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16335 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
16336 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16337 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16338 {
16339 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16340 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16341 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16342 }
16343 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16344 return rcStrict;
16345}
16346
16347
16348/**
16349 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16350 */
16351HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16352{
16353 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16354
16355 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16356 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16357 hmR0VmxReadExitQualVmcs(pVmxTransient);
16358 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16359 | CPUMCTX_EXTRN_HWVIRT
16360 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16361 AssertRCReturn(rc, rc);
16362
16363 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16364
16365 VMXVEXITINFO ExitInfo;
16366 RT_ZERO(ExitInfo);
16367 ExitInfo.uReason = pVmxTransient->uExitReason;
16368 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16369 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16370 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16371 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16372
16373 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16374 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16375 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16376 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16377 {
16378 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16379 rcStrict = VINF_SUCCESS;
16380 }
16381 return rcStrict;
16382}
16383
16384
16385/**
16386 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16387 */
16388HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16389{
16390 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16391
16392 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16393 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16394 hmR0VmxReadExitQualVmcs(pVmxTransient);
16395 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16396 | CPUMCTX_EXTRN_HWVIRT
16397 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16398 AssertRCReturn(rc, rc);
16399
16400 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16401
16402 VMXVEXITINFO ExitInfo;
16403 RT_ZERO(ExitInfo);
16404 ExitInfo.uReason = pVmxTransient->uExitReason;
16405 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16406 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16407 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16408 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16409
16410 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16411 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16412 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16413 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16414 {
16415 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16416 rcStrict = VINF_SUCCESS;
16417 }
16418 return rcStrict;
16419}
16420
16421
16422/**
16423 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16424 */
16425HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16426{
16427 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16428
16429 /*
16430 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16431 * thus might not need to import the shadow VMCS state, it's safer just in case
16432 * code elsewhere dares look at unsynced VMCS fields.
16433 */
16434 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16435 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16436 hmR0VmxReadExitQualVmcs(pVmxTransient);
16437 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16438 | CPUMCTX_EXTRN_HWVIRT
16439 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16440 AssertRCReturn(rc, rc);
16441
16442 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16443
16444 VMXVEXITINFO ExitInfo;
16445 RT_ZERO(ExitInfo);
16446 ExitInfo.uReason = pVmxTransient->uExitReason;
16447 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16448 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16449 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16450 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16451 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16452
16453 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16454 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16455 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16456 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16457 {
16458 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16459 rcStrict = VINF_SUCCESS;
16460 }
16461 return rcStrict;
16462}
16463
16464
16465/**
16466 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16467 */
16468HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16469{
16470 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16471
16472 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16473 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16474 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16475 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16476 AssertRCReturn(rc, rc);
16477
16478 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16479
16480 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16481 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16482 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16483 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16484 {
16485 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16486 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16487 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16488 }
16489 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16490 return rcStrict;
16491}
16492
16493
16494/**
16495 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16496 */
16497HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16498{
16499 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16500
16501 /*
16502 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16503 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16504 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16505 */
16506 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16507 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16508 hmR0VmxReadExitQualVmcs(pVmxTransient);
16509 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16510 | CPUMCTX_EXTRN_HWVIRT
16511 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16512 AssertRCReturn(rc, rc);
16513
16514 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16515
16516 VMXVEXITINFO ExitInfo;
16517 RT_ZERO(ExitInfo);
16518 ExitInfo.uReason = pVmxTransient->uExitReason;
16519 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16520 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16521 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16522 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16523 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16524
16525 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16526 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16527 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16528 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16529 {
16530 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16531 rcStrict = VINF_SUCCESS;
16532 }
16533 return rcStrict;
16534}
16535
16536
16537/**
16538 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16539 */
16540HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16541{
16542 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16543
16544 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16545 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16546 | CPUMCTX_EXTRN_HWVIRT
16547 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16548 AssertRCReturn(rc, rc);
16549
16550 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16551
16552 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16553 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16554 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16555 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16556 {
16557 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16558 rcStrict = VINF_SUCCESS;
16559 }
16560 return rcStrict;
16561}
16562
16563
16564/**
16565 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16566 */
16567HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16568{
16569 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16570
16571 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16572 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16573 hmR0VmxReadExitQualVmcs(pVmxTransient);
16574 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16575 | CPUMCTX_EXTRN_HWVIRT
16576 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16577 AssertRCReturn(rc, rc);
16578
16579 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16580
16581 VMXVEXITINFO ExitInfo;
16582 RT_ZERO(ExitInfo);
16583 ExitInfo.uReason = pVmxTransient->uExitReason;
16584 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16585 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16586 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16587 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16588
16589 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16590 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16591 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16592 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16593 {
16594 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16595 rcStrict = VINF_SUCCESS;
16596 }
16597 return rcStrict;
16598}
16599
16600
16601/**
16602 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16603 */
16604HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16605{
16606 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16607
16608 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16609 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16610 hmR0VmxReadExitQualVmcs(pVmxTransient);
16611 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16612 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16613 AssertRCReturn(rc, rc);
16614
16615 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16616
16617 VMXVEXITINFO ExitInfo;
16618 RT_ZERO(ExitInfo);
16619 ExitInfo.uReason = pVmxTransient->uExitReason;
16620 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16621 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16622 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16623 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16624
16625 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16626 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16627 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16628 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16629 {
16630 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16631 rcStrict = VINF_SUCCESS;
16632 }
16633 return rcStrict;
16634}
16635#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16636/** @} */
16637
16638
16639#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16640/** @name Nested-guest VM-exit handlers.
16641 * @{
16642 */
16643/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16644/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16645/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16646
16647/**
16648 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16649 * Conditional VM-exit.
16650 */
16651HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16652{
16653 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16654
16655 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16656
16657 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16658 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16659 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16660
16661 switch (uExitIntType)
16662 {
16663 /*
16664 * Physical NMIs:
16665 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16666 */
16667 case VMX_EXIT_INT_INFO_TYPE_NMI:
16668 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16669
16670 /*
16671 * Hardware exceptions,
16672 * Software exceptions,
16673 * Privileged software exceptions:
16674 * Figure out if the exception must be delivered to the guest or the nested-guest.
16675 */
16676 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16677 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16678 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16679 {
16680 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16681 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16682 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16683 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16684
16685 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16686 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16687 pVmxTransient->uExitIntErrorCode);
16688 if (fIntercept)
16689 {
16690 /* Exit qualification is required for debug and page-fault exceptions. */
16691 hmR0VmxReadExitQualVmcs(pVmxTransient);
16692
16693 /*
16694 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16695 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16696 * length. However, if delivery of a software interrupt, software exception or privileged
16697 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16698 */
16699 VMXVEXITINFO ExitInfo;
16700 RT_ZERO(ExitInfo);
16701 ExitInfo.uReason = pVmxTransient->uExitReason;
16702 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16703 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16704
16705 VMXVEXITEVENTINFO ExitEventInfo;
16706 RT_ZERO(ExitEventInfo);
16707 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16708 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16709 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16710 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16711
16712#ifdef DEBUG_ramshankar
16713 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16714 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16715 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16716 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16717 {
16718 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16719 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16720 }
16721#endif
16722 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16723 }
16724
16725 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16726 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16727 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16728 }
16729
16730 /*
16731 * Software interrupts:
16732 * VM-exits cannot be caused by software interrupts.
16733 *
16734 * External interrupts:
16735 * This should only happen when "acknowledge external interrupts on VM-exit"
16736 * control is set. However, we never set this when executing a guest or
16737 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16738 * the guest.
16739 */
16740 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16741 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16742 default:
16743 {
16744 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16745 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16746 }
16747 }
16748}
16749
16750
16751/**
16752 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16753 * Unconditional VM-exit.
16754 */
16755HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16756{
16757 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16758 return IEMExecVmxVmexitTripleFault(pVCpu);
16759}
16760
16761
16762/**
16763 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16764 */
16765HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16766{
16767 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16768
16769 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16770 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16771 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16772}
16773
16774
16775/**
16776 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16777 */
16778HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16779{
16780 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16781
16782 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16783 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16784 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16785}
16786
16787
16788/**
16789 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16790 * Unconditional VM-exit.
16791 */
16792HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16793{
16794 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16795
16796 hmR0VmxReadExitQualVmcs(pVmxTransient);
16797 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16798 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16799 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16800
16801 VMXVEXITINFO ExitInfo;
16802 RT_ZERO(ExitInfo);
16803 ExitInfo.uReason = pVmxTransient->uExitReason;
16804 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16805 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16806
16807 VMXVEXITEVENTINFO ExitEventInfo;
16808 RT_ZERO(ExitEventInfo);
16809 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16810 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16811 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16812}
16813
16814
16815/**
16816 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16817 */
16818HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16819{
16820 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16821
16822 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16823 {
16824 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16825 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16826 }
16827 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16828}
16829
16830
16831/**
16832 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16833 */
16834HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16835{
16836 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16837
16838 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16839 {
16840 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16841 hmR0VmxReadExitQualVmcs(pVmxTransient);
16842
16843 VMXVEXITINFO ExitInfo;
16844 RT_ZERO(ExitInfo);
16845 ExitInfo.uReason = pVmxTransient->uExitReason;
16846 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16847 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16848 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16849 }
16850 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16851}
16852
16853
16854/**
16855 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16856 */
16857HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16858{
16859 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16860
16861 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16862 {
16863 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16864 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16865 }
16866 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16867}
16868
16869
16870/**
16871 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16872 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16873 */
16874HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16875{
16876 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16877
16878 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16879 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16880
16881 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16882
16883 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16884 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16885 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16886
16887 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16888 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16889 u64VmcsField &= UINT64_C(0xffffffff);
16890
16891 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16892 {
16893 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16894 hmR0VmxReadExitQualVmcs(pVmxTransient);
16895
16896 VMXVEXITINFO ExitInfo;
16897 RT_ZERO(ExitInfo);
16898 ExitInfo.uReason = pVmxTransient->uExitReason;
16899 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16900 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16901 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16902 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16903 }
16904
16905 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16906 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16907 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16908}
16909
16910
16911/**
16912 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16913 */
16914HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16915{
16916 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16917
16918 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16919 {
16920 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16921 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16922 }
16923
16924 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16925}
16926
16927
16928/**
16929 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16930 * Conditional VM-exit.
16931 */
16932HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16933{
16934 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16935
16936 hmR0VmxReadExitQualVmcs(pVmxTransient);
16937 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16938
16939 VBOXSTRICTRC rcStrict;
16940 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16941 switch (uAccessType)
16942 {
16943 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16944 {
16945 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16946 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16947 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16948 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16949
16950 bool fIntercept;
16951 switch (iCrReg)
16952 {
16953 case 0:
16954 case 4:
16955 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(&pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16956 break;
16957
16958 case 3:
16959 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16960 break;
16961
16962 case 8:
16963 fIntercept = CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16964 break;
16965
16966 default:
16967 fIntercept = false;
16968 break;
16969 }
16970 if (fIntercept)
16971 {
16972 VMXVEXITINFO ExitInfo;
16973 RT_ZERO(ExitInfo);
16974 ExitInfo.uReason = pVmxTransient->uExitReason;
16975 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16976 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16977 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16978 }
16979 else
16980 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16981 break;
16982 }
16983
16984 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16985 {
16986 /*
16987 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16988 * CR2 reads do not cause a VM-exit.
16989 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16990 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16991 */
16992 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16993 if ( iCrReg == 3
16994 || iCrReg == 8)
16995 {
16996 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16997 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16998 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16999 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uIntercept))
17000 {
17001 VMXVEXITINFO ExitInfo;
17002 RT_ZERO(ExitInfo);
17003 ExitInfo.uReason = pVmxTransient->uExitReason;
17004 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17005 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17006 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17007 }
17008 else
17009 {
17010 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17011 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
17012 }
17013 }
17014 else
17015 {
17016 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17017 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17018 }
17019 break;
17020 }
17021
17022 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17023 {
17024 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17025 Assert(pVmcsNstGst);
17026 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17027 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17028 if ( (uGstHostMask & X86_CR0_TS)
17029 && (uReadShadow & X86_CR0_TS))
17030 {
17031 VMXVEXITINFO ExitInfo;
17032 RT_ZERO(ExitInfo);
17033 ExitInfo.uReason = pVmxTransient->uExitReason;
17034 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17035 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17036 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17037 }
17038 else
17039 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
17040 break;
17041 }
17042
17043 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17044 {
17045 RTGCPTR GCPtrEffDst;
17046 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17047 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17048 if (fMemOperand)
17049 {
17050 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17051 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17052 }
17053 else
17054 GCPtrEffDst = NIL_RTGCPTR;
17055
17056 if (CPUMIsGuestVmxLmswInterceptSet(&pVCpu->cpum.GstCtx, uNewMsw))
17057 {
17058 VMXVEXITINFO ExitInfo;
17059 RT_ZERO(ExitInfo);
17060 ExitInfo.uReason = pVmxTransient->uExitReason;
17061 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17062 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17063 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17064 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17065 }
17066 else
17067 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
17068 break;
17069 }
17070
17071 default:
17072 {
17073 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17074 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17075 }
17076 }
17077
17078 if (rcStrict == VINF_IEM_RAISED_XCPT)
17079 {
17080 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17081 rcStrict = VINF_SUCCESS;
17082 }
17083 return rcStrict;
17084}
17085
17086
17087/**
17088 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17089 * Conditional VM-exit.
17090 */
17091HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17092{
17093 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17094
17095 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17096 {
17097 hmR0VmxReadExitQualVmcs(pVmxTransient);
17098 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17099
17100 VMXVEXITINFO ExitInfo;
17101 RT_ZERO(ExitInfo);
17102 ExitInfo.uReason = pVmxTransient->uExitReason;
17103 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17104 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17105 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17106 }
17107 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17108}
17109
17110
17111/**
17112 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17113 * Conditional VM-exit.
17114 */
17115HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17116{
17117 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17118
17119 hmR0VmxReadExitQualVmcs(pVmxTransient);
17120
17121 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17122 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17123 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17124
17125 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17126 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17127 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17128 {
17129 /*
17130 * IN/OUT instruction:
17131 * - Provides VM-exit instruction length.
17132 *
17133 * INS/OUTS instruction:
17134 * - Provides VM-exit instruction length.
17135 * - Provides Guest-linear address.
17136 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17137 */
17138 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
17139 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17140
17141 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17142 pVmxTransient->ExitInstrInfo.u = 0;
17143 pVmxTransient->uGuestLinearAddr = 0;
17144
17145 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17146 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17147 if (fIOString)
17148 {
17149 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17150 if (fVmxInsOutsInfo)
17151 {
17152 Assert(RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17153 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17154 }
17155 }
17156
17157 VMXVEXITINFO ExitInfo;
17158 RT_ZERO(ExitInfo);
17159 ExitInfo.uReason = pVmxTransient->uExitReason;
17160 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17161 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17162 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17163 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17164 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17165 }
17166 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17167}
17168
17169
17170/**
17171 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17172 */
17173HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17174{
17175 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17176
17177 uint32_t fMsrpm;
17178 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17179 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17180 else
17181 fMsrpm = VMXMSRPM_EXIT_RD;
17182
17183 if (fMsrpm & VMXMSRPM_EXIT_RD)
17184 {
17185 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17186 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17187 }
17188 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17189}
17190
17191
17192/**
17193 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17194 */
17195HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17196{
17197 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17198
17199 uint32_t fMsrpm;
17200 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17201 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17202 else
17203 fMsrpm = VMXMSRPM_EXIT_WR;
17204
17205 if (fMsrpm & VMXMSRPM_EXIT_WR)
17206 {
17207 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17208 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17209 }
17210 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17211}
17212
17213
17214/**
17215 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17216 */
17217HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17218{
17219 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17220
17221 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17222 {
17223 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17224 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17225 }
17226 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17227}
17228
17229
17230/**
17231 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17232 * VM-exit.
17233 */
17234HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17235{
17236 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17237
17238 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17239 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17240 VMXVEXITINFO ExitInfo;
17241 RT_ZERO(ExitInfo);
17242 ExitInfo.uReason = pVmxTransient->uExitReason;
17243 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17244 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17245}
17246
17247
17248/**
17249 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17250 */
17251HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17252{
17253 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17254
17255 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17256 {
17257 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17258 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17259 }
17260 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17261}
17262
17263
17264/**
17265 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17266 */
17267HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17268{
17269 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17270
17271 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17272 * PAUSE when executing a nested-guest? If it does not, we would not need
17273 * to check for the intercepts here. Just call VM-exit... */
17274
17275 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17276 if ( CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17277 || CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17278 {
17279 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17280 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17281 }
17282 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17283}
17284
17285
17286/**
17287 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17288 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17289 */
17290HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17291{
17292 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17293
17294 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17295 {
17296 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17297 VMXVEXITINFO ExitInfo;
17298 RT_ZERO(ExitInfo);
17299 ExitInfo.uReason = pVmxTransient->uExitReason;
17300 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17301 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17302 }
17303 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17304}
17305
17306
17307/**
17308 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17309 * VM-exit.
17310 */
17311HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17312{
17313 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17314
17315 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17316 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17317 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17318 hmR0VmxReadExitQualVmcs(pVmxTransient);
17319
17320 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17321
17322 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
17323 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
17324
17325 VMXVEXITINFO ExitInfo;
17326 RT_ZERO(ExitInfo);
17327 ExitInfo.uReason = pVmxTransient->uExitReason;
17328 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17329 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17330
17331 VMXVEXITEVENTINFO ExitEventInfo;
17332 RT_ZERO(ExitEventInfo);
17333 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17334 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17335 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17336}
17337
17338
17339/**
17340 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17341 * Conditional VM-exit.
17342 */
17343HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17344{
17345 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17346
17347 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17348 hmR0VmxReadExitQualVmcs(pVmxTransient);
17349 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17350}
17351
17352
17353/**
17354 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17355 * Conditional VM-exit.
17356 */
17357HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17358{
17359 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17360
17361 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17362 hmR0VmxReadExitQualVmcs(pVmxTransient);
17363 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17364}
17365
17366
17367/**
17368 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17369 */
17370HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17371{
17372 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17373
17374 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17375 {
17376 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17377 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17378 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17379 }
17380 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17381}
17382
17383
17384/**
17385 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17386 */
17387HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17388{
17389 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17390
17391 if (CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17392 {
17393 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17394 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17395 }
17396 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17397}
17398
17399
17400/**
17401 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17402 */
17403HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17404{
17405 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17406
17407 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17408 {
17409 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17410 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17411 hmR0VmxReadExitQualVmcs(pVmxTransient);
17412 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17413
17414 VMXVEXITINFO ExitInfo;
17415 RT_ZERO(ExitInfo);
17416 ExitInfo.uReason = pVmxTransient->uExitReason;
17417 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17418 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17419 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17420 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17421 }
17422 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17423}
17424
17425
17426/**
17427 * Nested-guest VM-exit handler for invalid-guest state
17428 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17429 */
17430HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17431{
17432 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17433
17434 /*
17435 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17436 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17437 * Handle it like it's in an invalid guest state of the outer guest.
17438 *
17439 * When the fast path is implemented, this should be changed to cause the corresponding
17440 * nested-guest VM-exit.
17441 */
17442 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17443}
17444
17445
17446/**
17447 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17448 * and only provide the instruction length.
17449 *
17450 * Unconditional VM-exit.
17451 */
17452HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17453{
17454 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17455
17456#ifdef VBOX_STRICT
17457 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17458 switch (pVmxTransient->uExitReason)
17459 {
17460 case VMX_EXIT_ENCLS:
17461 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17462 break;
17463
17464 case VMX_EXIT_VMFUNC:
17465 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_VMFUNC));
17466 break;
17467 }
17468#endif
17469
17470 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17471 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17472}
17473
17474
17475/**
17476 * Nested-guest VM-exit handler for instructions that provide instruction length as
17477 * well as more information.
17478 *
17479 * Unconditional VM-exit.
17480 */
17481HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17482{
17483 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17484
17485#ifdef VBOX_STRICT
17486 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17487 switch (pVmxTransient->uExitReason)
17488 {
17489 case VMX_EXIT_GDTR_IDTR_ACCESS:
17490 case VMX_EXIT_LDTR_TR_ACCESS:
17491 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17492 break;
17493
17494 case VMX_EXIT_RDRAND:
17495 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17496 break;
17497
17498 case VMX_EXIT_RDSEED:
17499 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17500 break;
17501
17502 case VMX_EXIT_XSAVES:
17503 case VMX_EXIT_XRSTORS:
17504 /** @todo NSTVMX: Verify XSS-bitmap. */
17505 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17506 break;
17507
17508 case VMX_EXIT_UMWAIT:
17509 case VMX_EXIT_TPAUSE:
17510 Assert(CPUMIsGuestVmxProcCtlsSet(pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17511 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17512 break;
17513 }
17514#endif
17515
17516 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17517 hmR0VmxReadExitQualVmcs(pVmxTransient);
17518 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17519
17520 VMXVEXITINFO ExitInfo;
17521 RT_ZERO(ExitInfo);
17522 ExitInfo.uReason = pVmxTransient->uExitReason;
17523 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17524 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17525 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17526 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17527}
17528
17529/** @} */
17530#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17531
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