VirtualBox

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

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

VMM/HM: Doxygen fixes. 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 87562 2021-02-03 12:42:15Z 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 pVmcsInfo The VMCS info. object.
2704 */
2705static void hmR0VmxCheckHostEferMsr(PCVMXVMCSINFO pVmcsInfo)
2706{
2707 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2708
2709 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2710 {
2711 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2712 uint64_t const uHostEferMsrCache = g_uHmVmxHostMsrEfer;
2713 uint64_t uVmcsEferMsrVmcs;
2714 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2715 AssertRC(rc);
2716
2717 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2718 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2719 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2720 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2721 }
2722}
2723
2724
2725/**
2726 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2727 * VMCS are correct.
2728 *
2729 * @param pVCpu The cross context virtual CPU structure.
2730 * @param pVmcsInfo The VMCS info. object.
2731 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2732 */
2733static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2734{
2735 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2736
2737 /* Read the various MSR-area counts from the VMCS. */
2738 uint32_t cEntryLoadMsrs;
2739 uint32_t cExitStoreMsrs;
2740 uint32_t cExitLoadMsrs;
2741 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2742 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2743 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2744
2745 /* Verify all the MSR counts are the same. */
2746 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2747 Assert(cExitStoreMsrs == cExitLoadMsrs);
2748 uint32_t const cMsrs = cExitLoadMsrs;
2749
2750 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2751 Assert(cMsrs < VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc));
2752
2753 /* Verify the MSR counts are within the allocated page size. */
2754 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2755
2756 /* Verify the relevant contents of the MSR areas match. */
2757 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2758 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2759 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2760 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2761 for (uint32_t i = 0; i < cMsrs; i++)
2762 {
2763 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2764 if (fSeparateExitMsrStorePage)
2765 {
2766 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2767 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2768 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2769 }
2770
2771 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2772 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2773 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2774
2775 uint64_t const u64HostMsr = ASMRdMsr(pHostMsrLoad->u32Msr);
2776 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64HostMsr,
2777 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2778 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64HostMsr, cMsrs));
2779
2780 /* Verify that cached host EFER MSR matches what's loaded on the CPU. */
2781 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2782 AssertMsgReturnVoid(!fIsEferMsr || u64HostMsr == g_uHmVmxHostMsrEfer,
2783 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n", g_uHmVmxHostMsrEfer, u64HostMsr, cMsrs));
2784
2785 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2786 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2787 {
2788 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2789 if (fIsEferMsr)
2790 {
2791 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2792 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2793 }
2794 else
2795 {
2796 /* Verify LBR MSRs (used only for debugging) are intercepted. We don't passthru these MSRs to the guest yet. */
2797 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
2798 if ( pVM->hmr0.s.vmx.fLbr
2799 && ( hmR0VmxIsLbrBranchFromMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2800 || hmR0VmxIsLbrBranchToMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2801 || pGuestMsrLoad->u32Msr == pVM->hmr0.s.vmx.idLbrTosMsr))
2802 {
2803 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_EXIT_RD_WR,
2804 ("u32Msr=%#RX32 cMsrs=%u Passthru read/write for LBR MSRs!\n",
2805 pGuestMsrLoad->u32Msr, cMsrs));
2806 }
2807 else if (!fIsNstGstVmcs)
2808 {
2809 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_ALLOW_RD_WR,
2810 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2811 }
2812 else
2813 {
2814 /*
2815 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2816 * execute a nested-guest with MSR passthrough.
2817 *
2818 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2819 * allow passthrough too.
2820 */
2821 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2822 Assert(pvMsrBitmapNstGst);
2823 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2824 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2825 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2826 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2827 }
2828 }
2829 }
2830
2831 /* Move to the next MSR. */
2832 pHostMsrLoad++;
2833 pGuestMsrLoad++;
2834 pGuestMsrStore++;
2835 }
2836}
2837
2838#endif /* VBOX_STRICT */
2839
2840/**
2841 * Flushes the TLB using EPT.
2842 *
2843 * @returns VBox status code.
2844 * @param pVCpu The cross context virtual CPU structure of the calling
2845 * EMT. Can be NULL depending on @a enmTlbFlush.
2846 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2847 * enmTlbFlush.
2848 * @param enmTlbFlush Type of flush.
2849 *
2850 * @remarks Caller is responsible for making sure this function is called only
2851 * when NestedPaging is supported and providing @a enmTlbFlush that is
2852 * supported by the CPU.
2853 * @remarks Can be called with interrupts disabled.
2854 */
2855static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2856{
2857 uint64_t au64Descriptor[2];
2858 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2859 au64Descriptor[0] = 0;
2860 else
2861 {
2862 Assert(pVCpu);
2863 Assert(pVmcsInfo);
2864 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2865 }
2866 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2867
2868 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2869 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2870
2871 if ( RT_SUCCESS(rc)
2872 && pVCpu)
2873 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2874}
2875
2876
2877/**
2878 * Flushes the TLB using VPID.
2879 *
2880 * @returns VBox status code.
2881 * @param pVCpu The cross context virtual CPU structure of the calling
2882 * EMT. Can be NULL depending on @a enmTlbFlush.
2883 * @param enmTlbFlush Type of flush.
2884 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2885 * on @a enmTlbFlush).
2886 *
2887 * @remarks Can be called with interrupts disabled.
2888 */
2889static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2890{
2891 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid);
2892
2893 uint64_t au64Descriptor[2];
2894 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2895 {
2896 au64Descriptor[0] = 0;
2897 au64Descriptor[1] = 0;
2898 }
2899 else
2900 {
2901 AssertPtr(pVCpu);
2902 AssertMsg(pVCpu->hmr0.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hmr0.s.uCurrentAsid));
2903 AssertMsg(pVCpu->hmr0.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hmr0.s.uCurrentAsid));
2904 au64Descriptor[0] = pVCpu->hmr0.s.uCurrentAsid;
2905 au64Descriptor[1] = GCPtr;
2906 }
2907
2908 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2909 AssertMsg(rc == VINF_SUCCESS,
2910 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hmr0.s.uCurrentAsid : 0, GCPtr, rc));
2911
2912 if ( RT_SUCCESS(rc)
2913 && pVCpu)
2914 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2915 NOREF(rc);
2916}
2917
2918
2919/**
2920 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2921 * otherwise there is nothing really to invalidate.
2922 *
2923 * @returns VBox status code.
2924 * @param pVCpu The cross context virtual CPU structure.
2925 * @param GCVirt Guest virtual address of the page to invalidate.
2926 */
2927VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2928{
2929 AssertPtr(pVCpu);
2930 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2931
2932 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2933 {
2934 /*
2935 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2936 * the EPT case. See @bugref{6043} and @bugref{6177}.
2937 *
2938 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2939 * as this function maybe called in a loop with individual addresses.
2940 */
2941 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2942 if (pVM->hmr0.s.vmx.fVpid)
2943 {
2944 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
2945 {
2946 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2947 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2948 }
2949 else
2950 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2951 }
2952 else if (pVM->hmr0.s.fNestedPaging)
2953 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2954 }
2955
2956 return VINF_SUCCESS;
2957}
2958
2959
2960/**
2961 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2962 * case where neither EPT nor VPID is supported by the CPU.
2963 *
2964 * @param pHostCpu The HM physical-CPU structure.
2965 * @param pVCpu The cross context virtual CPU structure.
2966 *
2967 * @remarks Called with interrupts disabled.
2968 */
2969static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2970{
2971 AssertPtr(pVCpu);
2972 AssertPtr(pHostCpu);
2973
2974 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2975
2976 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2977 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
2978 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2979 pVCpu->hmr0.s.fForceTLBFlush = false;
2980 return;
2981}
2982
2983
2984/**
2985 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2986 *
2987 * @param pHostCpu The HM physical-CPU structure.
2988 * @param pVCpu The cross context virtual CPU structure.
2989 * @param pVmcsInfo The VMCS info. object.
2990 *
2991 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2992 * nomenclature. The reason is, to avoid confusion in compare statements
2993 * since the host-CPU copies are named "ASID".
2994 *
2995 * @remarks Called with interrupts disabled.
2996 */
2997static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2998{
2999#ifdef VBOX_WITH_STATISTICS
3000 bool fTlbFlushed = false;
3001# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
3002# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
3003 if (!fTlbFlushed) \
3004 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
3005 } while (0)
3006#else
3007# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
3008# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
3009#endif
3010
3011 AssertPtr(pVCpu);
3012 AssertPtr(pHostCpu);
3013 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3014
3015 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3016 AssertMsg(pVM->hmr0.s.fNestedPaging && pVM->hmr0.s.vmx.fVpid,
3017 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
3018 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hmr0.s.fNestedPaging, pVM->hmr0.s.vmx.fVpid));
3019
3020 /*
3021 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
3022 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3023 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3024 * cannot reuse the current ASID anymore.
3025 */
3026 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3027 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3028 {
3029 ++pHostCpu->uCurrentAsid;
3030 if (pHostCpu->uCurrentAsid >= g_uHmMaxAsid)
3031 {
3032 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
3033 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3034 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3035 }
3036
3037 pVCpu->hmr0.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3038 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3039 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3040
3041 /*
3042 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
3043 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
3044 */
3045 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3046 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3047 HMVMX_SET_TAGGED_TLB_FLUSHED();
3048 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
3049 }
3050 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
3051 {
3052 /*
3053 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
3054 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
3055 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
3056 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
3057 * mappings, see @bugref{6568}.
3058 *
3059 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
3060 */
3061 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3062 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3063 HMVMX_SET_TAGGED_TLB_FLUSHED();
3064 }
3065 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3066 {
3067 /*
3068 * The nested-guest specifies its own guest-physical address to use as the APIC-access
3069 * address which requires flushing the TLB of EPT cached structures.
3070 *
3071 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
3072 */
3073 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3074 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3075 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3076 HMVMX_SET_TAGGED_TLB_FLUSHED();
3077 }
3078
3079
3080 pVCpu->hmr0.s.fForceTLBFlush = false;
3081 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
3082
3083 Assert(pVCpu->hmr0.s.idLastCpu == pHostCpu->idCpu);
3084 Assert(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes);
3085 AssertMsg(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3086 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hmr0.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3087 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < g_uHmMaxAsid,
3088 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3089 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hmr0.s.idLastCpu, pVCpu->hmr0.s.cTlbFlushes));
3090 AssertMsg(pVCpu->hmr0.s.uCurrentAsid >= 1 && pVCpu->hmr0.s.uCurrentAsid < g_uHmMaxAsid,
3091 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hmr0.s.uCurrentAsid));
3092
3093 /* Update VMCS with the VPID. */
3094 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hmr0.s.uCurrentAsid);
3095 AssertRC(rc);
3096
3097#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3098}
3099
3100
3101/**
3102 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3103 *
3104 * @param pHostCpu The HM physical-CPU structure.
3105 * @param pVCpu The cross context virtual CPU structure.
3106 * @param pVmcsInfo The VMCS info. object.
3107 *
3108 * @remarks Called with interrupts disabled.
3109 */
3110static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3111{
3112 AssertPtr(pVCpu);
3113 AssertPtr(pHostCpu);
3114 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3115 AssertMsg(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3116 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3117
3118 /*
3119 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3120 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3121 */
3122 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3123 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3124 {
3125 pVCpu->hmr0.s.fForceTLBFlush = true;
3126 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3127 }
3128
3129 /* Check for explicit TLB flushes. */
3130 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3131 {
3132 pVCpu->hmr0.s.fForceTLBFlush = true;
3133 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3134 }
3135
3136 /* Check for TLB flushes while switching to/from a nested-guest. */
3137 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3138 {
3139 pVCpu->hmr0.s.fForceTLBFlush = true;
3140 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3141 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3142 }
3143
3144 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3145 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3146
3147 if (pVCpu->hmr0.s.fForceTLBFlush)
3148 {
3149 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.enmTlbFlushEpt);
3150 pVCpu->hmr0.s.fForceTLBFlush = false;
3151 }
3152}
3153
3154
3155/**
3156 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3157 *
3158 * @param pHostCpu The HM physical-CPU structure.
3159 * @param pVCpu The cross context virtual CPU structure.
3160 *
3161 * @remarks Called with interrupts disabled.
3162 */
3163static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3164{
3165 AssertPtr(pVCpu);
3166 AssertPtr(pHostCpu);
3167 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3168 AssertMsg(pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3169 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3170
3171 /*
3172 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3173 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3174 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3175 * cannot reuse the current ASID anymore.
3176 */
3177 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3178 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3179 {
3180 pVCpu->hmr0.s.fForceTLBFlush = true;
3181 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3182 }
3183
3184 /* Check for explicit TLB flushes. */
3185 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3186 {
3187 /*
3188 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3189 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3190 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3191 * include fExplicitFlush's too) - an obscure corner case.
3192 */
3193 pVCpu->hmr0.s.fForceTLBFlush = true;
3194 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3195 }
3196
3197 /* Check for TLB flushes while switching to/from a nested-guest. */
3198 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3199 {
3200 pVCpu->hmr0.s.fForceTLBFlush = true;
3201 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3202 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3203 }
3204
3205 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3206 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3207 if (pVCpu->hmr0.s.fForceTLBFlush)
3208 {
3209 ++pHostCpu->uCurrentAsid;
3210 if (pHostCpu->uCurrentAsid >= g_uHmMaxAsid)
3211 {
3212 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3213 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3214 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3215 }
3216
3217 pVCpu->hmr0.s.fForceTLBFlush = false;
3218 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3219 pVCpu->hmr0.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3220 if (pHostCpu->fFlushAsidBeforeUse)
3221 {
3222 if (pVM->hmr0.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3223 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3224 else if (pVM->hmr0.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3225 {
3226 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3227 pHostCpu->fFlushAsidBeforeUse = false;
3228 }
3229 else
3230 {
3231 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3232 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3233 }
3234 }
3235 }
3236
3237 AssertMsg(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3238 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hmr0.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3239 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < g_uHmMaxAsid,
3240 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3241 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hmr0.s.idLastCpu, pVCpu->hmr0.s.cTlbFlushes));
3242 AssertMsg(pVCpu->hmr0.s.uCurrentAsid >= 1 && pVCpu->hmr0.s.uCurrentAsid < g_uHmMaxAsid,
3243 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hmr0.s.uCurrentAsid));
3244
3245 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hmr0.s.uCurrentAsid);
3246 AssertRC(rc);
3247}
3248
3249
3250/**
3251 * Flushes the guest TLB entry based on CPU capabilities.
3252 *
3253 * @param pHostCpu The HM physical-CPU structure.
3254 * @param pVCpu The cross context virtual CPU structure.
3255 * @param pVmcsInfo The VMCS info. object.
3256 *
3257 * @remarks Called with interrupts disabled.
3258 */
3259static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3260{
3261#ifdef HMVMX_ALWAYS_FLUSH_TLB
3262 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3263#endif
3264 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3265 switch (pVM->hmr0.s.vmx.enmTlbFlushType)
3266 {
3267 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3268 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3269 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3270 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3271 default:
3272 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3273 break;
3274 }
3275 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3276}
3277
3278
3279/**
3280 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3281 * TLB entries from the host TLB before VM-entry.
3282 *
3283 * @returns VBox status code.
3284 * @param pVM The cross context VM structure.
3285 */
3286static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3287{
3288 /*
3289 * Determine optimal flush type for nested paging.
3290 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3291 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3292 */
3293 if (pVM->hmr0.s.fNestedPaging)
3294 {
3295 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3296 {
3297 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3298 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3299 else if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3300 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3301 else
3302 {
3303 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3304 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3305 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3306 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3307 }
3308
3309 /* Make sure the write-back cacheable memory type for EPT is supported. */
3310 if (RT_UNLIKELY(!(g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3311 {
3312 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3313 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3314 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3315 }
3316
3317 /* EPT requires a page-walk length of 4. */
3318 if (RT_UNLIKELY(!(g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3319 {
3320 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3321 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3322 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3323 }
3324 }
3325 else
3326 {
3327 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3328 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3329 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3330 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3331 }
3332 }
3333
3334 /*
3335 * Determine optimal flush type for VPID.
3336 */
3337 if (pVM->hmr0.s.vmx.fVpid)
3338 {
3339 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3340 {
3341 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3342 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3343 else if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3344 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3345 else
3346 {
3347 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3348 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3349 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3350 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3351 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3352 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3353 pVM->hm.s.vmx.fVpidForRing3 = pVM->hmr0.s.vmx.fVpid = false;
3354 }
3355 }
3356 else
3357 {
3358 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3359 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3360 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3361 pVM->hm.s.vmx.fVpidForRing3 = pVM->hmr0.s.vmx.fVpid = false;
3362 }
3363 }
3364
3365 /*
3366 * Setup the handler for flushing tagged-TLBs.
3367 */
3368 if (pVM->hmr0.s.fNestedPaging && pVM->hmr0.s.vmx.fVpid)
3369 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3370 else if (pVM->hmr0.s.fNestedPaging)
3371 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3372 else if (pVM->hmr0.s.vmx.fVpid)
3373 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3374 else
3375 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3376
3377
3378 /*
3379 * Copy out the result to ring-3.
3380 */
3381 pVM->hm.s.vmx.fVpidForRing3 = pVM->hmr0.s.vmx.fVpid;
3382 pVM->hm.s.vmx.enmTlbFlushTypeForRing3 = pVM->hmr0.s.vmx.enmTlbFlushType;
3383 pVM->hm.s.vmx.enmTlbFlushEptForRing3 = pVM->hmr0.s.vmx.enmTlbFlushEpt;
3384 pVM->hm.s.vmx.enmTlbFlushVpidForRing3 = pVM->hmr0.s.vmx.enmTlbFlushVpid;
3385 return VINF_SUCCESS;
3386}
3387
3388
3389/**
3390 * Sets up the LBR MSR ranges based on the host CPU.
3391 *
3392 * @returns VBox status code.
3393 * @param pVM The cross context VM structure.
3394 */
3395static int hmR0VmxSetupLbrMsrRange(PVMCC pVM)
3396{
3397 Assert(pVM->hmr0.s.vmx.fLbr);
3398 uint32_t idLbrFromIpMsrFirst;
3399 uint32_t idLbrFromIpMsrLast;
3400 uint32_t idLbrToIpMsrFirst;
3401 uint32_t idLbrToIpMsrLast;
3402 uint32_t idLbrTosMsr;
3403
3404 /*
3405 * Determine the LBR MSRs supported for this host CPU family and model.
3406 *
3407 * See Intel spec. 17.4.8 "LBR Stack".
3408 * See Intel "Model-Specific Registers" spec.
3409 */
3410 uint32_t const uFamilyModel = (pVM->cpum.ro.HostFeatures.uFamily << 8)
3411 | pVM->cpum.ro.HostFeatures.uModel;
3412 switch (uFamilyModel)
3413 {
3414 case 0x0f01: case 0x0f02:
3415 idLbrFromIpMsrFirst = MSR_P4_LASTBRANCH_0;
3416 idLbrFromIpMsrLast = MSR_P4_LASTBRANCH_3;
3417 idLbrToIpMsrFirst = 0x0;
3418 idLbrToIpMsrLast = 0x0;
3419 idLbrTosMsr = MSR_P4_LASTBRANCH_TOS;
3420 break;
3421
3422 case 0x065c: case 0x065f: case 0x064e: case 0x065e: case 0x068e:
3423 case 0x069e: case 0x0655: case 0x0666: case 0x067a: case 0x0667:
3424 case 0x066a: case 0x066c: case 0x067d: case 0x067e:
3425 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3426 idLbrFromIpMsrLast = MSR_LASTBRANCH_31_FROM_IP;
3427 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3428 idLbrToIpMsrLast = MSR_LASTBRANCH_31_TO_IP;
3429 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3430 break;
3431
3432 case 0x063d: case 0x0647: case 0x064f: case 0x0656: case 0x063c:
3433 case 0x0645: case 0x0646: case 0x063f: case 0x062a: case 0x062d:
3434 case 0x063a: case 0x063e: case 0x061a: case 0x061e: case 0x061f:
3435 case 0x062e: case 0x0625: case 0x062c: case 0x062f:
3436 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3437 idLbrFromIpMsrLast = MSR_LASTBRANCH_15_FROM_IP;
3438 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3439 idLbrToIpMsrLast = MSR_LASTBRANCH_15_TO_IP;
3440 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3441 break;
3442
3443 case 0x0617: case 0x061d: case 0x060f:
3444 idLbrFromIpMsrFirst = MSR_CORE2_LASTBRANCH_0_FROM_IP;
3445 idLbrFromIpMsrLast = MSR_CORE2_LASTBRANCH_3_FROM_IP;
3446 idLbrToIpMsrFirst = MSR_CORE2_LASTBRANCH_0_TO_IP;
3447 idLbrToIpMsrLast = MSR_CORE2_LASTBRANCH_3_TO_IP;
3448 idLbrTosMsr = MSR_CORE2_LASTBRANCH_TOS;
3449 break;
3450
3451 /* Atom and related microarchitectures we don't care about:
3452 case 0x0637: case 0x064a: case 0x064c: case 0x064d: case 0x065a:
3453 case 0x065d: case 0x061c: case 0x0626: case 0x0627: case 0x0635:
3454 case 0x0636: */
3455 /* All other CPUs: */
3456 default:
3457 {
3458 LogRelFunc(("Could not determine LBR stack size for the CPU model %#x\n", uFamilyModel));
3459 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_UNKNOWN;
3460 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3461 }
3462 }
3463
3464 /*
3465 * Validate.
3466 */
3467 uint32_t const cLbrStack = idLbrFromIpMsrLast - idLbrFromIpMsrFirst + 1;
3468 PCVMCPU pVCpu0 = VMCC_GET_CPU_0(pVM);
3469 AssertCompile( RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr)
3470 == RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrToIpMsr));
3471 if (cLbrStack > RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr))
3472 {
3473 LogRelFunc(("LBR stack size of the CPU (%u) exceeds our buffer size\n", cLbrStack));
3474 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_OVERFLOW;
3475 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3476 }
3477 NOREF(pVCpu0);
3478
3479 /*
3480 * Update the LBR info. to the VM struct. for use later.
3481 */
3482 pVM->hmr0.s.vmx.idLbrTosMsr = idLbrTosMsr;
3483
3484 pVM->hm.s.vmx.idLbrFromIpMsrFirstForRing3 = pVM->hmr0.s.vmx.idLbrFromIpMsrFirst = idLbrFromIpMsrFirst;
3485 pVM->hm.s.vmx.idLbrFromIpMsrLastForRing3 = pVM->hmr0.s.vmx.idLbrFromIpMsrLast = idLbrFromIpMsrLast;
3486
3487 pVM->hm.s.vmx.idLbrToIpMsrFirstForRing3 = pVM->hmr0.s.vmx.idLbrToIpMsrFirst = idLbrToIpMsrFirst;
3488 pVM->hm.s.vmx.idLbrToIpMsrLastForRing3 = pVM->hmr0.s.vmx.idLbrToIpMsrLast = idLbrToIpMsrLast;
3489 return VINF_SUCCESS;
3490}
3491
3492
3493#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3494/**
3495 * Sets up the shadow VMCS fields arrays.
3496 *
3497 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3498 * executing the guest.
3499 *
3500 * @returns VBox status code.
3501 * @param pVM The cross context VM structure.
3502 */
3503static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3504{
3505 /*
3506 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3507 * when the host does not support it.
3508 */
3509 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3510 if ( !fGstVmwriteAll
3511 || (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL))
3512 { /* likely. */ }
3513 else
3514 {
3515 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3516 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3517 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3518 }
3519
3520 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3521 uint32_t cRwFields = 0;
3522 uint32_t cRoFields = 0;
3523 for (uint32_t i = 0; i < cVmcsFields; i++)
3524 {
3525 VMXVMCSFIELD VmcsField;
3526 VmcsField.u = g_aVmcsFields[i];
3527
3528 /*
3529 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3530 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3531 * in the shadow VMCS fields array as they would be redundant.
3532 *
3533 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3534 * we must not include it in the shadow VMCS fields array. Guests attempting to
3535 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3536 * the required behavior.
3537 */
3538 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3539 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3540 {
3541 /*
3542 * Read-only fields are placed in a separate array so that while syncing shadow
3543 * VMCS fields later (which is more performance critical) we can avoid branches.
3544 *
3545 * However, if the guest can write to all fields (including read-only fields),
3546 * we treat it a as read/write field. Otherwise, writing to these fields would
3547 * cause a VMWRITE instruction error while syncing the shadow VMCS.
3548 */
3549 if ( fGstVmwriteAll
3550 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3551 pVM->hmr0.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3552 else
3553 pVM->hmr0.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3554 }
3555 }
3556
3557 /* Update the counts. */
3558 pVM->hmr0.s.vmx.cShadowVmcsFields = cRwFields;
3559 pVM->hmr0.s.vmx.cShadowVmcsRoFields = cRoFields;
3560 return VINF_SUCCESS;
3561}
3562
3563
3564/**
3565 * Sets up the VMREAD and VMWRITE bitmaps.
3566 *
3567 * @param pVM The cross context VM structure.
3568 */
3569static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3570{
3571 /*
3572 * By default, ensure guest attempts to access any VMCS fields cause VM-exits.
3573 */
3574 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3575 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hmr0.s.vmx.pvVmreadBitmap;
3576 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hmr0.s.vmx.pvVmwriteBitmap;
3577 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3578 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3579
3580 /*
3581 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3582 * VMREAD and VMWRITE bitmaps.
3583 */
3584 {
3585 uint32_t const *paShadowVmcsFields = pVM->hmr0.s.vmx.paShadowVmcsFields;
3586 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
3587 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3588 {
3589 uint32_t const uVmcsField = paShadowVmcsFields[i];
3590 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3591 Assert(uVmcsField >> 3 < cbBitmap);
3592 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3593 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3594 }
3595 }
3596
3597 /*
3598 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3599 * if the host supports VMWRITE to all supported VMCS fields.
3600 */
3601 if (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL)
3602 {
3603 uint32_t const *paShadowVmcsRoFields = pVM->hmr0.s.vmx.paShadowVmcsRoFields;
3604 uint32_t const cShadowVmcsRoFields = pVM->hmr0.s.vmx.cShadowVmcsRoFields;
3605 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3606 {
3607 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3608 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3609 Assert(uVmcsField >> 3 < cbBitmap);
3610 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3611 }
3612 }
3613}
3614#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3615
3616
3617/**
3618 * Sets up the virtual-APIC page address for the VMCS.
3619 *
3620 * @param pVmcsInfo The VMCS info. object.
3621 */
3622DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3623{
3624 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3625 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3626 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3627 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3628 AssertRC(rc);
3629}
3630
3631
3632/**
3633 * Sets up the MSR-bitmap address for the VMCS.
3634 *
3635 * @param pVmcsInfo The VMCS info. object.
3636 */
3637DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3638{
3639 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3640 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3641 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3642 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3643 AssertRC(rc);
3644}
3645
3646
3647/**
3648 * Sets up the APIC-access page address for the VMCS.
3649 *
3650 * @param pVCpu The cross context virtual CPU structure.
3651 */
3652DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3653{
3654 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysApicAccess;
3655 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3656 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3657 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3658 AssertRC(rc);
3659}
3660
3661
3662#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3663/**
3664 * Sets up the VMREAD bitmap address for the VMCS.
3665 *
3666 * @param pVCpu The cross context virtual CPU structure.
3667 */
3668DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3669{
3670 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysVmreadBitmap;
3671 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3672 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3673 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3674 AssertRC(rc);
3675}
3676
3677
3678/**
3679 * Sets up the VMWRITE bitmap address for the VMCS.
3680 *
3681 * @param pVCpu The cross context virtual CPU structure.
3682 */
3683DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3684{
3685 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysVmwriteBitmap;
3686 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3687 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3688 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3689 AssertRC(rc);
3690}
3691#endif
3692
3693
3694/**
3695 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3696 * in the VMCS.
3697 *
3698 * @returns VBox status code.
3699 * @param pVmcsInfo The VMCS info. object.
3700 */
3701DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3702{
3703 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3704 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3705 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3706
3707 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3708 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3709 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3710
3711 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3712 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3713 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3714
3715 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3716 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3717 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3718 return VINF_SUCCESS;
3719}
3720
3721
3722/**
3723 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3724 *
3725 * @param pVCpu The cross context virtual CPU structure.
3726 * @param pVmcsInfo The VMCS info. object.
3727 */
3728static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3729{
3730 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3731
3732 /*
3733 * By default, ensure guest attempts to access any MSR cause VM-exits.
3734 * This shall later be relaxed for specific MSRs as necessary.
3735 *
3736 * Note: For nested-guests, the entire bitmap will be merged prior to
3737 * executing the nested-guest using hardware-assisted VMX and hence there
3738 * is no need to perform this operation. See hmR0VmxMergeMsrBitmapNested.
3739 */
3740 Assert(pVmcsInfo->pvMsrBitmap);
3741 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
3742
3743 /*
3744 * The guest can access the following MSRs (read, write) without causing
3745 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3746 */
3747 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3748 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3749 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3750 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3751 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3752 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3753
3754 /*
3755 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3756 * associated with then. We never need to intercept access (writes need to be
3757 * executed without causing a VM-exit, reads will #GP fault anyway).
3758 *
3759 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3760 * read/write them. We swap the the guest/host MSR value using the
3761 * auto-load/store MSR area.
3762 */
3763 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3764 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3765 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3766 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3767 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3768 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3769
3770 /*
3771 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3772 * required for 64-bit guests.
3773 */
3774 if (pVM->hmr0.s.fAllow64BitGuests)
3775 {
3776 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3777 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3778 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3779 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3780 }
3781
3782 /*
3783 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3784 */
3785#ifdef VBOX_STRICT
3786 Assert(pVmcsInfo->pvMsrBitmap);
3787 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3788 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3789#endif
3790}
3791
3792
3793/**
3794 * Sets up pin-based VM-execution controls in the VMCS.
3795 *
3796 * @returns VBox status code.
3797 * @param pVCpu The cross context virtual CPU structure.
3798 * @param pVmcsInfo The VMCS info. object.
3799 */
3800static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3801{
3802 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3803 uint32_t fVal = g_HmMsrs.u.vmx.PinCtls.n.allowed0; /* Bits set here must always be set. */
3804 uint32_t const fZap = g_HmMsrs.u.vmx.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3805
3806 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3807 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3808
3809 if (g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3810 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3811
3812 /* Enable the VMX-preemption timer. */
3813 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
3814 {
3815 Assert(g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3816 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3817 }
3818
3819#if 0
3820 /* Enable posted-interrupt processing. */
3821 if (pVM->hm.s.fPostedIntrs)
3822 {
3823 Assert(g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3824 Assert(g_HmMsrs.u.vmx.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3825 fVal |= VMX_PIN_CTLS_POSTED_INT;
3826 }
3827#endif
3828
3829 if ((fVal & fZap) != fVal)
3830 {
3831 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3832 g_HmMsrs.u.vmx.PinCtls.n.allowed0, fVal, fZap));
3833 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3834 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3835 }
3836
3837 /* Commit it to the VMCS and update our cache. */
3838 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3839 AssertRC(rc);
3840 pVmcsInfo->u32PinCtls = fVal;
3841
3842 return VINF_SUCCESS;
3843}
3844
3845
3846/**
3847 * Sets up secondary processor-based VM-execution controls in the VMCS.
3848 *
3849 * @returns VBox status code.
3850 * @param pVCpu The cross context virtual CPU structure.
3851 * @param pVmcsInfo The VMCS info. object.
3852 */
3853static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3854{
3855 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3856 uint32_t fVal = g_HmMsrs.u.vmx.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3857 uint32_t const fZap = g_HmMsrs.u.vmx.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3858
3859 /* WBINVD causes a VM-exit. */
3860 if (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3861 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3862
3863 /* Enable EPT (aka nested-paging). */
3864 if (pVM->hmr0.s.fNestedPaging)
3865 fVal |= VMX_PROC_CTLS2_EPT;
3866
3867 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3868 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3869 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3870 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3871 fVal |= VMX_PROC_CTLS2_INVPCID;
3872
3873 /* Enable VPID. */
3874 if (pVM->hmr0.s.vmx.fVpid)
3875 fVal |= VMX_PROC_CTLS2_VPID;
3876
3877 /* Enable unrestricted guest execution. */
3878 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
3879 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3880
3881#if 0
3882 if (pVM->hm.s.fVirtApicRegs)
3883 {
3884 /* Enable APIC-register virtualization. */
3885 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3886 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3887
3888 /* Enable virtual-interrupt delivery. */
3889 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3890 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3891 }
3892#endif
3893
3894 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3895 where the TPR shadow resides. */
3896 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3897 * done dynamically. */
3898 if (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3899 {
3900 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3901 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3902 }
3903
3904 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3905 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3906 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3907 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3908 fVal |= VMX_PROC_CTLS2_RDTSCP;
3909
3910 /* Enable Pause-Loop exiting. */
3911 if ( (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3912 && pVM->hm.s.vmx.cPleGapTicks
3913 && pVM->hm.s.vmx.cPleWindowTicks)
3914 {
3915 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3916
3917 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3918 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3919 }
3920
3921 if ((fVal & fZap) != fVal)
3922 {
3923 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3924 g_HmMsrs.u.vmx.ProcCtls2.n.allowed0, fVal, fZap));
3925 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3926 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3927 }
3928
3929 /* Commit it to the VMCS and update our cache. */
3930 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3931 AssertRC(rc);
3932 pVmcsInfo->u32ProcCtls2 = fVal;
3933
3934 return VINF_SUCCESS;
3935}
3936
3937
3938/**
3939 * Sets up processor-based VM-execution controls in the VMCS.
3940 *
3941 * @returns VBox status code.
3942 * @param pVCpu The cross context virtual CPU structure.
3943 * @param pVmcsInfo The VMCS info. object.
3944 */
3945static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3946{
3947 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3948 uint32_t fVal = g_HmMsrs.u.vmx.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3949 uint32_t const fZap = g_HmMsrs.u.vmx.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3950
3951 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3952 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3953 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3954 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3955 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3956 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3957 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3958
3959 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3960 if ( !(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3961 || (g_HmMsrs.u.vmx.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3962 {
3963 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3964 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3965 }
3966
3967 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3968 if (!pVM->hmr0.s.fNestedPaging)
3969 {
3970 Assert(!pVM->hmr0.s.vmx.fUnrestrictedGuest);
3971 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3972 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3973 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3974 }
3975
3976 /* Use TPR shadowing if supported by the CPU. */
3977 if ( PDMHasApic(pVM)
3978 && (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
3979 {
3980 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3981 /* CR8 writes cause a VM-exit based on TPR threshold. */
3982 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3983 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3984 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3985 }
3986 else
3987 {
3988 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3989 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3990 if (pVM->hmr0.s.fAllow64BitGuests)
3991 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3992 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3993 }
3994
3995 /* Use MSR-bitmaps if supported by the CPU. */
3996 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3997 {
3998 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3999 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4000 }
4001
4002 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
4003 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
4004 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
4005
4006 if ((fVal & fZap) != fVal)
4007 {
4008 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4009 g_HmMsrs.u.vmx.ProcCtls.n.allowed0, fVal, fZap));
4010 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
4011 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4012 }
4013
4014 /* Commit it to the VMCS and update our cache. */
4015 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
4016 AssertRC(rc);
4017 pVmcsInfo->u32ProcCtls = fVal;
4018
4019 /* Set up MSR permissions that don't change through the lifetime of the VM. */
4020 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4021 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
4022
4023 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
4024 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
4025 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
4026
4027 /* Sanity check, should not really happen. */
4028 if (RT_LIKELY(!pVM->hmr0.s.vmx.fUnrestrictedGuest))
4029 { /* likely */ }
4030 else
4031 {
4032 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
4033 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4034 }
4035
4036 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
4037 return VINF_SUCCESS;
4038}
4039
4040
4041/**
4042 * Sets up miscellaneous (everything other than Pin, Processor and secondary
4043 * Processor-based VM-execution) control fields in the VMCS.
4044 *
4045 * @returns VBox status code.
4046 * @param pVCpu The cross context virtual CPU structure.
4047 * @param pVmcsInfo The VMCS info. object.
4048 */
4049static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4050{
4051#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4052 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUseVmcsShadowing)
4053 {
4054 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
4055 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
4056 }
4057#endif
4058
4059 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4060 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4061 AssertRC(rc);
4062
4063 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4064 if (RT_SUCCESS(rc))
4065 {
4066 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
4067 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
4068
4069 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
4070 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
4071
4072 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
4073 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
4074
4075 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fLbr)
4076 {
4077 rc = VMXWriteVmcsNw(VMX_VMCS64_GUEST_DEBUGCTL_FULL, MSR_IA32_DEBUGCTL_LBR);
4078 AssertRC(rc);
4079 }
4080 return VINF_SUCCESS;
4081 }
4082 else
4083 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
4084 return rc;
4085}
4086
4087
4088/**
4089 * Sets up the initial exception bitmap in the VMCS based on static conditions.
4090 *
4091 * We shall setup those exception intercepts that don't change during the
4092 * lifetime of the VM here. The rest are done dynamically while loading the
4093 * guest state.
4094 *
4095 * @param pVCpu The cross context virtual CPU structure.
4096 * @param pVmcsInfo The VMCS info. object.
4097 */
4098static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4099{
4100 /*
4101 * The following exceptions are always intercepted:
4102 *
4103 * #AC - To prevent the guest from hanging the CPU.
4104 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
4105 * recursive #DBs can cause a CPU hang.
4106 * #PF - To sync our shadow page tables when nested-paging is not used.
4107 */
4108 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging;
4109 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
4110 | RT_BIT(X86_XCPT_DB)
4111 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
4112
4113 /* Commit it to the VMCS. */
4114 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
4115 AssertRC(rc);
4116
4117 /* Update our cache of the exception bitmap. */
4118 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
4119}
4120
4121
4122#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4123/**
4124 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
4125 *
4126 * @returns VBox status code.
4127 * @param pVmcsInfo The VMCS info. object.
4128 */
4129static int hmR0VmxSetupVmcsCtlsNested(PVMXVMCSINFO pVmcsInfo)
4130{
4131 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4132 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4133 AssertRC(rc);
4134
4135 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4136 if (RT_SUCCESS(rc))
4137 {
4138 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4139 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4140
4141 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
4142 Assert(!pVmcsInfo->u64Cr0Mask);
4143 Assert(!pVmcsInfo->u64Cr4Mask);
4144 return VINF_SUCCESS;
4145 }
4146 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
4147 return rc;
4148}
4149#endif
4150
4151
4152/**
4153 * Sets pfnStartVm to the best suited variant.
4154 *
4155 * This must be called whenever anything changes relative to the hmR0VmXStartVm
4156 * variant selection:
4157 * - pVCpu->hm.s.fLoadSaveGuestXcr0
4158 * - HM_WSF_IBPB_ENTRY in pVCpu->hmr0.s.fWorldSwitcher
4159 * - HM_WSF_IBPB_EXIT in pVCpu->hmr0.s.fWorldSwitcher
4160 * - Perhaps: CPUMIsGuestFPUStateActive() (windows only)
4161 * - Perhaps: CPUMCTX.fXStateMask (windows only)
4162 *
4163 * We currently ASSUME that neither HM_WSF_IBPB_ENTRY nor HM_WSF_IBPB_EXIT
4164 * cannot be changed at runtime.
4165 */
4166static void hmR0VmxUpdateStartVmFunction(PVMCPUCC pVCpu)
4167{
4168 static const struct CLANGWORKAROUND { PFNHMVMXSTARTVM pfn; } s_aHmR0VmxStartVmFunctions[] =
4169 {
4170 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4171 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4172 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4173 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4174 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4175 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4176 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4177 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4178 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4179 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4180 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4181 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4182 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4183 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4184 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4185 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4186 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4187 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4188 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4189 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4190 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4191 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4192 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4193 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4194 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4195 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4196 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4197 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4198 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4199 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4200 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4201 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4202 };
4203 uintptr_t const idx = (pVCpu->hmr0.s.fLoadSaveGuestXcr0 ? 1 : 0)
4204 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_IBPB_ENTRY ? 2 : 0)
4205 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_L1D_ENTRY ? 4 : 0)
4206 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_MDS_ENTRY ? 8 : 0)
4207 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_IBPB_EXIT ? 16 : 0);
4208 PFNHMVMXSTARTVM const pfnStartVm = s_aHmR0VmxStartVmFunctions[idx].pfn;
4209 if (pVCpu->hmr0.s.vmx.pfnStartVm != pfnStartVm)
4210 pVCpu->hmr0.s.vmx.pfnStartVm = pfnStartVm;
4211}
4212
4213
4214/**
4215 * Selector FNHMSVMVMRUN implementation.
4216 */
4217static DECLCALLBACK(int) hmR0VmxStartVmSelector(PVMXVMCSINFO pVmcsInfo, PVMCPUCC pVCpu, bool fResume)
4218{
4219 hmR0VmxUpdateStartVmFunction(pVCpu);
4220 return pVCpu->hmr0.s.vmx.pfnStartVm(pVmcsInfo, pVCpu, fResume);
4221}
4222
4223
4224/**
4225 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
4226 * VMX.
4227 *
4228 * @returns VBox status code.
4229 * @param pVCpu The cross context virtual CPU structure.
4230 * @param pVmcsInfo The VMCS info. object.
4231 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
4232 */
4233static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
4234{
4235 Assert(pVmcsInfo->pvVmcs);
4236 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4237
4238 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
4239 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
4240 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
4241
4242 LogFlowFunc(("\n"));
4243
4244 /*
4245 * Initialize the VMCS using VMCLEAR before loading the VMCS.
4246 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
4247 */
4248 int rc = hmR0VmxClearVmcs(pVmcsInfo);
4249 if (RT_SUCCESS(rc))
4250 {
4251 rc = hmR0VmxLoadVmcs(pVmcsInfo);
4252 if (RT_SUCCESS(rc))
4253 {
4254 /*
4255 * Initialize the hardware-assisted VMX execution handler for guest and nested-guest VMCS.
4256 * The host is always 64-bit since we no longer support 32-bit hosts.
4257 * Currently we have just a single handler for all guest modes as well, see @bugref{6208#c73}.
4258 */
4259 if (!fIsNstGstVmcs)
4260 {
4261 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
4262 if (RT_SUCCESS(rc))
4263 {
4264 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
4265 if (RT_SUCCESS(rc))
4266 {
4267 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
4268 if (RT_SUCCESS(rc))
4269 {
4270 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4271#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4272 /*
4273 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4274 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4275 * making it fit for use when VMCS shadowing is later enabled.
4276 */
4277 if (pVmcsInfo->pvShadowVmcs)
4278 {
4279 VMXVMCSREVID VmcsRevId;
4280 VmcsRevId.u = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
4281 VmcsRevId.n.fIsShadowVmcs = 1;
4282 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4283 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4284 if (RT_SUCCESS(rc))
4285 { /* likely */ }
4286 else
4287 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4288 }
4289#endif
4290 }
4291 else
4292 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4293 }
4294 else
4295 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4296 }
4297 else
4298 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4299 }
4300 else
4301 {
4302#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4303 rc = hmR0VmxSetupVmcsCtlsNested(pVmcsInfo);
4304 if (RT_SUCCESS(rc))
4305 { /* likely */ }
4306 else
4307 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4308#else
4309 AssertFailed();
4310#endif
4311 }
4312 }
4313 else
4314 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4315 }
4316 else
4317 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4318
4319 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4320 if (RT_SUCCESS(rc))
4321 {
4322 rc = hmR0VmxClearVmcs(pVmcsInfo);
4323 if (RT_SUCCESS(rc))
4324 { /* likely */ }
4325 else
4326 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4327 }
4328
4329 /*
4330 * Update the last-error record both for failures and success, so we
4331 * can propagate the status code back to ring-3 for diagnostics.
4332 */
4333 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4334 NOREF(pszVmcs);
4335 return rc;
4336}
4337
4338
4339/**
4340 * Does global VT-x initialization (called during module initialization).
4341 *
4342 * @returns VBox status code.
4343 */
4344VMMR0DECL(int) VMXR0GlobalInit(void)
4345{
4346#ifdef HMVMX_USE_FUNCTION_TABLE
4347 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_aVMExitHandlers));
4348# ifdef VBOX_STRICT
4349 for (unsigned i = 0; i < RT_ELEMENTS(g_aVMExitHandlers); i++)
4350 Assert(g_aVMExitHandlers[i].pfn);
4351# endif
4352#endif
4353 return VINF_SUCCESS;
4354}
4355
4356
4357/**
4358 * Does global VT-x termination (called during module termination).
4359 */
4360VMMR0DECL(void) VMXR0GlobalTerm()
4361{
4362 /* Nothing to do currently. */
4363}
4364
4365
4366/**
4367 * Sets up and activates VT-x on the current CPU.
4368 *
4369 * @returns VBox status code.
4370 * @param pHostCpu The HM physical-CPU structure.
4371 * @param pVM The cross context VM structure. Can be
4372 * NULL after a host resume operation.
4373 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4374 * fEnabledByHost is @c true).
4375 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4376 * @a fEnabledByHost is @c true).
4377 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4378 * enable VT-x on the host.
4379 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4380 */
4381VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4382 PCSUPHWVIRTMSRS pHwvirtMsrs)
4383{
4384 AssertPtr(pHostCpu);
4385 AssertPtr(pHwvirtMsrs);
4386 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4387
4388 /* Enable VT-x if it's not already enabled by the host. */
4389 if (!fEnabledByHost)
4390 {
4391 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4392 if (RT_FAILURE(rc))
4393 return rc;
4394 }
4395
4396 /*
4397 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4398 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4399 * invalidated when flushing by VPID.
4400 */
4401 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4402 {
4403 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4404 pHostCpu->fFlushAsidBeforeUse = false;
4405 }
4406 else
4407 pHostCpu->fFlushAsidBeforeUse = true;
4408
4409 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4410 ++pHostCpu->cTlbFlushes;
4411
4412 return VINF_SUCCESS;
4413}
4414
4415
4416/**
4417 * Deactivates VT-x on the current CPU.
4418 *
4419 * @returns VBox status code.
4420 * @param pHostCpu The HM physical-CPU structure.
4421 * @param pvCpuPage Pointer to the VMXON region.
4422 * @param HCPhysCpuPage Physical address of the VMXON region.
4423 *
4424 * @remarks This function should never be called when SUPR0EnableVTx() or
4425 * similar was used to enable VT-x on the host.
4426 */
4427VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4428{
4429 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4430
4431 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4432 return hmR0VmxLeaveRootMode(pHostCpu);
4433}
4434
4435
4436/**
4437 * Does per-VM VT-x initialization.
4438 *
4439 * @returns VBox status code.
4440 * @param pVM The cross context VM structure.
4441 */
4442VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4443{
4444 AssertPtr(pVM);
4445 LogFlowFunc(("pVM=%p\n", pVM));
4446
4447 hmR0VmxStructsInit(pVM);
4448 int rc = hmR0VmxStructsAlloc(pVM);
4449 if (RT_FAILURE(rc))
4450 {
4451 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4452 return rc;
4453 }
4454
4455 /* Setup the crash dump page. */
4456#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4457 strcpy((char *)pVM->hmr0.s.vmx.pbScratch, "SCRATCH Magic");
4458 *(uint64_t *)(pVM->hmr0.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
4459#endif
4460 return VINF_SUCCESS;
4461}
4462
4463
4464/**
4465 * Does per-VM VT-x termination.
4466 *
4467 * @returns VBox status code.
4468 * @param pVM The cross context VM structure.
4469 */
4470VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4471{
4472 AssertPtr(pVM);
4473 LogFlowFunc(("pVM=%p\n", pVM));
4474
4475#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4476 if (pVM->hmr0.s.vmx.pbScratch)
4477 RT_BZERO(pVM->hmr0.s.vmx.pbScratch, X86_PAGE_4K_SIZE);
4478#endif
4479 hmR0VmxStructsFree(pVM);
4480 return VINF_SUCCESS;
4481}
4482
4483
4484/**
4485 * Sets up the VM for execution using hardware-assisted VMX.
4486 * This function is only called once per-VM during initialization.
4487 *
4488 * @returns VBox status code.
4489 * @param pVM The cross context VM structure.
4490 */
4491VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4492{
4493 AssertPtr(pVM);
4494 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4495
4496 LogFlowFunc(("pVM=%p\n", pVM));
4497
4498 /*
4499 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4500 * without causing a #GP.
4501 */
4502 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4503 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4504 { /* likely */ }
4505 else
4506 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4507
4508 /*
4509 * Check that nested paging is supported if enabled and copy over the flag to the
4510 * ring-0 only structure.
4511 */
4512 bool const fNestedPaging = pVM->hm.s.fNestedPagingCfg;
4513 AssertReturn( !fNestedPaging
4514 || (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_EPT), /** @todo use a ring-0 copy of ProcCtls2.n.allowed1 */
4515 VERR_INCOMPATIBLE_CONFIG);
4516 pVM->hmr0.s.fNestedPaging = fNestedPaging;
4517 pVM->hmr0.s.fAllow64BitGuests = pVM->hm.s.fAllow64BitGuestsCfg;
4518
4519 /*
4520 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4521 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4522 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4523 */
4524 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuestCfg;
4525 AssertReturn( !fUnrestrictedGuest
4526 || ( (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_UNRESTRICTED_GUEST)
4527 && fNestedPaging),
4528 VERR_INCOMPATIBLE_CONFIG);
4529 if ( !fUnrestrictedGuest
4530 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4531 || !pVM->hm.s.vmx.pRealModeTSS))
4532 {
4533 LogRelFunc(("Invalid real-on-v86 state.\n"));
4534 return VERR_INTERNAL_ERROR;
4535 }
4536 pVM->hmr0.s.vmx.fUnrestrictedGuest = fUnrestrictedGuest;
4537
4538 /* Initialize these always, see hmR3InitFinalizeR0().*/
4539 pVM->hm.s.vmx.enmTlbFlushEptForRing3 = pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4540 pVM->hm.s.vmx.enmTlbFlushVpidForRing3 = pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4541
4542 /* Setup the tagged-TLB flush handlers. */
4543 int rc = hmR0VmxSetupTaggedTlb(pVM);
4544 if (RT_FAILURE(rc))
4545 {
4546 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4547 return rc;
4548 }
4549
4550 /* Determine LBR capabilities. */
4551 pVM->hmr0.s.vmx.fLbr = pVM->hm.s.vmx.fLbrCfg;
4552 if (pVM->hmr0.s.vmx.fLbr)
4553 {
4554 rc = hmR0VmxSetupLbrMsrRange(pVM);
4555 if (RT_FAILURE(rc))
4556 {
4557 LogRelFunc(("Failed to setup LBR MSR range. rc=%Rrc\n", rc));
4558 return rc;
4559 }
4560 }
4561
4562#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4563 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4564 if (pVM->hmr0.s.vmx.fUseVmcsShadowing)
4565 {
4566 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4567 if (RT_SUCCESS(rc))
4568 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4569 else
4570 {
4571 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4572 return rc;
4573 }
4574 }
4575#endif
4576
4577 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4578 {
4579 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4580 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4581
4582 pVCpu->hmr0.s.vmx.pfnStartVm = hmR0VmxStartVmSelector;
4583
4584 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4585 if (RT_SUCCESS(rc))
4586 {
4587#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4588 if (pVM->cpum.ro.GuestFeatures.fVmx)
4589 {
4590 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4591 if (RT_SUCCESS(rc))
4592 { /* likely */ }
4593 else
4594 {
4595 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4596 return rc;
4597 }
4598 }
4599#endif
4600 }
4601 else
4602 {
4603 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4604 return rc;
4605 }
4606 }
4607
4608 return VINF_SUCCESS;
4609}
4610
4611
4612/**
4613 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4614 * the VMCS.
4615 * @returns CR4 for passing along to hmR0VmxExportHostSegmentRegs.
4616 */
4617static uint64_t hmR0VmxExportHostControlRegs(void)
4618{
4619 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4620 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4621 uint64_t uHostCr4 = ASMGetCR4();
4622 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, uHostCr4); AssertRC(rc);
4623 return uHostCr4;
4624}
4625
4626
4627/**
4628 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4629 * the host-state area in the VMCS.
4630 *
4631 * @returns VBox status code.
4632 * @param pVCpu The cross context virtual CPU structure.
4633 * @param uHostCr4 The host CR4 value.
4634 */
4635static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu, uint64_t uHostCr4)
4636{
4637 /*
4638 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4639 * will be messed up. We should -not- save the messed up state without restoring
4640 * the original host-state, see @bugref{7240}.
4641 *
4642 * This apparently can happen (most likely the FPU changes), deal with it rather than
4643 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4644 */
4645 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
4646 {
4647 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hmr0.s.vmx.fRestoreHostFlags,
4648 pVCpu->idCpu));
4649 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
4650 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
4651 }
4652
4653 /*
4654 * Get all the host info.
4655 * ASSUME it is safe to use rdfsbase and friends if the CR4.FSGSBASE bit is set
4656 * without also checking the cpuid bit.
4657 */
4658 uint32_t fRestoreHostFlags;
4659#if RT_INLINE_ASM_EXTERNAL
4660 if (uHostCr4 & X86_CR4_FSGSBASE)
4661 {
4662 hmR0VmxExportHostSegmentRegsAsmHlp(&pVCpu->hmr0.s.vmx.RestoreHost, true /*fHaveFsGsBase*/);
4663 fRestoreHostFlags = VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE;
4664 }
4665 else
4666 {
4667 hmR0VmxExportHostSegmentRegsAsmHlp(&pVCpu->hmr0.s.vmx.RestoreHost, false /*fHaveFsGsBase*/);
4668 fRestoreHostFlags = 0;
4669 }
4670 RTSEL uSelES = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelES;
4671 RTSEL uSelDS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelDS;
4672 RTSEL uSelFS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelFS;
4673 RTSEL uSelGS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelGS;
4674#else
4675 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR = ASMGetTR();
4676 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS = ASMGetSS();
4677 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS = ASMGetCS();
4678 ASMGetGDTR((PRTGDTR)&pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr);
4679 ASMGetIDTR((PRTIDTR)&pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr);
4680 if (uHostCr4 & X86_CR4_FSGSBASE)
4681 {
4682 pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase = ASMGetFSBase();
4683 pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase = ASMGetGSBase();
4684 fRestoreHostFlags = VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE;
4685 }
4686 else
4687 {
4688 pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase = ASMRdMsr(MSR_K8_FS_BASE);
4689 pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase = ASMRdMsr(MSR_K8_GS_BASE);
4690 fRestoreHostFlags = 0;
4691 }
4692 RTSEL uSelES, uSelDS, uSelFS, uSelGS;
4693 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelDS = uSelDS = ASMGetDS();
4694 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelES = uSelES = ASMGetES();
4695 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelFS = uSelFS = ASMGetFS();
4696 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelGS = uSelGS = ASMGetGS();
4697#endif
4698
4699 /*
4700 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4701 * gain VM-entry and restore them before we get preempted.
4702 *
4703 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4704 */
4705 RTSEL const uSelAll = uSelFS | uSelGS | uSelES | uSelDS;
4706 if (uSelAll & (X86_SEL_RPL | X86_SEL_LDT))
4707 {
4708 if (!(uSelAll & X86_SEL_LDT))
4709 {
4710#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_uVmcsVar) \
4711 do { \
4712 (a_uVmcsVar) = pVCpu->hmr0.s.vmx.RestoreHost.uHostSel##a_Seg; \
4713 if ((a_uVmcsVar) & X86_SEL_RPL) \
4714 { \
4715 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4716 (a_uVmcsVar) = 0; \
4717 } \
4718 } while (0)
4719 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4720 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4721 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4722 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4723#undef VMXLOCAL_ADJUST_HOST_SEG
4724 }
4725 else
4726 {
4727#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_uVmcsVar) \
4728 do { \
4729 (a_uVmcsVar) = pVCpu->hmr0.s.vmx.RestoreHost.uHostSel##a_Seg; \
4730 if ((a_uVmcsVar) & (X86_SEL_RPL | X86_SEL_LDT)) \
4731 { \
4732 if (!((a_uVmcsVar) & X86_SEL_LDT)) \
4733 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4734 else \
4735 { \
4736 uint32_t const fAttr = ASMGetSegAttr(a_uVmcsVar); \
4737 if ((fAttr & X86_DESC_P) && fAttr != UINT32_MAX) \
4738 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4739 } \
4740 (a_uVmcsVar) = 0; \
4741 } \
4742 } while (0)
4743 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4744 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4745 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4746 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4747#undef VMXLOCAL_ADJUST_HOST_SEG
4748 }
4749 }
4750
4751 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4752 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);
4753 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);
4754 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS & X86_SEL_LDT));
4755 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4756 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4757 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4758 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4759
4760 /*
4761 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4762 * them to the maximum limit (0xffff) on every VM-exit.
4763 */
4764 if (pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb != 0xffff)
4765 fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4766
4767 /*
4768 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4769 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4770 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4771 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4772 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4773 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4774 * at 0xffff on hosts where we are sure it won't cause trouble.
4775 */
4776#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4777 if (pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.cb < 0x0fff)
4778#else
4779 if (pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.cb != 0xffff)
4780#endif
4781 fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4782
4783 /*
4784 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4785 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4786 * RPL should be too in most cases.
4787 */
4788 RTSEL const uSelTR = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR;
4789 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb,
4790 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb),
4791 VERR_VMX_INVALID_HOST_STATE);
4792
4793 PCX86DESCHC pDesc = (PCX86DESCHC)(pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.uAddr + (uSelTR & X86_SEL_MASK));
4794 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4795
4796 /*
4797 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4798 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4799 * restoration if the host has something else. Task switching is not supported in 64-bit
4800 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4801 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4802 *
4803 * [1] See Intel spec. 3.5 "System Descriptor Types".
4804 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4805 */
4806 Assert(pDesc->System.u4Type == 11);
4807 if ( pDesc->System.u16LimitLow != 0x67
4808 || pDesc->System.u4LimitHigh)
4809 {
4810 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4811
4812 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4813 if (g_fHmHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4814 fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4815 if (g_fHmHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4816 {
4817 /* The GDT is read-only but the writable GDT is available. */
4818 fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4819 pVCpu->hmr0.s.vmx.RestoreHost.HostGdtrRw.cb = pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb;
4820 int rc = SUPR0GetCurrentGdtRw(&pVCpu->hmr0.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4821 AssertRCReturn(rc, rc);
4822 }
4823 }
4824
4825 pVCpu->hmr0.s.vmx.fRestoreHostFlags = fRestoreHostFlags;
4826
4827 /*
4828 * Do all the VMCS updates in one block to assist nested virtualization.
4829 */
4830 int rc;
4831 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS); AssertRC(rc);
4832 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS); AssertRC(rc);
4833 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4834 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4835 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4836 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4837 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR); AssertRC(rc);
4838 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.uAddr); AssertRC(rc);
4839 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.uAddr); AssertRC(rc);
4840 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase); AssertRC(rc);
4841 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase); AssertRC(rc);
4842 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase); AssertRC(rc);
4843
4844 return VINF_SUCCESS;
4845}
4846
4847
4848/**
4849 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4850 * host-state area of the VMCS.
4851 *
4852 * These MSRs will be automatically restored on the host after every successful
4853 * VM-exit.
4854 *
4855 * @param pVCpu The cross context virtual CPU structure.
4856 *
4857 * @remarks No-long-jump zone!!!
4858 */
4859static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4860{
4861 AssertPtr(pVCpu);
4862
4863 /*
4864 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4865 * rather than swapping them on every VM-entry.
4866 */
4867 hmR0VmxLazySaveHostMsrs(pVCpu);
4868
4869 /*
4870 * Host Sysenter MSRs.
4871 */
4872 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4873 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4874 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4875
4876 /*
4877 * Host EFER MSR.
4878 *
4879 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4880 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4881 */
4882 if (g_fHmVmxSupportsVmcsEfer)
4883 {
4884 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, g_uHmVmxHostMsrEfer);
4885 AssertRC(rc);
4886 }
4887
4888 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4889 * hmR0VmxExportGuestEntryExitCtls(). */
4890}
4891
4892
4893/**
4894 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4895 *
4896 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4897 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4898 *
4899 * @returns true if we need to load guest EFER, false otherwise.
4900 * @param pVCpu The cross context virtual CPU structure.
4901 * @param pVmxTransient The VMX-transient structure.
4902 *
4903 * @remarks Requires EFER, CR4.
4904 * @remarks No-long-jump zone!!!
4905 */
4906static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4907{
4908#ifdef HMVMX_ALWAYS_SWAP_EFER
4909 RT_NOREF2(pVCpu, pVmxTransient);
4910 return true;
4911#else
4912 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4913 uint64_t const u64HostEfer = g_uHmVmxHostMsrEfer;
4914 uint64_t const u64GuestEfer = pCtx->msrEFER;
4915
4916# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4917 /*
4918 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4919 * the nested-guest.
4920 */
4921 if ( pVmxTransient->fIsNestedGuest
4922 && ( CPUMIsGuestVmxEntryCtlsSet(pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4923 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4924 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4925 return true;
4926# else
4927 RT_NOREF(pVmxTransient);
4928#endif
4929
4930 /*
4931 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4932 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4933 */
4934 if ( CPUMIsGuestInLongModeEx(pCtx)
4935 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4936 return true;
4937
4938 /*
4939 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4940 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4941 *
4942 * See Intel spec. 4.5 "IA-32e Paging".
4943 * See Intel spec. 4.1.1 "Three Paging Modes".
4944 *
4945 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4946 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4947 */
4948 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4949 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4950 if ( (pCtx->cr4 & X86_CR4_PAE)
4951 && (pCtx->cr0 & X86_CR0_PG))
4952 {
4953 /*
4954 * If nested paging is not used, verify that the guest paging mode matches the
4955 * shadow paging mode which is/will be placed in the VMCS (which is what will
4956 * actually be used while executing the guest and not the CR4 shadow value).
4957 */
4958 AssertMsg( pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging
4959 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4960 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4961 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4962 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX,
4963 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4964 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4965 {
4966 /* Verify that the host is NX capable. */
4967 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4968 return true;
4969 }
4970 }
4971
4972 return false;
4973#endif
4974}
4975
4976
4977/**
4978 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4979 * VMCS.
4980 *
4981 * This is typically required when the guest changes paging mode.
4982 *
4983 * @returns VBox status code.
4984 * @param pVCpu The cross context virtual CPU structure.
4985 * @param pVmxTransient The VMX-transient structure.
4986 *
4987 * @remarks Requires EFER.
4988 * @remarks No-long-jump zone!!!
4989 */
4990static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4991{
4992 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4993 {
4994 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4995 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4996
4997 /*
4998 * VM-entry controls.
4999 */
5000 {
5001 uint32_t fVal = g_HmMsrs.u.vmx.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5002 uint32_t const fZap = g_HmMsrs.u.vmx.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5003
5004 /*
5005 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
5006 * The first VT-x capable CPUs only supported the 1-setting of this bit.
5007 *
5008 * For nested-guests, this is a mandatory VM-entry control. It's also
5009 * required because we do not want to leak host bits to the nested-guest.
5010 */
5011 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
5012
5013 /*
5014 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
5015 *
5016 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
5017 * required to get the nested-guest working with hardware-assisted VMX execution.
5018 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
5019 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
5020 * here rather than while merging the guest VMCS controls.
5021 */
5022 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
5023 {
5024 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
5025 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
5026 }
5027 else
5028 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
5029
5030 /*
5031 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
5032 *
5033 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
5034 * regardless of whether the nested-guest VMCS specifies it because we are free to
5035 * load whatever MSRs we require and we do not need to modify the guest visible copy
5036 * of the VM-entry MSR load area.
5037 */
5038 if ( g_fHmVmxSupportsVmcsEfer
5039 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
5040 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
5041 else
5042 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
5043
5044 /*
5045 * The following should -not- be set (since we're not in SMM mode):
5046 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
5047 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
5048 */
5049
5050 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
5051 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
5052
5053 if ((fVal & fZap) == fVal)
5054 { /* likely */ }
5055 else
5056 {
5057 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
5058 g_HmMsrs.u.vmx.EntryCtls.n.allowed0, fVal, fZap));
5059 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
5060 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5061 }
5062
5063 /* Commit it to the VMCS. */
5064 if (pVmcsInfo->u32EntryCtls != fVal)
5065 {
5066 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
5067 AssertRC(rc);
5068 pVmcsInfo->u32EntryCtls = fVal;
5069 }
5070 }
5071
5072 /*
5073 * VM-exit controls.
5074 */
5075 {
5076 uint32_t fVal = g_HmMsrs.u.vmx.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5077 uint32_t const fZap = g_HmMsrs.u.vmx.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5078
5079 /*
5080 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
5081 * supported the 1-setting of this bit.
5082 *
5083 * For nested-guests, we set the "save debug controls" as the converse
5084 * "load debug controls" is mandatory for nested-guests anyway.
5085 */
5086 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
5087
5088 /*
5089 * Set the host long mode active (EFER.LMA) bit (which Intel calls
5090 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
5091 * host EFER.LMA and EFER.LME bit to this value. See assertion in
5092 * hmR0VmxExportHostMsrs().
5093 *
5094 * For nested-guests, we always set this bit as we do not support 32-bit
5095 * hosts.
5096 */
5097 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5098
5099 /*
5100 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
5101 *
5102 * For nested-guests, we should use the "save IA32_EFER" control if we also
5103 * used the "load IA32_EFER" control while exporting VM-entry controls.
5104 */
5105 if ( g_fHmVmxSupportsVmcsEfer
5106 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
5107 {
5108 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
5109 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
5110 }
5111
5112 /*
5113 * Enable saving of the VMX-preemption timer value on VM-exit.
5114 * For nested-guests, currently not exposed/used.
5115 */
5116 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
5117 {
5118 Assert(g_HmMsrs.u.vmx.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER);
5119 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
5120 }
5121
5122 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
5123 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
5124
5125 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5126 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5127 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5128
5129 if ((fVal & fZap) == fVal)
5130 { /* likely */ }
5131 else
5132 {
5133 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5134 g_HmMsrs.u.vmx.ExitCtls.n.allowed0, fVal, fZap));
5135 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5136 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5137 }
5138
5139 /* Commit it to the VMCS. */
5140 if (pVmcsInfo->u32ExitCtls != fVal)
5141 {
5142 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5143 AssertRC(rc);
5144 pVmcsInfo->u32ExitCtls = fVal;
5145 }
5146 }
5147
5148 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5149 }
5150 return VINF_SUCCESS;
5151}
5152
5153
5154/**
5155 * Sets the TPR threshold in the VMCS.
5156 *
5157 * @param pVmcsInfo The VMCS info. object.
5158 * @param u32TprThreshold The TPR threshold (task-priority class only).
5159 */
5160DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5161{
5162 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5163 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5164 RT_NOREF(pVmcsInfo);
5165 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5166 AssertRC(rc);
5167}
5168
5169
5170/**
5171 * Exports the guest APIC TPR state into the VMCS.
5172 *
5173 * @param pVCpu The cross context virtual CPU structure.
5174 * @param pVmxTransient The VMX-transient structure.
5175 *
5176 * @remarks No-long-jump zone!!!
5177 */
5178static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5179{
5180 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5181 {
5182 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5183
5184 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5185 if (!pVmxTransient->fIsNestedGuest)
5186 {
5187 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5188 && APICIsEnabled(pVCpu))
5189 {
5190 /*
5191 * Setup TPR shadowing.
5192 */
5193 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5194 {
5195 bool fPendingIntr = false;
5196 uint8_t u8Tpr = 0;
5197 uint8_t u8PendingIntr = 0;
5198 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5199 AssertRC(rc);
5200
5201 /*
5202 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5203 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5204 * priority of the pending interrupt so we can deliver the interrupt. If there
5205 * are no interrupts pending, set threshold to 0 to not cause any
5206 * TPR-below-threshold VM-exits.
5207 */
5208 uint32_t u32TprThreshold = 0;
5209 if (fPendingIntr)
5210 {
5211 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5212 (which is the Task-Priority Class). */
5213 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5214 const uint8_t u8TprPriority = u8Tpr >> 4;
5215 if (u8PendingPriority <= u8TprPriority)
5216 u32TprThreshold = u8PendingPriority;
5217 }
5218
5219 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
5220 }
5221 }
5222 }
5223 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5224 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5225 }
5226}
5227
5228
5229/**
5230 * Gets the guest interruptibility-state and updates related force-flags.
5231 *
5232 * @returns Guest's interruptibility-state.
5233 * @param pVCpu The cross context virtual CPU structure.
5234 *
5235 * @remarks No-long-jump zone!!!
5236 */
5237static uint32_t hmR0VmxGetGuestIntrStateAndUpdateFFs(PVMCPUCC pVCpu)
5238{
5239 /*
5240 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5241 */
5242 uint32_t fIntrState = 0;
5243 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5244 {
5245 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
5246 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
5247
5248 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5249 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5250 {
5251 if (pCtx->eflags.Bits.u1IF)
5252 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5253 else
5254 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5255 }
5256 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5257 {
5258 /*
5259 * We can clear the inhibit force flag as even if we go back to the recompiler
5260 * without executing guest code in VT-x, the flag's condition to be cleared is
5261 * met and thus the cleared state is correct.
5262 */
5263 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5264 }
5265 }
5266
5267 /*
5268 * Check if we should inhibit NMI delivery.
5269 */
5270 if (CPUMIsGuestNmiBlocking(pVCpu))
5271 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5272
5273 /*
5274 * Validate.
5275 */
5276#ifdef VBOX_STRICT
5277 /* We don't support block-by-SMI yet.*/
5278 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
5279
5280 /* Block-by-STI must not be set when interrupts are disabled. */
5281 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
5282 {
5283 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5284 Assert(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_IF);
5285 }
5286#endif
5287
5288 return fIntrState;
5289}
5290
5291
5292/**
5293 * Exports the exception intercepts required for guest execution in the VMCS.
5294 *
5295 * @param pVCpu The cross context virtual CPU structure.
5296 * @param pVmxTransient The VMX-transient structure.
5297 *
5298 * @remarks No-long-jump zone!!!
5299 */
5300static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5301{
5302 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5303 {
5304 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5305 if ( !pVmxTransient->fIsNestedGuest
5306 && pVCpu->hm.s.fGIMTrapXcptUD)
5307 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5308 else
5309 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5310
5311 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5312 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5313 }
5314}
5315
5316
5317/**
5318 * Exports the guest's RIP into the guest-state area in the VMCS.
5319 *
5320 * @param pVCpu The cross context virtual CPU structure.
5321 *
5322 * @remarks No-long-jump zone!!!
5323 */
5324static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5325{
5326 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5327 {
5328 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5329
5330 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5331 AssertRC(rc);
5332
5333 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5334 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5335 }
5336}
5337
5338
5339/**
5340 * Exports the guest's RSP into the guest-state area in the VMCS.
5341 *
5342 * @param pVCpu The cross context virtual CPU structure.
5343 *
5344 * @remarks No-long-jump zone!!!
5345 */
5346static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5347{
5348 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5349 {
5350 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5351
5352 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5353 AssertRC(rc);
5354
5355 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5356 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5357 }
5358}
5359
5360
5361/**
5362 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5363 *
5364 * @param pVCpu The cross context virtual CPU structure.
5365 * @param pVmxTransient The VMX-transient structure.
5366 *
5367 * @remarks No-long-jump zone!!!
5368 */
5369static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5370{
5371 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5372 {
5373 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5374
5375 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5376 Let us assert it as such and use 32-bit VMWRITE. */
5377 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5378 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5379 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5380 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5381
5382 /*
5383 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5384 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5385 * can run the real-mode guest code under Virtual 8086 mode.
5386 */
5387 PVMXVMCSINFOSHARED pVmcsInfo = pVmxTransient->pVmcsInfo->pShared;
5388 if (pVmcsInfo->RealMode.fRealOnV86Active)
5389 {
5390 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5391 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5392 Assert(!pVmxTransient->fIsNestedGuest);
5393 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5394 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5395 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5396 }
5397
5398 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5399 AssertRC(rc);
5400
5401 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5402 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5403 }
5404}
5405
5406
5407#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5408/**
5409 * Copies the nested-guest VMCS to the shadow VMCS.
5410 *
5411 * @returns VBox status code.
5412 * @param pVCpu The cross context virtual CPU structure.
5413 * @param pVmcsInfo The VMCS info. object.
5414 *
5415 * @remarks No-long-jump zone!!!
5416 */
5417static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5418{
5419 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5420 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5421
5422 /*
5423 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5424 * current VMCS, as we may try saving guest lazy MSRs.
5425 *
5426 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5427 * calling the import VMCS code which is currently performing the guest MSR reads
5428 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5429 * and the rest of the VMX leave session machinery.
5430 */
5431 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5432
5433 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5434 if (RT_SUCCESS(rc))
5435 {
5436 /*
5437 * Copy all guest read/write VMCS fields.
5438 *
5439 * We don't check for VMWRITE failures here for performance reasons and
5440 * because they are not expected to fail, barring irrecoverable conditions
5441 * like hardware errors.
5442 */
5443 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
5444 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5445 {
5446 uint64_t u64Val;
5447 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsFields[i];
5448 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5449 VMXWriteVmcs64(uVmcsField, u64Val);
5450 }
5451
5452 /*
5453 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5454 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5455 */
5456 if (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL)
5457 {
5458 uint32_t const cShadowVmcsRoFields = pVM->hmr0.s.vmx.cShadowVmcsRoFields;
5459 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5460 {
5461 uint64_t u64Val;
5462 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsRoFields[i];
5463 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5464 VMXWriteVmcs64(uVmcsField, u64Val);
5465 }
5466 }
5467
5468 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5469 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5470 }
5471
5472 ASMSetFlags(fEFlags);
5473 return rc;
5474}
5475
5476
5477/**
5478 * Copies the shadow VMCS to the nested-guest VMCS.
5479 *
5480 * @returns VBox status code.
5481 * @param pVCpu The cross context virtual CPU structure.
5482 * @param pVmcsInfo The VMCS info. object.
5483 *
5484 * @remarks Called with interrupts disabled.
5485 */
5486static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5487{
5488 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5489 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5490 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5491
5492 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5493 if (RT_SUCCESS(rc))
5494 {
5495 /*
5496 * Copy guest read/write fields from the shadow VMCS.
5497 * Guest read-only fields cannot be modified, so no need to copy them.
5498 *
5499 * We don't check for VMREAD failures here for performance reasons and
5500 * because they are not expected to fail, barring irrecoverable conditions
5501 * like hardware errors.
5502 */
5503 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
5504 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5505 {
5506 uint64_t u64Val;
5507 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsFields[i];
5508 VMXReadVmcs64(uVmcsField, &u64Val);
5509 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5510 }
5511
5512 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5513 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5514 }
5515 return rc;
5516}
5517
5518
5519/**
5520 * Enables VMCS shadowing for the given VMCS info. object.
5521 *
5522 * @param pVmcsInfo The VMCS info. object.
5523 *
5524 * @remarks No-long-jump zone!!!
5525 */
5526static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5527{
5528 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5529 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5530 {
5531 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5532 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5533 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5534 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5535 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5536 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5537 Log4Func(("Enabled\n"));
5538 }
5539}
5540
5541
5542/**
5543 * Disables VMCS shadowing for the given VMCS info. object.
5544 *
5545 * @param pVmcsInfo The VMCS info. object.
5546 *
5547 * @remarks No-long-jump zone!!!
5548 */
5549static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5550{
5551 /*
5552 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5553 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5554 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5555 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5556 *
5557 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5558 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5559 */
5560 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5561 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5562 {
5563 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5564 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5565 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5566 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5567 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5568 Log4Func(("Disabled\n"));
5569 }
5570}
5571#endif
5572
5573
5574/**
5575 * Exports the guest hardware-virtualization state.
5576 *
5577 * @returns VBox status code.
5578 * @param pVCpu The cross context virtual CPU structure.
5579 * @param pVmxTransient The VMX-transient structure.
5580 *
5581 * @remarks No-long-jump zone!!!
5582 */
5583static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5584{
5585 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5586 {
5587#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5588 /*
5589 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5590 * VMCS shadowing.
5591 */
5592 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUseVmcsShadowing)
5593 {
5594 /*
5595 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5596 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5597 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5598 *
5599 * We check for VMX root mode here in case the guest executes VMXOFF without
5600 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5601 * not clear the current VMCS pointer.
5602 */
5603 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5604 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5605 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5606 && CPUMIsGuestVmxCurrentVmcsValid(&pVCpu->cpum.GstCtx))
5607 {
5608 /* Paranoia. */
5609 Assert(!pVmxTransient->fIsNestedGuest);
5610
5611 /*
5612 * For performance reasons, also check if the nested hypervisor's current VMCS
5613 * was newly loaded or modified before copying it to the shadow VMCS.
5614 */
5615 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5616 {
5617 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5618 AssertRCReturn(rc, rc);
5619 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5620 }
5621 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5622 }
5623 else
5624 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5625 }
5626#else
5627 NOREF(pVmxTransient);
5628#endif
5629 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5630 }
5631 return VINF_SUCCESS;
5632}
5633
5634
5635/**
5636 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5637 *
5638 * The guest FPU state is always pre-loaded hence we don't need to bother about
5639 * sharing FPU related CR0 bits between the guest and host.
5640 *
5641 * @returns VBox status code.
5642 * @param pVCpu The cross context virtual CPU structure.
5643 * @param pVmxTransient The VMX-transient structure.
5644 *
5645 * @remarks No-long-jump zone!!!
5646 */
5647static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5648{
5649 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5650 {
5651 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5652 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5653
5654 uint64_t fSetCr0 = g_HmMsrs.u.vmx.u64Cr0Fixed0;
5655 uint64_t const fZapCr0 = g_HmMsrs.u.vmx.u64Cr0Fixed1;
5656 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
5657 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5658 else
5659 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5660
5661 if (!pVmxTransient->fIsNestedGuest)
5662 {
5663 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5664 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5665 uint64_t const u64ShadowCr0 = u64GuestCr0;
5666 Assert(!RT_HI_U32(u64GuestCr0));
5667
5668 /*
5669 * Setup VT-x's view of the guest CR0.
5670 */
5671 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5672 if (pVM->hmr0.s.fNestedPaging)
5673 {
5674 if (CPUMIsGuestPagingEnabled(pVCpu))
5675 {
5676 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5677 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5678 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5679 }
5680 else
5681 {
5682 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5683 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5684 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5685 }
5686
5687 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5688 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
5689 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5690 }
5691 else
5692 {
5693 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5694 u64GuestCr0 |= X86_CR0_WP;
5695 }
5696
5697 /*
5698 * Guest FPU bits.
5699 *
5700 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5701 * using CR0.TS.
5702 *
5703 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5704 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5705 */
5706 u64GuestCr0 |= X86_CR0_NE;
5707
5708 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5709 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5710
5711 /*
5712 * Update exception intercepts.
5713 */
5714 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5715 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
5716 {
5717 Assert(PDMVmmDevHeapIsEnabled(pVM));
5718 Assert(pVM->hm.s.vmx.pRealModeTSS);
5719 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5720 }
5721 else
5722 {
5723 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5724 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5725 if (fInterceptMF)
5726 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5727 }
5728
5729 /* Additional intercepts for debugging, define these yourself explicitly. */
5730#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5731 uXcptBitmap |= 0
5732 | RT_BIT(X86_XCPT_BP)
5733 | RT_BIT(X86_XCPT_DE)
5734 | RT_BIT(X86_XCPT_NM)
5735 | RT_BIT(X86_XCPT_TS)
5736 | RT_BIT(X86_XCPT_UD)
5737 | RT_BIT(X86_XCPT_NP)
5738 | RT_BIT(X86_XCPT_SS)
5739 | RT_BIT(X86_XCPT_GP)
5740 | RT_BIT(X86_XCPT_PF)
5741 | RT_BIT(X86_XCPT_MF)
5742 ;
5743#elif defined(HMVMX_ALWAYS_TRAP_PF)
5744 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5745#endif
5746 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5747 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5748 Assert(pVM->hmr0.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5749
5750 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5751 u64GuestCr0 |= fSetCr0;
5752 u64GuestCr0 &= fZapCr0;
5753 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5754
5755 /* Commit the CR0 and related fields to the guest VMCS. */
5756 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5757 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5758 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5759 {
5760 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5761 AssertRC(rc);
5762 }
5763 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5764 {
5765 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5766 AssertRC(rc);
5767 }
5768
5769 /* Update our caches. */
5770 pVmcsInfo->u32ProcCtls = uProcCtls;
5771 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5772
5773 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5774 }
5775 else
5776 {
5777 /*
5778 * With nested-guests, we may have extended the guest/host mask here since we
5779 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5780 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5781 * originally supplied. We must copy those bits from the nested-guest CR0 into
5782 * the nested-guest CR0 read-shadow.
5783 */
5784 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5785 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5786 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(&pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5787 Assert(!RT_HI_U32(u64GuestCr0));
5788 Assert(u64GuestCr0 & X86_CR0_NE);
5789
5790 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5791 u64GuestCr0 |= fSetCr0;
5792 u64GuestCr0 &= fZapCr0;
5793 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5794
5795 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5796 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5797 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5798
5799 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5800 }
5801
5802 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5803 }
5804
5805 return VINF_SUCCESS;
5806}
5807
5808
5809/**
5810 * Exports the guest control registers (CR3, CR4) into the guest-state area
5811 * in the VMCS.
5812 *
5813 * @returns VBox strict status code.
5814 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5815 * without unrestricted guest access and the VMMDev is not presently
5816 * mapped (e.g. EFI32).
5817 *
5818 * @param pVCpu The cross context virtual CPU structure.
5819 * @param pVmxTransient The VMX-transient structure.
5820 *
5821 * @remarks No-long-jump zone!!!
5822 */
5823static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5824{
5825 int rc = VINF_SUCCESS;
5826 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5827
5828 /*
5829 * Guest CR2.
5830 * It's always loaded in the assembler code. Nothing to do here.
5831 */
5832
5833 /*
5834 * Guest CR3.
5835 */
5836 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5837 {
5838 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5839
5840 if (pVM->hmr0.s.fNestedPaging)
5841 {
5842 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5843 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5844
5845 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5846 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5847 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5848 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5849
5850 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5851 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5852 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5853
5854 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5855 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5856 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5857 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5858 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5859 || (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5860 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5861
5862 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5863 AssertRC(rc);
5864
5865 uint64_t u64GuestCr3;
5866 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5867 if ( pVM->hmr0.s.vmx.fUnrestrictedGuest
5868 || CPUMIsGuestPagingEnabledEx(pCtx))
5869 {
5870 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5871 if (CPUMIsGuestInPAEModeEx(pCtx))
5872 {
5873 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5874 AssertRC(rc);
5875 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5876 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5877 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5878 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5879 }
5880
5881 /*
5882 * The guest's view of its CR3 is unblemished with nested paging when the
5883 * guest is using paging or we have unrestricted guest execution to handle
5884 * the guest when it's not using paging.
5885 */
5886 u64GuestCr3 = pCtx->cr3;
5887 }
5888 else
5889 {
5890 /*
5891 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5892 * thinks it accesses physical memory directly, we use our identity-mapped
5893 * page table to map guest-linear to guest-physical addresses. EPT takes care
5894 * of translating it to host-physical addresses.
5895 */
5896 RTGCPHYS GCPhys;
5897 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5898
5899 /* We obtain it here every time as the guest could have relocated this PCI region. */
5900 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5901 if (RT_SUCCESS(rc))
5902 { /* likely */ }
5903 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5904 {
5905 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5906 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5907 }
5908 else
5909 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5910
5911 u64GuestCr3 = GCPhys;
5912 }
5913
5914 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5915 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5916 AssertRC(rc);
5917 }
5918 else
5919 {
5920 Assert(!pVmxTransient->fIsNestedGuest);
5921 /* Non-nested paging case, just use the hypervisor's CR3. */
5922 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5923
5924 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5925 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5926 AssertRC(rc);
5927 }
5928
5929 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5930 }
5931
5932 /*
5933 * Guest CR4.
5934 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5935 */
5936 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5937 {
5938 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5939 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5940
5941 uint64_t const fSetCr4 = g_HmMsrs.u.vmx.u64Cr4Fixed0;
5942 uint64_t const fZapCr4 = g_HmMsrs.u.vmx.u64Cr4Fixed1;
5943
5944 /*
5945 * With nested-guests, we may have extended the guest/host mask here (since we
5946 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5947 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5948 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5949 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5950 */
5951 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5952 uint64_t u64GuestCr4 = pCtx->cr4;
5953 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5954 ? pCtx->cr4
5955 : CPUMGetGuestVmxMaskedCr4(pCtx, pVmcsInfo->u64Cr4Mask);
5956 Assert(!RT_HI_U32(u64GuestCr4));
5957
5958 /*
5959 * Setup VT-x's view of the guest CR4.
5960 *
5961 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5962 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5963 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5964 *
5965 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5966 */
5967 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
5968 {
5969 Assert(pVM->hm.s.vmx.pRealModeTSS);
5970 Assert(PDMVmmDevHeapIsEnabled(pVM));
5971 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5972 }
5973
5974 if (pVM->hmr0.s.fNestedPaging)
5975 {
5976 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5977 && !pVM->hmr0.s.vmx.fUnrestrictedGuest)
5978 {
5979 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5980 u64GuestCr4 |= X86_CR4_PSE;
5981 /* Our identity mapping is a 32-bit page directory. */
5982 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5983 }
5984 /* else use guest CR4.*/
5985 }
5986 else
5987 {
5988 Assert(!pVmxTransient->fIsNestedGuest);
5989
5990 /*
5991 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5992 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5993 */
5994 switch (pVCpu->hm.s.enmShadowMode)
5995 {
5996 case PGMMODE_REAL: /* Real-mode. */
5997 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5998 case PGMMODE_32_BIT: /* 32-bit paging. */
5999 {
6000 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
6001 break;
6002 }
6003
6004 case PGMMODE_PAE: /* PAE paging. */
6005 case PGMMODE_PAE_NX: /* PAE paging with NX. */
6006 {
6007 u64GuestCr4 |= X86_CR4_PAE;
6008 break;
6009 }
6010
6011 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
6012 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
6013 {
6014#ifdef VBOX_WITH_64_BITS_GUESTS
6015 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
6016 Assert(u64GuestCr4 & X86_CR4_PAE);
6017 break;
6018#endif
6019 }
6020 default:
6021 AssertFailed();
6022 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6023 }
6024 }
6025
6026 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
6027 u64GuestCr4 |= fSetCr4;
6028 u64GuestCr4 &= fZapCr4;
6029
6030 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
6031 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
6032 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
6033
6034 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
6035 bool const fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
6036 if (fLoadSaveGuestXcr0 != pVCpu->hmr0.s.fLoadSaveGuestXcr0)
6037 {
6038 pVCpu->hmr0.s.fLoadSaveGuestXcr0 = fLoadSaveGuestXcr0;
6039 hmR0VmxUpdateStartVmFunction(pVCpu);
6040 }
6041
6042 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
6043
6044 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
6045 }
6046 return rc;
6047}
6048
6049
6050/**
6051 * Exports the guest debug registers into the guest-state area in the VMCS.
6052 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
6053 *
6054 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
6055 *
6056 * @returns VBox status code.
6057 * @param pVCpu The cross context virtual CPU structure.
6058 * @param pVmxTransient The VMX-transient structure.
6059 *
6060 * @remarks No-long-jump zone!!!
6061 */
6062static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6063{
6064 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
6065
6066 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
6067 * stepping. */
6068 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6069 if (pVmxTransient->fIsNestedGuest)
6070 {
6071 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
6072 AssertRC(rc);
6073
6074 /* Always intercept Mov DRx accesses for the nested-guest for now. */
6075 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6076 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
6077 AssertRC(rc);
6078 return VINF_SUCCESS;
6079 }
6080
6081#ifdef VBOX_STRICT
6082 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
6083 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
6084 {
6085 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
6086 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
6087 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
6088 }
6089#endif
6090
6091 bool fSteppingDB = false;
6092 bool fInterceptMovDRx = false;
6093 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6094 if (pVCpu->hm.s.fSingleInstruction)
6095 {
6096 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
6097 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
6098 {
6099 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
6100 Assert(fSteppingDB == false);
6101 }
6102 else
6103 {
6104 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
6105 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
6106 pVCpu->hmr0.s.fClearTrapFlag = true;
6107 fSteppingDB = true;
6108 }
6109 }
6110
6111 uint64_t u64GuestDr7;
6112 if ( fSteppingDB
6113 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
6114 {
6115 /*
6116 * Use the combined guest and host DRx values found in the hypervisor register set
6117 * because the hypervisor debugger has breakpoints active or someone is single stepping
6118 * on the host side without a monitor trap flag.
6119 *
6120 * Note! DBGF expects a clean DR6 state before executing guest code.
6121 */
6122 if (!CPUMIsHyperDebugStateActive(pVCpu))
6123 {
6124 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6125 Assert(CPUMIsHyperDebugStateActive(pVCpu));
6126 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
6127 }
6128
6129 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6130 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
6131 pVCpu->hmr0.s.fUsingHyperDR7 = true;
6132 fInterceptMovDRx = true;
6133 }
6134 else
6135 {
6136 /*
6137 * If the guest has enabled debug registers, we need to load them prior to
6138 * executing guest code so they'll trigger at the right time.
6139 */
6140 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
6141 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6142 {
6143 if (!CPUMIsGuestDebugStateActive(pVCpu))
6144 {
6145 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6146 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6147 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6148 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6149 }
6150 Assert(!fInterceptMovDRx);
6151 }
6152 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6153 {
6154 /*
6155 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6156 * must intercept #DB in order to maintain a correct DR6 guest value, and
6157 * because we need to intercept it to prevent nested #DBs from hanging the
6158 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6159 */
6160 fInterceptMovDRx = true;
6161 }
6162
6163 /* Update DR7 with the actual guest value. */
6164 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6165 pVCpu->hmr0.s.fUsingHyperDR7 = false;
6166 }
6167
6168 if (fInterceptMovDRx)
6169 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6170 else
6171 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6172
6173 /*
6174 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6175 * monitor-trap flag and update our cache.
6176 */
6177 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6178 {
6179 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6180 AssertRC(rc);
6181 pVmcsInfo->u32ProcCtls = uProcCtls;
6182 }
6183
6184 /*
6185 * Update guest DR7.
6186 */
6187 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
6188 AssertRC(rc);
6189
6190 /*
6191 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6192 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6193 *
6194 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6195 */
6196 if (fSteppingDB)
6197 {
6198 Assert(pVCpu->hm.s.fSingleInstruction);
6199 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6200
6201 uint32_t fIntrState = 0;
6202 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6203 AssertRC(rc);
6204
6205 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6206 {
6207 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6208 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6209 AssertRC(rc);
6210 }
6211 }
6212
6213 return VINF_SUCCESS;
6214}
6215
6216
6217#ifdef VBOX_STRICT
6218/**
6219 * Strict function to validate segment registers.
6220 *
6221 * @param pVCpu The cross context virtual CPU structure.
6222 * @param pVmcsInfo The VMCS info. object.
6223 *
6224 * @remarks Will import guest CR0 on strict builds during validation of
6225 * segments.
6226 */
6227static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
6228{
6229 /*
6230 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6231 *
6232 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6233 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6234 * unusable bit and doesn't change the guest-context value.
6235 */
6236 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6237 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6238 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6239 if ( !pVM->hmr0.s.vmx.fUnrestrictedGuest
6240 && ( !CPUMIsGuestInRealModeEx(pCtx)
6241 && !CPUMIsGuestInV86ModeEx(pCtx)))
6242 {
6243 /* Protected mode checks */
6244 /* CS */
6245 Assert(pCtx->cs.Attr.n.u1Present);
6246 Assert(!(pCtx->cs.Attr.u & 0xf00));
6247 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6248 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6249 || !(pCtx->cs.Attr.n.u1Granularity));
6250 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6251 || (pCtx->cs.Attr.n.u1Granularity));
6252 /* CS cannot be loaded with NULL in protected mode. */
6253 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6254 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6255 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6256 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6257 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6258 else
6259 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6260 /* SS */
6261 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6262 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6263 if ( !(pCtx->cr0 & X86_CR0_PE)
6264 || pCtx->cs.Attr.n.u4Type == 3)
6265 {
6266 Assert(!pCtx->ss.Attr.n.u2Dpl);
6267 }
6268 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6269 {
6270 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6271 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6272 Assert(pCtx->ss.Attr.n.u1Present);
6273 Assert(!(pCtx->ss.Attr.u & 0xf00));
6274 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6275 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6276 || !(pCtx->ss.Attr.n.u1Granularity));
6277 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6278 || (pCtx->ss.Attr.n.u1Granularity));
6279 }
6280 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6281 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6282 {
6283 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6284 Assert(pCtx->ds.Attr.n.u1Present);
6285 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6286 Assert(!(pCtx->ds.Attr.u & 0xf00));
6287 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6288 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6289 || !(pCtx->ds.Attr.n.u1Granularity));
6290 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6291 || (pCtx->ds.Attr.n.u1Granularity));
6292 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6293 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6294 }
6295 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6296 {
6297 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6298 Assert(pCtx->es.Attr.n.u1Present);
6299 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6300 Assert(!(pCtx->es.Attr.u & 0xf00));
6301 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6302 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6303 || !(pCtx->es.Attr.n.u1Granularity));
6304 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6305 || (pCtx->es.Attr.n.u1Granularity));
6306 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6307 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6308 }
6309 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6310 {
6311 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6312 Assert(pCtx->fs.Attr.n.u1Present);
6313 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6314 Assert(!(pCtx->fs.Attr.u & 0xf00));
6315 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6316 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6317 || !(pCtx->fs.Attr.n.u1Granularity));
6318 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6319 || (pCtx->fs.Attr.n.u1Granularity));
6320 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6321 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6322 }
6323 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6324 {
6325 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6326 Assert(pCtx->gs.Attr.n.u1Present);
6327 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6328 Assert(!(pCtx->gs.Attr.u & 0xf00));
6329 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6330 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6331 || !(pCtx->gs.Attr.n.u1Granularity));
6332 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6333 || (pCtx->gs.Attr.n.u1Granularity));
6334 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6335 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6336 }
6337 /* 64-bit capable CPUs. */
6338 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6339 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6340 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6341 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6342 }
6343 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6344 || ( CPUMIsGuestInRealModeEx(pCtx)
6345 && !pVM->hmr0.s.vmx.fUnrestrictedGuest))
6346 {
6347 /* Real and v86 mode checks. */
6348 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6349 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6350 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
6351 {
6352 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6353 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6354 }
6355 else
6356 {
6357 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6358 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6359 }
6360
6361 /* CS */
6362 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6363 Assert(pCtx->cs.u32Limit == 0xffff);
6364 Assert(u32CSAttr == 0xf3);
6365 /* SS */
6366 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6367 Assert(pCtx->ss.u32Limit == 0xffff);
6368 Assert(u32SSAttr == 0xf3);
6369 /* DS */
6370 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6371 Assert(pCtx->ds.u32Limit == 0xffff);
6372 Assert(u32DSAttr == 0xf3);
6373 /* ES */
6374 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6375 Assert(pCtx->es.u32Limit == 0xffff);
6376 Assert(u32ESAttr == 0xf3);
6377 /* FS */
6378 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6379 Assert(pCtx->fs.u32Limit == 0xffff);
6380 Assert(u32FSAttr == 0xf3);
6381 /* GS */
6382 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6383 Assert(pCtx->gs.u32Limit == 0xffff);
6384 Assert(u32GSAttr == 0xf3);
6385 /* 64-bit capable CPUs. */
6386 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6387 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6388 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6389 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6390 }
6391}
6392#endif /* VBOX_STRICT */
6393
6394
6395/**
6396 * Exports a guest segment register into the guest-state area in the VMCS.
6397 *
6398 * @returns VBox status code.
6399 * @param pVCpu The cross context virtual CPU structure.
6400 * @param pVmcsInfo The VMCS info. object.
6401 * @param iSegReg The segment register number (X86_SREG_XXX).
6402 * @param pSelReg Pointer to the segment selector.
6403 *
6404 * @remarks No-long-jump zone!!!
6405 */
6406static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint32_t iSegReg, PCCPUMSELREG pSelReg)
6407{
6408 Assert(iSegReg < X86_SREG_COUNT);
6409
6410 uint32_t u32Access = pSelReg->Attr.u;
6411 if (!pVmcsInfo->pShared->RealMode.fRealOnV86Active)
6412 {
6413 /*
6414 * The way to differentiate between whether this is really a null selector or was just
6415 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6416 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6417 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6418 * NULL selectors loaded in protected-mode have their attribute as 0.
6419 */
6420 if (u32Access)
6421 { }
6422 else
6423 u32Access = X86DESCATTR_UNUSABLE;
6424 }
6425 else
6426 {
6427 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6428 u32Access = 0xf3;
6429 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6430 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6431 RT_NOREF_PV(pVCpu);
6432 }
6433
6434 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6435 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6436 ("Access bit not set for usable segment. %.2s sel=%#x attr %#x\n", "ESCSSSDSFSGS" + iSegReg * 2, pSelReg, pSelReg->Attr.u));
6437
6438 /*
6439 * Commit it to the VMCS.
6440 */
6441 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]);
6442 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]);
6443 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
6444 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]);
6445 int rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), pSelReg->Sel); AssertRC(rc);
6446 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), pSelReg->u32Limit); AssertRC(rc);
6447 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), pSelReg->u64Base); AssertRC(rc);
6448 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), u32Access); AssertRC(rc);
6449 return VINF_SUCCESS;
6450}
6451
6452
6453/**
6454 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6455 * area in the VMCS.
6456 *
6457 * @returns VBox status code.
6458 * @param pVCpu The cross context virtual CPU structure.
6459 * @param pVmxTransient The VMX-transient structure.
6460 *
6461 * @remarks Will import guest CR0 on strict builds during validation of
6462 * segments.
6463 * @remarks No-long-jump zone!!!
6464 */
6465static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6466{
6467 int rc = VERR_INTERNAL_ERROR_5;
6468 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6469 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6470 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6471 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
6472
6473 /*
6474 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6475 */
6476 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6477 {
6478 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6479 {
6480 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6481 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6482 pVmcsInfoShared->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6483 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6484 AssertRC(rc);
6485 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6486 }
6487
6488 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6489 {
6490 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6491 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6492 pVmcsInfoShared->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6493 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6494 AssertRC(rc);
6495 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6496 }
6497
6498 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6499 {
6500 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6501 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6502 pVmcsInfoShared->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6503 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6504 AssertRC(rc);
6505 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6506 }
6507
6508 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6509 {
6510 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6511 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6512 pVmcsInfoShared->RealMode.AttrES.u = pCtx->es.Attr.u;
6513 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6514 AssertRC(rc);
6515 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6516 }
6517
6518 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6519 {
6520 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6521 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6522 pVmcsInfoShared->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6523 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6524 AssertRC(rc);
6525 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6526 }
6527
6528 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6529 {
6530 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6531 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6532 pVmcsInfoShared->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6533 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6534 AssertRC(rc);
6535 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6536 }
6537
6538#ifdef VBOX_STRICT
6539 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6540#endif
6541 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6542 pCtx->cs.Attr.u));
6543 }
6544
6545 /*
6546 * Guest TR.
6547 */
6548 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6549 {
6550 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6551
6552 /*
6553 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6554 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6555 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6556 */
6557 uint16_t u16Sel;
6558 uint32_t u32Limit;
6559 uint64_t u64Base;
6560 uint32_t u32AccessRights;
6561 if (!pVmcsInfoShared->RealMode.fRealOnV86Active)
6562 {
6563 u16Sel = pCtx->tr.Sel;
6564 u32Limit = pCtx->tr.u32Limit;
6565 u64Base = pCtx->tr.u64Base;
6566 u32AccessRights = pCtx->tr.Attr.u;
6567 }
6568 else
6569 {
6570 Assert(!pVmxTransient->fIsNestedGuest);
6571 Assert(pVM->hm.s.vmx.pRealModeTSS);
6572 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6573
6574 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6575 RTGCPHYS GCPhys;
6576 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6577 AssertRCReturn(rc, rc);
6578
6579 X86DESCATTR DescAttr;
6580 DescAttr.u = 0;
6581 DescAttr.n.u1Present = 1;
6582 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6583
6584 u16Sel = 0;
6585 u32Limit = HM_VTX_TSS_SIZE;
6586 u64Base = GCPhys;
6587 u32AccessRights = DescAttr.u;
6588 }
6589
6590 /* Validate. */
6591 Assert(!(u16Sel & RT_BIT(2)));
6592 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6593 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6594 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6595 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6596 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6597 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6598 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6599 Assert( (u32Limit & 0xfff) == 0xfff
6600 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6601 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6602 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6603
6604 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6605 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6606 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6607 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6608
6609 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6610 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6611 }
6612
6613 /*
6614 * Guest GDTR.
6615 */
6616 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6617 {
6618 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6619
6620 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6621 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6622
6623 /* Validate. */
6624 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6625
6626 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6627 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6628 }
6629
6630 /*
6631 * Guest LDTR.
6632 */
6633 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6634 {
6635 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6636
6637 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6638 uint32_t u32Access;
6639 if ( !pVmxTransient->fIsNestedGuest
6640 && !pCtx->ldtr.Attr.u)
6641 u32Access = X86DESCATTR_UNUSABLE;
6642 else
6643 u32Access = pCtx->ldtr.Attr.u;
6644
6645 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6646 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6647 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6648 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6649
6650 /* Validate. */
6651 if (!(u32Access & X86DESCATTR_UNUSABLE))
6652 {
6653 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6654 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6655 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6656 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6657 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6658 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6659 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6660 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6661 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6662 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6663 }
6664
6665 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6666 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6667 }
6668
6669 /*
6670 * Guest IDTR.
6671 */
6672 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6673 {
6674 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6675
6676 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6677 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6678
6679 /* Validate. */
6680 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6681
6682 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6683 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6684 }
6685
6686 return VINF_SUCCESS;
6687}
6688
6689
6690/**
6691 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6692 * areas.
6693 *
6694 * These MSRs will automatically be loaded to the host CPU on every successful
6695 * VM-entry and stored from the host CPU on every successful VM-exit.
6696 *
6697 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6698 * actual host MSR values are not- updated here for performance reasons. See
6699 * hmR0VmxExportHostMsrs().
6700 *
6701 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6702 *
6703 * @returns VBox status code.
6704 * @param pVCpu The cross context virtual CPU structure.
6705 * @param pVmxTransient The VMX-transient structure.
6706 *
6707 * @remarks No-long-jump zone!!!
6708 */
6709static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6710{
6711 AssertPtr(pVCpu);
6712 AssertPtr(pVmxTransient);
6713
6714 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6715 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6716
6717 /*
6718 * MSRs that we use the auto-load/store MSR area in the VMCS.
6719 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6720 * nothing to do here. The host MSR values are updated when it's safe in
6721 * hmR0VmxLazySaveHostMsrs().
6722 *
6723 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6724 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6725 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6726 * for any MSR that are not part of the lazy MSRs so we do not need to place
6727 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6728 */
6729 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6730 {
6731 /* No auto-load/store MSRs currently. */
6732 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6733 }
6734
6735 /*
6736 * Guest Sysenter MSRs.
6737 */
6738 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6739 {
6740 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6741
6742 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6743 {
6744 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6745 AssertRC(rc);
6746 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6747 }
6748
6749 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6750 {
6751 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6752 AssertRC(rc);
6753 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6754 }
6755
6756 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6757 {
6758 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6759 AssertRC(rc);
6760 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6761 }
6762 }
6763
6764 /*
6765 * Guest/host EFER MSR.
6766 */
6767 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6768 {
6769 /* Whether we are using the VMCS to swap the EFER MSR must have been
6770 determined earlier while exporting VM-entry/VM-exit controls. */
6771 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6772 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6773
6774 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6775 {
6776 /*
6777 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6778 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6779 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6780 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6781 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6782 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6783 * during VM-entry.
6784 */
6785 uint64_t uGuestEferMsr = pCtx->msrEFER;
6786 if (!pVM->hmr0.s.vmx.fUnrestrictedGuest)
6787 {
6788 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6789 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6790 else
6791 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6792 }
6793
6794 /*
6795 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6796 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6797 */
6798 if (g_fHmVmxSupportsVmcsEfer)
6799 {
6800 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6801 AssertRC(rc);
6802 }
6803 else
6804 {
6805 /*
6806 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6807 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6808 */
6809 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6810 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6811 AssertRCReturn(rc, rc);
6812 }
6813
6814 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6815 }
6816 else if (!g_fHmVmxSupportsVmcsEfer)
6817 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6818
6819 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6820 }
6821
6822 /*
6823 * Other MSRs.
6824 */
6825 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6826 {
6827 /* Speculation Control (R/W). */
6828 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6829 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6830 {
6831 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6832 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6833 AssertRCReturn(rc, rc);
6834 }
6835
6836 /* Last Branch Record. */
6837 if (pVM->hmr0.s.vmx.fLbr)
6838 {
6839 PVMXVMCSINFOSHARED const pVmcsInfoShared = pVmxTransient->pVmcsInfo->pShared;
6840 uint32_t const idFromIpMsrStart = pVM->hmr0.s.vmx.idLbrFromIpMsrFirst;
6841 uint32_t const idToIpMsrStart = pVM->hmr0.s.vmx.idLbrToIpMsrFirst;
6842 uint32_t const cLbrStack = pVM->hmr0.s.vmx.idLbrFromIpMsrLast - pVM->hmr0.s.vmx.idLbrFromIpMsrFirst + 1;
6843 Assert(cLbrStack <= 32);
6844 for (uint32_t i = 0; i < cLbrStack; i++)
6845 {
6846 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idFromIpMsrStart + i,
6847 pVmcsInfoShared->au64LbrFromIpMsr[i],
6848 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6849 AssertRCReturn(rc, rc);
6850
6851 /* Some CPUs don't have a Branch-To-IP MSR (P4 and related Xeons). */
6852 if (idToIpMsrStart != 0)
6853 {
6854 rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idToIpMsrStart + i,
6855 pVmcsInfoShared->au64LbrToIpMsr[i],
6856 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6857 AssertRCReturn(rc, rc);
6858 }
6859 }
6860
6861 /* Add LBR top-of-stack MSR (which contains the index to the most recent record). */
6862 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, pVM->hmr0.s.vmx.idLbrTosMsr,
6863 pVmcsInfoShared->u64LbrTosMsr, false /* fSetReadWrite */,
6864 false /* fUpdateHostMsr */);
6865 AssertRCReturn(rc, rc);
6866 }
6867
6868 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6869 }
6870
6871 return VINF_SUCCESS;
6872}
6873
6874
6875/**
6876 * Wrapper for running the guest code in VT-x.
6877 *
6878 * @returns VBox status code, no informational status codes.
6879 * @param pVCpu The cross context virtual CPU structure.
6880 * @param pVmxTransient The VMX-transient structure.
6881 *
6882 * @remarks No-long-jump zone!!!
6883 */
6884DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6885{
6886 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6887 pVCpu->cpum.GstCtx.fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6888
6889 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6890 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6891#ifdef VBOX_WITH_STATISTICS
6892 if (fResumeVM)
6893 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxVmResume);
6894 else
6895 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxVmLaunch);
6896#endif
6897 int rc = pVCpu->hmr0.s.vmx.pfnStartVm(pVmcsInfo, pVCpu, fResumeVM);
6898 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6899 return rc;
6900}
6901
6902
6903/**
6904 * Reports world-switch error and dumps some useful debug info.
6905 *
6906 * @param pVCpu The cross context virtual CPU structure.
6907 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6908 * @param pVmxTransient The VMX-transient structure (only
6909 * exitReason updated).
6910 */
6911static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6912{
6913 Assert(pVCpu);
6914 Assert(pVmxTransient);
6915 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6916
6917 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6918 switch (rcVMRun)
6919 {
6920 case VERR_VMX_INVALID_VMXON_PTR:
6921 AssertFailed();
6922 break;
6923 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6924 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6925 {
6926 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6927 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6928 AssertRC(rc);
6929 hmR0VmxReadExitQualVmcs(pVmxTransient);
6930
6931 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hmr0.s.idEnteredCpu;
6932 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6933 Cannot do it here as we may have been long preempted. */
6934
6935#ifdef VBOX_STRICT
6936 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6937 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6938 pVmxTransient->uExitReason));
6939 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6940 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6941 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6942 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6943 else
6944 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6945 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6946 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6947
6948 static struct
6949 {
6950 /** Name of the field to log. */
6951 const char *pszName;
6952 /** The VMCS field. */
6953 uint32_t uVmcsField;
6954 /** Whether host support of this field needs to be checked. */
6955 bool fCheckSupport;
6956 } const s_aVmcsFields[] =
6957 {
6958 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6959 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6960 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6961 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6962 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6963 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6964 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6965 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6966 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6967 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6968 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6969 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6970 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6971 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6972 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6973 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6974 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6975 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6976 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6977 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6978 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6979 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6980 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6981 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6982 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6983 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6984 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6985 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6986 /* The order of selector fields below are fixed! */
6987 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6988 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6989 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6990 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6991 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6992 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6993 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6994 /* End of ordered selector fields. */
6995 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6996 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6997 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6998 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6999 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
7000 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
7001 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
7002 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
7003 };
7004
7005 RTGDTR HostGdtr;
7006 ASMGetGDTR(&HostGdtr);
7007
7008 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
7009 for (uint32_t i = 0; i < cVmcsFields; i++)
7010 {
7011 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
7012
7013 bool fSupported;
7014 if (!s_aVmcsFields[i].fCheckSupport)
7015 fSupported = true;
7016 else
7017 {
7018 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7019 switch (uVmcsField)
7020 {
7021 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hmr0.s.fNestedPaging; break;
7022 case VMX_VMCS16_VPID: fSupported = pVM->hmr0.s.vmx.fVpid; break;
7023 case VMX_VMCS32_CTRL_PROC_EXEC2:
7024 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
7025 break;
7026 default:
7027 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
7028 }
7029 }
7030
7031 if (fSupported)
7032 {
7033 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
7034 switch (uWidth)
7035 {
7036 case VMX_VMCSFIELD_WIDTH_16BIT:
7037 {
7038 uint16_t u16Val;
7039 rc = VMXReadVmcs16(uVmcsField, &u16Val);
7040 AssertRC(rc);
7041 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
7042
7043 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
7044 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
7045 {
7046 if (u16Val < HostGdtr.cbGdt)
7047 {
7048 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
7049 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
7050 "Host FS", "Host GS", "Host TR" };
7051 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
7052 Assert(idxSel < RT_ELEMENTS(s_apszSel));
7053 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
7054 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
7055 }
7056 else
7057 Log4((" Selector value exceeds GDT limit!\n"));
7058 }
7059 break;
7060 }
7061
7062 case VMX_VMCSFIELD_WIDTH_32BIT:
7063 {
7064 uint32_t u32Val;
7065 rc = VMXReadVmcs32(uVmcsField, &u32Val);
7066 AssertRC(rc);
7067 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
7068 break;
7069 }
7070
7071 case VMX_VMCSFIELD_WIDTH_64BIT:
7072 case VMX_VMCSFIELD_WIDTH_NATURAL:
7073 {
7074 uint64_t u64Val;
7075 rc = VMXReadVmcs64(uVmcsField, &u64Val);
7076 AssertRC(rc);
7077 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
7078 break;
7079 }
7080 }
7081 }
7082 }
7083
7084 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
7085 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
7086 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
7087 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
7088 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
7089 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
7090#endif /* VBOX_STRICT */
7091 break;
7092 }
7093
7094 default:
7095 /* Impossible */
7096 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
7097 break;
7098 }
7099}
7100
7101
7102/**
7103 * Sets up the usage of TSC-offsetting and updates the VMCS.
7104 *
7105 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
7106 * VMX-preemption timer.
7107 *
7108 * @returns VBox status code.
7109 * @param pVCpu The cross context virtual CPU structure.
7110 * @param pVmxTransient The VMX-transient structure.
7111 *
7112 * @remarks No-long-jump zone!!!
7113 */
7114static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
7115{
7116 bool fOffsettedTsc;
7117 bool fParavirtTsc;
7118 uint64_t uTscOffset;
7119 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7120 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7121
7122 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
7123 {
7124 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
7125
7126 /* Make sure the returned values have sane upper and lower boundaries. */
7127 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7128 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
7129 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
7130 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7131
7132 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7133 * preemption timers here. We probably need to clamp the preemption timer,
7134 * after converting the timer value to the host. */
7135 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7136 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7137 AssertRC(rc);
7138 }
7139 else
7140 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7141
7142 if (fParavirtTsc)
7143 {
7144 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7145 information before every VM-entry, hence disable it for performance sake. */
7146#if 0
7147 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7148 AssertRC(rc);
7149#endif
7150 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7151 }
7152
7153 if ( fOffsettedTsc
7154 && RT_LIKELY(!pVCpu->hmr0.s.fDebugWantRdTscExit))
7155 {
7156 if (pVmxTransient->fIsNestedGuest)
7157 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7158 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
7159 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7160 }
7161 else
7162 {
7163 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7164 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7165 }
7166}
7167
7168
7169/**
7170 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7171 * VM-exit interruption info type.
7172 *
7173 * @returns The IEM exception flags.
7174 * @param uVector The event vector.
7175 * @param uVmxEventType The VMX event type.
7176 *
7177 * @remarks This function currently only constructs flags required for
7178 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7179 * and CR2 aspects of an exception are not included).
7180 */
7181static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7182{
7183 uint32_t fIemXcptFlags;
7184 switch (uVmxEventType)
7185 {
7186 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7187 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7188 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7189 break;
7190
7191 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7192 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7193 break;
7194
7195 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7196 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7197 break;
7198
7199 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7200 {
7201 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7202 if (uVector == X86_XCPT_BP)
7203 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7204 else if (uVector == X86_XCPT_OF)
7205 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7206 else
7207 {
7208 fIemXcptFlags = 0;
7209 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7210 }
7211 break;
7212 }
7213
7214 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7215 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7216 break;
7217
7218 default:
7219 fIemXcptFlags = 0;
7220 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7221 break;
7222 }
7223 return fIemXcptFlags;
7224}
7225
7226
7227/**
7228 * Sets an event as a pending event to be injected into the guest.
7229 *
7230 * @param pVCpu The cross context virtual CPU structure.
7231 * @param u32IntInfo The VM-entry interruption-information field.
7232 * @param cbInstr The VM-entry instruction length in bytes (for
7233 * software interrupts, exceptions and privileged
7234 * software exceptions).
7235 * @param u32ErrCode The VM-entry exception error code.
7236 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7237 * page-fault.
7238 */
7239DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7240 RTGCUINTPTR GCPtrFaultAddress)
7241{
7242 Assert(!pVCpu->hm.s.Event.fPending);
7243 pVCpu->hm.s.Event.fPending = true;
7244 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7245 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7246 pVCpu->hm.s.Event.cbInstr = cbInstr;
7247 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7248}
7249
7250
7251/**
7252 * Sets an external interrupt as pending-for-injection into the VM.
7253 *
7254 * @param pVCpu The cross context virtual CPU structure.
7255 * @param u8Interrupt The external interrupt vector.
7256 */
7257DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
7258{
7259 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7260 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7261 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7262 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7263 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7264}
7265
7266
7267/**
7268 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7269 *
7270 * @param pVCpu The cross context virtual CPU structure.
7271 */
7272DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
7273{
7274 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7275 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7276 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7277 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7278 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7279}
7280
7281
7282/**
7283 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7284 *
7285 * @param pVCpu The cross context virtual CPU structure.
7286 */
7287DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
7288{
7289 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7290 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7291 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7292 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7293 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7294}
7295
7296
7297/**
7298 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7299 *
7300 * @param pVCpu The cross context virtual CPU structure.
7301 */
7302DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
7303{
7304 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7305 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7306 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7307 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7308 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7309}
7310
7311
7312/**
7313 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7314 *
7315 * @param pVCpu The cross context virtual CPU structure.
7316 */
7317DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
7318{
7319 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7320 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7321 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7322 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7323 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7324}
7325
7326
7327#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7328/**
7329 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7330 *
7331 * @param pVCpu The cross context virtual CPU structure.
7332 * @param u32ErrCode The error code for the general-protection exception.
7333 */
7334DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7335{
7336 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7337 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7338 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7339 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7340 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7341}
7342
7343
7344/**
7345 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7346 *
7347 * @param pVCpu The cross context virtual CPU structure.
7348 * @param u32ErrCode The error code for the stack exception.
7349 */
7350DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7351{
7352 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7353 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7354 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7355 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7356 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7357}
7358#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7359
7360
7361/**
7362 * Fixes up attributes for the specified segment register.
7363 *
7364 * @param pVCpu The cross context virtual CPU structure.
7365 * @param pSelReg The segment register that needs fixing.
7366 * @param pszRegName The register name (for logging and assertions).
7367 */
7368static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, const char *pszRegName)
7369{
7370 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7371
7372 /*
7373 * If VT-x marks the segment as unusable, most other bits remain undefined:
7374 * - For CS the L, D and G bits have meaning.
7375 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7376 * - For the remaining data segments no bits are defined.
7377 *
7378 * The present bit and the unusable bit has been observed to be set at the
7379 * same time (the selector was supposed to be invalid as we started executing
7380 * a V8086 interrupt in ring-0).
7381 *
7382 * What should be important for the rest of the VBox code, is that the P bit is
7383 * cleared. Some of the other VBox code recognizes the unusable bit, but
7384 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7385 * safe side here, we'll strip off P and other bits we don't care about. If
7386 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7387 *
7388 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7389 */
7390#ifdef VBOX_STRICT
7391 uint32_t const uAttr = pSelReg->Attr.u;
7392#endif
7393
7394 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7395 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7396 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7397
7398#ifdef VBOX_STRICT
7399 VMMRZCallRing3Disable(pVCpu);
7400 Log4Func(("Unusable %s: sel=%#x attr=%#x -> %#x\n", pszRegName, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7401# ifdef DEBUG_bird
7402 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7403 ("%s: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7404 pszRegName, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7405# endif
7406 VMMRZCallRing3Enable(pVCpu);
7407 NOREF(uAttr);
7408#endif
7409 RT_NOREF2(pVCpu, pszRegName);
7410}
7411
7412
7413/**
7414 * Imports a guest segment register from the current VMCS into the guest-CPU
7415 * context.
7416 *
7417 * @param pVCpu The cross context virtual CPU structure.
7418 * @param iSegReg The segment register number (X86_SREG_XXX).
7419 *
7420 * @remarks Called with interrupts and/or preemption disabled.
7421 */
7422static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint32_t iSegReg)
7423{
7424 Assert(iSegReg < X86_SREG_COUNT);
7425 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]);
7426 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]);
7427 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
7428 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]);
7429
7430 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7431
7432 uint16_t u16Sel;
7433 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), &u16Sel); AssertRC(rc);
7434 pSelReg->Sel = u16Sel;
7435 pSelReg->ValidSel = u16Sel;
7436
7437 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), &pSelReg->u32Limit); AssertRC(rc);
7438 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), &pSelReg->u64Base); AssertRC(rc);
7439
7440 uint32_t u32Attr;
7441 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), &u32Attr); AssertRC(rc);
7442 pSelReg->Attr.u = u32Attr;
7443 if (u32Attr & X86DESCATTR_UNUSABLE)
7444 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, "ES\0CS\0SS\0DS\0FS\0GS" + iSegReg * 3);
7445
7446 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7447}
7448
7449
7450/**
7451 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7452 *
7453 * @param pVCpu The cross context virtual CPU structure.
7454 *
7455 * @remarks Called with interrupts and/or preemption disabled.
7456 */
7457static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7458{
7459 uint16_t u16Sel;
7460 uint64_t u64Base;
7461 uint32_t u32Limit, u32Attr;
7462 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7463 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7464 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7465 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7466
7467 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7468 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7469 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7470 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7471 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7472 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7473 if (u32Attr & X86DESCATTR_UNUSABLE)
7474 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, "LDTR");
7475}
7476
7477
7478/**
7479 * Imports the guest TR from the current VMCS into the guest-CPU context.
7480 *
7481 * @param pVCpu The cross context virtual CPU structure.
7482 *
7483 * @remarks Called with interrupts and/or preemption disabled.
7484 */
7485static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7486{
7487 uint16_t u16Sel;
7488 uint64_t u64Base;
7489 uint32_t u32Limit, u32Attr;
7490 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7491 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7492 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7493 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7494
7495 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7496 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7497 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7498 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7499 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7500 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7501 /* TR is the only selector that can never be unusable. */
7502 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7503}
7504
7505
7506/**
7507 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7508 *
7509 * @param pVCpu The cross context virtual CPU structure.
7510 *
7511 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7512 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7513 * instead!!!
7514 */
7515static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7516{
7517 uint64_t u64Val;
7518 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7519 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7520 {
7521 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7522 AssertRC(rc);
7523
7524 pCtx->rip = u64Val;
7525 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7526 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7527 }
7528}
7529
7530
7531/**
7532 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7533 *
7534 * @param pVCpu The cross context virtual CPU structure.
7535 * @param pVmcsInfo The VMCS info. object.
7536 *
7537 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7538 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7539 * instead!!!
7540 */
7541static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7542{
7543 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7544 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7545 {
7546 uint64_t u64Val;
7547 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7548 AssertRC(rc);
7549
7550 pCtx->rflags.u64 = u64Val;
7551 PCVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7552 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
7553 {
7554 pCtx->eflags.Bits.u1VM = 0;
7555 pCtx->eflags.Bits.u2IOPL = pVmcsInfoShared->RealMode.Eflags.Bits.u2IOPL;
7556 }
7557 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7558 }
7559}
7560
7561
7562/**
7563 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7564 * context.
7565 *
7566 * @param pVCpu The cross context virtual CPU structure.
7567 * @param pVmcsInfo The VMCS info. object.
7568 *
7569 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7570 * do not log!
7571 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7572 * instead!!!
7573 */
7574static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7575{
7576 uint32_t u32Val;
7577 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7578 if (!u32Val)
7579 {
7580 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7581 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7582 CPUMSetGuestNmiBlocking(pVCpu, false);
7583 }
7584 else
7585 {
7586 /*
7587 * We must import RIP here to set our EM interrupt-inhibited state.
7588 * We also import RFLAGS as our code that evaluates pending interrupts
7589 * before VM-entry requires it.
7590 */
7591 hmR0VmxImportGuestRip(pVCpu);
7592 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7593
7594 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7595 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7596 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7597 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7598
7599 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7600 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7601 }
7602}
7603
7604
7605/**
7606 * Worker for VMXR0ImportStateOnDemand.
7607 *
7608 * @returns VBox status code.
7609 * @param pVCpu The cross context virtual CPU structure.
7610 * @param pVmcsInfo The VMCS info. object.
7611 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7612 */
7613static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7614{
7615 int rc = VINF_SUCCESS;
7616 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7617 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7618 uint32_t u32Val;
7619
7620 /*
7621 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7622 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7623 * neither are other host platforms.
7624 *
7625 * Committing this temporarily as it prevents BSOD.
7626 *
7627 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7628 */
7629#ifdef RT_OS_WINDOWS
7630 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7631 return VERR_HM_IPE_1;
7632#endif
7633
7634 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7635
7636 /*
7637 * We disable interrupts to make the updating of the state and in particular
7638 * the fExtrn modification atomic wrt to preemption hooks.
7639 */
7640 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7641
7642 fWhat &= pCtx->fExtrn;
7643 if (fWhat)
7644 {
7645 do
7646 {
7647 if (fWhat & CPUMCTX_EXTRN_RIP)
7648 hmR0VmxImportGuestRip(pVCpu);
7649
7650 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7651 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7652
7653 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7654 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7655
7656 if (fWhat & CPUMCTX_EXTRN_RSP)
7657 {
7658 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7659 AssertRC(rc);
7660 }
7661
7662 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7663 {
7664 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7665 bool const fRealOnV86Active = pVmcsInfoShared->RealMode.fRealOnV86Active;
7666 if (fWhat & CPUMCTX_EXTRN_CS)
7667 {
7668 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7669 hmR0VmxImportGuestRip(pVCpu);
7670 if (fRealOnV86Active)
7671 pCtx->cs.Attr.u = pVmcsInfoShared->RealMode.AttrCS.u;
7672 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7673 }
7674 if (fWhat & CPUMCTX_EXTRN_SS)
7675 {
7676 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7677 if (fRealOnV86Active)
7678 pCtx->ss.Attr.u = pVmcsInfoShared->RealMode.AttrSS.u;
7679 }
7680 if (fWhat & CPUMCTX_EXTRN_DS)
7681 {
7682 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7683 if (fRealOnV86Active)
7684 pCtx->ds.Attr.u = pVmcsInfoShared->RealMode.AttrDS.u;
7685 }
7686 if (fWhat & CPUMCTX_EXTRN_ES)
7687 {
7688 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7689 if (fRealOnV86Active)
7690 pCtx->es.Attr.u = pVmcsInfoShared->RealMode.AttrES.u;
7691 }
7692 if (fWhat & CPUMCTX_EXTRN_FS)
7693 {
7694 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7695 if (fRealOnV86Active)
7696 pCtx->fs.Attr.u = pVmcsInfoShared->RealMode.AttrFS.u;
7697 }
7698 if (fWhat & CPUMCTX_EXTRN_GS)
7699 {
7700 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7701 if (fRealOnV86Active)
7702 pCtx->gs.Attr.u = pVmcsInfoShared->RealMode.AttrGS.u;
7703 }
7704 }
7705
7706 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7707 {
7708 if (fWhat & CPUMCTX_EXTRN_LDTR)
7709 hmR0VmxImportGuestLdtr(pVCpu);
7710
7711 if (fWhat & CPUMCTX_EXTRN_GDTR)
7712 {
7713 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7714 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7715 pCtx->gdtr.cbGdt = u32Val;
7716 }
7717
7718 /* Guest IDTR. */
7719 if (fWhat & CPUMCTX_EXTRN_IDTR)
7720 {
7721 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7722 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7723 pCtx->idtr.cbIdt = u32Val;
7724 }
7725
7726 /* Guest TR. */
7727 if (fWhat & CPUMCTX_EXTRN_TR)
7728 {
7729 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7730 don't need to import that one. */
7731 if (!pVmcsInfo->pShared->RealMode.fRealOnV86Active)
7732 hmR0VmxImportGuestTr(pVCpu);
7733 }
7734 }
7735
7736 if (fWhat & CPUMCTX_EXTRN_DR7)
7737 {
7738 if (!pVCpu->hmr0.s.fUsingHyperDR7)
7739 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7740 }
7741
7742 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7743 {
7744 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7745 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7746 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7747 pCtx->SysEnter.cs = u32Val;
7748 }
7749
7750 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7751 {
7752 if ( pVM->hmr0.s.fAllow64BitGuests
7753 && (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7754 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7755 }
7756
7757 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7758 {
7759 if ( pVM->hmr0.s.fAllow64BitGuests
7760 && (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7761 {
7762 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7763 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7764 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7765 }
7766 }
7767
7768 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7769 {
7770 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7771 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7772 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7773 Assert(pMsrs);
7774 Assert(cMsrs <= VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc));
7775 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7776 for (uint32_t i = 0; i < cMsrs; i++)
7777 {
7778 uint32_t const idMsr = pMsrs[i].u32Msr;
7779 switch (idMsr)
7780 {
7781 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7782 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7783 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7784 default:
7785 {
7786 uint32_t idxLbrMsr;
7787 if (pVM->hmr0.s.vmx.fLbr)
7788 {
7789 if (hmR0VmxIsLbrBranchFromMsr(pVM, idMsr, &idxLbrMsr))
7790 {
7791 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfoShared->au64LbrFromIpMsr));
7792 pVmcsInfoShared->au64LbrFromIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7793 break;
7794 }
7795 if (hmR0VmxIsLbrBranchToMsr(pVM, idMsr, &idxLbrMsr))
7796 {
7797 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfoShared->au64LbrFromIpMsr));
7798 pVmcsInfoShared->au64LbrToIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7799 break;
7800 }
7801 if (idMsr == pVM->hmr0.s.vmx.idLbrTosMsr)
7802 {
7803 pVmcsInfoShared->u64LbrTosMsr = pMsrs[i].u64Value;
7804 break;
7805 }
7806 /* Fallthru (no break) */
7807 }
7808 pCtx->fExtrn = 0;
7809 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7810 ASMSetFlags(fEFlags);
7811 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7812 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7813 }
7814 }
7815 }
7816 }
7817
7818 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7819 {
7820 if (fWhat & CPUMCTX_EXTRN_CR0)
7821 {
7822 uint64_t u64Cr0;
7823 uint64_t u64Shadow;
7824 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7825 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7826#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7827 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7828 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7829#else
7830 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7831 {
7832 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7833 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7834 }
7835 else
7836 {
7837 /*
7838 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7839 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7840 * re-construct CR0. See @bugref{9180#c95} for details.
7841 */
7842 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
7843 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7844 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7845 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7846 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7847 }
7848#endif
7849 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7850 CPUMSetGuestCR0(pVCpu, u64Cr0);
7851 VMMRZCallRing3Enable(pVCpu);
7852 }
7853
7854 if (fWhat & CPUMCTX_EXTRN_CR4)
7855 {
7856 uint64_t u64Cr4;
7857 uint64_t u64Shadow;
7858 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7859 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7860#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7861 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7862 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7863#else
7864 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7865 {
7866 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7867 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7868 }
7869 else
7870 {
7871 /*
7872 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7873 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7874 * re-construct CR4. See @bugref{9180#c95} for details.
7875 */
7876 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
7877 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7878 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7879 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7880 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7881 }
7882#endif
7883 pCtx->cr4 = u64Cr4;
7884 }
7885
7886 if (fWhat & CPUMCTX_EXTRN_CR3)
7887 {
7888 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7889 if ( pVM->hmr0.s.vmx.fUnrestrictedGuest
7890 || ( pVM->hmr0.s.fNestedPaging
7891 && CPUMIsGuestPagingEnabledEx(pCtx)))
7892 {
7893 uint64_t u64Cr3;
7894 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7895 if (pCtx->cr3 != u64Cr3)
7896 {
7897 pCtx->cr3 = u64Cr3;
7898 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7899 }
7900
7901 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7902 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7903 if (CPUMIsGuestInPAEModeEx(pCtx))
7904 {
7905 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7906 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7907 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7908 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7909 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7910 }
7911 }
7912 }
7913 }
7914
7915#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7916 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7917 {
7918 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7919 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7920 {
7921 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7922 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7923 if (RT_SUCCESS(rc))
7924 { /* likely */ }
7925 else
7926 break;
7927 }
7928 }
7929#endif
7930 } while (0);
7931
7932 if (RT_SUCCESS(rc))
7933 {
7934 /* Update fExtrn. */
7935 pCtx->fExtrn &= ~fWhat;
7936
7937 /* If everything has been imported, clear the HM keeper bit. */
7938 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7939 {
7940 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7941 Assert(!pCtx->fExtrn);
7942 }
7943 }
7944 }
7945 else
7946 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7947
7948 /*
7949 * Restore interrupts.
7950 */
7951 ASMSetFlags(fEFlags);
7952
7953 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7954
7955 if (RT_SUCCESS(rc))
7956 { /* likely */ }
7957 else
7958 return rc;
7959
7960 /*
7961 * Honor any pending CR3 updates.
7962 *
7963 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7964 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7965 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7966 *
7967 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7968 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7969 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7970 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7971 *
7972 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7973 */
7974 if (VMMRZCallRing3IsEnabled(pVCpu))
7975 {
7976 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7977 {
7978 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7979 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7980 }
7981
7982 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7983 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7984
7985 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7986 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7987 }
7988
7989 return VINF_SUCCESS;
7990}
7991
7992
7993/**
7994 * Saves the guest state from the VMCS into the guest-CPU context.
7995 *
7996 * @returns VBox status code.
7997 * @param pVCpu The cross context virtual CPU structure.
7998 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7999 */
8000VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
8001{
8002 AssertPtr(pVCpu);
8003 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8004 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
8005}
8006
8007
8008/**
8009 * Check per-VM and per-VCPU force flag actions that require us to go back to
8010 * ring-3 for one reason or another.
8011 *
8012 * @returns Strict VBox status code (i.e. informational status codes too)
8013 * @retval VINF_SUCCESS if we don't have any actions that require going back to
8014 * ring-3.
8015 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
8016 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
8017 * interrupts)
8018 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
8019 * all EMTs to be in ring-3.
8020 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
8021 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
8022 * to the EM loop.
8023 *
8024 * @param pVCpu The cross context virtual CPU structure.
8025 * @param pVmxTransient The VMX-transient structure.
8026 * @param fStepping Whether we are single-stepping the guest using the
8027 * hypervisor debugger.
8028 *
8029 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
8030 * is no longer in VMX non-root mode.
8031 */
8032static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, bool fStepping)
8033{
8034 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8035
8036 /*
8037 * Update pending interrupts into the APIC's IRR.
8038 */
8039 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
8040 APICUpdatePendingInterrupts(pVCpu);
8041
8042 /*
8043 * Anything pending? Should be more likely than not if we're doing a good job.
8044 */
8045 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8046 if ( !fStepping
8047 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
8048 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
8049 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
8050 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
8051 return VINF_SUCCESS;
8052
8053 /* Pending PGM C3 sync. */
8054 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
8055 {
8056 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8057 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
8058 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
8059 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
8060 if (rcStrict != VINF_SUCCESS)
8061 {
8062 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
8063 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
8064 return rcStrict;
8065 }
8066 }
8067
8068 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
8069 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
8070 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
8071 {
8072 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
8073 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
8074 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
8075 return rc;
8076 }
8077
8078 /* Pending VM request packets, such as hardware interrupts. */
8079 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
8080 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
8081 {
8082 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
8083 Log4Func(("Pending VM request forcing us back to ring-3\n"));
8084 return VINF_EM_PENDING_REQUEST;
8085 }
8086
8087 /* Pending PGM pool flushes. */
8088 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
8089 {
8090 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
8091 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
8092 return VINF_PGM_POOL_FLUSH_PENDING;
8093 }
8094
8095 /* Pending DMA requests. */
8096 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
8097 {
8098 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
8099 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
8100 return VINF_EM_RAW_TO_R3;
8101 }
8102
8103#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8104 /*
8105 * Pending nested-guest events.
8106 *
8107 * Please note the priority of these events are specified and important.
8108 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
8109 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
8110 */
8111 if (pVmxTransient->fIsNestedGuest)
8112 {
8113 /* Pending nested-guest APIC-write. */
8114 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
8115 {
8116 Log4Func(("Pending nested-guest APIC-write\n"));
8117 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
8118 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8119 return rcStrict;
8120 }
8121
8122 /* Pending nested-guest monitor-trap flag (MTF). */
8123 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
8124 {
8125 Log4Func(("Pending nested-guest MTF\n"));
8126 VBOXSTRICTRC rcStrict = IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */);
8127 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8128 return rcStrict;
8129 }
8130
8131 /* Pending nested-guest VMX-preemption timer expired. */
8132 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
8133 {
8134 Log4Func(("Pending nested-guest MTF\n"));
8135 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitPreemptTimer(pVCpu);
8136 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8137 return rcStrict;
8138 }
8139 }
8140#else
8141 NOREF(pVmxTransient);
8142#endif
8143
8144 return VINF_SUCCESS;
8145}
8146
8147
8148/**
8149 * Converts any TRPM trap into a pending HM event. This is typically used when
8150 * entering from ring-3 (not longjmp returns).
8151 *
8152 * @param pVCpu The cross context virtual CPU structure.
8153 */
8154static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
8155{
8156 Assert(TRPMHasTrap(pVCpu));
8157 Assert(!pVCpu->hm.s.Event.fPending);
8158
8159 uint8_t uVector;
8160 TRPMEVENT enmTrpmEvent;
8161 uint32_t uErrCode;
8162 RTGCUINTPTR GCPtrFaultAddress;
8163 uint8_t cbInstr;
8164 bool fIcebp;
8165
8166 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
8167 AssertRC(rc);
8168
8169 uint32_t u32IntInfo;
8170 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8171 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
8172
8173 rc = TRPMResetTrap(pVCpu);
8174 AssertRC(rc);
8175 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8176 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8177
8178 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8179}
8180
8181
8182/**
8183 * Converts the pending HM event into a TRPM trap.
8184 *
8185 * @param pVCpu The cross context virtual CPU structure.
8186 */
8187static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
8188{
8189 Assert(pVCpu->hm.s.Event.fPending);
8190
8191 /* If a trap was already pending, we did something wrong! */
8192 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8193
8194 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8195 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8196 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8197
8198 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8199
8200 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8201 AssertRC(rc);
8202
8203 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8204 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8205
8206 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8207 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8208 else
8209 {
8210 uint8_t const uVectorType = VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo);
8211 switch (uVectorType)
8212 {
8213 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
8214 TRPMSetTrapDueToIcebp(pVCpu);
8215 RT_FALL_THRU();
8216 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
8217 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
8218 {
8219 AssertMsg( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
8220 || ( uVector == X86_XCPT_BP /* INT3 */
8221 || uVector == X86_XCPT_OF /* INTO */
8222 || uVector == X86_XCPT_DB /* INT1 (ICEBP) */),
8223 ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uVectorType));
8224 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8225 break;
8226 }
8227 }
8228 }
8229
8230 /* We're now done converting the pending event. */
8231 pVCpu->hm.s.Event.fPending = false;
8232}
8233
8234
8235/**
8236 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8237 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8238 *
8239 * @param pVmcsInfo The VMCS info. object.
8240 */
8241static void hmR0VmxSetIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8242{
8243 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8244 {
8245 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8246 {
8247 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8248 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8249 AssertRC(rc);
8250 }
8251 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8252}
8253
8254
8255/**
8256 * Clears the interrupt-window exiting control in the VMCS.
8257 *
8258 * @param pVmcsInfo The VMCS info. object.
8259 */
8260DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8261{
8262 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8263 {
8264 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8265 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8266 AssertRC(rc);
8267 }
8268}
8269
8270
8271/**
8272 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8273 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8274 *
8275 * @param pVmcsInfo The VMCS info. object.
8276 */
8277static void hmR0VmxSetNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8278{
8279 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8280 {
8281 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8282 {
8283 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8284 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8285 AssertRC(rc);
8286 Log4Func(("Setup NMI-window exiting\n"));
8287 }
8288 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8289}
8290
8291
8292/**
8293 * Clears the NMI-window exiting control in the VMCS.
8294 *
8295 * @param pVmcsInfo The VMCS info. object.
8296 */
8297DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8298{
8299 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8300 {
8301 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8302 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8303 AssertRC(rc);
8304 }
8305}
8306
8307
8308/**
8309 * Does the necessary state syncing before returning to ring-3 for any reason
8310 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8311 *
8312 * @returns VBox status code.
8313 * @param pVCpu The cross context virtual CPU structure.
8314 * @param fImportState Whether to import the guest state from the VMCS back
8315 * to the guest-CPU context.
8316 *
8317 * @remarks No-long-jmp zone!!!
8318 */
8319static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
8320{
8321 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8322 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8323
8324 RTCPUID const idCpu = RTMpCpuId();
8325 Log4Func(("HostCpuId=%u\n", idCpu));
8326
8327 /*
8328 * !!! IMPORTANT !!!
8329 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
8330 */
8331
8332 /* Save the guest state if necessary. */
8333 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8334 if (fImportState)
8335 {
8336 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8337 AssertRCReturn(rc, rc);
8338 }
8339
8340 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8341 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8342 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8343
8344 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8345#ifdef VBOX_STRICT
8346 if (CPUMIsHyperDebugStateActive(pVCpu))
8347 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8348#endif
8349 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8350 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
8351 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
8352
8353 /* Restore host-state bits that VT-x only restores partially. */
8354 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
8355 {
8356 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hmr0.s.vmx.fRestoreHostFlags, idCpu));
8357 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
8358 }
8359 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
8360
8361 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8362 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8363 {
8364 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8365 if (!fImportState)
8366 {
8367 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8368 AssertRCReturn(rc, rc);
8369 }
8370 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8371 Assert(!pVCpu->hmr0.s.vmx.fLazyMsrs);
8372 }
8373 else
8374 pVCpu->hmr0.s.vmx.fLazyMsrs = 0;
8375
8376 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8377 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
8378
8379 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8380 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8381 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8382 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8383 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8384 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8385 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8386 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8387 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8388 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8389
8390 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8391
8392 /** @todo This partially defeats the purpose of having preemption hooks.
8393 * The problem is, deregistering the hooks should be moved to a place that
8394 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8395 * context.
8396 */
8397 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8398 AssertRCReturn(rc, rc);
8399
8400#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8401 /*
8402 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8403 * clear a shadow VMCS before allowing that VMCS to become active on another
8404 * logical processor. We may or may not be importing guest state which clears
8405 * it, so cover for it here.
8406 *
8407 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8408 */
8409 if ( pVmcsInfo->pvShadowVmcs
8410 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8411 {
8412 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8413 AssertRCReturn(rc, rc);
8414 }
8415
8416 /*
8417 * Flag that we need to re-export the host state if we switch to this VMCS before
8418 * executing guest or nested-guest code.
8419 */
8420 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8421#endif
8422
8423 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8424 NOREF(idCpu);
8425 return VINF_SUCCESS;
8426}
8427
8428
8429/**
8430 * Leaves the VT-x session.
8431 *
8432 * @returns VBox status code.
8433 * @param pVCpu The cross context virtual CPU structure.
8434 *
8435 * @remarks No-long-jmp zone!!!
8436 */
8437static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8438{
8439 HM_DISABLE_PREEMPT(pVCpu);
8440 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8441 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8442 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8443
8444 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8445 and done this from the VMXR0ThreadCtxCallback(). */
8446 if (!pVCpu->hmr0.s.fLeaveDone)
8447 {
8448 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8449 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8450 pVCpu->hmr0.s.fLeaveDone = true;
8451 }
8452 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8453
8454 /*
8455 * !!! IMPORTANT !!!
8456 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8457 */
8458
8459 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8460 /** @todo Deregistering here means we need to VMCLEAR always
8461 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8462 * for calling VMMR0ThreadCtxHookDisable here! */
8463 VMMR0ThreadCtxHookDisable(pVCpu);
8464
8465 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8466 int rc = HMR0LeaveCpu(pVCpu);
8467 HM_RESTORE_PREEMPT();
8468 return rc;
8469}
8470
8471
8472/**
8473 * Does the necessary state syncing before doing a longjmp to ring-3.
8474 *
8475 * @returns VBox status code.
8476 * @param pVCpu The cross context virtual CPU structure.
8477 *
8478 * @remarks No-long-jmp zone!!!
8479 */
8480DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8481{
8482 return hmR0VmxLeaveSession(pVCpu);
8483}
8484
8485
8486/**
8487 * Take necessary actions before going back to ring-3.
8488 *
8489 * An action requires us to go back to ring-3. This function does the necessary
8490 * steps before we can safely return to ring-3. This is not the same as longjmps
8491 * to ring-3, this is voluntary and prepares the guest so it may continue
8492 * executing outside HM (recompiler/IEM).
8493 *
8494 * @returns VBox status code.
8495 * @param pVCpu The cross context virtual CPU structure.
8496 * @param rcExit The reason for exiting to ring-3. Can be
8497 * VINF_VMM_UNKNOWN_RING3_CALL.
8498 */
8499static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8500{
8501 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8502
8503 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8504 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8505 {
8506 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8507 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8508 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hmr0.s.idEnteredCpu;
8509 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8510 }
8511
8512 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8513 VMMRZCallRing3Disable(pVCpu);
8514 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8515
8516 /*
8517 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8518 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8519 *
8520 * This is because execution may continue from ring-3 and we would need to inject
8521 * the event from there (hence place it back in TRPM).
8522 */
8523 if (pVCpu->hm.s.Event.fPending)
8524 {
8525 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8526 Assert(!pVCpu->hm.s.Event.fPending);
8527
8528 /* Clear the events from the VMCS. */
8529 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc);
8530 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0); AssertRC(rc);
8531 }
8532#ifdef VBOX_STRICT
8533 /*
8534 * We check for rcExit here since for errors like VERR_VMX_UNABLE_TO_START_VM (which are
8535 * fatal), we don't care about verifying duplicate injection of events. Errors like
8536 * VERR_EM_INTERPRET are converted to their VINF_* counterparts -prior- to calling this
8537 * function so those should and will be checked below.
8538 */
8539 else if (RT_SUCCESS(rcExit))
8540 {
8541 /*
8542 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8543 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8544 * occasionally, see @bugref{9180#c42}.
8545 *
8546 * However, if the VM-entry failed, any VM entry-interruption info. field would
8547 * be left unmodified as the event would not have been injected to the guest. In
8548 * such cases, don't assert, we're not going to continue guest execution anyway.
8549 */
8550 uint32_t uExitReason;
8551 uint32_t uEntryIntInfo;
8552 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8553 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8554 AssertRC(rc);
8555 AssertMsg(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo),
8556 ("uExitReason=%#RX32 uEntryIntInfo=%#RX32 rcExit=%d\n", uExitReason, uEntryIntInfo, VBOXSTRICTRC_VAL(rcExit)));
8557 }
8558#endif
8559
8560 /*
8561 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8562 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8563 * (e.g. TPR below threshold).
8564 */
8565 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8566 {
8567 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8568 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8569 }
8570
8571 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8572 and if we're injecting an event we should have a TRPM trap pending. */
8573 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8574#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8575 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8576#endif
8577
8578 /* Save guest state and restore host state bits. */
8579 int rc = hmR0VmxLeaveSession(pVCpu);
8580 AssertRCReturn(rc, rc);
8581 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8582
8583 /* Thread-context hooks are unregistered at this point!!! */
8584 /* Ring-3 callback notifications are unregistered at this point!!! */
8585
8586 /* Sync recompiler state. */
8587 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8588 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8589 | CPUM_CHANGED_LDTR
8590 | CPUM_CHANGED_GDTR
8591 | CPUM_CHANGED_IDTR
8592 | CPUM_CHANGED_TR
8593 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8594 if ( pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging
8595 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8596 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8597
8598 Assert(!pVCpu->hmr0.s.fClearTrapFlag);
8599
8600 /* Update the exit-to-ring 3 reason. */
8601 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8602
8603 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8604 if ( rcExit != VINF_EM_RAW_INTERRUPT
8605 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8606 {
8607 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8608 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8609 }
8610
8611 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8612 VMMRZCallRing3Enable(pVCpu);
8613 return rc;
8614}
8615
8616
8617/**
8618 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8619 * longjump to ring-3 and possibly get preempted.
8620 *
8621 * @returns VBox status code.
8622 * @param pVCpu The cross context virtual CPU structure.
8623 * @param enmOperation The operation causing the ring-3 longjump.
8624 */
8625VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8626{
8627 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8628 {
8629 /*
8630 * !!! IMPORTANT !!!
8631 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8632 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8633 */
8634 VMMRZCallRing3RemoveNotification(pVCpu);
8635 VMMRZCallRing3Disable(pVCpu);
8636 HM_DISABLE_PREEMPT(pVCpu);
8637
8638 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8639 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8640 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8641 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8642
8643 /* Restore host-state bits that VT-x only restores partially. */
8644 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
8645 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
8646 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
8647
8648 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8649 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8650 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8651
8652 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8653 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
8654 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8655
8656 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8657 cleared as part of importing the guest state above. */
8658 hmR0VmxClearVmcs(pVmcsInfo);
8659
8660 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8661 VMMR0ThreadCtxHookDisable(pVCpu);
8662
8663 /* Leave HM context. This takes care of local init (term). */
8664 HMR0LeaveCpu(pVCpu);
8665 HM_RESTORE_PREEMPT();
8666 return VINF_SUCCESS;
8667 }
8668
8669 Assert(pVCpu);
8670 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8671 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8672
8673 VMMRZCallRing3Disable(pVCpu);
8674 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8675
8676 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8677
8678 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8679 AssertRCReturn(rc, rc);
8680
8681 VMMRZCallRing3Enable(pVCpu);
8682 return VINF_SUCCESS;
8683}
8684
8685
8686/**
8687 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8688 * stack.
8689 *
8690 * @returns Strict VBox status code (i.e. informational status codes too).
8691 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8692 * @param pVCpu The cross context virtual CPU structure.
8693 * @param uValue The value to push to the guest stack.
8694 */
8695static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8696{
8697 /*
8698 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8699 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8700 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8701 */
8702 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8703 if (pCtx->sp == 1)
8704 return VINF_EM_RESET;
8705 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8706 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8707 AssertRC(rc);
8708 return rc;
8709}
8710
8711
8712/**
8713 * Injects an event into the guest upon VM-entry by updating the relevant fields
8714 * in the VM-entry area in the VMCS.
8715 *
8716 * @returns Strict VBox status code (i.e. informational status codes too).
8717 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8718 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8719 *
8720 * @param pVCpu The cross context virtual CPU structure.
8721 * @param pVmxTransient The VMX-transient structure.
8722 * @param pEvent The event being injected.
8723 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8724 * will be updated if necessary. This cannot not be NULL.
8725 * @param fStepping Whether we're single-stepping guest execution and should
8726 * return VINF_EM_DBG_STEPPED if the event is injected
8727 * directly (registers modified by us, not by hardware on
8728 * VM-entry).
8729 */
8730static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8731 uint32_t *pfIntrState)
8732{
8733 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8734 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8735 Assert(pfIntrState);
8736
8737 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8738 uint32_t u32IntInfo = pEvent->u64IntInfo;
8739 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8740 uint32_t const cbInstr = pEvent->cbInstr;
8741 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8742 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8743 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8744
8745#ifdef VBOX_STRICT
8746 /*
8747 * Validate the error-code-valid bit for hardware exceptions.
8748 * No error codes for exceptions in real-mode.
8749 *
8750 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8751 */
8752 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8753 && !CPUMIsGuestInRealModeEx(pCtx))
8754 {
8755 switch (uVector)
8756 {
8757 case X86_XCPT_PF:
8758 case X86_XCPT_DF:
8759 case X86_XCPT_TS:
8760 case X86_XCPT_NP:
8761 case X86_XCPT_SS:
8762 case X86_XCPT_GP:
8763 case X86_XCPT_AC:
8764 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8765 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8766 RT_FALL_THRU();
8767 default:
8768 break;
8769 }
8770 }
8771
8772 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8773 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8774 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8775#endif
8776
8777 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8778 || uIntType == VMX_EXIT_INT_INFO_TYPE_NMI
8779 || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT
8780 || uIntType == VMX_EXIT_INT_INFO_TYPE_SW_XCPT)
8781 {
8782 Assert(uVector <= X86_XCPT_LAST);
8783 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_NMI || uVector == X86_XCPT_NMI);
8784 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT || uVector == X86_XCPT_DB);
8785 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedXcptsR0[uVector]);
8786 }
8787 else
8788 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8789
8790 /*
8791 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8792 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8793 * interrupt handler in the (real-mode) guest.
8794 *
8795 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8796 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8797 */
8798 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8799 {
8800 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest)
8801 {
8802 /*
8803 * For CPUs with unrestricted guest execution enabled and with the guest
8804 * in real-mode, we must not set the deliver-error-code bit.
8805 *
8806 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8807 */
8808 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8809 }
8810 else
8811 {
8812 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8813 Assert(PDMVmmDevHeapIsEnabled(pVM));
8814 Assert(pVM->hm.s.vmx.pRealModeTSS);
8815 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8816
8817 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8818 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8819 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8820 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8821 AssertRCReturn(rc2, rc2);
8822
8823 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8824 size_t const cbIdtEntry = sizeof(X86IDTR16);
8825 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8826 {
8827 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8828 if (uVector == X86_XCPT_DF)
8829 return VINF_EM_RESET;
8830
8831 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8832 No error codes for exceptions in real-mode. */
8833 if (uVector == X86_XCPT_GP)
8834 {
8835 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8836 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8837 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8838 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8839 HMEVENT EventXcptDf;
8840 RT_ZERO(EventXcptDf);
8841 EventXcptDf.u64IntInfo = uXcptDfInfo;
8842 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8843 }
8844
8845 /*
8846 * If we're injecting an event with no valid IDT entry, inject a #GP.
8847 * No error codes for exceptions in real-mode.
8848 *
8849 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8850 */
8851 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8852 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8853 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8854 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8855 HMEVENT EventXcptGp;
8856 RT_ZERO(EventXcptGp);
8857 EventXcptGp.u64IntInfo = uXcptGpInfo;
8858 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8859 }
8860
8861 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8862 uint16_t uGuestIp = pCtx->ip;
8863 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8864 {
8865 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8866 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8867 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8868 }
8869 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8870 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8871
8872 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8873 X86IDTR16 IdtEntry;
8874 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8875 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8876 AssertRCReturn(rc2, rc2);
8877
8878 /* Construct the stack frame for the interrupt/exception handler. */
8879 VBOXSTRICTRC rcStrict;
8880 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8881 if (rcStrict == VINF_SUCCESS)
8882 {
8883 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8884 if (rcStrict == VINF_SUCCESS)
8885 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8886 }
8887
8888 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8889 if (rcStrict == VINF_SUCCESS)
8890 {
8891 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8892 pCtx->rip = IdtEntry.offSel;
8893 pCtx->cs.Sel = IdtEntry.uSel;
8894 pCtx->cs.ValidSel = IdtEntry.uSel;
8895 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8896 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8897 && uVector == X86_XCPT_PF)
8898 pCtx->cr2 = GCPtrFault;
8899
8900 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8901 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8902 | HM_CHANGED_GUEST_RSP);
8903
8904 /*
8905 * If we delivered a hardware exception (other than an NMI) and if there was
8906 * block-by-STI in effect, we should clear it.
8907 */
8908 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8909 {
8910 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8911 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8912 Log4Func(("Clearing inhibition due to STI\n"));
8913 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8914 }
8915
8916 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8917 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8918
8919 /*
8920 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8921 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8922 */
8923 pVCpu->hm.s.Event.fPending = false;
8924
8925 /*
8926 * If we eventually support nested-guest execution without unrestricted guest execution,
8927 * we should set fInterceptEvents here.
8928 */
8929 Assert(!pVmxTransient->fIsNestedGuest);
8930
8931 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8932 if (fStepping)
8933 rcStrict = VINF_EM_DBG_STEPPED;
8934 }
8935 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8936 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8937 return rcStrict;
8938 }
8939 }
8940
8941 /*
8942 * Validate.
8943 */
8944 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8945 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8946
8947 /*
8948 * Inject the event into the VMCS.
8949 */
8950 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8951 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8952 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8953 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8954 AssertRC(rc);
8955
8956 /*
8957 * Update guest CR2 if this is a page-fault.
8958 */
8959 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8960 pCtx->cr2 = GCPtrFault;
8961
8962 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8963 return VINF_SUCCESS;
8964}
8965
8966
8967/**
8968 * Evaluates the event to be delivered to the guest and sets it as the pending
8969 * event.
8970 *
8971 * Toggling of interrupt force-flags here is safe since we update TRPM on premature
8972 * exits to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must
8973 * NOT restore these force-flags.
8974 *
8975 * @returns Strict VBox status code (i.e. informational status codes too).
8976 * @param pVCpu The cross context virtual CPU structure.
8977 * @param pVmxTransient The VMX-transient structure.
8978 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8979 */
8980static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8981{
8982 Assert(pfIntrState);
8983 Assert(!TRPMHasTrap(pVCpu));
8984
8985 /*
8986 * Compute/update guest-interruptibility state related FFs.
8987 * The FFs will be used below while evaluating events to be injected.
8988 */
8989 *pfIntrState = hmR0VmxGetGuestIntrStateAndUpdateFFs(pVCpu);
8990
8991 /*
8992 * Evaluate if a new event needs to be injected.
8993 * An event that's already pending has already performed all necessary checks.
8994 */
8995 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8996 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8997 if ( !pVCpu->hm.s.Event.fPending
8998 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
8999 {
9000 /** @todo SMI. SMIs take priority over NMIs. */
9001
9002 /*
9003 * NMIs.
9004 * NMIs take priority over external interrupts.
9005 */
9006 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9007 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
9008 {
9009 /*
9010 * For a guest, the FF always indicates the guest's ability to receive an NMI.
9011 *
9012 * For a nested-guest, the FF always indicates the outer guest's ability to
9013 * receive an NMI while the guest-interruptibility state bit depends on whether
9014 * the nested-hypervisor is using virtual-NMIs.
9015 */
9016 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
9017 {
9018#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9019 if ( fIsNestedGuest
9020 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_NMI_EXIT))
9021 return IEMExecVmxVmexitXcptNmi(pVCpu);
9022#endif
9023 hmR0VmxSetPendingXcptNmi(pVCpu);
9024 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
9025 Log4Func(("NMI pending injection\n"));
9026
9027 /* We've injected the NMI, bail. */
9028 return VINF_SUCCESS;
9029 }
9030 else if (!fIsNestedGuest)
9031 hmR0VmxSetNmiWindowExitVmcs(pVmcsInfo);
9032 }
9033
9034 /*
9035 * External interrupts (PIC/APIC).
9036 * Once PDMGetInterrupt() returns a valid interrupt we -must- deliver it.
9037 * We cannot re-request the interrupt from the controller again.
9038 */
9039 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9040 && !pVCpu->hm.s.fSingleInstruction)
9041 {
9042 Assert(!DBGFIsStepping(pVCpu));
9043 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
9044 AssertRC(rc);
9045
9046 /*
9047 * We must not check EFLAGS directly when executing a nested-guest, use
9048 * CPUMIsGuestPhysIntrEnabled() instead as EFLAGS.IF does not control the blocking of
9049 * external interrupts when "External interrupt exiting" is set. This fixes a nasty
9050 * SMP hang while executing nested-guest VCPUs on spinlocks which aren't rescued by
9051 * other VM-exits (like a preemption timer), see @bugref{9562#c18}.
9052 *
9053 * See Intel spec. 25.4.1 "Event Blocking".
9054 */
9055 if (CPUMIsGuestPhysIntrEnabled(pVCpu))
9056 {
9057#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9058 if ( fIsNestedGuest
9059 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9060 {
9061 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
9062 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
9063 return rcStrict;
9064 }
9065#endif
9066 uint8_t u8Interrupt;
9067 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9068 if (RT_SUCCESS(rc))
9069 {
9070#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9071 if ( fIsNestedGuest
9072 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9073 {
9074 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9075 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
9076 return rcStrict;
9077 }
9078#endif
9079 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9080 Log4Func(("External interrupt (%#x) pending injection\n", u8Interrupt));
9081 }
9082 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9083 {
9084 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9085
9086 if ( !fIsNestedGuest
9087 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9088 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
9089 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
9090
9091 /*
9092 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9093 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9094 * need to re-set this force-flag here.
9095 */
9096 }
9097 else
9098 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9099
9100 /* We've injected the interrupt or taken necessary action, bail. */
9101 return VINF_SUCCESS;
9102 }
9103 if (!fIsNestedGuest)
9104 hmR0VmxSetIntWindowExitVmcs(pVmcsInfo);
9105 }
9106 }
9107 else if (!fIsNestedGuest)
9108 {
9109 /*
9110 * An event is being injected or we are in an interrupt shadow. Check if another event is
9111 * pending. If so, instruct VT-x to cause a VM-exit as soon as the guest is ready to accept
9112 * the pending event.
9113 */
9114 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
9115 hmR0VmxSetNmiWindowExitVmcs(pVmcsInfo);
9116 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9117 && !pVCpu->hm.s.fSingleInstruction)
9118 hmR0VmxSetIntWindowExitVmcs(pVmcsInfo);
9119 }
9120 /* else: for nested-guests, NMI/interrupt-window exiting will be picked up when merging VMCS controls. */
9121
9122 return VINF_SUCCESS;
9123}
9124
9125
9126/**
9127 * Injects any pending events into the guest if the guest is in a state to
9128 * receive them.
9129 *
9130 * @returns Strict VBox status code (i.e. informational status codes too).
9131 * @param pVCpu The cross context virtual CPU structure.
9132 * @param pVmxTransient The VMX-transient structure.
9133 * @param fIntrState The VT-x guest-interruptibility state.
9134 * @param fStepping Whether we are single-stepping the guest using the
9135 * hypervisor debugger and should return
9136 * VINF_EM_DBG_STEPPED if the event was dispatched
9137 * directly.
9138 */
9139static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9140{
9141 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9142 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9143
9144#ifdef VBOX_STRICT
9145 /*
9146 * Verify guest-interruptibility state.
9147 *
9148 * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
9149 * since injecting an event may modify the interruptibility state and we must thus always
9150 * use fIntrState.
9151 */
9152 {
9153 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9154 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9155 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9156 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9157 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9158 Assert(!TRPMHasTrap(pVCpu));
9159 NOREF(fBlockMovSS); NOREF(fBlockSti);
9160 }
9161#endif
9162
9163 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9164 if (pVCpu->hm.s.Event.fPending)
9165 {
9166 /*
9167 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9168 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9169 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9170 *
9171 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9172 */
9173 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9174#ifdef VBOX_STRICT
9175 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9176 {
9177 Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9178 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9179 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9180 }
9181 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9182 {
9183 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
9184 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9185 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9186 }
9187#endif
9188 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9189 uIntType));
9190
9191 /*
9192 * Inject the event and get any changes to the guest-interruptibility state.
9193 *
9194 * The guest-interruptibility state may need to be updated if we inject the event
9195 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9196 */
9197 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9198 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9199
9200 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9201 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9202 else
9203 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9204 }
9205
9206 /*
9207 * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
9208 * is an interrupt shadow (block-by-STI or block-by-MOV SS).
9209 */
9210 if ( (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9211 && !pVmxTransient->fIsNestedGuest)
9212 {
9213 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
9214
9215 if (!pVCpu->hm.s.fSingleInstruction)
9216 {
9217 /*
9218 * Set or clear the BS bit depending on whether the trap flag is active or not. We need
9219 * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
9220 */
9221 Assert(!DBGFIsStepping(pVCpu));
9222 uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
9223 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
9224 AssertRC(rc);
9225 }
9226 else
9227 {
9228 /*
9229 * We must not deliver a debug exception when single-stepping over STI/Mov-SS in the
9230 * hypervisor debugger using EFLAGS.TF but rather clear interrupt inhibition. However,
9231 * we take care of this case in hmR0VmxExportSharedDebugState and also the case if
9232 * we use MTF, so just make sure it's called before executing guest-code.
9233 */
9234 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR_MASK);
9235 }
9236 }
9237 /* else: for nested-guest currently handling while merging controls. */
9238
9239 /*
9240 * Finally, update the guest-interruptibility state.
9241 *
9242 * This is required for the real-on-v86 software interrupt injection, for
9243 * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
9244 */
9245 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9246 AssertRC(rc);
9247
9248 /*
9249 * There's no need to clear the VM-entry interruption-information field here if we're not
9250 * injecting anything. VT-x clears the valid bit on every VM-exit.
9251 *
9252 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9253 */
9254
9255 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9256 return rcStrict;
9257}
9258
9259
9260/**
9261 * Enters the VT-x session.
9262 *
9263 * @returns VBox status code.
9264 * @param pVCpu The cross context virtual CPU structure.
9265 */
9266VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
9267{
9268 AssertPtr(pVCpu);
9269 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9270 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9271
9272 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9273 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9274 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9275
9276#ifdef VBOX_STRICT
9277 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9278 RTCCUINTREG uHostCr4 = ASMGetCR4();
9279 if (!(uHostCr4 & X86_CR4_VMXE))
9280 {
9281 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9282 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9283 }
9284#endif
9285
9286 /*
9287 * Load the appropriate VMCS as the current and active one.
9288 */
9289 PVMXVMCSINFO pVmcsInfo;
9290 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9291 if (!fInNestedGuestMode)
9292 pVmcsInfo = &pVCpu->hmr0.s.vmx.VmcsInfo;
9293 else
9294 pVmcsInfo = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
9295 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9296 if (RT_SUCCESS(rc))
9297 {
9298 pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9299 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcsCopyForRing3 = fInNestedGuestMode;
9300 pVCpu->hmr0.s.fLeaveDone = false;
9301 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9302
9303 /*
9304 * Do the EMT scheduled L1D flush here if needed.
9305 */
9306 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9307 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9308 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9309 hmR0MdsClear();
9310 }
9311 return rc;
9312}
9313
9314
9315/**
9316 * The thread-context callback (only on platforms which support it).
9317 *
9318 * @param enmEvent The thread-context event.
9319 * @param pVCpu The cross context virtual CPU structure.
9320 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9321 * @thread EMT(pVCpu)
9322 */
9323VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
9324{
9325 AssertPtr(pVCpu);
9326 RT_NOREF1(fGlobalInit);
9327
9328 switch (enmEvent)
9329 {
9330 case RTTHREADCTXEVENT_OUT:
9331 {
9332 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9333 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9334 VMCPU_ASSERT_EMT(pVCpu);
9335
9336 /* No longjmps (logger flushes, locks) in this fragile context. */
9337 VMMRZCallRing3Disable(pVCpu);
9338 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9339
9340 /* Restore host-state (FPU, debug etc.) */
9341 if (!pVCpu->hmr0.s.fLeaveDone)
9342 {
9343 /*
9344 * Do -not- import the guest-state here as we might already be in the middle of importing
9345 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9346 */
9347 hmR0VmxLeave(pVCpu, false /* fImportState */);
9348 pVCpu->hmr0.s.fLeaveDone = true;
9349 }
9350
9351 /* Leave HM context, takes care of local init (term). */
9352 int rc = HMR0LeaveCpu(pVCpu);
9353 AssertRC(rc);
9354
9355 /* Restore longjmp state. */
9356 VMMRZCallRing3Enable(pVCpu);
9357 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9358 break;
9359 }
9360
9361 case RTTHREADCTXEVENT_IN:
9362 {
9363 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9364 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9365 VMCPU_ASSERT_EMT(pVCpu);
9366
9367 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9368 VMMRZCallRing3Disable(pVCpu);
9369 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9370
9371 /* Initialize the bare minimum state required for HM. This takes care of
9372 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9373 int rc = hmR0EnterCpu(pVCpu);
9374 AssertRC(rc);
9375 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9376 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9377
9378 /* Load the active VMCS as the current one. */
9379 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9380 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9381 AssertRC(rc);
9382 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9383 pVCpu->hmr0.s.fLeaveDone = false;
9384
9385 /* Do the EMT scheduled L1D flush if needed. */
9386 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9387 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9388
9389 /* Restore longjmp state. */
9390 VMMRZCallRing3Enable(pVCpu);
9391 break;
9392 }
9393
9394 default:
9395 break;
9396 }
9397}
9398
9399
9400/**
9401 * Exports the host state into the VMCS host-state area.
9402 * Sets up the VM-exit MSR-load area.
9403 *
9404 * The CPU state will be loaded from these fields on every successful VM-exit.
9405 *
9406 * @returns VBox status code.
9407 * @param pVCpu The cross context virtual CPU structure.
9408 *
9409 * @remarks No-long-jump zone!!!
9410 */
9411static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
9412{
9413 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9414
9415 int rc = VINF_SUCCESS;
9416 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9417 {
9418 uint64_t uHostCr4 = hmR0VmxExportHostControlRegs();
9419
9420 rc = hmR0VmxExportHostSegmentRegs(pVCpu, uHostCr4);
9421 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9422
9423 hmR0VmxExportHostMsrs(pVCpu);
9424
9425 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9426 }
9427 return rc;
9428}
9429
9430
9431/**
9432 * Saves the host state in the VMCS host-state.
9433 *
9434 * @returns VBox status code.
9435 * @param pVCpu The cross context virtual CPU structure.
9436 *
9437 * @remarks No-long-jump zone!!!
9438 */
9439VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
9440{
9441 AssertPtr(pVCpu);
9442 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9443
9444 /*
9445 * Export the host state here while entering HM context.
9446 * When thread-context hooks are used, we might get preempted and have to re-save the host
9447 * state but most of the time we won't be, so do it here before we disable interrupts.
9448 */
9449 return hmR0VmxExportHostState(pVCpu);
9450}
9451
9452
9453/**
9454 * Exports the guest state into the VMCS guest-state area.
9455 *
9456 * The will typically be done before VM-entry when the guest-CPU state and the
9457 * VMCS state may potentially be out of sync.
9458 *
9459 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9460 * VM-entry controls.
9461 * Sets up the appropriate VMX non-root function to execute guest code based on
9462 * the guest CPU mode.
9463 *
9464 * @returns VBox strict status code.
9465 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9466 * without unrestricted guest execution and the VMMDev is not presently
9467 * mapped (e.g. EFI32).
9468 *
9469 * @param pVCpu The cross context virtual CPU structure.
9470 * @param pVmxTransient The VMX-transient structure.
9471 *
9472 * @remarks No-long-jump zone!!!
9473 */
9474static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9475{
9476 AssertPtr(pVCpu);
9477 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9478 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9479
9480 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9481
9482 /*
9483 * Determine real-on-v86 mode.
9484 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9485 */
9486 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmxTransient->pVmcsInfo->pShared;
9487 if ( pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest
9488 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9489 pVmcsInfoShared->RealMode.fRealOnV86Active = false;
9490 else
9491 {
9492 Assert(!pVmxTransient->fIsNestedGuest);
9493 pVmcsInfoShared->RealMode.fRealOnV86Active = true;
9494 }
9495
9496 /*
9497 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9498 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9499 */
9500 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9501 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9502
9503 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9504 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9505
9506 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9507 if (rcStrict == VINF_SUCCESS)
9508 { /* likely */ }
9509 else
9510 {
9511 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9512 return rcStrict;
9513 }
9514
9515 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9516 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9517
9518 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9519 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9520
9521 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9522 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9523 hmR0VmxExportGuestRip(pVCpu);
9524 hmR0VmxExportGuestRsp(pVCpu);
9525 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9526
9527 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9528 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9529
9530 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9531 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9532 | HM_CHANGED_GUEST_CR2
9533 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9534 | HM_CHANGED_GUEST_X87
9535 | HM_CHANGED_GUEST_SSE_AVX
9536 | HM_CHANGED_GUEST_OTHER_XSAVE
9537 | HM_CHANGED_GUEST_XCRx
9538 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9539 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9540 | HM_CHANGED_GUEST_TSC_AUX
9541 | HM_CHANGED_GUEST_OTHER_MSRS
9542 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9543
9544 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9545 return rc;
9546}
9547
9548
9549/**
9550 * Exports the state shared between the host and guest into the VMCS.
9551 *
9552 * @param pVCpu The cross context virtual CPU structure.
9553 * @param pVmxTransient The VMX-transient structure.
9554 *
9555 * @remarks No-long-jump zone!!!
9556 */
9557static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9558{
9559 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9560 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9561
9562 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9563 {
9564 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9565 AssertRC(rc);
9566 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9567
9568 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9569 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9570 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9571 }
9572
9573 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9574 {
9575 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9576 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9577 }
9578
9579 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9580 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9581}
9582
9583
9584/**
9585 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9586 *
9587 * @returns Strict VBox status code (i.e. informational status codes too).
9588 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9589 * without unrestricted guest execution and the VMMDev is not presently
9590 * mapped (e.g. EFI32).
9591 *
9592 * @param pVCpu The cross context virtual CPU structure.
9593 * @param pVmxTransient The VMX-transient structure.
9594 *
9595 * @remarks No-long-jump zone!!!
9596 */
9597static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9598{
9599 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9600 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9601 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9602
9603#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9604 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9605#endif
9606
9607 /*
9608 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9609 * changes. First try to export only these without going through all other changed-flag checks.
9610 */
9611 VBOXSTRICTRC rcStrict;
9612 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9613 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9614 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9615
9616 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9617 if ( (fCtxChanged & fMinimalMask)
9618 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9619 {
9620 hmR0VmxExportGuestRip(pVCpu);
9621 hmR0VmxExportGuestRsp(pVCpu);
9622 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9623 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9624 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9625 }
9626 /* If anything else also changed, go through the full export routine and export as required. */
9627 else if (fCtxChanged & fCtxMask)
9628 {
9629 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9630 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9631 { /* likely */}
9632 else
9633 {
9634 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9635 VBOXSTRICTRC_VAL(rcStrict)));
9636 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9637 return rcStrict;
9638 }
9639 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9640 }
9641 /* Nothing changed, nothing to load here. */
9642 else
9643 rcStrict = VINF_SUCCESS;
9644
9645#ifdef VBOX_STRICT
9646 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9647 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9648 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9649#endif
9650 return rcStrict;
9651}
9652
9653
9654/**
9655 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9656 * and update error record fields accordingly.
9657 *
9658 * @returns VMX_IGS_* error codes.
9659 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9660 * wrong with the guest state.
9661 *
9662 * @param pVCpu The cross context virtual CPU structure.
9663 * @param pVmcsInfo The VMCS info. object.
9664 *
9665 * @remarks This function assumes our cache of the VMCS controls
9666 * are valid, i.e. hmR0VmxCheckCachedVmcsCtls() succeeded.
9667 */
9668static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9669{
9670#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9671#define HMVMX_CHECK_BREAK(expr, err) do { \
9672 if (!(expr)) { uError = (err); break; } \
9673 } while (0)
9674
9675 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9676 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9677 uint32_t uError = VMX_IGS_ERROR;
9678 uint32_t u32IntrState = 0;
9679 bool const fUnrestrictedGuest = pVM->hmr0.s.vmx.fUnrestrictedGuest;
9680 do
9681 {
9682 int rc;
9683
9684 /*
9685 * Guest-interruptibility state.
9686 *
9687 * Read this first so that any check that fails prior to those that actually
9688 * require the guest-interruptibility state would still reflect the correct
9689 * VMCS value and avoids causing further confusion.
9690 */
9691 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9692 AssertRC(rc);
9693
9694 uint32_t u32Val;
9695 uint64_t u64Val;
9696
9697 /*
9698 * CR0.
9699 */
9700 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9701 uint64_t fSetCr0 = (g_HmMsrs.u.vmx.u64Cr0Fixed0 & g_HmMsrs.u.vmx.u64Cr0Fixed1);
9702 uint64_t const fZapCr0 = (g_HmMsrs.u.vmx.u64Cr0Fixed0 | g_HmMsrs.u.vmx.u64Cr0Fixed1);
9703 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9704 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9705 if (fUnrestrictedGuest)
9706 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9707
9708 uint64_t u64GuestCr0;
9709 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9710 AssertRC(rc);
9711 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9712 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9713 if ( !fUnrestrictedGuest
9714 && (u64GuestCr0 & X86_CR0_PG)
9715 && !(u64GuestCr0 & X86_CR0_PE))
9716 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9717
9718 /*
9719 * CR4.
9720 */
9721 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9722 uint64_t const fSetCr4 = (g_HmMsrs.u.vmx.u64Cr4Fixed0 & g_HmMsrs.u.vmx.u64Cr4Fixed1);
9723 uint64_t const fZapCr4 = (g_HmMsrs.u.vmx.u64Cr4Fixed0 | g_HmMsrs.u.vmx.u64Cr4Fixed1);
9724
9725 uint64_t u64GuestCr4;
9726 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9727 AssertRC(rc);
9728 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9729 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9730
9731 /*
9732 * IA32_DEBUGCTL MSR.
9733 */
9734 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9735 AssertRC(rc);
9736 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9737 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9738 {
9739 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9740 }
9741 uint64_t u64DebugCtlMsr = u64Val;
9742
9743#ifdef VBOX_STRICT
9744 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9745 AssertRC(rc);
9746 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9747#endif
9748 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9749
9750 /*
9751 * RIP and RFLAGS.
9752 */
9753 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9754 AssertRC(rc);
9755 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9756 if ( !fLongModeGuest
9757 || !pCtx->cs.Attr.n.u1Long)
9758 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9759 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9760 * must be identical if the "IA-32e mode guest" VM-entry
9761 * control is 1 and CS.L is 1. No check applies if the
9762 * CPU supports 64 linear-address bits. */
9763
9764 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9765 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9766 AssertRC(rc);
9767 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9768 VMX_IGS_RFLAGS_RESERVED);
9769 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9770 uint32_t const u32Eflags = u64Val;
9771
9772 if ( fLongModeGuest
9773 || ( fUnrestrictedGuest
9774 && !(u64GuestCr0 & X86_CR0_PE)))
9775 {
9776 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9777 }
9778
9779 uint32_t u32EntryInfo;
9780 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9781 AssertRC(rc);
9782 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9783 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9784
9785 /*
9786 * 64-bit checks.
9787 */
9788 if (fLongModeGuest)
9789 {
9790 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9791 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9792 }
9793
9794 if ( !fLongModeGuest
9795 && (u64GuestCr4 & X86_CR4_PCIDE))
9796 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9797
9798 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9799 * 51:32 beyond the processor's physical-address width are 0. */
9800
9801 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9802 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9803 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9804
9805 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9806 AssertRC(rc);
9807 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9808
9809 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9810 AssertRC(rc);
9811 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9812
9813 /*
9814 * PERF_GLOBAL MSR.
9815 */
9816 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9817 {
9818 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9819 AssertRC(rc);
9820 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9821 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9822 }
9823
9824 /*
9825 * PAT MSR.
9826 */
9827 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9828 {
9829 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9830 AssertRC(rc);
9831 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9832 for (unsigned i = 0; i < 8; i++)
9833 {
9834 uint8_t u8Val = (u64Val & 0xff);
9835 if ( u8Val != 0 /* UC */
9836 && u8Val != 1 /* WC */
9837 && u8Val != 4 /* WT */
9838 && u8Val != 5 /* WP */
9839 && u8Val != 6 /* WB */
9840 && u8Val != 7 /* UC- */)
9841 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9842 u64Val >>= 8;
9843 }
9844 }
9845
9846 /*
9847 * EFER MSR.
9848 */
9849 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9850 {
9851 Assert(g_fHmVmxSupportsVmcsEfer);
9852 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9853 AssertRC(rc);
9854 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9855 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9856 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9857 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9858 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9859 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9860 * iemVmxVmentryCheckGuestState(). */
9861 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9862 || !(u64GuestCr0 & X86_CR0_PG)
9863 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9864 VMX_IGS_EFER_LMA_LME_MISMATCH);
9865 }
9866
9867 /*
9868 * Segment registers.
9869 */
9870 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9871 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9872 if (!(u32Eflags & X86_EFL_VM))
9873 {
9874 /* CS */
9875 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9876 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9877 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9878 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9879 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9880 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9881 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9882 /* CS cannot be loaded with NULL in protected mode. */
9883 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9884 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9885 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9886 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9887 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9888 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9889 else if (fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9890 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9891 else
9892 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9893
9894 /* SS */
9895 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9896 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9897 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9898 if ( !(pCtx->cr0 & X86_CR0_PE)
9899 || pCtx->cs.Attr.n.u4Type == 3)
9900 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9901
9902 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9903 {
9904 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9905 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9906 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9907 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9908 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9909 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9910 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9911 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9912 }
9913
9914 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9915 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9916 {
9917 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9918 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9919 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9920 || pCtx->ds.Attr.n.u4Type > 11
9921 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9922 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9923 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9924 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9925 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9926 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9927 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9928 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9929 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9930 }
9931 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9932 {
9933 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9934 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9935 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9936 || pCtx->es.Attr.n.u4Type > 11
9937 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9938 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9939 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9940 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9941 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9942 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9943 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9944 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9945 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9946 }
9947 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9948 {
9949 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9950 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9951 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9952 || pCtx->fs.Attr.n.u4Type > 11
9953 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9954 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9955 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9956 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9957 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9958 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9959 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9960 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9961 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9962 }
9963 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9964 {
9965 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9966 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9967 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9968 || pCtx->gs.Attr.n.u4Type > 11
9969 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9970 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9971 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9972 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9973 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9974 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9975 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9976 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9977 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9978 }
9979 /* 64-bit capable CPUs. */
9980 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9981 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9982 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9983 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9984 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9985 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9986 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9987 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9988 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9989 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9990 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9991 }
9992 else
9993 {
9994 /* V86 mode checks. */
9995 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9996 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
9997 {
9998 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9999 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
10000 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
10001 }
10002 else
10003 {
10004 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
10005 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
10006 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
10007 }
10008
10009 /* CS */
10010 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10011 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10012 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10013 /* SS */
10014 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10015 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10016 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10017 /* DS */
10018 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10019 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10020 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10021 /* ES */
10022 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10023 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10024 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10025 /* FS */
10026 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10027 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10028 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10029 /* GS */
10030 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10031 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10032 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10033 /* 64-bit capable CPUs. */
10034 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10035 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10036 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10037 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10038 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10039 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10040 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10041 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10042 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10043 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10044 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10045 }
10046
10047 /*
10048 * TR.
10049 */
10050 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10051 /* 64-bit capable CPUs. */
10052 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10053 if (fLongModeGuest)
10054 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10055 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10056 else
10057 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10058 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10059 VMX_IGS_TR_ATTR_TYPE_INVALID);
10060 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10061 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10062 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10063 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10064 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10065 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10066 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10067 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10068
10069 /*
10070 * GDTR and IDTR (64-bit capable checks).
10071 */
10072 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10073 AssertRC(rc);
10074 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10075
10076 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10077 AssertRC(rc);
10078 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10079
10080 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10081 AssertRC(rc);
10082 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10083
10084 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10085 AssertRC(rc);
10086 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10087
10088 /*
10089 * Guest Non-Register State.
10090 */
10091 /* Activity State. */
10092 uint32_t u32ActivityState;
10093 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10094 AssertRC(rc);
10095 HMVMX_CHECK_BREAK( !u32ActivityState
10096 || (u32ActivityState & RT_BF_GET(g_HmMsrs.u.vmx.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10097 VMX_IGS_ACTIVITY_STATE_INVALID);
10098 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10099 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10100
10101 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10102 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10103 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10104
10105 /** @todo Activity state and injecting interrupts. Left as a todo since we
10106 * currently don't use activity states but ACTIVE. */
10107
10108 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10109 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10110
10111 /* Guest interruptibility-state. */
10112 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10113 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10114 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10115 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10116 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10117 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10118 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10119 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10120 {
10121 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10122 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10123 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10124 }
10125 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10126 {
10127 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10128 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10129 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10130 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10131 }
10132 /** @todo Assumes the processor is not in SMM. */
10133 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10134 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10135 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10136 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10137 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10138 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10139 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10140 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10141
10142 /* Pending debug exceptions. */
10143 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10144 AssertRC(rc);
10145 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10146 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10147 u32Val = u64Val; /* For pending debug exceptions checks below. */
10148
10149 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10150 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10151 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10152 {
10153 if ( (u32Eflags & X86_EFL_TF)
10154 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10155 {
10156 /* Bit 14 is PendingDebug.BS. */
10157 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10158 }
10159 if ( !(u32Eflags & X86_EFL_TF)
10160 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10161 {
10162 /* Bit 14 is PendingDebug.BS. */
10163 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10164 }
10165 }
10166
10167 /* VMCS link pointer. */
10168 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10169 AssertRC(rc);
10170 if (u64Val != UINT64_C(0xffffffffffffffff))
10171 {
10172 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10173 /** @todo Bits beyond the processor's physical-address width MBZ. */
10174 /** @todo SMM checks. */
10175 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10176 Assert(pVmcsInfo->pvShadowVmcs);
10177 VMXVMCSREVID VmcsRevId;
10178 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10179 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID),
10180 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10181 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10182 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10183 }
10184
10185 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10186 * not using nested paging? */
10187 if ( pVM->hmr0.s.fNestedPaging
10188 && !fLongModeGuest
10189 && CPUMIsGuestInPAEModeEx(pCtx))
10190 {
10191 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10192 AssertRC(rc);
10193 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10194
10195 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10196 AssertRC(rc);
10197 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10198
10199 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10200 AssertRC(rc);
10201 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10202
10203 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10204 AssertRC(rc);
10205 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10206 }
10207
10208 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10209 if (uError == VMX_IGS_ERROR)
10210 uError = VMX_IGS_REASON_NOT_FOUND;
10211 } while (0);
10212
10213 pVCpu->hm.s.u32HMError = uError;
10214 pVCpu->hm.s.vmx.LastError.u32GuestIntrState = u32IntrState;
10215 return uError;
10216
10217#undef HMVMX_ERROR_BREAK
10218#undef HMVMX_CHECK_BREAK
10219}
10220
10221
10222/**
10223 * Map the APIC-access page for virtualizing APIC accesses.
10224 *
10225 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10226 * this not done as part of exporting guest state, see @bugref{8721}.
10227 *
10228 * @returns VBox status code.
10229 * @param pVCpu The cross context virtual CPU structure.
10230 */
10231static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
10232{
10233 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10234 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10235
10236 Assert(PDMHasApic(pVM));
10237 Assert(u64MsrApicBase);
10238
10239 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10240 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10241
10242 /* Unalias the existing mapping. */
10243 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10244 AssertRCReturn(rc, rc);
10245
10246 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10247 Assert(pVM->hmr0.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10248 rc = IOMR0MmioMapMmioHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hmr0.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10249 AssertRCReturn(rc, rc);
10250
10251 /* Update the per-VCPU cache of the APIC base MSR. */
10252 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10253 return VINF_SUCCESS;
10254}
10255
10256
10257/**
10258 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10259 * CPU.
10260 *
10261 * @param idCpu The ID for the CPU the function is called on.
10262 * @param pvUser1 Null, not used.
10263 * @param pvUser2 Null, not used.
10264 */
10265static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10266{
10267 RT_NOREF3(idCpu, pvUser1, pvUser2);
10268 VMXDispatchHostNmi();
10269}
10270
10271
10272/**
10273 * Dispatching an NMI on the host CPU that received it.
10274 *
10275 * @returns VBox status code.
10276 * @param pVCpu The cross context virtual CPU structure.
10277 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10278 * executing when receiving the host NMI in VMX non-root
10279 * operation.
10280 */
10281static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
10282{
10283 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
10284 Assert(idCpu != NIL_RTCPUID);
10285
10286 /*
10287 * We don't want to delay dispatching the NMI any more than we have to. However,
10288 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10289 * after executing guest or nested-guest code for the following reasons:
10290 *
10291 * - We would need to perform VMREADs with interrupts disabled and is orders of
10292 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
10293 * supported by the host hypervisor.
10294 *
10295 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10296 * longer period of time just for handling an edge case like host NMIs which do
10297 * not occur nearly as frequently as other VM-exits.
10298 *
10299 * Let's cover the most likely scenario first. Check if we are on the target CPU
10300 * and dispatch the NMI right away. This should be much faster than calling into
10301 * RTMpOnSpecific() machinery.
10302 */
10303 bool fDispatched = false;
10304 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10305 if (idCpu == RTMpCpuId())
10306 {
10307 VMXDispatchHostNmi();
10308 fDispatched = true;
10309 }
10310 ASMSetFlags(fEFlags);
10311 if (fDispatched)
10312 {
10313 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10314 return VINF_SUCCESS;
10315 }
10316
10317 /*
10318 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10319 * there should be no race or recursion even if we are unlucky enough to be preempted
10320 * (to the target CPU) without dispatching the host NMI above.
10321 */
10322 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10323 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10324}
10325
10326
10327#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10328/**
10329 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10330 * nested-guest using hardware-assisted VMX.
10331 *
10332 * @param pVCpu The cross context virtual CPU structure.
10333 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10334 * @param pVmcsInfoGst The guest VMCS info. object.
10335 */
10336static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10337{
10338 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10339 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10340 Assert(pu64MsrBitmap);
10341
10342 /*
10343 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10344 * MSR that is intercepted by the guest is also intercepted while executing the
10345 * nested-guest using hardware-assisted VMX.
10346 *
10347 * Note! If the nested-guest is not using an MSR bitmap, every MSR must cause a
10348 * nested-guest VM-exit even if the outer guest is not intercepting some
10349 * MSRs. We cannot assume the caller has initialized the nested-guest
10350 * MSR bitmap in this case.
10351 *
10352 * The nested hypervisor may also switch whether it uses MSR bitmaps for
10353 * each of its VM-entry, hence initializing it once per-VM while setting
10354 * up the nested-guest VMCS is not sufficient.
10355 */
10356 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10357 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10358 {
10359 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10360 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10361 Assert(pu64MsrBitmapNstGst);
10362 Assert(pu64MsrBitmapGst);
10363
10364 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10365 for (uint32_t i = 0; i < cFrags; i++)
10366 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10367 }
10368 else
10369 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10370}
10371
10372
10373/**
10374 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10375 * hardware-assisted VMX execution of the nested-guest.
10376 *
10377 * For a guest, we don't modify these controls once we set up the VMCS and hence
10378 * this function is never called.
10379 *
10380 * For nested-guests since the nested hypervisor provides these controls on every
10381 * nested-guest VM-entry and could potentially change them everytime we need to
10382 * merge them before every nested-guest VM-entry.
10383 *
10384 * @returns VBox status code.
10385 * @param pVCpu The cross context virtual CPU structure.
10386 */
10387static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
10388{
10389 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10390 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
10391 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10392 Assert(pVmcsNstGst);
10393
10394 /*
10395 * Merge the controls with the requirements of the guest VMCS.
10396 *
10397 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10398 * VMCS with the features supported by the physical CPU as it's already done by the
10399 * VMLAUNCH/VMRESUME instruction emulation.
10400 *
10401 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10402 * derived from the VMX features supported by the physical CPU.
10403 */
10404
10405 /* Pin-based VM-execution controls. */
10406 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10407
10408 /* Processor-based VM-execution controls. */
10409 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10410 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10411 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10412 | VMX_PROC_CTLS_USE_TPR_SHADOW
10413 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10414
10415 /* Secondary processor-based VM-execution controls. */
10416 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10417 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10418 | VMX_PROC_CTLS2_INVPCID
10419 | VMX_PROC_CTLS2_VMCS_SHADOWING
10420 | VMX_PROC_CTLS2_RDTSCP
10421 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10422 | VMX_PROC_CTLS2_APIC_REG_VIRT
10423 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10424 | VMX_PROC_CTLS2_VMFUNC));
10425
10426 /*
10427 * VM-entry controls:
10428 * These controls contains state that depends on the nested-guest state (primarily
10429 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10430 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
10431 * properly continue executing the nested-guest if the EFER MSR changes but does not
10432 * cause a nested-guest VM-exits.
10433 *
10434 * VM-exit controls:
10435 * These controls specify the host state on return. We cannot use the controls from
10436 * the nested hypervisor state as is as it would contain the guest state rather than
10437 * the host state. Since the host state is subject to change (e.g. preemption, trips
10438 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10439 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10440 *
10441 * VM-entry MSR-load:
10442 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10443 * context by the VMLAUNCH/VMRESUME instruction emulation.
10444 *
10445 * VM-exit MSR-store:
10446 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10447 * back into the VM-exit MSR-store area.
10448 *
10449 * VM-exit MSR-load areas:
10450 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10451 * can entirely ignore what the nested hypervisor wants to load here.
10452 */
10453
10454 /*
10455 * Exception bitmap.
10456 *
10457 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10458 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10459 * code more flexible if intercepting exceptions become more dynamic in the future we do
10460 * it as part of exporting the nested-guest state.
10461 */
10462 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10463
10464 /*
10465 * CR0/CR4 guest/host mask.
10466 *
10467 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10468 * cause VM-exits, so we need to merge them here.
10469 */
10470 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10471 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10472
10473 /*
10474 * Page-fault error-code mask and match.
10475 *
10476 * Although we require unrestricted guest execution (and thereby nested-paging) for
10477 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10478 * normally intercept #PFs, it might intercept them for debugging purposes.
10479 *
10480 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10481 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10482 */
10483 uint32_t u32XcptPFMask;
10484 uint32_t u32XcptPFMatch;
10485 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10486 {
10487 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10488 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10489 }
10490 else
10491 {
10492 u32XcptPFMask = 0;
10493 u32XcptPFMatch = 0;
10494 }
10495
10496 /*
10497 * Pause-Loop exiting.
10498 */
10499 /** @todo r=bird: given that both pVM->hm.s.vmx.cPleGapTicks and
10500 * pVM->hm.s.vmx.cPleWindowTicks defaults to zero, I cannot see how
10501 * this will work... */
10502 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10503 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10504
10505 /*
10506 * Pending debug exceptions.
10507 * Currently just copy whatever the nested-guest provides us.
10508 */
10509 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10510
10511 /*
10512 * I/O Bitmap.
10513 *
10514 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10515 * intercept all I/O port accesses.
10516 */
10517 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10518 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10519
10520 /*
10521 * VMCS shadowing.
10522 *
10523 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10524 * enabled while executing the nested-guest.
10525 */
10526 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10527
10528 /*
10529 * APIC-access page.
10530 */
10531 RTHCPHYS HCPhysApicAccess;
10532 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10533 {
10534 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10535 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10536
10537 /** @todo NSTVMX: This is not really correct but currently is required to make
10538 * things work. We need to re-enable the page handler when we fallback to
10539 * IEM execution of the nested-guest! */
10540 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10541
10542 void *pvPage;
10543 PGMPAGEMAPLOCK PgLockApicAccess;
10544 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10545 if (RT_SUCCESS(rc))
10546 {
10547 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10548 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10549
10550 /** @todo Handle proper releasing of page-mapping lock later. */
10551 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10552 }
10553 else
10554 return rc;
10555 }
10556 else
10557 HCPhysApicAccess = 0;
10558
10559 /*
10560 * Virtual-APIC page and TPR threshold.
10561 */
10562 RTHCPHYS HCPhysVirtApic;
10563 uint32_t u32TprThreshold;
10564 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10565 {
10566 Assert(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10567 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10568
10569 void *pvPage;
10570 PGMPAGEMAPLOCK PgLockVirtApic;
10571 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10572 if (RT_SUCCESS(rc))
10573 {
10574 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10575 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10576
10577 /** @todo Handle proper releasing of page-mapping lock later. */
10578 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10579 }
10580 else
10581 return rc;
10582
10583 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10584 }
10585 else
10586 {
10587 HCPhysVirtApic = 0;
10588 u32TprThreshold = 0;
10589
10590 /*
10591 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10592 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10593 * be taken care of by EPT/shadow paging.
10594 */
10595 if (pVM->hmr0.s.fAllow64BitGuests)
10596 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10597 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10598 }
10599
10600 /*
10601 * Validate basic assumptions.
10602 */
10603 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
10604 Assert(pVM->hmr0.s.vmx.fUnrestrictedGuest);
10605 Assert(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10606 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10607
10608 /*
10609 * Commit it to the nested-guest VMCS.
10610 */
10611 int rc = VINF_SUCCESS;
10612 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10613 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10614 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10615 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10616 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10617 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10618 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10619 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10620 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10621 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10622 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10623 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10624 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10625 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10626 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10627 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10628 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10629 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10630 {
10631 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10632 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10633 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10634 }
10635 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10636 {
10637 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10638 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10639 }
10640 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10641 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10642 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10643 AssertRC(rc);
10644
10645 /*
10646 * Update the nested-guest VMCS cache.
10647 */
10648 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10649 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10650 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10651 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10652 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10653 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10654 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10655 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10656 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10657
10658 /*
10659 * We need to flush the TLB if we are switching the APIC-access page address.
10660 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10661 */
10662 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10663 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10664
10665 /*
10666 * MSR bitmap.
10667 *
10668 * The MSR bitmap address has already been initialized while setting up the nested-guest
10669 * VMCS, here we need to merge the MSR bitmaps.
10670 */
10671 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10672 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10673
10674 return VINF_SUCCESS;
10675}
10676#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10677
10678
10679/**
10680 * Does the preparations before executing guest code in VT-x.
10681 *
10682 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10683 * recompiler/IEM. We must be cautious what we do here regarding committing
10684 * guest-state information into the VMCS assuming we assuredly execute the
10685 * guest in VT-x mode.
10686 *
10687 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10688 * the common-state (TRPM/forceflags), we must undo those changes so that the
10689 * recompiler/IEM can (and should) use them when it resumes guest execution.
10690 * Otherwise such operations must be done when we can no longer exit to ring-3.
10691 *
10692 * @returns Strict VBox status code (i.e. informational status codes too).
10693 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10694 * have been disabled.
10695 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10696 * pending events).
10697 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10698 * double-fault into the guest.
10699 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10700 * dispatched directly.
10701 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10702 *
10703 * @param pVCpu The cross context virtual CPU structure.
10704 * @param pVmxTransient The VMX-transient structure.
10705 * @param fStepping Whether we are single-stepping the guest in the
10706 * hypervisor debugger. Makes us ignore some of the reasons
10707 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10708 * if event dispatching took place.
10709 */
10710static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10711{
10712 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10713
10714 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10715
10716#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10717 if (pVmxTransient->fIsNestedGuest)
10718 {
10719 RT_NOREF2(pVCpu, fStepping);
10720 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10721 return VINF_EM_RESCHEDULE_REM;
10722 }
10723#endif
10724
10725 /*
10726 * Check and process force flag actions, some of which might require us to go back to ring-3.
10727 */
10728 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, pVmxTransient, fStepping);
10729 if (rcStrict == VINF_SUCCESS)
10730 {
10731 /* FFs don't get set all the time. */
10732#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10733 if ( pVmxTransient->fIsNestedGuest
10734 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10735 {
10736 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10737 return VINF_VMX_VMEXIT;
10738 }
10739#endif
10740 }
10741 else
10742 return rcStrict;
10743
10744 /*
10745 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10746 */
10747 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10748 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10749 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10750 && PDMHasApic(pVM))
10751 {
10752 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10753 AssertRCReturn(rc, rc);
10754 }
10755
10756#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10757 /*
10758 * Merge guest VMCS controls with the nested-guest VMCS controls.
10759 *
10760 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10761 * saved state), we should be okay with merging controls as we initialize the
10762 * guest VMCS controls as part of VM setup phase.
10763 */
10764 if ( pVmxTransient->fIsNestedGuest
10765 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10766 {
10767 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10768 AssertRCReturn(rc, rc);
10769 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10770 }
10771#endif
10772
10773 /*
10774 * Evaluate events to be injected into the guest.
10775 *
10776 * Events in TRPM can be injected without inspecting the guest state.
10777 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10778 * guest to cause a VM-exit the next time they are ready to receive the event.
10779 *
10780 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10781 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10782 * subject to interecption. Otherwise, we should have checked and injected them
10783 * manually elsewhere (IEM).
10784 */
10785 if (TRPMHasTrap(pVCpu))
10786 {
10787 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10788 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10789 }
10790
10791 uint32_t fIntrState;
10792 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10793
10794#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10795 /*
10796 * While evaluating pending events if something failed (unlikely) or if we were
10797 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10798 */
10799 if (rcStrict != VINF_SUCCESS)
10800 return rcStrict;
10801 if ( pVmxTransient->fIsNestedGuest
10802 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10803 {
10804 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10805 return VINF_VMX_VMEXIT;
10806 }
10807#else
10808 Assert(rcStrict == VINF_SUCCESS);
10809#endif
10810
10811 /*
10812 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10813 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10814 * also result in triple-faulting the VM.
10815 *
10816 * With nested-guests, the above does not apply since unrestricted guest execution is a
10817 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10818 */
10819 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10820 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10821 { /* likely */ }
10822 else
10823 {
10824 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10825 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10826 return rcStrict;
10827 }
10828
10829 /*
10830 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10831 * import CR3 themselves. We will need to update them here, as even as late as the above
10832 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10833 * the below force flags to be set.
10834 */
10835 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10836 {
10837 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10838 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10839 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10840 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10841 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10842 }
10843 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10844 {
10845 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10846 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10847 }
10848
10849#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10850 /* Paranoia. */
10851 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10852#endif
10853
10854 /*
10855 * No longjmps to ring-3 from this point on!!!
10856 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10857 * This also disables flushing of the R0-logger instance (if any).
10858 */
10859 VMMRZCallRing3Disable(pVCpu);
10860
10861 /*
10862 * Export the guest state bits.
10863 *
10864 * We cannot perform longjmps while loading the guest state because we do not preserve the
10865 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10866 * CPU migration.
10867 *
10868 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10869 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10870 */
10871 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10872 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10873 { /* likely */ }
10874 else
10875 {
10876 VMMRZCallRing3Enable(pVCpu);
10877 return rcStrict;
10878 }
10879
10880 /*
10881 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10882 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10883 * preemption disabled for a while. Since this is purely to aid the
10884 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10885 * disable interrupt on NT.
10886 *
10887 * We need to check for force-flags that could've possible been altered since we last
10888 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10889 * see @bugref{6398}).
10890 *
10891 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10892 * to ring-3 before executing guest code.
10893 */
10894 pVmxTransient->fEFlags = ASMIntDisableFlags();
10895
10896 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10897 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10898 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10899 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10900 {
10901 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10902 {
10903#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10904 /*
10905 * If we are executing a nested-guest make sure that we should intercept subsequent
10906 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10907 * the VM-exit instruction emulation happy.
10908 */
10909 if (pVmxTransient->fIsNestedGuest)
10910 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10911#endif
10912
10913 /*
10914 * We've injected any pending events. This is really the point of no return (to ring-3).
10915 *
10916 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10917 * returns from this function, so do -not- enable them here.
10918 */
10919 pVCpu->hm.s.Event.fPending = false;
10920 return VINF_SUCCESS;
10921 }
10922
10923 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10924 rcStrict = VINF_EM_RAW_INTERRUPT;
10925 }
10926 else
10927 {
10928 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10929 rcStrict = VINF_EM_RAW_TO_R3;
10930 }
10931
10932 ASMSetFlags(pVmxTransient->fEFlags);
10933 VMMRZCallRing3Enable(pVCpu);
10934
10935 return rcStrict;
10936}
10937
10938
10939/**
10940 * Final preparations before executing guest code using hardware-assisted VMX.
10941 *
10942 * We can no longer get preempted to a different host CPU and there are no returns
10943 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10944 * failures), this function is not intended to fail sans unrecoverable hardware
10945 * errors.
10946 *
10947 * @param pVCpu The cross context virtual CPU structure.
10948 * @param pVmxTransient The VMX-transient structure.
10949 *
10950 * @remarks Called with preemption disabled.
10951 * @remarks No-long-jump zone!!!
10952 */
10953static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10954{
10955 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10956 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10957 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10958 Assert(!pVCpu->hm.s.Event.fPending);
10959
10960 /*
10961 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10962 */
10963 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10964 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10965
10966 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10967 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10968 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10969 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10970
10971 if (!CPUMIsGuestFPUStateActive(pVCpu))
10972 {
10973 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10974 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10975 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10976 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10977 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10978 }
10979
10980 /*
10981 * Re-export the host state bits as we may've been preempted (only happens when
10982 * thread-context hooks are used or when the VM start function changes) or if
10983 * the host CR0 is modified while loading the guest FPU state above.
10984 *
10985 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10986 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10987 * see @bugref{8432}.
10988 *
10989 * This may also happen when switching to/from a nested-guest VMCS without leaving
10990 * ring-0.
10991 */
10992 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10993 {
10994 hmR0VmxExportHostState(pVCpu);
10995 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10996 }
10997 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10998
10999 /*
11000 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
11001 */
11002 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
11003 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
11004 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
11005
11006 /*
11007 * Store status of the shared guest/host debug state at the time of VM-entry.
11008 */
11009 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
11010 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11011
11012 /*
11013 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11014 * more than one conditional check. The post-run side of our code shall determine
11015 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11016 */
11017 if (pVmcsInfo->pbVirtApic)
11018 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11019
11020 /*
11021 * Update the host MSRs values in the VM-exit MSR-load area.
11022 */
11023 if (!pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs)
11024 {
11025 if (pVmcsInfo->cExitMsrLoad > 0)
11026 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11027 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = true;
11028 }
11029
11030 /*
11031 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11032 * VMX-preemption timer based on the next virtual sync clock deadline.
11033 */
11034 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11035 || idCurrentCpu != pVCpu->hmr0.s.idLastCpu)
11036 {
11037 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
11038 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11039 }
11040
11041 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11042 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11043 if (!fIsRdtscIntercepted)
11044 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11045 else
11046 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11047
11048 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11049 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11050 Assert(idCurrentCpu == pVCpu->hmr0.s.idLastCpu);
11051 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
11052 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
11053 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
11054
11055 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11056
11057 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11058 as we're about to start executing the guest. */
11059
11060 /*
11061 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11062 *
11063 * This is done this late as updating the TSC offsetting/preemption timer above
11064 * figures out if we can skip intercepting RDTSCP by calculating the number of
11065 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11066 */
11067 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11068 && !fIsRdtscIntercepted)
11069 {
11070 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11071
11072 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11073 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11074 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11075 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11076 AssertRC(rc);
11077 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11078 pVmxTransient->fRemoveTscAuxMsr = true;
11079 }
11080
11081#ifdef VBOX_STRICT
11082 Assert(pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs);
11083 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11084 hmR0VmxCheckHostEferMsr(pVmcsInfo);
11085 AssertRC(hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11086#endif
11087
11088#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11089 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11090 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11091 * see @bugref{9180#c54}. */
11092 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11093 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11094 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11095#endif
11096}
11097
11098
11099/**
11100 * First C routine invoked after running guest code using hardware-assisted VMX.
11101 *
11102 * @param pVCpu The cross context virtual CPU structure.
11103 * @param pVmxTransient The VMX-transient structure.
11104 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11105 *
11106 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11107 *
11108 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11109 * unconditionally when it is safe to do so.
11110 */
11111static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11112{
11113 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
11114
11115 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11116 ASMAtomicIncU32(&pVCpu->hmr0.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11117 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11118 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11119 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11120 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11121
11122 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11123 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11124 {
11125 uint64_t uGstTsc;
11126 if (!pVmxTransient->fIsNestedGuest)
11127 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11128 else
11129 {
11130 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11131 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11132 }
11133 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11134 }
11135
11136 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11137 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
11138 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11139
11140 pVCpu->hmr0.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11141 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11142#ifdef VBOX_STRICT
11143 hmR0VmxCheckHostEferMsr(pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11144#endif
11145 Assert(!ASMIntAreEnabled());
11146 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11147 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11148
11149#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11150 /*
11151 * Clean all the VMCS fields in the transient structure before reading
11152 * anything from the VMCS.
11153 */
11154 pVmxTransient->uExitReason = 0;
11155 pVmxTransient->uExitIntErrorCode = 0;
11156 pVmxTransient->uExitQual = 0;
11157 pVmxTransient->uGuestLinearAddr = 0;
11158 pVmxTransient->uExitIntInfo = 0;
11159 pVmxTransient->cbExitInstr = 0;
11160 pVmxTransient->ExitInstrInfo.u = 0;
11161 pVmxTransient->uEntryIntInfo = 0;
11162 pVmxTransient->uEntryXcptErrorCode = 0;
11163 pVmxTransient->cbEntryInstr = 0;
11164 pVmxTransient->uIdtVectoringInfo = 0;
11165 pVmxTransient->uIdtVectoringErrorCode = 0;
11166#endif
11167
11168 /*
11169 * Save the basic VM-exit reason and check if the VM-entry failed.
11170 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11171 */
11172 uint32_t uExitReason;
11173 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11174 AssertRC(rc);
11175 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11176 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11177
11178 /*
11179 * Log the VM-exit before logging anything else as otherwise it might be a
11180 * tad confusing what happens before and after the world-switch.
11181 */
11182 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11183
11184 /*
11185 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11186 * bitmap permissions, if it was added before VM-entry.
11187 */
11188 if (pVmxTransient->fRemoveTscAuxMsr)
11189 {
11190 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11191 pVmxTransient->fRemoveTscAuxMsr = false;
11192 }
11193
11194 /*
11195 * Check if VMLAUNCH/VMRESUME succeeded.
11196 * If this failed, we cause a guru meditation and cease further execution.
11197 *
11198 * However, if we are executing a nested-guest we might fail if we use the
11199 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11200 */
11201 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11202 {
11203 /*
11204 * Update the VM-exit history array here even if the VM-entry failed due to:
11205 * - Invalid guest state.
11206 * - MSR loading.
11207 * - Machine-check event.
11208 *
11209 * In any of the above cases we will still have a "valid" VM-exit reason
11210 * despite @a fVMEntryFailed being false.
11211 *
11212 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11213 *
11214 * Note! We don't have CS or RIP at this point. Will probably address that later
11215 * by amending the history entry added here.
11216 */
11217 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11218 UINT64_MAX, uHostTsc);
11219
11220 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11221 {
11222 VMMRZCallRing3Enable(pVCpu);
11223
11224 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11225 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11226
11227#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
11228 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
11229#endif
11230
11231 /*
11232 * Import the guest-interruptibility state always as we need it while evaluating
11233 * injecting events on re-entry.
11234 *
11235 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11236 * checking for real-mode while exporting the state because all bits that cause
11237 * mode changes wrt CR0 are intercepted.
11238 */
11239 uint64_t const fImportMask = CPUMCTX_EXTRN_HM_VMX_INT_STATE
11240#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11241 | HMVMX_CPUMCTX_EXTRN_ALL
11242#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11243 | CPUMCTX_EXTRN_RFLAGS
11244#endif
11245 ;
11246 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImportMask);
11247 AssertRC(rc);
11248
11249 /*
11250 * Sync the TPR shadow with our APIC state.
11251 */
11252 if ( !pVmxTransient->fIsNestedGuest
11253 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
11254 {
11255 Assert(pVmcsInfo->pbVirtApic);
11256 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11257 {
11258 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11259 AssertRC(rc);
11260 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11261 }
11262 }
11263
11264 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11265 return;
11266 }
11267 }
11268#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11269 else if (pVmxTransient->fIsNestedGuest)
11270 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11271#endif
11272 else
11273 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11274
11275 VMMRZCallRing3Enable(pVCpu);
11276}
11277
11278
11279/**
11280 * Runs the guest code using hardware-assisted VMX the normal way.
11281 *
11282 * @returns VBox status code.
11283 * @param pVCpu The cross context virtual CPU structure.
11284 * @param pcLoops Pointer to the number of executed loops.
11285 */
11286static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
11287{
11288 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
11289 Assert(pcLoops);
11290 Assert(*pcLoops <= cMaxResumeLoops);
11291 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11292
11293#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11294 /*
11295 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11296 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11297 * guest VMCS while entering the VMX ring-0 session.
11298 */
11299 if (pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
11300 {
11301 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11302 if (RT_SUCCESS(rc))
11303 { /* likely */ }
11304 else
11305 {
11306 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11307 return rc;
11308 }
11309 }
11310#endif
11311
11312 VMXTRANSIENT VmxTransient;
11313 RT_ZERO(VmxTransient);
11314 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11315
11316 /* Paranoia. */
11317 Assert(VmxTransient.pVmcsInfo == &pVCpu->hmr0.s.vmx.VmcsInfo);
11318
11319 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11320 for (;;)
11321 {
11322 Assert(!HMR0SuspendPending());
11323 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11324 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11325
11326 /*
11327 * Preparatory work for running nested-guest code, this may force us to
11328 * return to ring-3.
11329 *
11330 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11331 */
11332 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11333 if (rcStrict != VINF_SUCCESS)
11334 break;
11335
11336 /* Interrupts are disabled at this point! */
11337 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11338 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11339 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11340 /* Interrupts are re-enabled at this point! */
11341
11342 /*
11343 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11344 */
11345 if (RT_SUCCESS(rcRun))
11346 { /* very likely */ }
11347 else
11348 {
11349 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11350 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11351 return rcRun;
11352 }
11353
11354 /*
11355 * Profile the VM-exit.
11356 */
11357 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11358 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11359 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11360 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11361 HMVMX_START_EXIT_DISPATCH_PROF();
11362
11363 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11364
11365 /*
11366 * Handle the VM-exit.
11367 */
11368#ifdef HMVMX_USE_FUNCTION_TABLE
11369 rcStrict = g_aVMExitHandlers[VmxTransient.uExitReason].pfn(pVCpu, &VmxTransient);
11370#else
11371 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11372#endif
11373 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11374 if (rcStrict == VINF_SUCCESS)
11375 {
11376 if (++(*pcLoops) <= cMaxResumeLoops)
11377 continue;
11378 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11379 rcStrict = VINF_EM_RAW_INTERRUPT;
11380 }
11381 break;
11382 }
11383
11384 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11385 return rcStrict;
11386}
11387
11388
11389#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11390/**
11391 * Runs the nested-guest code using hardware-assisted VMX.
11392 *
11393 * @returns VBox status code.
11394 * @param pVCpu The cross context virtual CPU structure.
11395 * @param pcLoops Pointer to the number of executed loops.
11396 *
11397 * @sa hmR0VmxRunGuestCodeNormal.
11398 */
11399static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
11400{
11401 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
11402 Assert(pcLoops);
11403 Assert(*pcLoops <= cMaxResumeLoops);
11404 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11405
11406 /*
11407 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11408 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11409 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11410 */
11411 if (!pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
11412 {
11413 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11414 if (RT_SUCCESS(rc))
11415 { /* likely */ }
11416 else
11417 {
11418 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11419 return rc;
11420 }
11421 }
11422
11423 VMXTRANSIENT VmxTransient;
11424 RT_ZERO(VmxTransient);
11425 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11426 VmxTransient.fIsNestedGuest = true;
11427
11428 /* Paranoia. */
11429 Assert(VmxTransient.pVmcsInfo == &pVCpu->hmr0.s.vmx.VmcsInfoNstGst);
11430
11431 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11432 for (;;)
11433 {
11434 Assert(!HMR0SuspendPending());
11435 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11436 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11437
11438 /*
11439 * Preparatory work for running guest code, this may force us to
11440 * return to ring-3.
11441 *
11442 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11443 */
11444 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11445 if (rcStrict != VINF_SUCCESS)
11446 break;
11447
11448 /* Interrupts are disabled at this point! */
11449 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11450 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11451 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11452 /* Interrupts are re-enabled at this point! */
11453
11454 /*
11455 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11456 */
11457 if (RT_SUCCESS(rcRun))
11458 { /* very likely */ }
11459 else
11460 {
11461 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11462 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11463 return rcRun;
11464 }
11465
11466 /*
11467 * Profile the VM-exit.
11468 */
11469 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11470 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11471 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11472 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11473 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11474 HMVMX_START_EXIT_DISPATCH_PROF();
11475
11476 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11477
11478 /*
11479 * Handle the VM-exit.
11480 */
11481 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11482 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11483 if (rcStrict == VINF_SUCCESS)
11484 {
11485 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11486 {
11487 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11488 rcStrict = VINF_VMX_VMEXIT;
11489 }
11490 else
11491 {
11492 if (++(*pcLoops) <= cMaxResumeLoops)
11493 continue;
11494 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11495 rcStrict = VINF_EM_RAW_INTERRUPT;
11496 }
11497 }
11498 else
11499 Assert(rcStrict != VINF_VMX_VMEXIT);
11500 break;
11501 }
11502
11503 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11504 return rcStrict;
11505}
11506#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11507
11508
11509/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11510 * probes.
11511 *
11512 * The following few functions and associated structure contains the bloat
11513 * necessary for providing detailed debug events and dtrace probes as well as
11514 * reliable host side single stepping. This works on the principle of
11515 * "subclassing" the normal execution loop and workers. We replace the loop
11516 * method completely and override selected helpers to add necessary adjustments
11517 * to their core operation.
11518 *
11519 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11520 * any performance for debug and analysis features.
11521 *
11522 * @{
11523 */
11524
11525/**
11526 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11527 * the debug run loop.
11528 */
11529typedef struct VMXRUNDBGSTATE
11530{
11531 /** The RIP we started executing at. This is for detecting that we stepped. */
11532 uint64_t uRipStart;
11533 /** The CS we started executing with. */
11534 uint16_t uCsStart;
11535
11536 /** Whether we've actually modified the 1st execution control field. */
11537 bool fModifiedProcCtls : 1;
11538 /** Whether we've actually modified the 2nd execution control field. */
11539 bool fModifiedProcCtls2 : 1;
11540 /** Whether we've actually modified the exception bitmap. */
11541 bool fModifiedXcptBitmap : 1;
11542
11543 /** We desire the modified the CR0 mask to be cleared. */
11544 bool fClearCr0Mask : 1;
11545 /** We desire the modified the CR4 mask to be cleared. */
11546 bool fClearCr4Mask : 1;
11547 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11548 uint32_t fCpe1Extra;
11549 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11550 uint32_t fCpe1Unwanted;
11551 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11552 uint32_t fCpe2Extra;
11553 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11554 uint32_t bmXcptExtra;
11555 /** The sequence number of the Dtrace provider settings the state was
11556 * configured against. */
11557 uint32_t uDtraceSettingsSeqNo;
11558 /** VM-exits to check (one bit per VM-exit). */
11559 uint32_t bmExitsToCheck[3];
11560
11561 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11562 uint32_t fProcCtlsInitial;
11563 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11564 uint32_t fProcCtls2Initial;
11565 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11566 uint32_t bmXcptInitial;
11567} VMXRUNDBGSTATE;
11568AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11569typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11570
11571
11572/**
11573 * Initializes the VMXRUNDBGSTATE structure.
11574 *
11575 * @param pVCpu The cross context virtual CPU structure of the
11576 * calling EMT.
11577 * @param pVmxTransient The VMX-transient structure.
11578 * @param pDbgState The debug state to initialize.
11579 */
11580static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11581{
11582 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11583 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11584
11585 pDbgState->fModifiedProcCtls = false;
11586 pDbgState->fModifiedProcCtls2 = false;
11587 pDbgState->fModifiedXcptBitmap = false;
11588 pDbgState->fClearCr0Mask = false;
11589 pDbgState->fClearCr4Mask = false;
11590 pDbgState->fCpe1Extra = 0;
11591 pDbgState->fCpe1Unwanted = 0;
11592 pDbgState->fCpe2Extra = 0;
11593 pDbgState->bmXcptExtra = 0;
11594 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11595 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11596 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11597}
11598
11599
11600/**
11601 * Updates the VMSC fields with changes requested by @a pDbgState.
11602 *
11603 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11604 * immediately before executing guest code, i.e. when interrupts are disabled.
11605 * We don't check status codes here as we cannot easily assert or return in the
11606 * latter case.
11607 *
11608 * @param pVCpu The cross context virtual CPU structure.
11609 * @param pVmxTransient The VMX-transient structure.
11610 * @param pDbgState The debug state.
11611 */
11612static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11613{
11614 /*
11615 * Ensure desired flags in VMCS control fields are set.
11616 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11617 *
11618 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11619 * there should be no stale data in pCtx at this point.
11620 */
11621 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11622 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11623 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11624 {
11625 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11626 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11627 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11628 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11629 pDbgState->fModifiedProcCtls = true;
11630 }
11631
11632 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11633 {
11634 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11635 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11636 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11637 pDbgState->fModifiedProcCtls2 = true;
11638 }
11639
11640 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11641 {
11642 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11643 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11644 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11645 pDbgState->fModifiedXcptBitmap = true;
11646 }
11647
11648 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11649 {
11650 pVmcsInfo->u64Cr0Mask = 0;
11651 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11652 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11653 }
11654
11655 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11656 {
11657 pVmcsInfo->u64Cr4Mask = 0;
11658 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11659 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11660 }
11661
11662 NOREF(pVCpu);
11663}
11664
11665
11666/**
11667 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11668 * re-entry next time around.
11669 *
11670 * @returns Strict VBox status code (i.e. informational status codes too).
11671 * @param pVCpu The cross context virtual CPU structure.
11672 * @param pVmxTransient The VMX-transient structure.
11673 * @param pDbgState The debug state.
11674 * @param rcStrict The return code from executing the guest using single
11675 * stepping.
11676 */
11677static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11678 VBOXSTRICTRC rcStrict)
11679{
11680 /*
11681 * Restore VM-exit control settings as we may not reenter this function the
11682 * next time around.
11683 */
11684 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11685
11686 /* We reload the initial value, trigger what we can of recalculations the
11687 next time around. From the looks of things, that's all that's required atm. */
11688 if (pDbgState->fModifiedProcCtls)
11689 {
11690 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11691 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11692 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11693 AssertRC(rc2);
11694 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11695 }
11696
11697 /* We're currently the only ones messing with this one, so just restore the
11698 cached value and reload the field. */
11699 if ( pDbgState->fModifiedProcCtls2
11700 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11701 {
11702 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11703 AssertRC(rc2);
11704 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11705 }
11706
11707 /* If we've modified the exception bitmap, we restore it and trigger
11708 reloading and partial recalculation the next time around. */
11709 if (pDbgState->fModifiedXcptBitmap)
11710 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11711
11712 return rcStrict;
11713}
11714
11715
11716/**
11717 * Configures VM-exit controls for current DBGF and DTrace settings.
11718 *
11719 * This updates @a pDbgState and the VMCS execution control fields to reflect
11720 * the necessary VM-exits demanded by DBGF and DTrace.
11721 *
11722 * @param pVCpu The cross context virtual CPU structure.
11723 * @param pVmxTransient The VMX-transient structure. May update
11724 * fUpdatedTscOffsettingAndPreemptTimer.
11725 * @param pDbgState The debug state.
11726 */
11727static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11728{
11729 /*
11730 * Take down the dtrace serial number so we can spot changes.
11731 */
11732 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11733 ASMCompilerBarrier();
11734
11735 /*
11736 * We'll rebuild most of the middle block of data members (holding the
11737 * current settings) as we go along here, so start by clearing it all.
11738 */
11739 pDbgState->bmXcptExtra = 0;
11740 pDbgState->fCpe1Extra = 0;
11741 pDbgState->fCpe1Unwanted = 0;
11742 pDbgState->fCpe2Extra = 0;
11743 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11744 pDbgState->bmExitsToCheck[i] = 0;
11745
11746 /*
11747 * Software interrupts (INT XXh) - no idea how to trigger these...
11748 */
11749 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11750 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11751 || VBOXVMM_INT_SOFTWARE_ENABLED())
11752 {
11753 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11754 }
11755
11756 /*
11757 * INT3 breakpoints - triggered by #BP exceptions.
11758 */
11759 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11760 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11761
11762 /*
11763 * Exception bitmap and XCPT events+probes.
11764 */
11765 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11766 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11767 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11768
11769 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11770 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11771 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11772 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11773 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11774 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11775 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11776 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11777 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11778 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11779 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11780 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11781 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11782 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11783 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11784 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11785 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11786 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11787
11788 if (pDbgState->bmXcptExtra)
11789 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11790
11791 /*
11792 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11793 *
11794 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11795 * So, when adding/changing/removing please don't forget to update it.
11796 *
11797 * Some of the macros are picking up local variables to save horizontal space,
11798 * (being able to see it in a table is the lesser evil here).
11799 */
11800#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11801 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11802 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11803#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11804 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11805 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11806 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11807 } else do { } while (0)
11808#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11809 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11810 { \
11811 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11812 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11813 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11814 } else do { } while (0)
11815#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11816 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11817 { \
11818 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11819 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11820 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11821 } else do { } while (0)
11822#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11823 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11824 { \
11825 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11826 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11827 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11828 } else do { } while (0)
11829
11830 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11831 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11832 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11833 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11834 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11835
11836 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11837 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11838 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11839 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11840 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11841 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11842 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11843 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11844 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11845 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11846 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11847 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11848 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11849 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11850 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11851 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11852 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11853 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11854 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11855 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11856 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11857 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11858 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11859 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11860 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11861 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11862 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11863 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11864 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11865 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11866 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11867 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11868 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11869 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11870 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11871 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11872
11873 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11874 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11875 {
11876 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11877 | CPUMCTX_EXTRN_APIC_TPR);
11878 AssertRC(rc);
11879
11880#if 0 /** @todo fix me */
11881 pDbgState->fClearCr0Mask = true;
11882 pDbgState->fClearCr4Mask = true;
11883#endif
11884 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11885 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11886 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11887 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11888 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11889 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11890 require clearing here and in the loop if we start using it. */
11891 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11892 }
11893 else
11894 {
11895 if (pDbgState->fClearCr0Mask)
11896 {
11897 pDbgState->fClearCr0Mask = false;
11898 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11899 }
11900 if (pDbgState->fClearCr4Mask)
11901 {
11902 pDbgState->fClearCr4Mask = false;
11903 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11904 }
11905 }
11906 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11907 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11908
11909 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11910 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11911 {
11912 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11913 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11914 }
11915 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11916 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11917
11918 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11919 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11920 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11921 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11922 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11923 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11924 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11925 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11926#if 0 /** @todo too slow, fix handler. */
11927 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11928#endif
11929 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11930
11931 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11932 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11933 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11934 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11935 {
11936 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11937 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11938 }
11939 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11940 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11941 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11942 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11943
11944 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11945 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11946 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11947 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11948 {
11949 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11950 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11951 }
11952 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11953 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11954 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11955 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11956
11957 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11958 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11959 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11960 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11961 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11962 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11963 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11964 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11965 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11966 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11967 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11968 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11969 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11970 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11971 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11972 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11973 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11974 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11975 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11976 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11977 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11978 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11979
11980#undef IS_EITHER_ENABLED
11981#undef SET_ONLY_XBM_IF_EITHER_EN
11982#undef SET_CPE1_XBM_IF_EITHER_EN
11983#undef SET_CPEU_XBM_IF_EITHER_EN
11984#undef SET_CPE2_XBM_IF_EITHER_EN
11985
11986 /*
11987 * Sanitize the control stuff.
11988 */
11989 pDbgState->fCpe2Extra &= g_HmMsrs.u.vmx.ProcCtls2.n.allowed1;
11990 if (pDbgState->fCpe2Extra)
11991 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11992 pDbgState->fCpe1Extra &= g_HmMsrs.u.vmx.ProcCtls.n.allowed1;
11993 pDbgState->fCpe1Unwanted &= ~g_HmMsrs.u.vmx.ProcCtls.n.allowed0;
11994 if (pVCpu->hmr0.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11995 {
11996 pVCpu->hmr0.s.fDebugWantRdTscExit ^= true;
11997 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11998 }
11999
12000 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
12001 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
12002 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
12003 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
12004}
12005
12006
12007/**
12008 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
12009 * appropriate.
12010 *
12011 * The caller has checked the VM-exit against the
12012 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12013 * already, so we don't have to do that either.
12014 *
12015 * @returns Strict VBox status code (i.e. informational status codes too).
12016 * @param pVCpu The cross context virtual CPU structure.
12017 * @param pVmxTransient The VMX-transient structure.
12018 * @param uExitReason The VM-exit reason.
12019 *
12020 * @remarks The name of this function is displayed by dtrace, so keep it short
12021 * and to the point. No longer than 33 chars long, please.
12022 */
12023static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12024{
12025 /*
12026 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12027 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12028 *
12029 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12030 * does. Must add/change/remove both places. Same ordering, please.
12031 *
12032 * Added/removed events must also be reflected in the next section
12033 * where we dispatch dtrace events.
12034 */
12035 bool fDtrace1 = false;
12036 bool fDtrace2 = false;
12037 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12038 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12039 uint32_t uEventArg = 0;
12040#define SET_EXIT(a_EventSubName) \
12041 do { \
12042 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12043 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12044 } while (0)
12045#define SET_BOTH(a_EventSubName) \
12046 do { \
12047 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12048 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12049 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12050 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12051 } while (0)
12052 switch (uExitReason)
12053 {
12054 case VMX_EXIT_MTF:
12055 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12056
12057 case VMX_EXIT_XCPT_OR_NMI:
12058 {
12059 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12060 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12061 {
12062 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12063 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12064 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12065 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12066 {
12067 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12068 {
12069 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12070 uEventArg = pVmxTransient->uExitIntErrorCode;
12071 }
12072 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12073 switch (enmEvent1)
12074 {
12075 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12076 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12077 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12078 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12079 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12080 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12081 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12082 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12083 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12084 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12085 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12086 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12087 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12088 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12089 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12090 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12091 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12092 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12093 default: break;
12094 }
12095 }
12096 else
12097 AssertFailed();
12098 break;
12099
12100 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12101 uEventArg = idxVector;
12102 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12103 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12104 break;
12105 }
12106 break;
12107 }
12108
12109 case VMX_EXIT_TRIPLE_FAULT:
12110 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12111 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12112 break;
12113 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12114 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12115 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12116 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12117 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12118
12119 /* Instruction specific VM-exits: */
12120 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12121 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12122 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12123 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12124 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12125 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12126 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12127 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12128 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12129 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12130 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12131 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12132 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12133 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12134 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12135 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12136 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12137 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12138 case VMX_EXIT_MOV_CRX:
12139 hmR0VmxReadExitQualVmcs(pVmxTransient);
12140 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12141 SET_BOTH(CRX_READ);
12142 else
12143 SET_BOTH(CRX_WRITE);
12144 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12145 break;
12146 case VMX_EXIT_MOV_DRX:
12147 hmR0VmxReadExitQualVmcs(pVmxTransient);
12148 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12149 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12150 SET_BOTH(DRX_READ);
12151 else
12152 SET_BOTH(DRX_WRITE);
12153 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12154 break;
12155 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12156 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12157 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12158 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12159 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12160 case VMX_EXIT_GDTR_IDTR_ACCESS:
12161 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12162 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12163 {
12164 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12165 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12166 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12167 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12168 }
12169 break;
12170
12171 case VMX_EXIT_LDTR_TR_ACCESS:
12172 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12173 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12174 {
12175 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12176 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12177 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12178 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12179 }
12180 break;
12181
12182 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12183 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12184 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12185 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12186 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12187 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12188 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12189 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12190 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12191 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12192 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12193
12194 /* Events that aren't relevant at this point. */
12195 case VMX_EXIT_EXT_INT:
12196 case VMX_EXIT_INT_WINDOW:
12197 case VMX_EXIT_NMI_WINDOW:
12198 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12199 case VMX_EXIT_PREEMPT_TIMER:
12200 case VMX_EXIT_IO_INSTR:
12201 break;
12202
12203 /* Errors and unexpected events. */
12204 case VMX_EXIT_INIT_SIGNAL:
12205 case VMX_EXIT_SIPI:
12206 case VMX_EXIT_IO_SMI:
12207 case VMX_EXIT_SMI:
12208 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12209 case VMX_EXIT_ERR_MSR_LOAD:
12210 case VMX_EXIT_ERR_MACHINE_CHECK:
12211 case VMX_EXIT_PML_FULL:
12212 case VMX_EXIT_VIRTUALIZED_EOI:
12213 break;
12214
12215 default:
12216 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12217 break;
12218 }
12219#undef SET_BOTH
12220#undef SET_EXIT
12221
12222 /*
12223 * Dtrace tracepoints go first. We do them here at once so we don't
12224 * have to copy the guest state saving and stuff a few dozen times.
12225 * Down side is that we've got to repeat the switch, though this time
12226 * we use enmEvent since the probes are a subset of what DBGF does.
12227 */
12228 if (fDtrace1 || fDtrace2)
12229 {
12230 hmR0VmxReadExitQualVmcs(pVmxTransient);
12231 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12232 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12233 switch (enmEvent1)
12234 {
12235 /** @todo consider which extra parameters would be helpful for each probe. */
12236 case DBGFEVENT_END: break;
12237 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12238 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12239 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12240 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12241 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12242 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12243 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12244 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12245 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12246 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12247 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12248 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12249 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12250 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12251 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12252 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12253 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12254 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12255 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12256 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12257 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12258 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12259 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12260 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12261 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12262 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12263 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12264 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12265 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12266 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12267 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12268 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12269 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12270 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12271 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12272 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12273 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12274 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12275 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12276 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12277 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12278 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12279 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12280 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12281 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12282 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12283 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12284 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12285 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12286 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12287 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12288 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12289 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12290 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12291 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12292 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12293 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12294 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12295 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12296 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12297 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12298 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12299 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12300 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12301 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12302 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12303 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12304 }
12305 switch (enmEvent2)
12306 {
12307 /** @todo consider which extra parameters would be helpful for each probe. */
12308 case DBGFEVENT_END: break;
12309 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12310 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12311 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12312 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12313 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12314 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12315 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12316 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12317 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12318 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12319 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12320 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12321 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12322 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12323 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12324 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12325 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12326 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12327 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12328 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12329 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12330 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12331 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12332 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12333 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12334 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12335 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12336 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12337 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12338 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12339 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12340 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12341 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12342 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12343 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12344 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12345 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12346 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12347 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12348 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12349 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12350 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12351 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12352 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12353 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12354 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12355 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12356 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12357 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12358 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12359 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12360 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12361 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12362 }
12363 }
12364
12365 /*
12366 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12367 * the DBGF call will do a full check).
12368 *
12369 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12370 * Note! If we have to events, we prioritize the first, i.e. the instruction
12371 * one, in order to avoid event nesting.
12372 */
12373 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
12374 if ( enmEvent1 != DBGFEVENT_END
12375 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12376 {
12377 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12378 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12379 if (rcStrict != VINF_SUCCESS)
12380 return rcStrict;
12381 }
12382 else if ( enmEvent2 != DBGFEVENT_END
12383 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12384 {
12385 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12386 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12387 if (rcStrict != VINF_SUCCESS)
12388 return rcStrict;
12389 }
12390
12391 return VINF_SUCCESS;
12392}
12393
12394
12395/**
12396 * Single-stepping VM-exit filtering.
12397 *
12398 * This is preprocessing the VM-exits and deciding whether we've gotten far
12399 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12400 * handling is performed.
12401 *
12402 * @returns Strict VBox status code (i.e. informational status codes too).
12403 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12404 * @param pVmxTransient The VMX-transient structure.
12405 * @param pDbgState The debug state.
12406 */
12407DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12408{
12409 /*
12410 * Expensive (saves context) generic dtrace VM-exit probe.
12411 */
12412 uint32_t const uExitReason = pVmxTransient->uExitReason;
12413 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12414 { /* more likely */ }
12415 else
12416 {
12417 hmR0VmxReadExitQualVmcs(pVmxTransient);
12418 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12419 AssertRC(rc);
12420 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12421 }
12422
12423 /*
12424 * Check for host NMI, just to get that out of the way.
12425 */
12426 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12427 { /* normally likely */ }
12428 else
12429 {
12430 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12431 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12432 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12433 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12434 }
12435
12436 /*
12437 * Check for single stepping event if we're stepping.
12438 */
12439 if (pVCpu->hm.s.fSingleInstruction)
12440 {
12441 switch (uExitReason)
12442 {
12443 case VMX_EXIT_MTF:
12444 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12445
12446 /* Various events: */
12447 case VMX_EXIT_XCPT_OR_NMI:
12448 case VMX_EXIT_EXT_INT:
12449 case VMX_EXIT_TRIPLE_FAULT:
12450 case VMX_EXIT_INT_WINDOW:
12451 case VMX_EXIT_NMI_WINDOW:
12452 case VMX_EXIT_TASK_SWITCH:
12453 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12454 case VMX_EXIT_APIC_ACCESS:
12455 case VMX_EXIT_EPT_VIOLATION:
12456 case VMX_EXIT_EPT_MISCONFIG:
12457 case VMX_EXIT_PREEMPT_TIMER:
12458
12459 /* Instruction specific VM-exits: */
12460 case VMX_EXIT_CPUID:
12461 case VMX_EXIT_GETSEC:
12462 case VMX_EXIT_HLT:
12463 case VMX_EXIT_INVD:
12464 case VMX_EXIT_INVLPG:
12465 case VMX_EXIT_RDPMC:
12466 case VMX_EXIT_RDTSC:
12467 case VMX_EXIT_RSM:
12468 case VMX_EXIT_VMCALL:
12469 case VMX_EXIT_VMCLEAR:
12470 case VMX_EXIT_VMLAUNCH:
12471 case VMX_EXIT_VMPTRLD:
12472 case VMX_EXIT_VMPTRST:
12473 case VMX_EXIT_VMREAD:
12474 case VMX_EXIT_VMRESUME:
12475 case VMX_EXIT_VMWRITE:
12476 case VMX_EXIT_VMXOFF:
12477 case VMX_EXIT_VMXON:
12478 case VMX_EXIT_MOV_CRX:
12479 case VMX_EXIT_MOV_DRX:
12480 case VMX_EXIT_IO_INSTR:
12481 case VMX_EXIT_RDMSR:
12482 case VMX_EXIT_WRMSR:
12483 case VMX_EXIT_MWAIT:
12484 case VMX_EXIT_MONITOR:
12485 case VMX_EXIT_PAUSE:
12486 case VMX_EXIT_GDTR_IDTR_ACCESS:
12487 case VMX_EXIT_LDTR_TR_ACCESS:
12488 case VMX_EXIT_INVEPT:
12489 case VMX_EXIT_RDTSCP:
12490 case VMX_EXIT_INVVPID:
12491 case VMX_EXIT_WBINVD:
12492 case VMX_EXIT_XSETBV:
12493 case VMX_EXIT_RDRAND:
12494 case VMX_EXIT_INVPCID:
12495 case VMX_EXIT_VMFUNC:
12496 case VMX_EXIT_RDSEED:
12497 case VMX_EXIT_XSAVES:
12498 case VMX_EXIT_XRSTORS:
12499 {
12500 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12501 AssertRCReturn(rc, rc);
12502 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12503 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12504 return VINF_EM_DBG_STEPPED;
12505 break;
12506 }
12507
12508 /* Errors and unexpected events: */
12509 case VMX_EXIT_INIT_SIGNAL:
12510 case VMX_EXIT_SIPI:
12511 case VMX_EXIT_IO_SMI:
12512 case VMX_EXIT_SMI:
12513 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12514 case VMX_EXIT_ERR_MSR_LOAD:
12515 case VMX_EXIT_ERR_MACHINE_CHECK:
12516 case VMX_EXIT_PML_FULL:
12517 case VMX_EXIT_VIRTUALIZED_EOI:
12518 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12519 break;
12520
12521 default:
12522 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12523 break;
12524 }
12525 }
12526
12527 /*
12528 * Check for debugger event breakpoints and dtrace probes.
12529 */
12530 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12531 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12532 {
12533 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12534 if (rcStrict != VINF_SUCCESS)
12535 return rcStrict;
12536 }
12537
12538 /*
12539 * Normal processing.
12540 */
12541#ifdef HMVMX_USE_FUNCTION_TABLE
12542 return g_aVMExitHandlers[uExitReason].pfn(pVCpu, pVmxTransient);
12543#else
12544 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12545#endif
12546}
12547
12548
12549/**
12550 * Single steps guest code using hardware-assisted VMX.
12551 *
12552 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12553 * but single-stepping through the hypervisor debugger.
12554 *
12555 * @returns Strict VBox status code (i.e. informational status codes too).
12556 * @param pVCpu The cross context virtual CPU structure.
12557 * @param pcLoops Pointer to the number of executed loops.
12558 *
12559 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12560 */
12561static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12562{
12563 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
12564 Assert(pcLoops);
12565 Assert(*pcLoops <= cMaxResumeLoops);
12566
12567 VMXTRANSIENT VmxTransient;
12568 RT_ZERO(VmxTransient);
12569 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12570
12571 /* Set HMCPU indicators. */
12572 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12573 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12574 pVCpu->hmr0.s.fDebugWantRdTscExit = false;
12575 pVCpu->hmr0.s.fUsingDebugLoop = true;
12576
12577 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12578 VMXRUNDBGSTATE DbgState;
12579 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12580 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12581
12582 /*
12583 * The loop.
12584 */
12585 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12586 for (;;)
12587 {
12588 Assert(!HMR0SuspendPending());
12589 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12590 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12591 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12592
12593 /* Set up VM-execution controls the next two can respond to. */
12594 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12595
12596 /*
12597 * Preparatory work for running guest code, this may force us to
12598 * return to ring-3.
12599 *
12600 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12601 */
12602 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12603 if (rcStrict != VINF_SUCCESS)
12604 break;
12605
12606 /* Interrupts are disabled at this point! */
12607 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12608
12609 /* Override any obnoxious code in the above two calls. */
12610 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12611
12612 /*
12613 * Finally execute the guest.
12614 */
12615 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12616
12617 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12618 /* Interrupts are re-enabled at this point! */
12619
12620 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12621 if (RT_SUCCESS(rcRun))
12622 { /* very likely */ }
12623 else
12624 {
12625 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12626 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12627 return rcRun;
12628 }
12629
12630 /* Profile the VM-exit. */
12631 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12632 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12633 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12634 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12635 HMVMX_START_EXIT_DISPATCH_PROF();
12636
12637 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12638
12639 /*
12640 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12641 */
12642 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12643 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12644 if (rcStrict != VINF_SUCCESS)
12645 break;
12646 if (++(*pcLoops) > cMaxResumeLoops)
12647 {
12648 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12649 rcStrict = VINF_EM_RAW_INTERRUPT;
12650 break;
12651 }
12652
12653 /*
12654 * Stepping: Did the RIP change, if so, consider it a single step.
12655 * Otherwise, make sure one of the TFs gets set.
12656 */
12657 if (fStepping)
12658 {
12659 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12660 AssertRC(rc);
12661 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12662 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12663 {
12664 rcStrict = VINF_EM_DBG_STEPPED;
12665 break;
12666 }
12667 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12668 }
12669
12670 /*
12671 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12672 */
12673 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12674 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12675
12676 /* Restore all controls applied by hmR0VmxPreRunGuestDebugStateApply above. */
12677 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12678 Assert(rcStrict == VINF_SUCCESS);
12679 }
12680
12681 /*
12682 * Clear the X86_EFL_TF if necessary.
12683 */
12684 if (pVCpu->hmr0.s.fClearTrapFlag)
12685 {
12686 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12687 AssertRC(rc);
12688 pVCpu->hmr0.s.fClearTrapFlag = false;
12689 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12690 }
12691 /** @todo there seems to be issues with the resume flag when the monitor trap
12692 * flag is pending without being used. Seen early in bios init when
12693 * accessing APIC page in protected mode. */
12694
12695 /* Restore HMCPU indicators. */
12696 pVCpu->hmr0.s.fUsingDebugLoop = false;
12697 pVCpu->hmr0.s.fDebugWantRdTscExit = false;
12698 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12699
12700 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12701 return rcStrict;
12702}
12703
12704
12705/** @} */
12706
12707
12708/**
12709 * Checks if any expensive dtrace probes are enabled and we should go to the
12710 * debug loop.
12711 *
12712 * @returns true if we should use debug loop, false if not.
12713 */
12714static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12715{
12716 /* It's probably faster to OR the raw 32-bit counter variables together.
12717 Since the variables are in an array and the probes are next to one
12718 another (more or less), we have good locality. So, better read
12719 eight-nine cache lines ever time and only have one conditional, than
12720 128+ conditionals, right? */
12721 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12722 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12723 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12724 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12725 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12726 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12727 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12728 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12729 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12730 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12731 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12732 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12733 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12734 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12735 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12736 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12737 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12738 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12739 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12740 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12741 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12742 ) != 0
12743 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12744 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12745 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12746 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12747 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12748 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12749 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12750 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12751 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12752 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12753 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12754 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12755 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12756 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12757 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12758 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12759 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12760 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12761 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12762 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12763 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12764 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12765 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12766 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12767 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12768 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12769 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12770 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12771 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12772 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12773 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12774 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12775 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12776 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12777 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12778 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12779 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12780 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12781 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12782 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12783 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12784 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12785 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12786 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12787 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12788 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12789 ) != 0
12790 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12791 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12792 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12793 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12794 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12795 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12796 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12797 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12798 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12799 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12800 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12801 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12802 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12803 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12804 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12805 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12806 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12807 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12808 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12809 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12810 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12811 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12812 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12813 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12814 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12815 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12816 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12817 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12818 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12819 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12820 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12821 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12822 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12823 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12824 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12825 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12826 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12827 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12828 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12829 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12830 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12831 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12832 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12833 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12834 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12835 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12836 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12837 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12838 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12839 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12840 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12841 ) != 0;
12842}
12843
12844
12845/**
12846 * Runs the guest using hardware-assisted VMX.
12847 *
12848 * @returns Strict VBox status code (i.e. informational status codes too).
12849 * @param pVCpu The cross context virtual CPU structure.
12850 */
12851VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12852{
12853 AssertPtr(pVCpu);
12854 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12855 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12856 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12857 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12858
12859 VBOXSTRICTRC rcStrict;
12860 uint32_t cLoops = 0;
12861 for (;;)
12862 {
12863#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12864 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12865#else
12866 NOREF(pCtx);
12867 bool const fInNestedGuestMode = false;
12868#endif
12869 if (!fInNestedGuestMode)
12870 {
12871 if ( !pVCpu->hm.s.fUseDebugLoop
12872 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12873 && !DBGFIsStepping(pVCpu)
12874 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12875 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12876 else
12877 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12878 }
12879#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12880 else
12881 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12882
12883 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12884 {
12885 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12886 continue;
12887 }
12888 if (rcStrict == VINF_VMX_VMEXIT)
12889 {
12890 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12891 continue;
12892 }
12893#endif
12894 break;
12895 }
12896
12897 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12898 switch (rcLoop)
12899 {
12900 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12901 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12902 }
12903
12904 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12905 if (RT_FAILURE(rc2))
12906 {
12907 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12908 rcStrict = rc2;
12909 }
12910 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12911 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12912 return rcStrict;
12913}
12914
12915
12916#ifndef HMVMX_USE_FUNCTION_TABLE
12917/**
12918 * Handles a guest VM-exit from hardware-assisted VMX execution.
12919 *
12920 * @returns Strict VBox status code (i.e. informational status codes too).
12921 * @param pVCpu The cross context virtual CPU structure.
12922 * @param pVmxTransient The VMX-transient structure.
12923 */
12924DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12925{
12926#ifdef DEBUG_ramshankar
12927# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12928 do { \
12929 if (a_fSave != 0) \
12930 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12931 VBOXSTRICTRC rcStrict = a_CallExpr; \
12932 if (a_fSave != 0) \
12933 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12934 return rcStrict; \
12935 } while (0)
12936#else
12937# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12938#endif
12939 uint32_t const uExitReason = pVmxTransient->uExitReason;
12940 switch (uExitReason)
12941 {
12942 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12943 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12944 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12945 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12946 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12947 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12948 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12949 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12950 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12951 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12952 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12953 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12954 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12955 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12956 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12957 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12958 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12959 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12960 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12961 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12962 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12963 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12964 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12965 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12966 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12967 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12968 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12969 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12970 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12971 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12972#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12973 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12974 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12975 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12976 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12977 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12978 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12979 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12980 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12981 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12982 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12983 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12984#else
12985 case VMX_EXIT_VMCLEAR:
12986 case VMX_EXIT_VMLAUNCH:
12987 case VMX_EXIT_VMPTRLD:
12988 case VMX_EXIT_VMPTRST:
12989 case VMX_EXIT_VMREAD:
12990 case VMX_EXIT_VMRESUME:
12991 case VMX_EXIT_VMWRITE:
12992 case VMX_EXIT_VMXOFF:
12993 case VMX_EXIT_VMXON:
12994 case VMX_EXIT_INVVPID:
12995 case VMX_EXIT_INVEPT:
12996 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12997#endif
12998
12999 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
13000 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
13001 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
13002
13003 case VMX_EXIT_INIT_SIGNAL:
13004 case VMX_EXIT_SIPI:
13005 case VMX_EXIT_IO_SMI:
13006 case VMX_EXIT_SMI:
13007 case VMX_EXIT_ERR_MSR_LOAD:
13008 case VMX_EXIT_ERR_MACHINE_CHECK:
13009 case VMX_EXIT_PML_FULL:
13010 case VMX_EXIT_VIRTUALIZED_EOI:
13011 case VMX_EXIT_GDTR_IDTR_ACCESS:
13012 case VMX_EXIT_LDTR_TR_ACCESS:
13013 case VMX_EXIT_APIC_WRITE:
13014 case VMX_EXIT_RDRAND:
13015 case VMX_EXIT_RSM:
13016 case VMX_EXIT_VMFUNC:
13017 case VMX_EXIT_ENCLS:
13018 case VMX_EXIT_RDSEED:
13019 case VMX_EXIT_XSAVES:
13020 case VMX_EXIT_XRSTORS:
13021 case VMX_EXIT_UMWAIT:
13022 case VMX_EXIT_TPAUSE:
13023 default:
13024 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13025 }
13026#undef VMEXIT_CALL_RET
13027}
13028#endif /* !HMVMX_USE_FUNCTION_TABLE */
13029
13030
13031#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13032/**
13033 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13034 *
13035 * @returns Strict VBox status code (i.e. informational status codes too).
13036 * @param pVCpu The cross context virtual CPU structure.
13037 * @param pVmxTransient The VMX-transient structure.
13038 */
13039DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13040{
13041 uint32_t const uExitReason = pVmxTransient->uExitReason;
13042 switch (uExitReason)
13043 {
13044 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13045 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13046 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13047 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13048 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13049
13050 /*
13051 * We shouldn't direct host physical interrupts to the nested-guest.
13052 */
13053 case VMX_EXIT_EXT_INT:
13054 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13055
13056 /*
13057 * Instructions that cause VM-exits unconditionally or the condition is
13058 * always is taken solely from the nested hypervisor (meaning if the VM-exit
13059 * happens, it's guaranteed to be a nested-guest VM-exit).
13060 *
13061 * - Provides VM-exit instruction length ONLY.
13062 */
13063 case VMX_EXIT_CPUID: /* Unconditional. */
13064 case VMX_EXIT_VMCALL:
13065 case VMX_EXIT_GETSEC:
13066 case VMX_EXIT_INVD:
13067 case VMX_EXIT_XSETBV:
13068 case VMX_EXIT_VMLAUNCH:
13069 case VMX_EXIT_VMRESUME:
13070 case VMX_EXIT_VMXOFF:
13071 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
13072 case VMX_EXIT_VMFUNC:
13073 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13074
13075 /*
13076 * Instructions that cause VM-exits unconditionally or the condition is
13077 * always is taken solely from the nested hypervisor (meaning if the VM-exit
13078 * happens, it's guaranteed to be a nested-guest VM-exit).
13079 *
13080 * - Provides VM-exit instruction length.
13081 * - Provides VM-exit information.
13082 * - Optionally provides Exit qualification.
13083 *
13084 * Since Exit qualification is 0 for all VM-exits where it is not
13085 * applicable, reading and passing it to the guest should produce
13086 * defined behavior.
13087 *
13088 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13089 */
13090 case VMX_EXIT_INVEPT: /* Unconditional. */
13091 case VMX_EXIT_INVVPID:
13092 case VMX_EXIT_VMCLEAR:
13093 case VMX_EXIT_VMPTRLD:
13094 case VMX_EXIT_VMPTRST:
13095 case VMX_EXIT_VMXON:
13096 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
13097 case VMX_EXIT_LDTR_TR_ACCESS:
13098 case VMX_EXIT_RDRAND:
13099 case VMX_EXIT_RDSEED:
13100 case VMX_EXIT_XSAVES:
13101 case VMX_EXIT_XRSTORS:
13102 case VMX_EXIT_UMWAIT:
13103 case VMX_EXIT_TPAUSE:
13104 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13105
13106 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13107 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13108 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13109 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13110 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13111 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13112 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13113 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13114 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13115 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13116 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13117 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13118 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13119 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13120 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13121 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13122 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13123 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13124 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13125
13126 case VMX_EXIT_PREEMPT_TIMER:
13127 {
13128 /** @todo NSTVMX: Preempt timer. */
13129 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13130 }
13131
13132 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13133 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13134
13135 case VMX_EXIT_VMREAD:
13136 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13137
13138 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13139 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13140
13141 case VMX_EXIT_INIT_SIGNAL:
13142 case VMX_EXIT_SIPI:
13143 case VMX_EXIT_IO_SMI:
13144 case VMX_EXIT_SMI:
13145 case VMX_EXIT_ERR_MSR_LOAD:
13146 case VMX_EXIT_ERR_MACHINE_CHECK:
13147 case VMX_EXIT_PML_FULL:
13148 case VMX_EXIT_RSM:
13149 default:
13150 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13151 }
13152}
13153#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13154
13155
13156/** @name VM-exit helpers.
13157 * @{
13158 */
13159/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13160/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13161/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13162
13163/** Macro for VM-exits called unexpectedly. */
13164#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13165 do { \
13166 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13167 return VERR_VMX_UNEXPECTED_EXIT; \
13168 } while (0)
13169
13170#ifdef VBOX_STRICT
13171/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13172# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13173 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13174
13175# define HMVMX_ASSERT_PREEMPT_CPUID() \
13176 do { \
13177 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13178 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13179 } while (0)
13180
13181# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13182 do { \
13183 AssertPtr((a_pVCpu)); \
13184 AssertPtr((a_pVmxTransient)); \
13185 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13186 Assert((a_pVmxTransient)->pVmcsInfo); \
13187 Assert(ASMIntAreEnabled()); \
13188 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13189 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13190 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13191 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13192 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13193 HMVMX_ASSERT_PREEMPT_CPUID(); \
13194 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13195 } while (0)
13196
13197# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13198 do { \
13199 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13200 Assert((a_pVmxTransient)->fIsNestedGuest); \
13201 } while (0)
13202
13203# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13204 do { \
13205 Log4Func(("\n")); \
13206 } while (0)
13207#else
13208# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13209 do { \
13210 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13211 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13212 } while (0)
13213
13214# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13215 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13216
13217# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13218#endif
13219
13220#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13221/** Macro that does the necessary privilege checks and intercepted VM-exits for
13222 * guests that attempted to execute a VMX instruction. */
13223# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13224 do \
13225 { \
13226 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13227 if (rcStrictTmp == VINF_SUCCESS) \
13228 { /* likely */ } \
13229 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13230 { \
13231 Assert((a_pVCpu)->hm.s.Event.fPending); \
13232 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13233 return VINF_SUCCESS; \
13234 } \
13235 else \
13236 { \
13237 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13238 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13239 } \
13240 } while (0)
13241
13242/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13243# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13244 do \
13245 { \
13246 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13247 (a_pGCPtrEffAddr)); \
13248 if (rcStrictTmp == VINF_SUCCESS) \
13249 { /* likely */ } \
13250 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13251 { \
13252 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13253 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13254 NOREF(uXcptTmp); \
13255 return VINF_SUCCESS; \
13256 } \
13257 else \
13258 { \
13259 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13260 return rcStrictTmp; \
13261 } \
13262 } while (0)
13263#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13264
13265
13266/**
13267 * Advances the guest RIP by the specified number of bytes.
13268 *
13269 * @param pVCpu The cross context virtual CPU structure.
13270 * @param cbInstr Number of bytes to advance the RIP by.
13271 *
13272 * @remarks No-long-jump zone!!!
13273 */
13274DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
13275{
13276 /* Advance the RIP. */
13277 pVCpu->cpum.GstCtx.rip += cbInstr;
13278 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13279
13280 /* Update interrupt inhibition. */
13281 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13282 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13283 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13284}
13285
13286
13287/**
13288 * Advances the guest RIP after reading it from the VMCS.
13289 *
13290 * @returns VBox status code, no informational status codes.
13291 * @param pVCpu The cross context virtual CPU structure.
13292 * @param pVmxTransient The VMX-transient structure.
13293 *
13294 * @remarks No-long-jump zone!!!
13295 */
13296static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13297{
13298 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13299 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13300 AssertRCReturn(rc, rc);
13301
13302 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
13303 return VINF_SUCCESS;
13304}
13305
13306
13307/**
13308 * Handle a condition that occurred while delivering an event through the guest or
13309 * nested-guest IDT.
13310 *
13311 * @returns Strict VBox status code (i.e. informational status codes too).
13312 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13313 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13314 * to continue execution of the guest which will delivery the \#DF.
13315 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13316 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13317 *
13318 * @param pVCpu The cross context virtual CPU structure.
13319 * @param pVmxTransient The VMX-transient structure.
13320 *
13321 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13322 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13323 * is due to an EPT violation, PML full or SPP-related event.
13324 *
13325 * @remarks No-long-jump zone!!!
13326 */
13327static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13328{
13329 Assert(!pVCpu->hm.s.Event.fPending);
13330 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13331 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13332 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13333 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13334 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13335
13336 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13337 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13338 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13339 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13340 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13341 {
13342 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13343 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13344
13345 /*
13346 * If the event was a software interrupt (generated with INT n) or a software exception
13347 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13348 * can handle the VM-exit and continue guest execution which will re-execute the
13349 * instruction rather than re-injecting the exception, as that can cause premature
13350 * trips to ring-3 before injection and involve TRPM which currently has no way of
13351 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13352 * the problem).
13353 */
13354 IEMXCPTRAISE enmRaise;
13355 IEMXCPTRAISEINFO fRaiseInfo;
13356 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13357 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13358 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13359 {
13360 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13361 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13362 }
13363 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13364 {
13365 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13366 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13367 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13368
13369 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13370 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13371
13372 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13373
13374 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13375 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13376 {
13377 pVmxTransient->fVectoringPF = true;
13378 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13379 }
13380 }
13381 else
13382 {
13383 /*
13384 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13385 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13386 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13387 */
13388 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13389 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13390 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13391 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13392 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13393 }
13394
13395 /*
13396 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13397 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13398 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13399 * subsequent VM-entry would fail, see @bugref{7445}.
13400 *
13401 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13402 */
13403 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13404 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13405 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13406 && CPUMIsGuestNmiBlocking(pVCpu))
13407 {
13408 CPUMSetGuestNmiBlocking(pVCpu, false);
13409 }
13410
13411 switch (enmRaise)
13412 {
13413 case IEMXCPTRAISE_CURRENT_XCPT:
13414 {
13415 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13416 Assert(rcStrict == VINF_SUCCESS);
13417 break;
13418 }
13419
13420 case IEMXCPTRAISE_PREV_EVENT:
13421 {
13422 uint32_t u32ErrCode;
13423 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13424 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13425 else
13426 u32ErrCode = 0;
13427
13428 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13429 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13430 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13431 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13432
13433 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13434 pVCpu->hm.s.Event.u32ErrCode));
13435 Assert(rcStrict == VINF_SUCCESS);
13436 break;
13437 }
13438
13439 case IEMXCPTRAISE_REEXEC_INSTR:
13440 Assert(rcStrict == VINF_SUCCESS);
13441 break;
13442
13443 case IEMXCPTRAISE_DOUBLE_FAULT:
13444 {
13445 /*
13446 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13447 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13448 */
13449 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13450 {
13451 pVmxTransient->fVectoringDoublePF = true;
13452 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13453 pVCpu->cpum.GstCtx.cr2));
13454 rcStrict = VINF_SUCCESS;
13455 }
13456 else
13457 {
13458 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13459 hmR0VmxSetPendingXcptDF(pVCpu);
13460 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13461 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13462 rcStrict = VINF_HM_DOUBLE_FAULT;
13463 }
13464 break;
13465 }
13466
13467 case IEMXCPTRAISE_TRIPLE_FAULT:
13468 {
13469 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13470 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13471 rcStrict = VINF_EM_RESET;
13472 break;
13473 }
13474
13475 case IEMXCPTRAISE_CPU_HANG:
13476 {
13477 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13478 rcStrict = VERR_EM_GUEST_CPU_HANG;
13479 break;
13480 }
13481
13482 default:
13483 {
13484 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13485 rcStrict = VERR_VMX_IPE_2;
13486 break;
13487 }
13488 }
13489 }
13490 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13491 && !CPUMIsGuestNmiBlocking(pVCpu))
13492 {
13493 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13494 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13495 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13496 {
13497 /*
13498 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13499 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13500 * that virtual NMIs remain blocked until the IRET execution is completed.
13501 *
13502 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13503 */
13504 CPUMSetGuestNmiBlocking(pVCpu, true);
13505 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13506 }
13507 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13508 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13509 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13510 {
13511 /*
13512 * Execution of IRET caused an EPT violation, page-modification log-full event or
13513 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13514 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13515 * that virtual NMIs remain blocked until the IRET execution is completed.
13516 *
13517 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13518 */
13519 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13520 {
13521 CPUMSetGuestNmiBlocking(pVCpu, true);
13522 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13523 }
13524 }
13525 }
13526
13527 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13528 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13529 return rcStrict;
13530}
13531
13532
13533#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13534/**
13535 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13536 * guest attempting to execute a VMX instruction.
13537 *
13538 * @returns Strict VBox status code (i.e. informational status codes too).
13539 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13540 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13541 *
13542 * @param pVCpu The cross context virtual CPU structure.
13543 * @param uExitReason The VM-exit reason.
13544 *
13545 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13546 * @remarks No-long-jump zone!!!
13547 */
13548static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13549{
13550 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13551 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13552
13553 /*
13554 * The physical CPU would have already checked the CPU mode/code segment.
13555 * We shall just assert here for paranoia.
13556 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13557 */
13558 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13559 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13560 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13561
13562 if (uExitReason == VMX_EXIT_VMXON)
13563 {
13564 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13565
13566 /*
13567 * We check CR4.VMXE because it is required to be always set while in VMX operation
13568 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13569 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13570 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13571 */
13572 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13573 {
13574 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13575 hmR0VmxSetPendingXcptUD(pVCpu);
13576 return VINF_HM_PENDING_XCPT;
13577 }
13578 }
13579 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13580 {
13581 /*
13582 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13583 * (other than VMXON), we need to raise a #UD.
13584 */
13585 Log4Func(("Not in VMX root mode -> #UD\n"));
13586 hmR0VmxSetPendingXcptUD(pVCpu);
13587 return VINF_HM_PENDING_XCPT;
13588 }
13589
13590 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13591 return VINF_SUCCESS;
13592}
13593
13594
13595/**
13596 * Decodes the memory operand of an instruction that caused a VM-exit.
13597 *
13598 * The Exit qualification field provides the displacement field for memory
13599 * operand instructions, if any.
13600 *
13601 * @returns Strict VBox status code (i.e. informational status codes too).
13602 * @retval VINF_SUCCESS if the operand was successfully decoded.
13603 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13604 * operand.
13605 * @param pVCpu The cross context virtual CPU structure.
13606 * @param uExitInstrInfo The VM-exit instruction information field.
13607 * @param enmMemAccess The memory operand's access type (read or write).
13608 * @param GCPtrDisp The instruction displacement field, if any. For
13609 * RIP-relative addressing pass RIP + displacement here.
13610 * @param pGCPtrMem Where to store the effective destination memory address.
13611 *
13612 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13613 * virtual-8086 mode hence skips those checks while verifying if the
13614 * segment is valid.
13615 */
13616static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13617 PRTGCPTR pGCPtrMem)
13618{
13619 Assert(pGCPtrMem);
13620 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13621 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13622 | CPUMCTX_EXTRN_CR0);
13623
13624 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13625 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13626 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13627
13628 VMXEXITINSTRINFO ExitInstrInfo;
13629 ExitInstrInfo.u = uExitInstrInfo;
13630 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13631 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13632 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13633 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13634 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13635 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13636 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13637 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13638 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13639
13640 /*
13641 * Validate instruction information.
13642 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13643 */
13644 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13645 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13646 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13647 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13648 AssertLogRelMsgReturn(fIsMemOperand,
13649 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13650
13651 /*
13652 * Compute the complete effective address.
13653 *
13654 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13655 * See AMD spec. 4.5.2 "Segment Registers".
13656 */
13657 RTGCPTR GCPtrMem = GCPtrDisp;
13658 if (fBaseRegValid)
13659 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13660 if (fIdxRegValid)
13661 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13662
13663 RTGCPTR const GCPtrOff = GCPtrMem;
13664 if ( !fIsLongMode
13665 || iSegReg >= X86_SREG_FS)
13666 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13667 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13668
13669 /*
13670 * Validate effective address.
13671 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13672 */
13673 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13674 Assert(cbAccess > 0);
13675 if (fIsLongMode)
13676 {
13677 if (X86_IS_CANONICAL(GCPtrMem))
13678 {
13679 *pGCPtrMem = GCPtrMem;
13680 return VINF_SUCCESS;
13681 }
13682
13683 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13684 * "Data Limit Checks in 64-bit Mode". */
13685 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13686 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13687 return VINF_HM_PENDING_XCPT;
13688 }
13689
13690 /*
13691 * This is a watered down version of iemMemApplySegment().
13692 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13693 * and segment CPL/DPL checks are skipped.
13694 */
13695 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13696 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13697 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13698
13699 /* Check if the segment is present and usable. */
13700 if ( pSel->Attr.n.u1Present
13701 && !pSel->Attr.n.u1Unusable)
13702 {
13703 Assert(pSel->Attr.n.u1DescType);
13704 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13705 {
13706 /* Check permissions for the data segment. */
13707 if ( enmMemAccess == VMXMEMACCESS_WRITE
13708 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13709 {
13710 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13711 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13712 return VINF_HM_PENDING_XCPT;
13713 }
13714
13715 /* Check limits if it's a normal data segment. */
13716 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13717 {
13718 if ( GCPtrFirst32 > pSel->u32Limit
13719 || GCPtrLast32 > pSel->u32Limit)
13720 {
13721 Log4Func(("Data segment limit exceeded. "
13722 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13723 GCPtrLast32, pSel->u32Limit));
13724 if (iSegReg == X86_SREG_SS)
13725 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13726 else
13727 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13728 return VINF_HM_PENDING_XCPT;
13729 }
13730 }
13731 else
13732 {
13733 /* Check limits if it's an expand-down data segment.
13734 Note! The upper boundary is defined by the B bit, not the G bit! */
13735 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13736 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13737 {
13738 Log4Func(("Expand-down data segment limit exceeded. "
13739 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13740 GCPtrLast32, pSel->u32Limit));
13741 if (iSegReg == X86_SREG_SS)
13742 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13743 else
13744 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13745 return VINF_HM_PENDING_XCPT;
13746 }
13747 }
13748 }
13749 else
13750 {
13751 /* Check permissions for the code segment. */
13752 if ( enmMemAccess == VMXMEMACCESS_WRITE
13753 || ( enmMemAccess == VMXMEMACCESS_READ
13754 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13755 {
13756 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13757 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13758 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13759 return VINF_HM_PENDING_XCPT;
13760 }
13761
13762 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13763 if ( GCPtrFirst32 > pSel->u32Limit
13764 || GCPtrLast32 > pSel->u32Limit)
13765 {
13766 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13767 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13768 if (iSegReg == X86_SREG_SS)
13769 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13770 else
13771 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13772 return VINF_HM_PENDING_XCPT;
13773 }
13774 }
13775 }
13776 else
13777 {
13778 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13779 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13780 return VINF_HM_PENDING_XCPT;
13781 }
13782
13783 *pGCPtrMem = GCPtrMem;
13784 return VINF_SUCCESS;
13785}
13786#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13787
13788
13789/**
13790 * VM-exit helper for LMSW.
13791 */
13792static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13793{
13794 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13795 AssertRCReturn(rc, rc);
13796
13797 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13798 AssertMsg( rcStrict == VINF_SUCCESS
13799 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13800
13801 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13802 if (rcStrict == VINF_IEM_RAISED_XCPT)
13803 {
13804 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13805 rcStrict = VINF_SUCCESS;
13806 }
13807
13808 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13809 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13810 return rcStrict;
13811}
13812
13813
13814/**
13815 * VM-exit helper for CLTS.
13816 */
13817static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13818{
13819 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13820 AssertRCReturn(rc, rc);
13821
13822 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13823 AssertMsg( rcStrict == VINF_SUCCESS
13824 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13825
13826 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13827 if (rcStrict == VINF_IEM_RAISED_XCPT)
13828 {
13829 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13830 rcStrict = VINF_SUCCESS;
13831 }
13832
13833 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13834 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13835 return rcStrict;
13836}
13837
13838
13839/**
13840 * VM-exit helper for MOV from CRx (CRx read).
13841 */
13842static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13843{
13844 Assert(iCrReg < 16);
13845 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13846
13847 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13848 AssertRCReturn(rc, rc);
13849
13850 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13851 AssertMsg( rcStrict == VINF_SUCCESS
13852 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13853
13854 if (iGReg == X86_GREG_xSP)
13855 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13856 else
13857 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13858#ifdef VBOX_WITH_STATISTICS
13859 switch (iCrReg)
13860 {
13861 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13862 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13863 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13864 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13865 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13866 }
13867#endif
13868 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13869 return rcStrict;
13870}
13871
13872
13873/**
13874 * VM-exit helper for MOV to CRx (CRx write).
13875 */
13876static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13877{
13878 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13879 AssertRCReturn(rc, rc);
13880
13881 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13882 AssertMsg( rcStrict == VINF_SUCCESS
13883 || rcStrict == VINF_IEM_RAISED_XCPT
13884 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13885
13886 switch (iCrReg)
13887 {
13888 case 0:
13889 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13890 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13891 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13892 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13893 break;
13894
13895 case 2:
13896 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13897 /* Nothing to do here, CR2 it's not part of the VMCS. */
13898 break;
13899
13900 case 3:
13901 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13902 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13903 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13904 break;
13905
13906 case 4:
13907 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13908 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13909 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13910 pVCpu->cpum.GstCtx.cr4, pVCpu->hmr0.s.fLoadSaveGuestXcr0));
13911 break;
13912
13913 case 8:
13914 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13915 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13916 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13917 break;
13918
13919 default:
13920 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13921 break;
13922 }
13923
13924 if (rcStrict == VINF_IEM_RAISED_XCPT)
13925 {
13926 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13927 rcStrict = VINF_SUCCESS;
13928 }
13929 return rcStrict;
13930}
13931
13932
13933/**
13934 * VM-exit exception handler for \#PF (Page-fault exception).
13935 *
13936 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13937 */
13938static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13939{
13940 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13941 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13942 hmR0VmxReadExitQualVmcs(pVmxTransient);
13943
13944 if (!pVM->hmr0.s.fNestedPaging)
13945 { /* likely */ }
13946 else
13947 {
13948#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13949 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hmr0.s.fUsingDebugLoop);
13950#endif
13951 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13952 if (!pVmxTransient->fVectoringDoublePF)
13953 {
13954 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13955 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13956 }
13957 else
13958 {
13959 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13960 Assert(!pVmxTransient->fIsNestedGuest);
13961 hmR0VmxSetPendingXcptDF(pVCpu);
13962 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13963 }
13964 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13965 return VINF_SUCCESS;
13966 }
13967
13968 Assert(!pVmxTransient->fIsNestedGuest);
13969
13970 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13971 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13972 if (pVmxTransient->fVectoringPF)
13973 {
13974 Assert(pVCpu->hm.s.Event.fPending);
13975 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13976 }
13977
13978 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13979 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13980 AssertRCReturn(rc, rc);
13981
13982 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13983 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13984
13985 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13986 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13987
13988 Log4Func(("#PF: rc=%Rrc\n", rc));
13989 if (rc == VINF_SUCCESS)
13990 {
13991 /*
13992 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13993 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13994 */
13995 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13996 TRPMResetTrap(pVCpu);
13997 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13998 return rc;
13999 }
14000
14001 if (rc == VINF_EM_RAW_GUEST_TRAP)
14002 {
14003 if (!pVmxTransient->fVectoringDoublePF)
14004 {
14005 /* It's a guest page fault and needs to be reflected to the guest. */
14006 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
14007 TRPMResetTrap(pVCpu);
14008 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
14009 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14010 uGstErrorCode, pVmxTransient->uExitQual);
14011 }
14012 else
14013 {
14014 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14015 TRPMResetTrap(pVCpu);
14016 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14017 hmR0VmxSetPendingXcptDF(pVCpu);
14018 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14019 }
14020
14021 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14022 return VINF_SUCCESS;
14023 }
14024
14025 TRPMResetTrap(pVCpu);
14026 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14027 return rc;
14028}
14029
14030
14031/**
14032 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14033 *
14034 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14035 */
14036static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14037{
14038 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14039 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14040
14041 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14042 AssertRCReturn(rc, rc);
14043
14044 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14045 {
14046 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14047 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14048
14049 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14050 * provides VM-exit instruction length. If this causes problem later,
14051 * disassemble the instruction like it's done on AMD-V. */
14052 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14053 AssertRCReturn(rc2, rc2);
14054 return rc;
14055 }
14056
14057 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
14058 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14059 return VINF_SUCCESS;
14060}
14061
14062
14063/**
14064 * VM-exit exception handler for \#BP (Breakpoint exception).
14065 *
14066 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14067 */
14068static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14069{
14070 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14071 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14072
14073 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14074 AssertRCReturn(rc, rc);
14075
14076 if (!pVmxTransient->fIsNestedGuest)
14077 rc = DBGFTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
14078 else
14079 rc = VINF_EM_RAW_GUEST_TRAP;
14080
14081 if (rc == VINF_EM_RAW_GUEST_TRAP)
14082 {
14083 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14084 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14085 rc = VINF_SUCCESS;
14086 }
14087
14088 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
14089 return rc;
14090}
14091
14092
14093/**
14094 * VM-exit exception handler for \#AC (Alignment-check exception).
14095 *
14096 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14097 */
14098static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14099{
14100 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14101 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14102
14103 /* Re-inject it. We'll detect any nesting before getting here. */
14104 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14105 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14106 return VINF_SUCCESS;
14107}
14108
14109
14110/**
14111 * VM-exit exception handler for \#DB (Debug exception).
14112 *
14113 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14114 */
14115static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14116{
14117 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14118 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14119
14120 /*
14121 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14122 */
14123 hmR0VmxReadExitQualVmcs(pVmxTransient);
14124
14125 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14126 uint64_t const uDR6 = X86_DR6_INIT_VAL
14127 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14128 | X86_DR6_BD | X86_DR6_BS));
14129
14130 int rc;
14131 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14132 if (!pVmxTransient->fIsNestedGuest)
14133 {
14134 rc = DBGFTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14135
14136 /*
14137 * Prevents stepping twice over the same instruction when the guest is stepping using
14138 * EFLAGS.TF and the hypervisor debugger is stepping using MTF.
14139 * Testcase: DOSQEMM, break (using "ba x 1") at cs:rip 0x70:0x774 and step (using "t").
14140 */
14141 if ( rc == VINF_EM_DBG_STEPPED
14142 && (pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MONITOR_TRAP_FLAG))
14143 {
14144 Assert(pVCpu->hm.s.fSingleInstruction);
14145 rc = VINF_EM_RAW_GUEST_TRAP;
14146 }
14147 }
14148 else
14149 rc = VINF_EM_RAW_GUEST_TRAP;
14150 Log6Func(("rc=%Rrc\n", rc));
14151 if (rc == VINF_EM_RAW_GUEST_TRAP)
14152 {
14153 /*
14154 * The exception was for the guest. Update DR6, DR7.GD and
14155 * IA32_DEBUGCTL.LBR before forwarding it.
14156 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14157 */
14158 VMMRZCallRing3Disable(pVCpu);
14159 HM_DISABLE_PREEMPT(pVCpu);
14160
14161 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14162 pCtx->dr[6] |= uDR6;
14163 if (CPUMIsGuestDebugStateActive(pVCpu))
14164 ASMSetDR6(pCtx->dr[6]);
14165
14166 HM_RESTORE_PREEMPT();
14167 VMMRZCallRing3Enable(pVCpu);
14168
14169 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14170 AssertRCReturn(rc, rc);
14171
14172 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14173 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
14174
14175 /* Paranoia. */
14176 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
14177 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14178
14179 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
14180 AssertRC(rc);
14181
14182 /*
14183 * Raise #DB in the guest.
14184 *
14185 * It is important to reflect exactly what the VM-exit gave us (preserving the
14186 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14187 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14188 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14189 *
14190 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14191 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14192 */
14193 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14194 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14195 return VINF_SUCCESS;
14196 }
14197
14198 /*
14199 * Not a guest trap, must be a hypervisor related debug event then.
14200 * Update DR6 in case someone is interested in it.
14201 */
14202 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14203 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14204 CPUMSetHyperDR6(pVCpu, uDR6);
14205
14206 return rc;
14207}
14208
14209
14210/**
14211 * Hacks its way around the lovely mesa driver's backdoor accesses.
14212 *
14213 * @sa hmR0SvmHandleMesaDrvGp.
14214 */
14215static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14216{
14217 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14218 RT_NOREF(pCtx);
14219
14220 /* For now we'll just skip the instruction. */
14221 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14222}
14223
14224
14225/**
14226 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14227 * backdoor logging w/o checking what it is running inside.
14228 *
14229 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14230 * backdoor port and magic numbers loaded in registers.
14231 *
14232 * @returns true if it is, false if it isn't.
14233 * @sa hmR0SvmIsMesaDrvGp.
14234 */
14235DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14236{
14237 /* 0xed: IN eAX,dx */
14238 uint8_t abInstr[1];
14239 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
14240 return false;
14241
14242 /* Check that it is #GP(0). */
14243 if (pVmxTransient->uExitIntErrorCode != 0)
14244 return false;
14245
14246 /* Check magic and port. */
14247 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14248 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14249 if (pCtx->rax != UINT32_C(0x564d5868))
14250 return false;
14251 if (pCtx->dx != UINT32_C(0x5658))
14252 return false;
14253
14254 /* Flat ring-3 CS. */
14255 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14256 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14257 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14258 if (pCtx->cs.Attr.n.u2Dpl != 3)
14259 return false;
14260 if (pCtx->cs.u64Base != 0)
14261 return false;
14262
14263 /* Check opcode. */
14264 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14265 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14266 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14267 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14268 if (RT_FAILURE(rc))
14269 return false;
14270 if (abInstr[0] != 0xed)
14271 return false;
14272
14273 return true;
14274}
14275
14276
14277/**
14278 * VM-exit exception handler for \#GP (General-protection exception).
14279 *
14280 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14281 */
14282static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14283{
14284 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14285 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14286
14287 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14288 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14289 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
14290 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
14291 { /* likely */ }
14292 else
14293 {
14294#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14295 Assert(pVCpu->hmr0.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14296#endif
14297 /*
14298 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14299 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14300 */
14301 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14302 AssertRCReturn(rc, rc);
14303 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14304 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14305
14306 if ( pVmxTransient->fIsNestedGuest
14307 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14308 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14309 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14310 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14311 else
14312 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14313 return rc;
14314 }
14315
14316 Assert(CPUMIsGuestInRealModeEx(pCtx));
14317 Assert(!pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest);
14318 Assert(!pVmxTransient->fIsNestedGuest);
14319
14320 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14321 AssertRCReturn(rc, rc);
14322
14323 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14324 if (rcStrict == VINF_SUCCESS)
14325 {
14326 if (!CPUMIsGuestInRealModeEx(pCtx))
14327 {
14328 /*
14329 * The guest is no longer in real-mode, check if we can continue executing the
14330 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14331 */
14332 pVmcsInfoShared->RealMode.fRealOnV86Active = false;
14333 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
14334 {
14335 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14336 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14337 }
14338 else
14339 {
14340 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14341 rcStrict = VINF_EM_RESCHEDULE;
14342 }
14343 }
14344 else
14345 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14346 }
14347 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14348 {
14349 rcStrict = VINF_SUCCESS;
14350 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14351 }
14352 return VBOXSTRICTRC_VAL(rcStrict);
14353}
14354
14355
14356/**
14357 * VM-exit exception handler wrapper for all other exceptions that are not handled
14358 * by a specific handler.
14359 *
14360 * This simply re-injects the exception back into the VM without any special
14361 * processing.
14362 *
14363 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14364 */
14365static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14366{
14367 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14368
14369#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14370 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14371 AssertMsg(pVCpu->hmr0.s.fUsingDebugLoop || pVmcsInfo->pShared->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14372 ("uVector=%#x u32XcptBitmap=%#X32\n",
14373 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14374 NOREF(pVmcsInfo);
14375#endif
14376
14377 /*
14378 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14379 * would have been handled while checking exits due to event delivery.
14380 */
14381 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14382
14383#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14384 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14385 AssertRCReturn(rc, rc);
14386 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14387#endif
14388
14389#ifdef VBOX_WITH_STATISTICS
14390 switch (uVector)
14391 {
14392 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14393 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14394 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14395 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14396 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14397 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14398 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14399 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14400 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14401 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14402 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14403 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14404 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14405 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14406 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14407 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14408 default:
14409 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14410 break;
14411 }
14412#endif
14413
14414 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14415 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14416 NOREF(uVector);
14417
14418 /* Re-inject the original exception into the guest. */
14419 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14420 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14421 return VINF_SUCCESS;
14422}
14423
14424
14425/**
14426 * VM-exit exception handler for all exceptions (except NMIs!).
14427 *
14428 * @remarks This may be called for both guests and nested-guests. Take care to not
14429 * make assumptions and avoid doing anything that is not relevant when
14430 * executing a nested-guest (e.g., Mesa driver hacks).
14431 */
14432static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14433{
14434 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14435
14436 /*
14437 * If this VM-exit occurred while delivering an event through the guest IDT, take
14438 * action based on the return code and additional hints (e.g. for page-faults)
14439 * that will be updated in the VMX transient structure.
14440 */
14441 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14442 if (rcStrict == VINF_SUCCESS)
14443 {
14444 /*
14445 * If an exception caused a VM-exit due to delivery of an event, the original
14446 * event may have to be re-injected into the guest. We shall reinject it and
14447 * continue guest execution. However, page-fault is a complicated case and
14448 * needs additional processing done in hmR0VmxExitXcptPF().
14449 */
14450 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14451 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14452 if ( !pVCpu->hm.s.Event.fPending
14453 || uVector == X86_XCPT_PF)
14454 {
14455 switch (uVector)
14456 {
14457 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14458 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14459 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14460 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14461 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14462 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14463 default:
14464 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14465 }
14466 }
14467 /* else: inject pending event before resuming guest execution. */
14468 }
14469 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14470 {
14471 Assert(pVCpu->hm.s.Event.fPending);
14472 rcStrict = VINF_SUCCESS;
14473 }
14474
14475 return rcStrict;
14476}
14477/** @} */
14478
14479
14480/** @name VM-exit handlers.
14481 * @{
14482 */
14483/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14484/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14485/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14486
14487/**
14488 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14489 */
14490HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14491{
14492 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14493 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14494 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14495 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14496 return VINF_SUCCESS;
14497 return VINF_EM_RAW_INTERRUPT;
14498}
14499
14500
14501/**
14502 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14503 * VM-exit.
14504 */
14505HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14506{
14507 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14508 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14509
14510 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14511
14512 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14513 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14514 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14515
14516 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14517 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14518 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14519 NOREF(pVmcsInfo);
14520
14521 VBOXSTRICTRC rcStrict;
14522 switch (uExitIntType)
14523 {
14524 /*
14525 * Host physical NMIs:
14526 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14527 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14528 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14529 *
14530 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14531 * See Intel spec. 27.5.5 "Updating Non-Register State".
14532 */
14533 case VMX_EXIT_INT_INFO_TYPE_NMI:
14534 {
14535 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14536 break;
14537 }
14538
14539 /*
14540 * Privileged software exceptions (#DB from ICEBP),
14541 * Software exceptions (#BP and #OF),
14542 * Hardware exceptions:
14543 * Process the required exceptions and resume guest execution if possible.
14544 */
14545 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14546 Assert(uVector == X86_XCPT_DB);
14547 RT_FALL_THRU();
14548 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14549 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14550 RT_FALL_THRU();
14551 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14552 {
14553 NOREF(uVector);
14554 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14555 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14556 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14557 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14558
14559 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14560 break;
14561 }
14562
14563 default:
14564 {
14565 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14566 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14567 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14568 break;
14569 }
14570 }
14571
14572 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14573 return rcStrict;
14574}
14575
14576
14577/**
14578 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14579 */
14580HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14581{
14582 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14583
14584 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14585 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14586 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14587
14588 /* Evaluate and deliver pending events and resume guest execution. */
14589 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14590 return VINF_SUCCESS;
14591}
14592
14593
14594/**
14595 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14596 */
14597HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14598{
14599 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14600
14601 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14602 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14603 {
14604 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14605 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14606 }
14607
14608 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14609
14610 /*
14611 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14612 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14613 */
14614 uint32_t fIntrState;
14615 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14616 AssertRC(rc);
14617 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14618 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14619 {
14620 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14621 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14622
14623 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14624 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14625 AssertRC(rc);
14626 }
14627
14628 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14629 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14630
14631 /* Evaluate and deliver pending events and resume guest execution. */
14632 return VINF_SUCCESS;
14633}
14634
14635
14636/**
14637 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14638 */
14639HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14640{
14641 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14642 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14643}
14644
14645
14646/**
14647 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14648 */
14649HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14650{
14651 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14652 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14653}
14654
14655
14656/**
14657 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14658 */
14659HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14660{
14661 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14662
14663 /*
14664 * Get the state we need and update the exit history entry.
14665 */
14666 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14667 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14668
14669 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14670 AssertRCReturn(rc, rc);
14671
14672 VBOXSTRICTRC rcStrict;
14673 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14674 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14675 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14676 if (!pExitRec)
14677 {
14678 /*
14679 * Regular CPUID instruction execution.
14680 */
14681 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14682 if (rcStrict == VINF_SUCCESS)
14683 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14684 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14685 {
14686 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14687 rcStrict = VINF_SUCCESS;
14688 }
14689 }
14690 else
14691 {
14692 /*
14693 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14694 */
14695 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14696 AssertRCReturn(rc2, rc2);
14697
14698 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14699 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14700
14701 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14702 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14703
14704 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14705 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14706 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14707 }
14708 return rcStrict;
14709}
14710
14711
14712/**
14713 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14714 */
14715HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14716{
14717 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14718
14719 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14720 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14721 AssertRCReturn(rc, rc);
14722
14723 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14724 return VINF_EM_RAW_EMULATE_INSTR;
14725
14726 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14727 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14728}
14729
14730
14731/**
14732 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14733 */
14734HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14735{
14736 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14737
14738 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14739 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14740 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14741 AssertRCReturn(rc, rc);
14742
14743 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14744 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14745 {
14746 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14747 we must reset offsetting on VM-entry. See @bugref{6634}. */
14748 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14749 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14750 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14751 }
14752 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14753 {
14754 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14755 rcStrict = VINF_SUCCESS;
14756 }
14757 return rcStrict;
14758}
14759
14760
14761/**
14762 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14763 */
14764HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14765{
14766 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14767
14768 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14769 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14770 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14771 AssertRCReturn(rc, rc);
14772
14773 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14774 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14775 {
14776 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14777 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14778 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14779 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14780 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14781 }
14782 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14783 {
14784 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14785 rcStrict = VINF_SUCCESS;
14786 }
14787 return rcStrict;
14788}
14789
14790
14791/**
14792 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14793 */
14794HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14795{
14796 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14797
14798 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14799 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14800 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14801 AssertRCReturn(rc, rc);
14802
14803 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14804 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14805 if (RT_LIKELY(rc == VINF_SUCCESS))
14806 {
14807 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14808 Assert(pVmxTransient->cbExitInstr == 2);
14809 }
14810 else
14811 {
14812 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14813 rc = VERR_EM_INTERPRETER;
14814 }
14815 return rc;
14816}
14817
14818
14819/**
14820 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14821 */
14822HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14823{
14824 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14825
14826 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14827 if (EMAreHypercallInstructionsEnabled(pVCpu))
14828 {
14829 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14830 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14831 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14832 AssertRCReturn(rc, rc);
14833
14834 /* Perform the hypercall. */
14835 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14836 if (rcStrict == VINF_SUCCESS)
14837 {
14838 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14839 AssertRCReturn(rc, rc);
14840 }
14841 else
14842 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14843 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14844 || RT_FAILURE(rcStrict));
14845
14846 /* If the hypercall changes anything other than guest's general-purpose registers,
14847 we would need to reload the guest changed bits here before VM-entry. */
14848 }
14849 else
14850 Log4Func(("Hypercalls not enabled\n"));
14851
14852 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14853 if (RT_FAILURE(rcStrict))
14854 {
14855 hmR0VmxSetPendingXcptUD(pVCpu);
14856 rcStrict = VINF_SUCCESS;
14857 }
14858
14859 return rcStrict;
14860}
14861
14862
14863/**
14864 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14865 */
14866HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14867{
14868 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14869 Assert(!pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging || pVCpu->hmr0.s.fUsingDebugLoop);
14870
14871 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14872 hmR0VmxReadExitQualVmcs(pVmxTransient);
14873 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14874 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14875 AssertRCReturn(rc, rc);
14876
14877 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14878
14879 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14880 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14881 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14882 {
14883 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14884 rcStrict = VINF_SUCCESS;
14885 }
14886 else
14887 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14888 VBOXSTRICTRC_VAL(rcStrict)));
14889 return rcStrict;
14890}
14891
14892
14893/**
14894 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14895 */
14896HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14897{
14898 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14899
14900 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14901 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14902 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14903 AssertRCReturn(rc, rc);
14904
14905 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14906 if (rcStrict == VINF_SUCCESS)
14907 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14908 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14909 {
14910 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14911 rcStrict = VINF_SUCCESS;
14912 }
14913
14914 return rcStrict;
14915}
14916
14917
14918/**
14919 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14920 */
14921HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14922{
14923 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14924
14925 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14926 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14927 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14928 AssertRCReturn(rc, rc);
14929
14930 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14931 if (RT_SUCCESS(rcStrict))
14932 {
14933 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14934 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14935 rcStrict = VINF_SUCCESS;
14936 }
14937
14938 return rcStrict;
14939}
14940
14941
14942/**
14943 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14944 * VM-exit.
14945 */
14946HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14947{
14948 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14949 return VINF_EM_RESET;
14950}
14951
14952
14953/**
14954 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14955 */
14956HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14957{
14958 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14959
14960 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14961 AssertRCReturn(rc, rc);
14962
14963 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14964 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14965 rc = VINF_SUCCESS;
14966 else
14967 rc = VINF_EM_HALT;
14968
14969 if (rc != VINF_SUCCESS)
14970 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14971 return rc;
14972}
14973
14974
14975/**
14976 * VM-exit handler for instructions that result in a \#UD exception delivered to
14977 * the guest.
14978 */
14979HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14980{
14981 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14982 hmR0VmxSetPendingXcptUD(pVCpu);
14983 return VINF_SUCCESS;
14984}
14985
14986
14987/**
14988 * VM-exit handler for expiry of the VMX-preemption timer.
14989 */
14990HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14991{
14992 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14993
14994 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14995 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14996
14997 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14998 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14999 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
15000 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
15001 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
15002}
15003
15004
15005/**
15006 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
15007 */
15008HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15009{
15010 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15011
15012 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15013 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15014 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15015 AssertRCReturn(rc, rc);
15016
15017 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
15018 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15019 : HM_CHANGED_RAISED_XCPT_MASK);
15020
15021 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15022 bool const fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15023 if (fLoadSaveGuestXcr0 != pVCpu->hmr0.s.fLoadSaveGuestXcr0)
15024 {
15025 pVCpu->hmr0.s.fLoadSaveGuestXcr0 = fLoadSaveGuestXcr0;
15026 hmR0VmxUpdateStartVmFunction(pVCpu);
15027 }
15028
15029 return rcStrict;
15030}
15031
15032
15033/**
15034 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15035 */
15036HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15037{
15038 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15039
15040 /** @todo Enable the new code after finding a reliably guest test-case. */
15041#if 1
15042 return VERR_EM_INTERPRETER;
15043#else
15044 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15045 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15046 hmR0VmxReadExitQualVmcs(pVmxTransient);
15047 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15048 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15049 AssertRCReturn(rc, rc);
15050
15051 /* Paranoia. Ensure this has a memory operand. */
15052 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
15053
15054 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
15055 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
15056 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
15057 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
15058
15059 RTGCPTR GCPtrDesc;
15060 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
15061
15062 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
15063 GCPtrDesc, uType);
15064 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15065 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15066 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15067 {
15068 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15069 rcStrict = VINF_SUCCESS;
15070 }
15071 return rcStrict;
15072#endif
15073}
15074
15075
15076/**
15077 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15078 * VM-exit.
15079 */
15080HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15081{
15082 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15083 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15084 AssertRCReturn(rc, rc);
15085
15086 rc = hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15087 if (RT_FAILURE(rc))
15088 return rc;
15089
15090 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15091 NOREF(uInvalidReason);
15092
15093#ifdef VBOX_STRICT
15094 uint32_t fIntrState;
15095 uint64_t u64Val;
15096 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15097 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15098 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15099
15100 Log4(("uInvalidReason %u\n", uInvalidReason));
15101 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15102 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15103 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15104
15105 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
15106 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15107 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
15108 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
15109 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
15110 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
15111 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
15112 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
15113 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
15114 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
15115 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
15116 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
15117 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging)
15118 {
15119 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15120 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15121 }
15122 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
15123#endif
15124
15125 return VERR_VMX_INVALID_GUEST_STATE;
15126}
15127
15128/**
15129 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15130 */
15131HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15132{
15133 /*
15134 * Cumulative notes of all recognized but unexpected VM-exits.
15135 *
15136 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
15137 * nested-paging is used.
15138 *
15139 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15140 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15141 * this function (and thereby stop VM execution) for handling such instructions.
15142 *
15143 *
15144 * VMX_EXIT_INIT_SIGNAL:
15145 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15146 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15147 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15148 *
15149 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15150 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15151 * See Intel spec. "23.8 Restrictions on VMX operation".
15152 *
15153 * VMX_EXIT_SIPI:
15154 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15155 * activity state is used. We don't make use of it as our guests don't have direct
15156 * access to the host local APIC.
15157 *
15158 * See Intel spec. 25.3 "Other Causes of VM-exits".
15159 *
15160 * VMX_EXIT_IO_SMI:
15161 * VMX_EXIT_SMI:
15162 * This can only happen if we support dual-monitor treatment of SMI, which can be
15163 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15164 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15165 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15166 *
15167 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15168 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15169 *
15170 * VMX_EXIT_ERR_MSR_LOAD:
15171 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15172 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15173 * execution.
15174 *
15175 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15176 *
15177 * VMX_EXIT_ERR_MACHINE_CHECK:
15178 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15179 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15180 * #MC exception abort class exception is raised. We thus cannot assume a
15181 * reasonable chance of continuing any sort of execution and we bail.
15182 *
15183 * See Intel spec. 15.1 "Machine-check Architecture".
15184 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15185 *
15186 * VMX_EXIT_PML_FULL:
15187 * VMX_EXIT_VIRTUALIZED_EOI:
15188 * VMX_EXIT_APIC_WRITE:
15189 * We do not currently support any of these features and thus they are all unexpected
15190 * VM-exits.
15191 *
15192 * VMX_EXIT_GDTR_IDTR_ACCESS:
15193 * VMX_EXIT_LDTR_TR_ACCESS:
15194 * VMX_EXIT_RDRAND:
15195 * VMX_EXIT_RSM:
15196 * VMX_EXIT_VMFUNC:
15197 * VMX_EXIT_ENCLS:
15198 * VMX_EXIT_RDSEED:
15199 * VMX_EXIT_XSAVES:
15200 * VMX_EXIT_XRSTORS:
15201 * VMX_EXIT_UMWAIT:
15202 * VMX_EXIT_TPAUSE:
15203 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15204 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15205 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15206 *
15207 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15208 */
15209 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15210 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15211 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15212}
15213
15214
15215/**
15216 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15217 */
15218HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15219{
15220 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15221
15222 /** @todo Optimize this: We currently drag in the whole MSR state
15223 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15224 * MSRs required. That would require changes to IEM and possibly CPUM too.
15225 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15226 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15227 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15228 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15229 switch (idMsr)
15230 {
15231 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15232 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15233 }
15234
15235 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15236 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15237 AssertRCReturn(rc, rc);
15238
15239 Log4Func(("ecx=%#RX32\n", idMsr));
15240
15241#ifdef VBOX_STRICT
15242 Assert(!pVmxTransient->fIsNestedGuest);
15243 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15244 {
15245 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15246 && idMsr != MSR_K6_EFER)
15247 {
15248 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15249 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15250 }
15251 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15252 {
15253 Assert(pVmcsInfo->pvMsrBitmap);
15254 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15255 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15256 {
15257 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15258 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15259 }
15260 }
15261 }
15262#endif
15263
15264 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
15265 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15266 if (rcStrict == VINF_SUCCESS)
15267 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15268 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15269 {
15270 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15271 rcStrict = VINF_SUCCESS;
15272 }
15273 else
15274 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ || rcStrict == VINF_EM_TRIPLE_FAULT,
15275 ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15276
15277 return rcStrict;
15278}
15279
15280
15281/**
15282 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15283 */
15284HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15285{
15286 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15287
15288 /** @todo Optimize this: We currently drag in the whole MSR state
15289 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15290 * MSRs required. That would require changes to IEM and possibly CPUM too.
15291 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15292 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15293 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15294
15295 /*
15296 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15297 * Although we don't need to fetch the base as it will be overwritten shortly, while
15298 * loading guest-state we would also load the entire segment register including limit
15299 * and attributes and thus we need to load them here.
15300 */
15301 switch (idMsr)
15302 {
15303 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15304 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15305 }
15306
15307 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15308 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15309 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15310 AssertRCReturn(rc, rc);
15311
15312 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15313
15314 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
15315 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15316
15317 if (rcStrict == VINF_SUCCESS)
15318 {
15319 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15320
15321 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15322 if ( idMsr == MSR_IA32_APICBASE
15323 || ( idMsr >= MSR_IA32_X2APIC_START
15324 && idMsr <= MSR_IA32_X2APIC_END))
15325 {
15326 /*
15327 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15328 * When full APIC register virtualization is implemented we'll have to make
15329 * sure APIC state is saved from the VMCS before IEM changes it.
15330 */
15331 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15332 }
15333 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15334 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15335 else if (idMsr == MSR_K6_EFER)
15336 {
15337 /*
15338 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15339 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15340 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15341 */
15342 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15343 }
15344
15345 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15346 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15347 {
15348 switch (idMsr)
15349 {
15350 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15351 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15352 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15353 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15354 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15355 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15356 default:
15357 {
15358 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15359 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15360 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15361 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15362 break;
15363 }
15364 }
15365 }
15366#ifdef VBOX_STRICT
15367 else
15368 {
15369 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15370 switch (idMsr)
15371 {
15372 case MSR_IA32_SYSENTER_CS:
15373 case MSR_IA32_SYSENTER_EIP:
15374 case MSR_IA32_SYSENTER_ESP:
15375 case MSR_K8_FS_BASE:
15376 case MSR_K8_GS_BASE:
15377 {
15378 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15379 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15380 }
15381
15382 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15383 default:
15384 {
15385 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15386 {
15387 /* EFER MSR writes are always intercepted. */
15388 if (idMsr != MSR_K6_EFER)
15389 {
15390 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15391 idMsr));
15392 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15393 }
15394 }
15395
15396 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15397 {
15398 Assert(pVmcsInfo->pvMsrBitmap);
15399 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15400 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15401 {
15402 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15403 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15404 }
15405 }
15406 break;
15407 }
15408 }
15409 }
15410#endif /* VBOX_STRICT */
15411 }
15412 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15413 {
15414 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15415 rcStrict = VINF_SUCCESS;
15416 }
15417 else
15418 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE || rcStrict == VINF_EM_TRIPLE_FAULT,
15419 ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15420
15421 return rcStrict;
15422}
15423
15424
15425/**
15426 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15427 */
15428HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15429{
15430 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15431
15432 /** @todo The guest has likely hit a contended spinlock. We might want to
15433 * poke a schedule different guest VCPU. */
15434 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15435 if (RT_SUCCESS(rc))
15436 return VINF_EM_RAW_INTERRUPT;
15437
15438 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15439 return rc;
15440}
15441
15442
15443/**
15444 * VM-exit handler for when the TPR value is lowered below the specified
15445 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15446 */
15447HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15448{
15449 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15450 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15451
15452 /*
15453 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15454 * We'll re-evaluate pending interrupts and inject them before the next VM
15455 * entry so we can just continue execution here.
15456 */
15457 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15458 return VINF_SUCCESS;
15459}
15460
15461
15462/**
15463 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15464 * VM-exit.
15465 *
15466 * @retval VINF_SUCCESS when guest execution can continue.
15467 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15468 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15469 * incompatible guest state for VMX execution (real-on-v86 case).
15470 */
15471HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15472{
15473 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15474 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15475
15476 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15477 hmR0VmxReadExitQualVmcs(pVmxTransient);
15478 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15479
15480 VBOXSTRICTRC rcStrict;
15481 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15482 uint64_t const uExitQual = pVmxTransient->uExitQual;
15483 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15484 switch (uAccessType)
15485 {
15486 /*
15487 * MOV to CRx.
15488 */
15489 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15490 {
15491 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15492 AssertRCReturn(rc, rc);
15493
15494 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15495 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15496 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15497 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15498
15499 /*
15500 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15501 * - When nested paging isn't used.
15502 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15503 * - We are executing in the VM debug loop.
15504 */
15505 Assert( iCrReg != 3
15506 || !pVM->hmr0.s.fNestedPaging
15507 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15508 || pVCpu->hmr0.s.fUsingDebugLoop);
15509
15510 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15511 Assert( iCrReg != 8
15512 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15513
15514 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15515 AssertMsg( rcStrict == VINF_SUCCESS
15516 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15517
15518 /*
15519 * This is a kludge for handling switches back to real mode when we try to use
15520 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15521 * deal with special selector values, so we have to return to ring-3 and run
15522 * there till the selector values are V86 mode compatible.
15523 *
15524 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15525 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15526 * this function.
15527 */
15528 if ( iCrReg == 0
15529 && rcStrict == VINF_SUCCESS
15530 && !pVM->hmr0.s.vmx.fUnrestrictedGuest
15531 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15532 && (uOldCr0 & X86_CR0_PE)
15533 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15534 {
15535 /** @todo Check selectors rather than returning all the time. */
15536 Assert(!pVmxTransient->fIsNestedGuest);
15537 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15538 rcStrict = VINF_EM_RESCHEDULE_REM;
15539 }
15540 break;
15541 }
15542
15543 /*
15544 * MOV from CRx.
15545 */
15546 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15547 {
15548 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15549 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15550
15551 /*
15552 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15553 * - When nested paging isn't used.
15554 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15555 * - We are executing in the VM debug loop.
15556 */
15557 Assert( iCrReg != 3
15558 || !pVM->hmr0.s.fNestedPaging
15559 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15560 || pVCpu->hmr0.s.fLeaveDone);
15561
15562 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15563 Assert( iCrReg != 8
15564 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15565
15566 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15567 break;
15568 }
15569
15570 /*
15571 * CLTS (Clear Task-Switch Flag in CR0).
15572 */
15573 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15574 {
15575 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15576 break;
15577 }
15578
15579 /*
15580 * LMSW (Load Machine-Status Word into CR0).
15581 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15582 */
15583 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15584 {
15585 RTGCPTR GCPtrEffDst;
15586 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15587 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15588 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15589 if (fMemOperand)
15590 {
15591 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15592 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15593 }
15594 else
15595 GCPtrEffDst = NIL_RTGCPTR;
15596 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15597 break;
15598 }
15599
15600 default:
15601 {
15602 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15603 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15604 }
15605 }
15606
15607 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15608 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15609 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15610
15611 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15612 NOREF(pVM);
15613 return rcStrict;
15614}
15615
15616
15617/**
15618 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15619 * VM-exit.
15620 */
15621HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15622{
15623 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15624 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15625
15626 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15627 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15628 hmR0VmxReadExitQualVmcs(pVmxTransient);
15629 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15630 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15631 | CPUMCTX_EXTRN_EFER);
15632 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15633 AssertRCReturn(rc, rc);
15634
15635 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15636 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15637 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15638 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15639 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15640 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15641 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15642 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15643
15644 /*
15645 * Update exit history to see if this exit can be optimized.
15646 */
15647 VBOXSTRICTRC rcStrict;
15648 PCEMEXITREC pExitRec = NULL;
15649 if ( !fGstStepping
15650 && !fDbgStepping)
15651 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15652 !fIOString
15653 ? !fIOWrite
15654 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15655 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15656 : !fIOWrite
15657 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15658 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15659 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15660 if (!pExitRec)
15661 {
15662 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15663 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15664
15665 uint32_t const cbValue = s_aIOSizes[uIOSize];
15666 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15667 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15668 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15669 if (fIOString)
15670 {
15671 /*
15672 * INS/OUTS - I/O String instruction.
15673 *
15674 * Use instruction-information if available, otherwise fall back on
15675 * interpreting the instruction.
15676 */
15677 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15678 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15679 bool const fInsOutsInfo = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15680 if (fInsOutsInfo)
15681 {
15682 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15683 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15684 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15685 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15686 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15687 if (fIOWrite)
15688 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15689 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15690 else
15691 {
15692 /*
15693 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15694 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15695 * See Intel Instruction spec. for "INS".
15696 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15697 */
15698 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15699 }
15700 }
15701 else
15702 rcStrict = IEMExecOne(pVCpu);
15703
15704 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15705 fUpdateRipAlready = true;
15706 }
15707 else
15708 {
15709 /*
15710 * IN/OUT - I/O instruction.
15711 */
15712 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15713 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15714 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15715 if (fIOWrite)
15716 {
15717 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15718 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15719 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15720 && !pCtx->eflags.Bits.u1TF)
15721 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15722 }
15723 else
15724 {
15725 uint32_t u32Result = 0;
15726 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15727 if (IOM_SUCCESS(rcStrict))
15728 {
15729 /* Save result of I/O IN instr. in AL/AX/EAX. */
15730 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15731 }
15732 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15733 && !pCtx->eflags.Bits.u1TF)
15734 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15735 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15736 }
15737 }
15738
15739 if (IOM_SUCCESS(rcStrict))
15740 {
15741 if (!fUpdateRipAlready)
15742 {
15743 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15744 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15745 }
15746
15747 /*
15748 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15749 * while booting Fedora 17 64-bit guest.
15750 *
15751 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15752 */
15753 if (fIOString)
15754 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15755
15756 /*
15757 * If any I/O breakpoints are armed, we need to check if one triggered
15758 * and take appropriate action.
15759 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15760 */
15761 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15762 AssertRCReturn(rc, rc);
15763
15764 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15765 * execution engines about whether hyper BPs and such are pending. */
15766 uint32_t const uDr7 = pCtx->dr[7];
15767 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15768 && X86_DR7_ANY_RW_IO(uDr7)
15769 && (pCtx->cr4 & X86_CR4_DE))
15770 || DBGFBpIsHwIoArmed(pVM)))
15771 {
15772 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15773
15774 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15775 VMMRZCallRing3Disable(pVCpu);
15776 HM_DISABLE_PREEMPT(pVCpu);
15777
15778 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15779
15780 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15781 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15782 {
15783 /* Raise #DB. */
15784 if (fIsGuestDbgActive)
15785 ASMSetDR6(pCtx->dr[6]);
15786 if (pCtx->dr[7] != uDr7)
15787 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15788
15789 hmR0VmxSetPendingXcptDB(pVCpu);
15790 }
15791 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15792 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15793 else if ( rcStrict2 != VINF_SUCCESS
15794 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15795 rcStrict = rcStrict2;
15796 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15797
15798 HM_RESTORE_PREEMPT();
15799 VMMRZCallRing3Enable(pVCpu);
15800 }
15801 }
15802
15803#ifdef VBOX_STRICT
15804 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15805 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15806 Assert(!fIOWrite);
15807 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15808 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15809 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15810 Assert(fIOWrite);
15811 else
15812 {
15813# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15814 * statuses, that the VMM device and some others may return. See
15815 * IOM_SUCCESS() for guidance. */
15816 AssertMsg( RT_FAILURE(rcStrict)
15817 || rcStrict == VINF_SUCCESS
15818 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15819 || rcStrict == VINF_EM_DBG_BREAKPOINT
15820 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15821 || rcStrict == VINF_EM_RAW_TO_R3
15822 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15823# endif
15824 }
15825#endif
15826 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15827 }
15828 else
15829 {
15830 /*
15831 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15832 */
15833 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15834 AssertRCReturn(rc2, rc2);
15835 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15836 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15837 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15838 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15839 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15840 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15841
15842 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15843 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15844
15845 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15846 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15847 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15848 }
15849 return rcStrict;
15850}
15851
15852
15853/**
15854 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15855 * VM-exit.
15856 */
15857HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15858{
15859 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15860
15861 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15862 hmR0VmxReadExitQualVmcs(pVmxTransient);
15863 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15864 {
15865 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15866 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15867 {
15868 uint32_t uErrCode;
15869 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15870 {
15871 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15872 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15873 }
15874 else
15875 uErrCode = 0;
15876
15877 RTGCUINTPTR GCPtrFaultAddress;
15878 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15879 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15880 else
15881 GCPtrFaultAddress = 0;
15882
15883 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15884
15885 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15886 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15887
15888 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15889 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15890 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15891 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15892 }
15893 }
15894
15895 /* Fall back to the interpreter to emulate the task-switch. */
15896 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15897 return VERR_EM_INTERPRETER;
15898}
15899
15900
15901/**
15902 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15903 */
15904HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15905{
15906 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15907
15908 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15909 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15910 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15911 AssertRC(rc);
15912 return VINF_EM_DBG_STEPPED;
15913}
15914
15915
15916/**
15917 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15918 */
15919HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15920{
15921 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15922 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15923
15924 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15925 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15926 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15927 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15928 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15929
15930 /*
15931 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15932 */
15933 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15934 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15935 {
15936 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15937 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15938 {
15939 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15940 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15941 }
15942 }
15943 else
15944 {
15945 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15946 return rcStrict;
15947 }
15948
15949 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15950 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15951 hmR0VmxReadExitQualVmcs(pVmxTransient);
15952 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15953 AssertRCReturn(rc, rc);
15954
15955 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15956 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15957 switch (uAccessType)
15958 {
15959 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15960 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15961 {
15962 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15963 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15964 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15965
15966 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15967 GCPhys &= PAGE_BASE_GC_MASK;
15968 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15969 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15970 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15971
15972 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
15973 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
15974 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15975 if ( rcStrict == VINF_SUCCESS
15976 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15977 || rcStrict == VERR_PAGE_NOT_PRESENT)
15978 {
15979 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15980 | HM_CHANGED_GUEST_APIC_TPR);
15981 rcStrict = VINF_SUCCESS;
15982 }
15983 break;
15984 }
15985
15986 default:
15987 {
15988 Log4Func(("uAccessType=%#x\n", uAccessType));
15989 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15990 break;
15991 }
15992 }
15993
15994 if (rcStrict != VINF_SUCCESS)
15995 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15996 return rcStrict;
15997}
15998
15999
16000/**
16001 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
16002 * VM-exit.
16003 */
16004HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16005{
16006 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16007 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16008
16009 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
16010 if (!pVmxTransient->fIsNestedGuest)
16011 {
16012 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16013 if (pVmxTransient->fWasGuestDebugStateActive)
16014 {
16015 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16016 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16017 }
16018
16019 if ( !pVCpu->hm.s.fSingleInstruction
16020 && !pVmxTransient->fWasHyperDebugStateActive)
16021 {
16022 Assert(!DBGFIsStepping(pVCpu));
16023 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16024
16025 /* Don't intercept MOV DRx any more. */
16026 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16027 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16028 AssertRC(rc);
16029
16030 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16031 VMMRZCallRing3Disable(pVCpu);
16032 HM_DISABLE_PREEMPT(pVCpu);
16033
16034 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16035 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16036 Assert(CPUMIsGuestDebugStateActive(pVCpu));
16037
16038 HM_RESTORE_PREEMPT();
16039 VMMRZCallRing3Enable(pVCpu);
16040
16041#ifdef VBOX_WITH_STATISTICS
16042 hmR0VmxReadExitQualVmcs(pVmxTransient);
16043 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16044 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16045 else
16046 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16047#endif
16048 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16049 return VINF_SUCCESS;
16050 }
16051 }
16052
16053 /*
16054 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16055 * The EFER MSR is always up-to-date.
16056 * Update the segment registers and DR7 from the CPU.
16057 */
16058 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16059 hmR0VmxReadExitQualVmcs(pVmxTransient);
16060 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16061 AssertRCReturn(rc, rc);
16062 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16063
16064 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16065 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16066 {
16067 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16068 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16069 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16070 if (RT_SUCCESS(rc))
16071 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16072 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16073 }
16074 else
16075 {
16076 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16077 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16078 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16079 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16080 }
16081
16082 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16083 if (RT_SUCCESS(rc))
16084 {
16085 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16086 AssertRCReturn(rc2, rc2);
16087 return VINF_SUCCESS;
16088 }
16089 return rc;
16090}
16091
16092
16093/**
16094 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16095 * Conditional VM-exit.
16096 */
16097HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16098{
16099 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16100 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16101
16102 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16103 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16104 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16105 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16106 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16107
16108 /*
16109 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16110 */
16111 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16112 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16113 {
16114 /*
16115 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16116 * instruction emulation to inject the original event. Otherwise, injecting the original event
16117 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
16118 */
16119 if (!pVCpu->hm.s.Event.fPending)
16120 { /* likely */ }
16121 else
16122 {
16123 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16124#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16125 /** @todo NSTVMX: Think about how this should be handled. */
16126 if (pVmxTransient->fIsNestedGuest)
16127 return VERR_VMX_IPE_3;
16128#endif
16129 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16130 }
16131 }
16132 else
16133 {
16134 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16135 return rcStrict;
16136 }
16137
16138 /*
16139 * Get sufficient state and update the exit history entry.
16140 */
16141 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16142 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16143 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16144 AssertRCReturn(rc, rc);
16145
16146 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16147 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16148 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16149 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16150 if (!pExitRec)
16151 {
16152 /*
16153 * If we succeed, resume guest execution.
16154 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16155 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16156 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16157 * weird case. See @bugref{6043}.
16158 */
16159 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16160 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16161/** @todo bird: We can probably just go straight to IOM here and assume that
16162 * it's MMIO, then fall back on PGM if that hunch didn't work out so
16163 * well. However, we need to address that aliasing workarounds that
16164 * PGMR0Trap0eHandlerNPMisconfig implements. So, some care is needed.
16165 *
16166 * Might also be interesting to see if we can get this done more or
16167 * less locklessly inside IOM. Need to consider the lookup table
16168 * updating and use a bit more carefully first (or do all updates via
16169 * rendezvous) */
16170 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16171 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16172 if ( rcStrict == VINF_SUCCESS
16173 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16174 || rcStrict == VERR_PAGE_NOT_PRESENT)
16175 {
16176 /* Successfully handled MMIO operation. */
16177 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16178 | HM_CHANGED_GUEST_APIC_TPR);
16179 rcStrict = VINF_SUCCESS;
16180 }
16181 }
16182 else
16183 {
16184 /*
16185 * Frequent exit or something needing probing. Call EMHistoryExec.
16186 */
16187 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16188 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16189
16190 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16191 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16192
16193 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16194 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16195 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16196 }
16197 return rcStrict;
16198}
16199
16200
16201/**
16202 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16203 * VM-exit.
16204 */
16205HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16206{
16207 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16208 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16209
16210 hmR0VmxReadExitQualVmcs(pVmxTransient);
16211 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16212 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16213 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16214 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16215 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16216
16217 /*
16218 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16219 */
16220 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16221 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16222 {
16223 /*
16224 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16225 * we shall resolve the nested #PF and re-inject the original event.
16226 */
16227 if (pVCpu->hm.s.Event.fPending)
16228 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16229 }
16230 else
16231 {
16232 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16233 return rcStrict;
16234 }
16235
16236 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16237 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16238 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16239 AssertRCReturn(rc, rc);
16240
16241 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16242 uint64_t const uExitQual = pVmxTransient->uExitQual;
16243 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16244
16245 RTGCUINT uErrorCode = 0;
16246 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16247 uErrorCode |= X86_TRAP_PF_ID;
16248 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16249 uErrorCode |= X86_TRAP_PF_RW;
16250 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16251 uErrorCode |= X86_TRAP_PF_P;
16252
16253 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16254 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16255 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16256
16257 /*
16258 * Handle the pagefault trap for the nested shadow table.
16259 */
16260 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16261 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16262 TRPMResetTrap(pVCpu);
16263
16264 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16265 if ( rcStrict == VINF_SUCCESS
16266 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16267 || rcStrict == VERR_PAGE_NOT_PRESENT)
16268 {
16269 /* Successfully synced our nested page tables. */
16270 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16271 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16272 return VINF_SUCCESS;
16273 }
16274
16275 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16276 return rcStrict;
16277}
16278
16279
16280#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16281/**
16282 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16283 */
16284HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16285{
16286 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16287
16288 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16289 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16290 hmR0VmxReadExitQualVmcs(pVmxTransient);
16291 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16292 | CPUMCTX_EXTRN_HWVIRT
16293 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16294 AssertRCReturn(rc, rc);
16295
16296 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16297
16298 VMXVEXITINFO ExitInfo;
16299 RT_ZERO(ExitInfo);
16300 ExitInfo.uReason = pVmxTransient->uExitReason;
16301 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16302 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16303 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16304 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16305
16306 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16307 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16308 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16309 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16310 {
16311 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16312 rcStrict = VINF_SUCCESS;
16313 }
16314 return rcStrict;
16315}
16316
16317
16318/**
16319 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16320 */
16321HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16322{
16323 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16324
16325 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16326 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16327 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16328 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16329 AssertRCReturn(rc, rc);
16330
16331 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16332
16333 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16334 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
16335 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16336 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16337 {
16338 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16339 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16340 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16341 }
16342 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16343 return rcStrict;
16344}
16345
16346
16347/**
16348 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16349 */
16350HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16351{
16352 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16353
16354 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16355 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16356 hmR0VmxReadExitQualVmcs(pVmxTransient);
16357 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16358 | CPUMCTX_EXTRN_HWVIRT
16359 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16360 AssertRCReturn(rc, rc);
16361
16362 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16363
16364 VMXVEXITINFO ExitInfo;
16365 RT_ZERO(ExitInfo);
16366 ExitInfo.uReason = pVmxTransient->uExitReason;
16367 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16368 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16369 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16370 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16371
16372 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16373 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16374 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16375 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16376 {
16377 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16378 rcStrict = VINF_SUCCESS;
16379 }
16380 return rcStrict;
16381}
16382
16383
16384/**
16385 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16386 */
16387HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16388{
16389 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16390
16391 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16392 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16393 hmR0VmxReadExitQualVmcs(pVmxTransient);
16394 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16395 | CPUMCTX_EXTRN_HWVIRT
16396 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16397 AssertRCReturn(rc, rc);
16398
16399 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16400
16401 VMXVEXITINFO ExitInfo;
16402 RT_ZERO(ExitInfo);
16403 ExitInfo.uReason = pVmxTransient->uExitReason;
16404 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16405 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16406 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16407 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16408
16409 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16410 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16411 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16412 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16413 {
16414 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16415 rcStrict = VINF_SUCCESS;
16416 }
16417 return rcStrict;
16418}
16419
16420
16421/**
16422 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16423 */
16424HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16425{
16426 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16427
16428 /*
16429 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16430 * thus might not need to import the shadow VMCS state, it's safer just in case
16431 * code elsewhere dares look at unsynced VMCS fields.
16432 */
16433 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16434 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16435 hmR0VmxReadExitQualVmcs(pVmxTransient);
16436 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16437 | CPUMCTX_EXTRN_HWVIRT
16438 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16439 AssertRCReturn(rc, rc);
16440
16441 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16442
16443 VMXVEXITINFO ExitInfo;
16444 RT_ZERO(ExitInfo);
16445 ExitInfo.uReason = pVmxTransient->uExitReason;
16446 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16447 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16448 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16449 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16450 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16451
16452 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16453 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16454 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16455 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16456 {
16457 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16458 rcStrict = VINF_SUCCESS;
16459 }
16460 return rcStrict;
16461}
16462
16463
16464/**
16465 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16466 */
16467HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16468{
16469 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16470
16471 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16472 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16473 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16474 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16475 AssertRCReturn(rc, rc);
16476
16477 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16478
16479 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16480 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16481 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16482 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16483 {
16484 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16485 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16486 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16487 }
16488 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16489 return rcStrict;
16490}
16491
16492
16493/**
16494 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16495 */
16496HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16497{
16498 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16499
16500 /*
16501 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16502 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16503 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16504 */
16505 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16506 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16507 hmR0VmxReadExitQualVmcs(pVmxTransient);
16508 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16509 | CPUMCTX_EXTRN_HWVIRT
16510 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16511 AssertRCReturn(rc, rc);
16512
16513 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16514
16515 VMXVEXITINFO ExitInfo;
16516 RT_ZERO(ExitInfo);
16517 ExitInfo.uReason = pVmxTransient->uExitReason;
16518 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16519 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16520 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16521 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16522 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16523
16524 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16525 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16526 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16527 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16528 {
16529 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16530 rcStrict = VINF_SUCCESS;
16531 }
16532 return rcStrict;
16533}
16534
16535
16536/**
16537 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16538 */
16539HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16540{
16541 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16542
16543 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16544 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16545 | CPUMCTX_EXTRN_HWVIRT
16546 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16547 AssertRCReturn(rc, rc);
16548
16549 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16550
16551 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16552 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16553 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16554 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16555 {
16556 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16557 rcStrict = VINF_SUCCESS;
16558 }
16559 return rcStrict;
16560}
16561
16562
16563/**
16564 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16565 */
16566HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16567{
16568 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16569
16570 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16571 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16572 hmR0VmxReadExitQualVmcs(pVmxTransient);
16573 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16574 | CPUMCTX_EXTRN_HWVIRT
16575 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16576 AssertRCReturn(rc, rc);
16577
16578 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16579
16580 VMXVEXITINFO ExitInfo;
16581 RT_ZERO(ExitInfo);
16582 ExitInfo.uReason = pVmxTransient->uExitReason;
16583 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16584 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16585 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16586 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16587
16588 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16589 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16590 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16591 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16592 {
16593 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16594 rcStrict = VINF_SUCCESS;
16595 }
16596 return rcStrict;
16597}
16598
16599
16600/**
16601 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16602 */
16603HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16604{
16605 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16606
16607 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16608 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16609 hmR0VmxReadExitQualVmcs(pVmxTransient);
16610 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16611 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16612 AssertRCReturn(rc, rc);
16613
16614 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16615
16616 VMXVEXITINFO ExitInfo;
16617 RT_ZERO(ExitInfo);
16618 ExitInfo.uReason = pVmxTransient->uExitReason;
16619 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16620 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16621 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16622 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16623
16624 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16625 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16626 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16627 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16628 {
16629 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16630 rcStrict = VINF_SUCCESS;
16631 }
16632 return rcStrict;
16633}
16634#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16635/** @} */
16636
16637
16638#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16639/** @name Nested-guest VM-exit handlers.
16640 * @{
16641 */
16642/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16643/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16644/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16645
16646/**
16647 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16648 * Conditional VM-exit.
16649 */
16650HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16651{
16652 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16653
16654 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16655
16656 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16657 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16658 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16659
16660 switch (uExitIntType)
16661 {
16662 /*
16663 * Physical NMIs:
16664 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16665 */
16666 case VMX_EXIT_INT_INFO_TYPE_NMI:
16667 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16668
16669 /*
16670 * Hardware exceptions,
16671 * Software exceptions,
16672 * Privileged software exceptions:
16673 * Figure out if the exception must be delivered to the guest or the nested-guest.
16674 */
16675 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16676 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16677 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16678 {
16679 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16680 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16681 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16682 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16683
16684 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16685 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16686 pVmxTransient->uExitIntErrorCode);
16687 if (fIntercept)
16688 {
16689 /* Exit qualification is required for debug and page-fault exceptions. */
16690 hmR0VmxReadExitQualVmcs(pVmxTransient);
16691
16692 /*
16693 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16694 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16695 * length. However, if delivery of a software interrupt, software exception or privileged
16696 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16697 */
16698 VMXVEXITINFO ExitInfo;
16699 RT_ZERO(ExitInfo);
16700 ExitInfo.uReason = pVmxTransient->uExitReason;
16701 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16702 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16703
16704 VMXVEXITEVENTINFO ExitEventInfo;
16705 RT_ZERO(ExitEventInfo);
16706 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16707 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16708 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16709 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16710
16711#ifdef DEBUG_ramshankar
16712 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16713 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16714 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16715 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16716 {
16717 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16718 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16719 }
16720#endif
16721 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16722 }
16723
16724 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16725 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16726 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16727 }
16728
16729 /*
16730 * Software interrupts:
16731 * VM-exits cannot be caused by software interrupts.
16732 *
16733 * External interrupts:
16734 * This should only happen when "acknowledge external interrupts on VM-exit"
16735 * control is set. However, we never set this when executing a guest or
16736 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16737 * the guest.
16738 */
16739 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16740 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16741 default:
16742 {
16743 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16744 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16745 }
16746 }
16747}
16748
16749
16750/**
16751 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16752 * Unconditional VM-exit.
16753 */
16754HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16755{
16756 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16757 return IEMExecVmxVmexitTripleFault(pVCpu);
16758}
16759
16760
16761/**
16762 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16763 */
16764HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16765{
16766 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16767
16768 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16769 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16770 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16771}
16772
16773
16774/**
16775 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16776 */
16777HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16778{
16779 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16780
16781 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16782 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16783 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16784}
16785
16786
16787/**
16788 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16789 * Unconditional VM-exit.
16790 */
16791HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16792{
16793 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16794
16795 hmR0VmxReadExitQualVmcs(pVmxTransient);
16796 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16797 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16798 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16799
16800 VMXVEXITINFO ExitInfo;
16801 RT_ZERO(ExitInfo);
16802 ExitInfo.uReason = pVmxTransient->uExitReason;
16803 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16804 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16805
16806 VMXVEXITEVENTINFO ExitEventInfo;
16807 RT_ZERO(ExitEventInfo);
16808 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16809 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16810 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16811}
16812
16813
16814/**
16815 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16816 */
16817HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16818{
16819 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16820
16821 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16822 {
16823 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16824 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16825 }
16826 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16827}
16828
16829
16830/**
16831 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16832 */
16833HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16834{
16835 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16836
16837 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16838 {
16839 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16840 hmR0VmxReadExitQualVmcs(pVmxTransient);
16841
16842 VMXVEXITINFO ExitInfo;
16843 RT_ZERO(ExitInfo);
16844 ExitInfo.uReason = pVmxTransient->uExitReason;
16845 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16846 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16847 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16848 }
16849 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16850}
16851
16852
16853/**
16854 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16855 */
16856HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16857{
16858 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16859
16860 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16861 {
16862 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16863 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16864 }
16865 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16866}
16867
16868
16869/**
16870 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16871 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16872 */
16873HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16874{
16875 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16876
16877 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16878 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16879
16880 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16881
16882 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16883 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16884 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16885
16886 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16887 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16888 u64VmcsField &= UINT64_C(0xffffffff);
16889
16890 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16891 {
16892 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16893 hmR0VmxReadExitQualVmcs(pVmxTransient);
16894
16895 VMXVEXITINFO ExitInfo;
16896 RT_ZERO(ExitInfo);
16897 ExitInfo.uReason = pVmxTransient->uExitReason;
16898 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16899 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16900 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16901 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16902 }
16903
16904 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16905 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16906 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16907}
16908
16909
16910/**
16911 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16912 */
16913HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16914{
16915 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16916
16917 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16918 {
16919 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16920 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16921 }
16922
16923 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16924}
16925
16926
16927/**
16928 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16929 * Conditional VM-exit.
16930 */
16931HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16932{
16933 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16934
16935 hmR0VmxReadExitQualVmcs(pVmxTransient);
16936 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16937
16938 VBOXSTRICTRC rcStrict;
16939 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16940 switch (uAccessType)
16941 {
16942 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16943 {
16944 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16945 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16946 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16947 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16948
16949 bool fIntercept;
16950 switch (iCrReg)
16951 {
16952 case 0:
16953 case 4:
16954 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(&pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16955 break;
16956
16957 case 3:
16958 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16959 break;
16960
16961 case 8:
16962 fIntercept = CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16963 break;
16964
16965 default:
16966 fIntercept = false;
16967 break;
16968 }
16969 if (fIntercept)
16970 {
16971 VMXVEXITINFO ExitInfo;
16972 RT_ZERO(ExitInfo);
16973 ExitInfo.uReason = pVmxTransient->uExitReason;
16974 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16975 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16976 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16977 }
16978 else
16979 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16980 break;
16981 }
16982
16983 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16984 {
16985 /*
16986 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16987 * CR2 reads do not cause a VM-exit.
16988 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16989 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16990 */
16991 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16992 if ( iCrReg == 3
16993 || iCrReg == 8)
16994 {
16995 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16996 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16997 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16998 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uIntercept))
16999 {
17000 VMXVEXITINFO ExitInfo;
17001 RT_ZERO(ExitInfo);
17002 ExitInfo.uReason = pVmxTransient->uExitReason;
17003 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17004 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17005 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17006 }
17007 else
17008 {
17009 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17010 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
17011 }
17012 }
17013 else
17014 {
17015 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17016 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17017 }
17018 break;
17019 }
17020
17021 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17022 {
17023 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17024 Assert(pVmcsNstGst);
17025 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17026 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17027 if ( (uGstHostMask & X86_CR0_TS)
17028 && (uReadShadow & X86_CR0_TS))
17029 {
17030 VMXVEXITINFO ExitInfo;
17031 RT_ZERO(ExitInfo);
17032 ExitInfo.uReason = pVmxTransient->uExitReason;
17033 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17034 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17035 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17036 }
17037 else
17038 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
17039 break;
17040 }
17041
17042 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17043 {
17044 RTGCPTR GCPtrEffDst;
17045 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17046 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17047 if (fMemOperand)
17048 {
17049 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17050 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17051 }
17052 else
17053 GCPtrEffDst = NIL_RTGCPTR;
17054
17055 if (CPUMIsGuestVmxLmswInterceptSet(&pVCpu->cpum.GstCtx, uNewMsw))
17056 {
17057 VMXVEXITINFO ExitInfo;
17058 RT_ZERO(ExitInfo);
17059 ExitInfo.uReason = pVmxTransient->uExitReason;
17060 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17061 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17062 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17063 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17064 }
17065 else
17066 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
17067 break;
17068 }
17069
17070 default:
17071 {
17072 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17073 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17074 }
17075 }
17076
17077 if (rcStrict == VINF_IEM_RAISED_XCPT)
17078 {
17079 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17080 rcStrict = VINF_SUCCESS;
17081 }
17082 return rcStrict;
17083}
17084
17085
17086/**
17087 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17088 * Conditional VM-exit.
17089 */
17090HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17091{
17092 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17093
17094 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17095 {
17096 hmR0VmxReadExitQualVmcs(pVmxTransient);
17097 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17098
17099 VMXVEXITINFO ExitInfo;
17100 RT_ZERO(ExitInfo);
17101 ExitInfo.uReason = pVmxTransient->uExitReason;
17102 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17103 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17104 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17105 }
17106 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17107}
17108
17109
17110/**
17111 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17112 * Conditional VM-exit.
17113 */
17114HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17115{
17116 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17117
17118 hmR0VmxReadExitQualVmcs(pVmxTransient);
17119
17120 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17121 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17122 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17123
17124 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17125 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17126 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17127 {
17128 /*
17129 * IN/OUT instruction:
17130 * - Provides VM-exit instruction length.
17131 *
17132 * INS/OUTS instruction:
17133 * - Provides VM-exit instruction length.
17134 * - Provides Guest-linear address.
17135 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17136 */
17137 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
17138 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17139
17140 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17141 pVmxTransient->ExitInstrInfo.u = 0;
17142 pVmxTransient->uGuestLinearAddr = 0;
17143
17144 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17145 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17146 if (fIOString)
17147 {
17148 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17149 if (fVmxInsOutsInfo)
17150 {
17151 Assert(RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17152 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17153 }
17154 }
17155
17156 VMXVEXITINFO ExitInfo;
17157 RT_ZERO(ExitInfo);
17158 ExitInfo.uReason = pVmxTransient->uExitReason;
17159 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17160 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17161 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17162 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17163 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17164 }
17165 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17166}
17167
17168
17169/**
17170 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17171 */
17172HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17173{
17174 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17175
17176 uint32_t fMsrpm;
17177 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17178 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17179 else
17180 fMsrpm = VMXMSRPM_EXIT_RD;
17181
17182 if (fMsrpm & VMXMSRPM_EXIT_RD)
17183 {
17184 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17185 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17186 }
17187 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17188}
17189
17190
17191/**
17192 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17193 */
17194HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17195{
17196 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17197
17198 uint32_t fMsrpm;
17199 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17200 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17201 else
17202 fMsrpm = VMXMSRPM_EXIT_WR;
17203
17204 if (fMsrpm & VMXMSRPM_EXIT_WR)
17205 {
17206 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17207 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17208 }
17209 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17210}
17211
17212
17213/**
17214 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17215 */
17216HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17217{
17218 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17219
17220 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17221 {
17222 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17223 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17224 }
17225 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17226}
17227
17228
17229/**
17230 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17231 * VM-exit.
17232 */
17233HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17234{
17235 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17236
17237 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17238 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17239 VMXVEXITINFO ExitInfo;
17240 RT_ZERO(ExitInfo);
17241 ExitInfo.uReason = pVmxTransient->uExitReason;
17242 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17243 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17244}
17245
17246
17247/**
17248 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17249 */
17250HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17251{
17252 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17253
17254 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17255 {
17256 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17257 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17258 }
17259 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17260}
17261
17262
17263/**
17264 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17265 */
17266HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17267{
17268 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17269
17270 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17271 * PAUSE when executing a nested-guest? If it does not, we would not need
17272 * to check for the intercepts here. Just call VM-exit... */
17273
17274 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17275 if ( CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17276 || CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17277 {
17278 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17279 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17280 }
17281 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17282}
17283
17284
17285/**
17286 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17287 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17288 */
17289HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17290{
17291 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17292
17293 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17294 {
17295 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17296 VMXVEXITINFO ExitInfo;
17297 RT_ZERO(ExitInfo);
17298 ExitInfo.uReason = pVmxTransient->uExitReason;
17299 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17300 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17301 }
17302 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17303}
17304
17305
17306/**
17307 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17308 * VM-exit.
17309 */
17310HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17311{
17312 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17313
17314 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17315 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17316 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17317 hmR0VmxReadExitQualVmcs(pVmxTransient);
17318
17319 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17320
17321 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
17322 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
17323
17324 VMXVEXITINFO ExitInfo;
17325 RT_ZERO(ExitInfo);
17326 ExitInfo.uReason = pVmxTransient->uExitReason;
17327 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17328 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17329
17330 VMXVEXITEVENTINFO ExitEventInfo;
17331 RT_ZERO(ExitEventInfo);
17332 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17333 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17334 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17335}
17336
17337
17338/**
17339 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17340 * Conditional VM-exit.
17341 */
17342HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17343{
17344 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17345
17346 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17347 hmR0VmxReadExitQualVmcs(pVmxTransient);
17348 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17349}
17350
17351
17352/**
17353 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17354 * Conditional VM-exit.
17355 */
17356HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17357{
17358 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17359
17360 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17361 hmR0VmxReadExitQualVmcs(pVmxTransient);
17362 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17363}
17364
17365
17366/**
17367 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17368 */
17369HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17370{
17371 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17372
17373 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17374 {
17375 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17376 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17377 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17378 }
17379 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17380}
17381
17382
17383/**
17384 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17385 */
17386HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17387{
17388 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17389
17390 if (CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17391 {
17392 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17393 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17394 }
17395 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17396}
17397
17398
17399/**
17400 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17401 */
17402HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17403{
17404 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17405
17406 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17407 {
17408 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17409 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17410 hmR0VmxReadExitQualVmcs(pVmxTransient);
17411 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17412
17413 VMXVEXITINFO ExitInfo;
17414 RT_ZERO(ExitInfo);
17415 ExitInfo.uReason = pVmxTransient->uExitReason;
17416 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17417 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17418 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17419 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17420 }
17421 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17422}
17423
17424
17425/**
17426 * Nested-guest VM-exit handler for invalid-guest state
17427 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17428 */
17429HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17430{
17431 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17432
17433 /*
17434 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17435 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17436 * Handle it like it's in an invalid guest state of the outer guest.
17437 *
17438 * When the fast path is implemented, this should be changed to cause the corresponding
17439 * nested-guest VM-exit.
17440 */
17441 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17442}
17443
17444
17445/**
17446 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17447 * and only provide the instruction length.
17448 *
17449 * Unconditional VM-exit.
17450 */
17451HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17452{
17453 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17454
17455#ifdef VBOX_STRICT
17456 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17457 switch (pVmxTransient->uExitReason)
17458 {
17459 case VMX_EXIT_ENCLS:
17460 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17461 break;
17462
17463 case VMX_EXIT_VMFUNC:
17464 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_VMFUNC));
17465 break;
17466 }
17467#endif
17468
17469 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17470 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17471}
17472
17473
17474/**
17475 * Nested-guest VM-exit handler for instructions that provide instruction length as
17476 * well as more information.
17477 *
17478 * Unconditional VM-exit.
17479 */
17480HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17481{
17482 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17483
17484#ifdef VBOX_STRICT
17485 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17486 switch (pVmxTransient->uExitReason)
17487 {
17488 case VMX_EXIT_GDTR_IDTR_ACCESS:
17489 case VMX_EXIT_LDTR_TR_ACCESS:
17490 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17491 break;
17492
17493 case VMX_EXIT_RDRAND:
17494 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17495 break;
17496
17497 case VMX_EXIT_RDSEED:
17498 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17499 break;
17500
17501 case VMX_EXIT_XSAVES:
17502 case VMX_EXIT_XRSTORS:
17503 /** @todo NSTVMX: Verify XSS-bitmap. */
17504 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17505 break;
17506
17507 case VMX_EXIT_UMWAIT:
17508 case VMX_EXIT_TPAUSE:
17509 Assert(CPUMIsGuestVmxProcCtlsSet(pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17510 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17511 break;
17512 }
17513#endif
17514
17515 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17516 hmR0VmxReadExitQualVmcs(pVmxTransient);
17517 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17518
17519 VMXVEXITINFO ExitInfo;
17520 RT_ZERO(ExitInfo);
17521 ExitInfo.uReason = pVmxTransient->uExitReason;
17522 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17523 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17524 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17525 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17526}
17527
17528/** @} */
17529#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17530
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