VirtualBox

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

Last change on this file since 90932 was 90932, checked in by vboxsync, 3 years ago

VMM: Nested VMX: bugref:10092 Renamed VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_XXX to VMX_VMCS64_CTRL_VE_XCPT_INFO_ADDR_XXX and fixed comment typo. No functional change.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 740.0 KB
Line 
1/* $Id: HMVMXR0.cpp 90932 2021-08-27 05:42:03Z 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_VE_XCPT_INFO_ADDR_FULL,
537 VMX_VMCS64_CTRL_VE_XCPT_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_SPPTP_FULL,
543 VMX_VMCS64_CTRL_SPPTP_HIGH,
544 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
545 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
546 VMX_VMCS64_CTRL_PROC_EXEC3_FULL,
547 VMX_VMCS64_CTRL_PROC_EXEC3_HIGH,
548 VMX_VMCS64_CTRL_ENCLV_EXITING_BITMAP_FULL,
549 VMX_VMCS64_CTRL_ENCLV_EXITING_BITMAP_HIGH,
550
551 /* 64-bit read-only data fields. */
552 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
553 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
554
555 /* 64-bit guest-state fields. */
556 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
557 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
558 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
559 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
560 VMX_VMCS64_GUEST_PAT_FULL,
561 VMX_VMCS64_GUEST_PAT_HIGH,
562 VMX_VMCS64_GUEST_EFER_FULL,
563 VMX_VMCS64_GUEST_EFER_HIGH,
564 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
565 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
566 VMX_VMCS64_GUEST_PDPTE0_FULL,
567 VMX_VMCS64_GUEST_PDPTE0_HIGH,
568 VMX_VMCS64_GUEST_PDPTE1_FULL,
569 VMX_VMCS64_GUEST_PDPTE1_HIGH,
570 VMX_VMCS64_GUEST_PDPTE2_FULL,
571 VMX_VMCS64_GUEST_PDPTE2_HIGH,
572 VMX_VMCS64_GUEST_PDPTE3_FULL,
573 VMX_VMCS64_GUEST_PDPTE3_HIGH,
574 VMX_VMCS64_GUEST_BNDCFGS_FULL,
575 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
576 VMX_VMCS64_GUEST_RTIT_CTL_FULL,
577 VMX_VMCS64_GUEST_RTIT_CTL_HIGH,
578 VMX_VMCS64_GUEST_PKRS_FULL,
579 VMX_VMCS64_GUEST_PKRS_HIGH,
580
581 /* 64-bit host-state fields. */
582 VMX_VMCS64_HOST_PAT_FULL,
583 VMX_VMCS64_HOST_PAT_HIGH,
584 VMX_VMCS64_HOST_EFER_FULL,
585 VMX_VMCS64_HOST_EFER_HIGH,
586 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
587 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
588 VMX_VMCS64_HOST_PKRS_FULL,
589 VMX_VMCS64_HOST_PKRS_HIGH,
590
591 /* 32-bit control fields. */
592 VMX_VMCS32_CTRL_PIN_EXEC,
593 VMX_VMCS32_CTRL_PROC_EXEC,
594 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
595 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
596 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
597 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
598 VMX_VMCS32_CTRL_EXIT,
599 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
600 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
601 VMX_VMCS32_CTRL_ENTRY,
602 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
603 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
604 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
605 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
606 VMX_VMCS32_CTRL_TPR_THRESHOLD,
607 VMX_VMCS32_CTRL_PROC_EXEC2,
608 VMX_VMCS32_CTRL_PLE_GAP,
609 VMX_VMCS32_CTRL_PLE_WINDOW,
610
611 /* 32-bits read-only fields. */
612 VMX_VMCS32_RO_VM_INSTR_ERROR,
613 VMX_VMCS32_RO_EXIT_REASON,
614 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
615 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
616 VMX_VMCS32_RO_IDT_VECTORING_INFO,
617 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
618 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
619 VMX_VMCS32_RO_EXIT_INSTR_INFO,
620
621 /* 32-bit guest-state fields. */
622 VMX_VMCS32_GUEST_ES_LIMIT,
623 VMX_VMCS32_GUEST_CS_LIMIT,
624 VMX_VMCS32_GUEST_SS_LIMIT,
625 VMX_VMCS32_GUEST_DS_LIMIT,
626 VMX_VMCS32_GUEST_FS_LIMIT,
627 VMX_VMCS32_GUEST_GS_LIMIT,
628 VMX_VMCS32_GUEST_LDTR_LIMIT,
629 VMX_VMCS32_GUEST_TR_LIMIT,
630 VMX_VMCS32_GUEST_GDTR_LIMIT,
631 VMX_VMCS32_GUEST_IDTR_LIMIT,
632 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
633 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
634 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
635 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
636 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
637 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
638 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
639 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
640 VMX_VMCS32_GUEST_INT_STATE,
641 VMX_VMCS32_GUEST_ACTIVITY_STATE,
642 VMX_VMCS32_GUEST_SMBASE,
643 VMX_VMCS32_GUEST_SYSENTER_CS,
644 VMX_VMCS32_PREEMPT_TIMER_VALUE,
645
646 /* 32-bit host-state fields. */
647 VMX_VMCS32_HOST_SYSENTER_CS,
648
649 /* Natural-width control fields. */
650 VMX_VMCS_CTRL_CR0_MASK,
651 VMX_VMCS_CTRL_CR4_MASK,
652 VMX_VMCS_CTRL_CR0_READ_SHADOW,
653 VMX_VMCS_CTRL_CR4_READ_SHADOW,
654 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
655 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
656 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
657 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
658
659 /* Natural-width read-only data fields. */
660 VMX_VMCS_RO_EXIT_QUALIFICATION,
661 VMX_VMCS_RO_IO_RCX,
662 VMX_VMCS_RO_IO_RSI,
663 VMX_VMCS_RO_IO_RDI,
664 VMX_VMCS_RO_IO_RIP,
665 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
666
667 /* Natural-width guest-state field */
668 VMX_VMCS_GUEST_CR0,
669 VMX_VMCS_GUEST_CR3,
670 VMX_VMCS_GUEST_CR4,
671 VMX_VMCS_GUEST_ES_BASE,
672 VMX_VMCS_GUEST_CS_BASE,
673 VMX_VMCS_GUEST_SS_BASE,
674 VMX_VMCS_GUEST_DS_BASE,
675 VMX_VMCS_GUEST_FS_BASE,
676 VMX_VMCS_GUEST_GS_BASE,
677 VMX_VMCS_GUEST_LDTR_BASE,
678 VMX_VMCS_GUEST_TR_BASE,
679 VMX_VMCS_GUEST_GDTR_BASE,
680 VMX_VMCS_GUEST_IDTR_BASE,
681 VMX_VMCS_GUEST_DR7,
682 VMX_VMCS_GUEST_RSP,
683 VMX_VMCS_GUEST_RIP,
684 VMX_VMCS_GUEST_RFLAGS,
685 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
686 VMX_VMCS_GUEST_SYSENTER_ESP,
687 VMX_VMCS_GUEST_SYSENTER_EIP,
688 VMX_VMCS_GUEST_S_CET,
689 VMX_VMCS_GUEST_SSP,
690 VMX_VMCS_GUEST_INTR_SSP_TABLE_ADDR,
691
692 /* Natural-width host-state fields */
693 VMX_VMCS_HOST_CR0,
694 VMX_VMCS_HOST_CR3,
695 VMX_VMCS_HOST_CR4,
696 VMX_VMCS_HOST_FS_BASE,
697 VMX_VMCS_HOST_GS_BASE,
698 VMX_VMCS_HOST_TR_BASE,
699 VMX_VMCS_HOST_GDTR_BASE,
700 VMX_VMCS_HOST_IDTR_BASE,
701 VMX_VMCS_HOST_SYSENTER_ESP,
702 VMX_VMCS_HOST_SYSENTER_EIP,
703 VMX_VMCS_HOST_RSP,
704 VMX_VMCS_HOST_RIP,
705 VMX_VMCS_HOST_S_CET,
706 VMX_VMCS_HOST_SSP,
707 VMX_VMCS_HOST_INTR_SSP_TABLE_ADDR
708};
709#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
710
711#ifdef VBOX_STRICT
712static const uint32_t g_aVmcsSegBase[] =
713{
714 VMX_VMCS_GUEST_ES_BASE,
715 VMX_VMCS_GUEST_CS_BASE,
716 VMX_VMCS_GUEST_SS_BASE,
717 VMX_VMCS_GUEST_DS_BASE,
718 VMX_VMCS_GUEST_FS_BASE,
719 VMX_VMCS_GUEST_GS_BASE
720};
721static const uint32_t g_aVmcsSegSel[] =
722{
723 VMX_VMCS16_GUEST_ES_SEL,
724 VMX_VMCS16_GUEST_CS_SEL,
725 VMX_VMCS16_GUEST_SS_SEL,
726 VMX_VMCS16_GUEST_DS_SEL,
727 VMX_VMCS16_GUEST_FS_SEL,
728 VMX_VMCS16_GUEST_GS_SEL
729};
730static const uint32_t g_aVmcsSegLimit[] =
731{
732 VMX_VMCS32_GUEST_ES_LIMIT,
733 VMX_VMCS32_GUEST_CS_LIMIT,
734 VMX_VMCS32_GUEST_SS_LIMIT,
735 VMX_VMCS32_GUEST_DS_LIMIT,
736 VMX_VMCS32_GUEST_FS_LIMIT,
737 VMX_VMCS32_GUEST_GS_LIMIT
738};
739static const uint32_t g_aVmcsSegAttr[] =
740{
741 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
742 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
743 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
744 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
745 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
746 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
747};
748AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
749AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
750AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
751AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
752#endif /* VBOX_STRICT */
753
754#ifdef HMVMX_USE_FUNCTION_TABLE
755/**
756 * VMX_EXIT dispatch table.
757 */
758static const struct CLANG11NOTHROWWEIRDNESS { PFNVMXEXITHANDLER pfn; } g_aVMExitHandlers[VMX_EXIT_MAX + 1] =
759{
760 /* 0 VMX_EXIT_XCPT_OR_NMI */ { hmR0VmxExitXcptOrNmi },
761 /* 1 VMX_EXIT_EXT_INT */ { hmR0VmxExitExtInt },
762 /* 2 VMX_EXIT_TRIPLE_FAULT */ { hmR0VmxExitTripleFault },
763 /* 3 VMX_EXIT_INIT_SIGNAL */ { hmR0VmxExitErrUnexpected },
764 /* 4 VMX_EXIT_SIPI */ { hmR0VmxExitErrUnexpected },
765 /* 5 VMX_EXIT_IO_SMI */ { hmR0VmxExitErrUnexpected },
766 /* 6 VMX_EXIT_SMI */ { hmR0VmxExitErrUnexpected },
767 /* 7 VMX_EXIT_INT_WINDOW */ { hmR0VmxExitIntWindow },
768 /* 8 VMX_EXIT_NMI_WINDOW */ { hmR0VmxExitNmiWindow },
769 /* 9 VMX_EXIT_TASK_SWITCH */ { hmR0VmxExitTaskSwitch },
770 /* 10 VMX_EXIT_CPUID */ { hmR0VmxExitCpuid },
771 /* 11 VMX_EXIT_GETSEC */ { hmR0VmxExitGetsec },
772 /* 12 VMX_EXIT_HLT */ { hmR0VmxExitHlt },
773 /* 13 VMX_EXIT_INVD */ { hmR0VmxExitInvd },
774 /* 14 VMX_EXIT_INVLPG */ { hmR0VmxExitInvlpg },
775 /* 15 VMX_EXIT_RDPMC */ { hmR0VmxExitRdpmc },
776 /* 16 VMX_EXIT_RDTSC */ { hmR0VmxExitRdtsc },
777 /* 17 VMX_EXIT_RSM */ { hmR0VmxExitErrUnexpected },
778 /* 18 VMX_EXIT_VMCALL */ { hmR0VmxExitVmcall },
779#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
780 /* 19 VMX_EXIT_VMCLEAR */ { hmR0VmxExitVmclear },
781 /* 20 VMX_EXIT_VMLAUNCH */ { hmR0VmxExitVmlaunch },
782 /* 21 VMX_EXIT_VMPTRLD */ { hmR0VmxExitVmptrld },
783 /* 22 VMX_EXIT_VMPTRST */ { hmR0VmxExitVmptrst },
784 /* 23 VMX_EXIT_VMREAD */ { hmR0VmxExitVmread },
785 /* 24 VMX_EXIT_VMRESUME */ { hmR0VmxExitVmresume },
786 /* 25 VMX_EXIT_VMWRITE */ { hmR0VmxExitVmwrite },
787 /* 26 VMX_EXIT_VMXOFF */ { hmR0VmxExitVmxoff },
788 /* 27 VMX_EXIT_VMXON */ { hmR0VmxExitVmxon },
789#else
790 /* 19 VMX_EXIT_VMCLEAR */ { hmR0VmxExitSetPendingXcptUD },
791 /* 20 VMX_EXIT_VMLAUNCH */ { hmR0VmxExitSetPendingXcptUD },
792 /* 21 VMX_EXIT_VMPTRLD */ { hmR0VmxExitSetPendingXcptUD },
793 /* 22 VMX_EXIT_VMPTRST */ { hmR0VmxExitSetPendingXcptUD },
794 /* 23 VMX_EXIT_VMREAD */ { hmR0VmxExitSetPendingXcptUD },
795 /* 24 VMX_EXIT_VMRESUME */ { hmR0VmxExitSetPendingXcptUD },
796 /* 25 VMX_EXIT_VMWRITE */ { hmR0VmxExitSetPendingXcptUD },
797 /* 26 VMX_EXIT_VMXOFF */ { hmR0VmxExitSetPendingXcptUD },
798 /* 27 VMX_EXIT_VMXON */ { hmR0VmxExitSetPendingXcptUD },
799#endif
800 /* 28 VMX_EXIT_MOV_CRX */ { hmR0VmxExitMovCRx },
801 /* 29 VMX_EXIT_MOV_DRX */ { hmR0VmxExitMovDRx },
802 /* 30 VMX_EXIT_IO_INSTR */ { hmR0VmxExitIoInstr },
803 /* 31 VMX_EXIT_RDMSR */ { hmR0VmxExitRdmsr },
804 /* 32 VMX_EXIT_WRMSR */ { hmR0VmxExitWrmsr },
805 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ { hmR0VmxExitErrInvalidGuestState },
806 /* 34 VMX_EXIT_ERR_MSR_LOAD */ { hmR0VmxExitErrUnexpected },
807 /* 35 UNDEFINED */ { hmR0VmxExitErrUnexpected },
808 /* 36 VMX_EXIT_MWAIT */ { hmR0VmxExitMwait },
809 /* 37 VMX_EXIT_MTF */ { hmR0VmxExitMtf },
810 /* 38 UNDEFINED */ { hmR0VmxExitErrUnexpected },
811 /* 39 VMX_EXIT_MONITOR */ { hmR0VmxExitMonitor },
812 /* 40 VMX_EXIT_PAUSE */ { hmR0VmxExitPause },
813 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ { hmR0VmxExitErrUnexpected },
814 /* 42 UNDEFINED */ { hmR0VmxExitErrUnexpected },
815 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ { hmR0VmxExitTprBelowThreshold },
816 /* 44 VMX_EXIT_APIC_ACCESS */ { hmR0VmxExitApicAccess },
817 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ { hmR0VmxExitErrUnexpected },
818 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ { hmR0VmxExitErrUnexpected },
819 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ { hmR0VmxExitErrUnexpected },
820 /* 48 VMX_EXIT_EPT_VIOLATION */ { hmR0VmxExitEptViolation },
821 /* 49 VMX_EXIT_EPT_MISCONFIG */ { hmR0VmxExitEptMisconfig },
822 /* 50 VMX_EXIT_INVEPT */ { hmR0VmxExitSetPendingXcptUD },
823 /* 51 VMX_EXIT_RDTSCP */ { hmR0VmxExitRdtscp },
824 /* 52 VMX_EXIT_PREEMPT_TIMER */ { hmR0VmxExitPreemptTimer },
825#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
826 /* 53 VMX_EXIT_INVVPID */ { hmR0VmxExitInvvpid },
827#else
828 /* 53 VMX_EXIT_INVVPID */ { hmR0VmxExitSetPendingXcptUD },
829#endif
830 /* 54 VMX_EXIT_WBINVD */ { hmR0VmxExitWbinvd },
831 /* 55 VMX_EXIT_XSETBV */ { hmR0VmxExitXsetbv },
832 /* 56 VMX_EXIT_APIC_WRITE */ { hmR0VmxExitErrUnexpected },
833 /* 57 VMX_EXIT_RDRAND */ { hmR0VmxExitErrUnexpected },
834 /* 58 VMX_EXIT_INVPCID */ { hmR0VmxExitInvpcid },
835 /* 59 VMX_EXIT_VMFUNC */ { hmR0VmxExitErrUnexpected },
836 /* 60 VMX_EXIT_ENCLS */ { hmR0VmxExitErrUnexpected },
837 /* 61 VMX_EXIT_RDSEED */ { hmR0VmxExitErrUnexpected },
838 /* 62 VMX_EXIT_PML_FULL */ { hmR0VmxExitErrUnexpected },
839 /* 63 VMX_EXIT_XSAVES */ { hmR0VmxExitErrUnexpected },
840 /* 64 VMX_EXIT_XRSTORS */ { hmR0VmxExitErrUnexpected },
841 /* 65 UNDEFINED */ { hmR0VmxExitErrUnexpected },
842 /* 66 VMX_EXIT_SPP_EVENT */ { hmR0VmxExitErrUnexpected },
843 /* 67 VMX_EXIT_UMWAIT */ { hmR0VmxExitErrUnexpected },
844 /* 68 VMX_EXIT_TPAUSE */ { hmR0VmxExitErrUnexpected },
845};
846#endif /* HMVMX_USE_FUNCTION_TABLE */
847
848#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
849static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
850{
851 /* 0 */ "(Not Used)",
852 /* 1 */ "VMCALL executed in VMX root operation.",
853 /* 2 */ "VMCLEAR with invalid physical address.",
854 /* 3 */ "VMCLEAR with VMXON pointer.",
855 /* 4 */ "VMLAUNCH with non-clear VMCS.",
856 /* 5 */ "VMRESUME with non-launched VMCS.",
857 /* 6 */ "VMRESUME after VMXOFF",
858 /* 7 */ "VM-entry with invalid control fields.",
859 /* 8 */ "VM-entry with invalid host state fields.",
860 /* 9 */ "VMPTRLD with invalid physical address.",
861 /* 10 */ "VMPTRLD with VMXON pointer.",
862 /* 11 */ "VMPTRLD with incorrect revision identifier.",
863 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
864 /* 13 */ "VMWRITE to read-only VMCS component.",
865 /* 14 */ "(Not Used)",
866 /* 15 */ "VMXON executed in VMX root operation.",
867 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
868 /* 17 */ "VM-entry with non-launched executing VMCS.",
869 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
870 /* 19 */ "VMCALL with non-clear VMCS.",
871 /* 20 */ "VMCALL with invalid VM-exit control fields.",
872 /* 21 */ "(Not Used)",
873 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
874 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
875 /* 24 */ "VMCALL with invalid SMM-monitor features.",
876 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
877 /* 26 */ "VM-entry with events blocked by MOV SS.",
878 /* 27 */ "(Not Used)",
879 /* 28 */ "Invalid operand to INVEPT/INVVPID."
880};
881#endif /* VBOX_STRICT && LOG_ENABLED */
882
883
884/**
885 * Checks if the given MSR is part of the lastbranch-from-IP MSR stack.
886 * @returns @c true if it's part of LBR stack, @c false otherwise.
887 *
888 * @param pVM The cross context VM structure.
889 * @param idMsr The MSR.
890 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
891 * Optional, can be NULL.
892 *
893 * @remarks Must only be called when LBR is enabled.
894 */
895DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchFromMsr(PCVMCC pVM, uint32_t idMsr, uint32_t *pidxMsr)
896{
897 Assert(pVM->hmr0.s.vmx.fLbr);
898 Assert(pVM->hmr0.s.vmx.idLbrFromIpMsrFirst);
899 uint32_t const cLbrStack = pVM->hmr0.s.vmx.idLbrFromIpMsrLast - pVM->hmr0.s.vmx.idLbrFromIpMsrFirst + 1;
900 uint32_t const idxMsr = idMsr - pVM->hmr0.s.vmx.idLbrFromIpMsrFirst;
901 if (idxMsr < cLbrStack)
902 {
903 if (pidxMsr)
904 *pidxMsr = idxMsr;
905 return true;
906 }
907 return false;
908}
909
910
911/**
912 * Checks if the given MSR is part of the lastbranch-to-IP MSR stack.
913 * @returns @c true if it's part of LBR stack, @c false otherwise.
914 *
915 * @param pVM The cross context VM structure.
916 * @param idMsr The MSR.
917 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
918 * Optional, can be NULL.
919 *
920 * @remarks Must only be called when LBR is enabled and when lastbranch-to-IP MSRs
921 * are supported by the CPU (see hmR0VmxSetupLbrMsrRange).
922 */
923DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchToMsr(PCVMCC pVM, uint32_t idMsr, uint32_t *pidxMsr)
924{
925 Assert(pVM->hmr0.s.vmx.fLbr);
926 if (pVM->hmr0.s.vmx.idLbrToIpMsrFirst)
927 {
928 uint32_t const cLbrStack = pVM->hmr0.s.vmx.idLbrToIpMsrLast - pVM->hmr0.s.vmx.idLbrToIpMsrFirst + 1;
929 uint32_t const idxMsr = idMsr - pVM->hmr0.s.vmx.idLbrToIpMsrFirst;
930 if (idxMsr < cLbrStack)
931 {
932 if (pidxMsr)
933 *pidxMsr = idxMsr;
934 return true;
935 }
936 }
937 return false;
938}
939
940
941/**
942 * Gets the CR0 guest/host mask.
943 *
944 * These bits typically does not change through the lifetime of a VM. Any bit set in
945 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
946 * by the guest.
947 *
948 * @returns The CR0 guest/host mask.
949 * @param pVCpu The cross context virtual CPU structure.
950 */
951static uint64_t hmR0VmxGetFixedCr0Mask(PCVMCPUCC pVCpu)
952{
953 /*
954 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
955 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
956 *
957 * Furthermore, modifications to any bits that are reserved/unspecified currently
958 * by the Intel spec. must also cause a VM-exit. This prevents unpredictable behavior
959 * when future CPUs specify and use currently reserved/unspecified bits.
960 */
961 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
962 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
963 * and @bugref{6944}. */
964 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
965 return ( X86_CR0_PE
966 | X86_CR0_NE
967 | (pVM->hmr0.s.fNestedPaging ? 0 : X86_CR0_WP)
968 | X86_CR0_PG
969 | VMX_EXIT_HOST_CR0_IGNORE_MASK);
970}
971
972
973/**
974 * Gets the CR4 guest/host mask.
975 *
976 * These bits typically does not change through the lifetime of a VM. Any bit set in
977 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
978 * by the guest.
979 *
980 * @returns The CR4 guest/host mask.
981 * @param pVCpu The cross context virtual CPU structure.
982 */
983static uint64_t hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
984{
985 /*
986 * We construct a mask of all CR4 bits that the guest can modify without causing
987 * a VM-exit. Then invert this mask to obtain all CR4 bits that should cause
988 * a VM-exit when the guest attempts to modify them when executing using
989 * hardware-assisted VMX.
990 *
991 * When a feature is not exposed to the guest (and may be present on the host),
992 * we want to intercept guest modifications to the bit so we can emulate proper
993 * behavior (e.g., #GP).
994 *
995 * Furthermore, only modifications to those bits that don't require immediate
996 * emulation is allowed. For e.g., PCIDE is excluded because the behavior
997 * depends on CR3 which might not always be the guest value while executing
998 * using hardware-assisted VMX.
999 */
1000 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
1001 bool const fFsGsBase = pVM->cpum.ro.GuestFeatures.fFsGsBase;
1002 bool const fXSaveRstor = pVM->cpum.ro.GuestFeatures.fXSaveRstor;
1003 bool const fFxSaveRstor = pVM->cpum.ro.GuestFeatures.fFxSaveRstor;
1004
1005 /*
1006 * Paranoia.
1007 * Ensure features exposed to the guest are present on the host.
1008 */
1009 Assert(!fFsGsBase || pVM->cpum.ro.HostFeatures.fFsGsBase);
1010 Assert(!fXSaveRstor || pVM->cpum.ro.HostFeatures.fXSaveRstor);
1011 Assert(!fFxSaveRstor || pVM->cpum.ro.HostFeatures.fFxSaveRstor);
1012
1013 uint64_t const fGstMask = ( X86_CR4_PVI
1014 | X86_CR4_TSD
1015 | X86_CR4_DE
1016 | X86_CR4_MCE
1017 | X86_CR4_PCE
1018 | X86_CR4_OSXMMEEXCPT
1019 | (fFsGsBase ? X86_CR4_FSGSBASE : 0)
1020 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
1021 | (fFxSaveRstor ? X86_CR4_OSFXSR : 0));
1022 return ~fGstMask;
1023}
1024
1025
1026/**
1027 * Gets the active (in use) VMCS info. object for the specified VCPU.
1028 *
1029 * This is either the guest or nested-guest VMCS info. and need not necessarily
1030 * pertain to the "current" VMCS (in the VMX definition of the term). For instance,
1031 * if the VM-entry failed due to an invalid-guest state, we may have "cleared" the
1032 * current VMCS while returning to ring-3. However, the VMCS info. object for that
1033 * VMCS would still be active and returned here so that we could dump the VMCS
1034 * fields to ring-3 for diagnostics. This function is thus only used to
1035 * distinguish between the nested-guest or guest VMCS.
1036 *
1037 * @returns The active VMCS information.
1038 * @param pVCpu The cross context virtual CPU structure.
1039 *
1040 * @thread EMT.
1041 * @remarks This function may be called with preemption or interrupts disabled!
1042 */
1043DECLINLINE(PVMXVMCSINFO) hmGetVmxActiveVmcsInfo(PVMCPUCC pVCpu)
1044{
1045 if (!pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
1046 return &pVCpu->hmr0.s.vmx.VmcsInfo;
1047 return &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1048}
1049
1050
1051/**
1052 * Returns whether the VM-exit MSR-store area differs from the VM-exit MSR-load
1053 * area.
1054 *
1055 * @returns @c true if it's different, @c false otherwise.
1056 * @param pVmcsInfo The VMCS info. object.
1057 */
1058DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
1059{
1060 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
1061 && pVmcsInfo->pvGuestMsrStore);
1062}
1063
1064
1065/**
1066 * Sets the given Processor-based VM-execution controls.
1067 *
1068 * @param pVmxTransient The VMX-transient structure.
1069 * @param uProcCtls The Processor-based VM-execution controls to set.
1070 */
1071static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1072{
1073 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1074 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
1075 {
1076 pVmcsInfo->u32ProcCtls |= uProcCtls;
1077 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1078 AssertRC(rc);
1079 }
1080}
1081
1082
1083/**
1084 * Removes the given Processor-based VM-execution controls.
1085 *
1086 * @param pVCpu The cross context virtual CPU structure.
1087 * @param pVmxTransient The VMX-transient structure.
1088 * @param uProcCtls The Processor-based VM-execution controls to remove.
1089 *
1090 * @remarks When executing a nested-guest, this will not remove any of the specified
1091 * controls if the nested hypervisor has set any one of them.
1092 */
1093static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1094{
1095 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1096 if (pVmcsInfo->u32ProcCtls & uProcCtls)
1097 {
1098#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1099 if ( !pVmxTransient->fIsNestedGuest
1100 || !CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uProcCtls))
1101#else
1102 NOREF(pVCpu);
1103 if (!pVmxTransient->fIsNestedGuest)
1104#endif
1105 {
1106 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
1107 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1108 AssertRC(rc);
1109 }
1110 }
1111}
1112
1113
1114/**
1115 * Sets the TSC offset for the current VMCS.
1116 *
1117 * @param uTscOffset The TSC offset to set.
1118 * @param pVmcsInfo The VMCS info. object.
1119 */
1120static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
1121{
1122 if (pVmcsInfo->u64TscOffset != uTscOffset)
1123 {
1124 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
1125 AssertRC(rc);
1126 pVmcsInfo->u64TscOffset = uTscOffset;
1127 }
1128}
1129
1130
1131/**
1132 * Adds one or more exceptions to the exception bitmap and commits it to the current
1133 * VMCS.
1134 *
1135 * @param pVmxTransient The VMX-transient structure.
1136 * @param uXcptMask The exception(s) to add.
1137 */
1138static void hmR0VmxAddXcptInterceptMask(PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1139{
1140 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1141 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1142 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1143 {
1144 uXcptBitmap |= uXcptMask;
1145 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1146 AssertRC(rc);
1147 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1148 }
1149}
1150
1151
1152/**
1153 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1154 *
1155 * @param pVmxTransient The VMX-transient structure.
1156 * @param uXcpt The exception to add.
1157 */
1158static void hmR0VmxAddXcptIntercept(PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1159{
1160 Assert(uXcpt <= X86_XCPT_LAST);
1161 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1162}
1163
1164
1165/**
1166 * Remove one or more exceptions from the exception bitmap and commits it to the
1167 * current VMCS.
1168 *
1169 * This takes care of not removing the exception intercept if a nested-guest
1170 * requires the exception to be intercepted.
1171 *
1172 * @returns VBox status code.
1173 * @param pVCpu The cross context virtual CPU structure.
1174 * @param pVmxTransient The VMX-transient structure.
1175 * @param uXcptMask The exception(s) to remove.
1176 */
1177static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1178{
1179 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1180 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1181 if (u32XcptBitmap & uXcptMask)
1182 {
1183#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1184 if (!pVmxTransient->fIsNestedGuest)
1185 { /* likely */ }
1186 else
1187 {
1188 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1189 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1190 }
1191#endif
1192#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1193 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1194 | RT_BIT(X86_XCPT_DE)
1195 | RT_BIT(X86_XCPT_NM)
1196 | RT_BIT(X86_XCPT_TS)
1197 | RT_BIT(X86_XCPT_UD)
1198 | RT_BIT(X86_XCPT_NP)
1199 | RT_BIT(X86_XCPT_SS)
1200 | RT_BIT(X86_XCPT_GP)
1201 | RT_BIT(X86_XCPT_PF)
1202 | RT_BIT(X86_XCPT_MF));
1203#elif defined(HMVMX_ALWAYS_TRAP_PF)
1204 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1205#endif
1206 if (uXcptMask)
1207 {
1208 /* Validate we are not removing any essential exception intercepts. */
1209 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1210 NOREF(pVCpu);
1211 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1212 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1213
1214 /* Remove it from the exception bitmap. */
1215 u32XcptBitmap &= ~uXcptMask;
1216
1217 /* Commit and update the cache if necessary. */
1218 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1219 {
1220 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1221 AssertRC(rc);
1222 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1223 }
1224 }
1225 }
1226 return VINF_SUCCESS;
1227}
1228
1229
1230/**
1231 * Remove an exceptions from the exception bitmap and commits it to the current
1232 * VMCS.
1233 *
1234 * @returns VBox status code.
1235 * @param pVCpu The cross context virtual CPU structure.
1236 * @param pVmxTransient The VMX-transient structure.
1237 * @param uXcpt The exception to remove.
1238 */
1239static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1240{
1241 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1242}
1243
1244
1245/**
1246 * Loads the VMCS specified by the VMCS info. object.
1247 *
1248 * @returns VBox status code.
1249 * @param pVmcsInfo The VMCS info. object.
1250 *
1251 * @remarks Can be called with interrupts disabled.
1252 */
1253static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1254{
1255 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1256 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1257
1258 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1259 if (RT_SUCCESS(rc))
1260 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1261 return rc;
1262}
1263
1264
1265/**
1266 * Clears the VMCS specified by the VMCS info. object.
1267 *
1268 * @returns VBox status code.
1269 * @param pVmcsInfo The VMCS info. object.
1270 *
1271 * @remarks Can be called with interrupts disabled.
1272 */
1273static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1274{
1275 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1276 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1277
1278 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1279 if (RT_SUCCESS(rc))
1280 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1281 return rc;
1282}
1283
1284
1285#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1286/**
1287 * Loads the shadow VMCS specified by the VMCS info. object.
1288 *
1289 * @returns VBox status code.
1290 * @param pVmcsInfo The VMCS info. object.
1291 *
1292 * @remarks Can be called with interrupts disabled.
1293 */
1294static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1295{
1296 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1297 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1298
1299 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1300 if (RT_SUCCESS(rc))
1301 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1302 return rc;
1303}
1304
1305
1306/**
1307 * Clears the shadow VMCS specified by the VMCS info. object.
1308 *
1309 * @returns VBox status code.
1310 * @param pVmcsInfo The VMCS info. object.
1311 *
1312 * @remarks Can be called with interrupts disabled.
1313 */
1314static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1315{
1316 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1317 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1318
1319 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1320 if (RT_SUCCESS(rc))
1321 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1322 return rc;
1323}
1324
1325
1326/**
1327 * Switches from and to the specified VMCSes.
1328 *
1329 * @returns VBox status code.
1330 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1331 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1332 *
1333 * @remarks Called with interrupts disabled.
1334 */
1335static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1336{
1337 /*
1338 * Clear the VMCS we are switching out if it has not already been cleared.
1339 * This will sync any CPU internal data back to the VMCS.
1340 */
1341 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1342 {
1343 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1344 if (RT_SUCCESS(rc))
1345 {
1346 /*
1347 * The shadow VMCS, if any, would not be active at this point since we
1348 * would have cleared it while importing the virtual hardware-virtualization
1349 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1350 * clear the shadow VMCS here, just assert for safety.
1351 */
1352 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1353 }
1354 else
1355 return rc;
1356 }
1357
1358 /*
1359 * Clear the VMCS we are switching to if it has not already been cleared.
1360 * This will initialize the VMCS launch state to "clear" required for loading it.
1361 *
1362 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1363 */
1364 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1365 {
1366 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1367 if (RT_SUCCESS(rc))
1368 { /* likely */ }
1369 else
1370 return rc;
1371 }
1372
1373 /*
1374 * Finally, load the VMCS we are switching to.
1375 */
1376 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1377}
1378
1379
1380/**
1381 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1382 * caller.
1383 *
1384 * @returns VBox status code.
1385 * @param pVCpu The cross context virtual CPU structure.
1386 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1387 * true) or guest VMCS (pass false).
1388 */
1389static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1390{
1391 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1392 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1393
1394 PVMXVMCSINFO pVmcsInfoFrom;
1395 PVMXVMCSINFO pVmcsInfoTo;
1396 if (fSwitchToNstGstVmcs)
1397 {
1398 pVmcsInfoFrom = &pVCpu->hmr0.s.vmx.VmcsInfo;
1399 pVmcsInfoTo = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1400 }
1401 else
1402 {
1403 pVmcsInfoFrom = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1404 pVmcsInfoTo = &pVCpu->hmr0.s.vmx.VmcsInfo;
1405 }
1406
1407 /*
1408 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1409 * preemption hook code path acquires the current VMCS.
1410 */
1411 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1412
1413 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1414 if (RT_SUCCESS(rc))
1415 {
1416 pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1417 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcsCopyForRing3 = fSwitchToNstGstVmcs;
1418
1419 /*
1420 * If we are switching to a VMCS that was executed on a different host CPU or was
1421 * never executed before, flag that we need to export the host state before executing
1422 * guest/nested-guest code using hardware-assisted VMX.
1423 *
1424 * This could probably be done in a preemptible context since the preemption hook
1425 * will flag the necessary change in host context. However, since preemption is
1426 * already disabled and to avoid making assumptions about host specific code in
1427 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1428 * disabled.
1429 */
1430 if (pVmcsInfoTo->idHostCpuState == RTMpCpuId())
1431 { /* likely */ }
1432 else
1433 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1434
1435 ASMSetFlags(fEFlags);
1436
1437 /*
1438 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1439 * flag that we need to update the host MSR values there. Even if we decide in the
1440 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1441 * if its content differs, we would have to update the host MSRs anyway.
1442 */
1443 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
1444 }
1445 else
1446 ASMSetFlags(fEFlags);
1447 return rc;
1448}
1449#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1450
1451
1452/**
1453 * Updates the VM's last error record.
1454 *
1455 * If there was a VMX instruction error, reads the error data from the VMCS and
1456 * updates VCPU's last error record as well.
1457 *
1458 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1459 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1460 * VERR_VMX_INVALID_VMCS_FIELD.
1461 * @param rc The error code.
1462 */
1463static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1464{
1465 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1466 || rc == VERR_VMX_UNABLE_TO_START_VM)
1467 {
1468 AssertPtrReturnVoid(pVCpu);
1469 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1470 }
1471 pVCpu->CTX_SUFF(pVM)->hm.s.ForR3.rcInit = rc;
1472}
1473
1474
1475#ifdef VBOX_STRICT
1476/**
1477 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1478 * transient structure.
1479 *
1480 * @param pVmxTransient The VMX-transient structure.
1481 */
1482DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1483{
1484 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1485 AssertRC(rc);
1486}
1487
1488
1489/**
1490 * Reads the VM-entry exception error code field from the VMCS into
1491 * the VMX transient structure.
1492 *
1493 * @param pVmxTransient The VMX-transient structure.
1494 */
1495DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1496{
1497 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1498 AssertRC(rc);
1499}
1500
1501
1502/**
1503 * Reads the VM-entry exception error code field from the VMCS into
1504 * the VMX transient structure.
1505 *
1506 * @param pVmxTransient The VMX-transient structure.
1507 */
1508DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1509{
1510 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1511 AssertRC(rc);
1512}
1513#endif /* VBOX_STRICT */
1514
1515
1516/**
1517 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1518 * transient structure.
1519 *
1520 * @param pVmxTransient The VMX-transient structure.
1521 */
1522DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1523{
1524 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1525 {
1526 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1527 AssertRC(rc);
1528 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1529 }
1530}
1531
1532
1533/**
1534 * Reads the VM-exit interruption error code from the VMCS into the VMX
1535 * transient structure.
1536 *
1537 * @param pVmxTransient The VMX-transient structure.
1538 */
1539DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1540{
1541 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1542 {
1543 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1544 AssertRC(rc);
1545 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1546 }
1547}
1548
1549
1550/**
1551 * Reads the VM-exit instruction length field from the VMCS into the VMX
1552 * transient structure.
1553 *
1554 * @param pVmxTransient The VMX-transient structure.
1555 */
1556DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1557{
1558 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1559 {
1560 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1561 AssertRC(rc);
1562 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1563 }
1564}
1565
1566
1567/**
1568 * Reads the VM-exit instruction-information field from the VMCS into
1569 * the VMX transient structure.
1570 *
1571 * @param pVmxTransient The VMX-transient structure.
1572 */
1573DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1574{
1575 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1576 {
1577 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1578 AssertRC(rc);
1579 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1580 }
1581}
1582
1583
1584/**
1585 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1586 *
1587 * @param pVmxTransient The VMX-transient structure.
1588 */
1589DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1590{
1591 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1592 {
1593 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1594 AssertRC(rc);
1595 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1596 }
1597}
1598
1599
1600/**
1601 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1602 *
1603 * @param pVmxTransient The VMX-transient structure.
1604 */
1605DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1606{
1607 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1608 {
1609 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1610 AssertRC(rc);
1611 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1612 }
1613}
1614
1615
1616/**
1617 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1618 *
1619 * @param pVmxTransient The VMX-transient structure.
1620 */
1621DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1622{
1623 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1624 {
1625 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1626 AssertRC(rc);
1627 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1628 }
1629}
1630
1631#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1632/**
1633 * Reads the Guest pending-debug exceptions from the VMCS into the VMX transient
1634 * structure.
1635 *
1636 * @param pVmxTransient The VMX-transient structure.
1637 */
1638DECLINLINE(void) hmR0VmxReadGuestPendingDbgXctps(PVMXTRANSIENT pVmxTransient)
1639{
1640 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PENDING_DBG_XCPTS))
1641 {
1642 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &pVmxTransient->uGuestPendingDbgXcpts);
1643 AssertRC(rc);
1644 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PENDING_DBG_XCPTS;
1645 }
1646}
1647#endif
1648
1649/**
1650 * Reads the IDT-vectoring information field from the VMCS into the VMX
1651 * transient structure.
1652 *
1653 * @param pVmxTransient The VMX-transient structure.
1654 *
1655 * @remarks No-long-jump zone!!!
1656 */
1657DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1658{
1659 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1660 {
1661 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1662 AssertRC(rc);
1663 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1664 }
1665}
1666
1667
1668/**
1669 * Reads the IDT-vectoring error code from the VMCS into the VMX
1670 * transient structure.
1671 *
1672 * @param pVmxTransient The VMX-transient structure.
1673 */
1674DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1675{
1676 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1677 {
1678 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1679 AssertRC(rc);
1680 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1681 }
1682}
1683
1684#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1685/**
1686 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1687 *
1688 * @param pVmxTransient The VMX-transient structure.
1689 */
1690static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1691{
1692 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1693 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1694 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1695 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1696 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1697 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1698 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1699 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1700 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1701 AssertRC(rc);
1702 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1703 | HMVMX_READ_EXIT_INSTR_LEN
1704 | HMVMX_READ_EXIT_INSTR_INFO
1705 | HMVMX_READ_IDT_VECTORING_INFO
1706 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1707 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1708 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1709 | HMVMX_READ_GUEST_LINEAR_ADDR
1710 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1711}
1712#endif
1713
1714/**
1715 * Enters VMX root mode operation on the current CPU.
1716 *
1717 * @returns VBox status code.
1718 * @param pHostCpu The HM physical-CPU structure.
1719 * @param pVM The cross context VM structure. Can be
1720 * NULL, after a resume.
1721 * @param HCPhysCpuPage Physical address of the VMXON region.
1722 * @param pvCpuPage Pointer to the VMXON region.
1723 */
1724static int hmR0VmxEnterRootMode(PHMPHYSCPU pHostCpu, PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1725{
1726 Assert(pHostCpu);
1727 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1728 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1729 Assert(pvCpuPage);
1730 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1731
1732 if (pVM)
1733 {
1734 /* Write the VMCS revision identifier to the VMXON region. */
1735 *(uint32_t *)pvCpuPage = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
1736 }
1737
1738 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1739 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1740
1741 /* Enable the VMX bit in CR4 if necessary. */
1742 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1743
1744 /* Record whether VMXE was already prior to us enabling it above. */
1745 pHostCpu->fVmxeAlreadyEnabled = RT_BOOL(uOldCr4 & X86_CR4_VMXE);
1746
1747 /* Enter VMX root mode. */
1748 int rc = VMXEnable(HCPhysCpuPage);
1749 if (RT_FAILURE(rc))
1750 {
1751 /* Restore CR4.VMXE if it was not set prior to our attempt to set it above. */
1752 if (!pHostCpu->fVmxeAlreadyEnabled)
1753 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1754
1755 if (pVM)
1756 pVM->hm.s.ForR3.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1757 }
1758
1759 /* Restore interrupts. */
1760 ASMSetFlags(fEFlags);
1761 return rc;
1762}
1763
1764
1765/**
1766 * Exits VMX root mode operation on the current CPU.
1767 *
1768 * @returns VBox status code.
1769 * @param pHostCpu The HM physical-CPU structure.
1770 */
1771static int hmR0VmxLeaveRootMode(PHMPHYSCPU pHostCpu)
1772{
1773 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1774
1775 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1776 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1777
1778 /* If we're for some reason not in VMX root mode, then don't leave it. */
1779 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1780
1781 int rc;
1782 if (uHostCr4 & X86_CR4_VMXE)
1783 {
1784 /* Exit VMX root mode and clear the VMX bit in CR4. */
1785 VMXDisable();
1786
1787 /* Clear CR4.VMXE only if it was clear prior to use setting it. */
1788 if (!pHostCpu->fVmxeAlreadyEnabled)
1789 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1790
1791 rc = VINF_SUCCESS;
1792 }
1793 else
1794 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1795
1796 /* Restore interrupts. */
1797 ASMSetFlags(fEFlags);
1798 return rc;
1799}
1800
1801
1802/**
1803 * Allocates pages specified as specified by an array of VMX page allocation info
1804 * objects.
1805 *
1806 * The pages contents are zero'd after allocation.
1807 *
1808 * @returns VBox status code.
1809 * @param phMemObj Where to return the handle to the allocation.
1810 * @param paAllocInfo The pointer to the first element of the VMX
1811 * page-allocation info object array.
1812 * @param cEntries The number of elements in the @a paAllocInfo array.
1813 */
1814static int hmR0VmxPagesAllocZ(PRTR0MEMOBJ phMemObj, PVMXPAGEALLOCINFO paAllocInfo, uint32_t cEntries)
1815{
1816 *phMemObj = NIL_RTR0MEMOBJ;
1817
1818 /* Figure out how many pages to allocate. */
1819 uint32_t cPages = 0;
1820 for (uint32_t iPage = 0; iPage < cEntries; iPage++)
1821 cPages += !!paAllocInfo[iPage].fValid;
1822
1823 /* Allocate the pages. */
1824 if (cPages)
1825 {
1826 size_t const cbPages = cPages << PAGE_SHIFT;
1827 int rc = RTR0MemObjAllocPage(phMemObj, cbPages, false /* fExecutable */);
1828 if (RT_FAILURE(rc))
1829 return rc;
1830
1831 /* Zero the contents and assign each page to the corresponding VMX page-allocation entry. */
1832 void *pvFirstPage = RTR0MemObjAddress(*phMemObj);
1833 RT_BZERO(pvFirstPage, cbPages);
1834
1835 uint32_t iPage = 0;
1836 for (uint32_t i = 0; i < cEntries; i++)
1837 if (paAllocInfo[i].fValid)
1838 {
1839 RTHCPHYS const HCPhysPage = RTR0MemObjGetPagePhysAddr(*phMemObj, iPage);
1840 void *pvPage = (void *)((uintptr_t)pvFirstPage + (iPage << X86_PAGE_4K_SHIFT));
1841 Assert(HCPhysPage && HCPhysPage != NIL_RTHCPHYS);
1842 AssertPtr(pvPage);
1843
1844 Assert(paAllocInfo[iPage].pHCPhys);
1845 Assert(paAllocInfo[iPage].ppVirt);
1846 *paAllocInfo[iPage].pHCPhys = HCPhysPage;
1847 *paAllocInfo[iPage].ppVirt = pvPage;
1848
1849 /* Move to next page. */
1850 ++iPage;
1851 }
1852
1853 /* Make sure all valid (requested) pages have been assigned. */
1854 Assert(iPage == cPages);
1855 }
1856 return VINF_SUCCESS;
1857}
1858
1859
1860/**
1861 * Frees pages allocated using hmR0VmxPagesAllocZ.
1862 *
1863 * @param phMemObj Pointer to the memory object handle. Will be set to
1864 * NIL.
1865 */
1866DECL_FORCE_INLINE(void) hmR0VmxPagesFree(PRTR0MEMOBJ phMemObj)
1867{
1868 /* We can cleanup wholesale since it's all one allocation. */
1869 if (*phMemObj != NIL_RTR0MEMOBJ)
1870 {
1871 RTR0MemObjFree(*phMemObj, true /* fFreeMappings */);
1872 *phMemObj = NIL_RTR0MEMOBJ;
1873 }
1874}
1875
1876
1877/**
1878 * Initializes a VMCS info. object.
1879 *
1880 * @param pVmcsInfo The VMCS info. object.
1881 * @param pVmcsInfoShared The VMCS info. object shared with ring-3.
1882 */
1883static void hmR0VmxVmcsInfoInit(PVMXVMCSINFO pVmcsInfo, PVMXVMCSINFOSHARED pVmcsInfoShared)
1884{
1885 RT_ZERO(*pVmcsInfo);
1886 RT_ZERO(*pVmcsInfoShared);
1887
1888 pVmcsInfo->pShared = pVmcsInfoShared;
1889 Assert(pVmcsInfo->hMemObj == NIL_RTR0MEMOBJ);
1890 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1891 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1892 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1893 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1894 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1895 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1896 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1897 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1898 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1899 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
1900 pVmcsInfo->idHostCpuExec = NIL_RTCPUID;
1901}
1902
1903
1904/**
1905 * Frees the VT-x structures for a VMCS info. object.
1906 *
1907 * @param pVmcsInfo The VMCS info. object.
1908 * @param pVmcsInfoShared The VMCS info. object shared with ring-3.
1909 */
1910static void hmR0VmxVmcsInfoFree(PVMXVMCSINFO pVmcsInfo, PVMXVMCSINFOSHARED pVmcsInfoShared)
1911{
1912 hmR0VmxPagesFree(&pVmcsInfo->hMemObj);
1913 hmR0VmxVmcsInfoInit(pVmcsInfo, pVmcsInfoShared);
1914}
1915
1916
1917/**
1918 * Allocates the VT-x structures for a VMCS info. object.
1919 *
1920 * @returns VBox status code.
1921 * @param pVCpu The cross context virtual CPU structure.
1922 * @param pVmcsInfo The VMCS info. object.
1923 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1924 *
1925 * @remarks The caller is expected to take care of any and all allocation failures.
1926 * This function will not perform any cleanup for failures half-way
1927 * through.
1928 */
1929static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1930{
1931 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1932
1933 bool const fMsrBitmaps = RT_BOOL(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS);
1934 bool const fShadowVmcs = !fIsNstGstVmcs ? pVM->hmr0.s.vmx.fUseVmcsShadowing : pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing;
1935 Assert(!pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing); /* VMCS shadowing is not yet exposed to the guest. */
1936 VMXPAGEALLOCINFO aAllocInfo[] =
1937 {
1938 { true, 0 /* Unused */, &pVmcsInfo->HCPhysVmcs, &pVmcsInfo->pvVmcs },
1939 { true, 0 /* Unused */, &pVmcsInfo->HCPhysGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad },
1940 { true, 0 /* Unused */, &pVmcsInfo->HCPhysHostMsrLoad, &pVmcsInfo->pvHostMsrLoad },
1941 { fMsrBitmaps, 0 /* Unused */, &pVmcsInfo->HCPhysMsrBitmap, &pVmcsInfo->pvMsrBitmap },
1942 { fShadowVmcs, 0 /* Unused */, &pVmcsInfo->HCPhysShadowVmcs, &pVmcsInfo->pvShadowVmcs },
1943 };
1944
1945 int rc = hmR0VmxPagesAllocZ(&pVmcsInfo->hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1946 if (RT_FAILURE(rc))
1947 return rc;
1948
1949 /*
1950 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1951 * Because they contain a symmetric list of guest MSRs to load on VM-entry and store on VM-exit.
1952 */
1953 AssertCompile(RT_ELEMENTS(aAllocInfo) > 0);
1954 Assert(pVmcsInfo->HCPhysGuestMsrLoad != NIL_RTHCPHYS);
1955 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1956 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1957
1958 /*
1959 * Get the virtual-APIC page rather than allocating them again.
1960 */
1961 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1962 {
1963 if (!fIsNstGstVmcs)
1964 {
1965 if (PDMHasApic(pVM))
1966 {
1967 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1968 if (RT_FAILURE(rc))
1969 return rc;
1970 Assert(pVmcsInfo->pbVirtApic);
1971 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1972 }
1973 }
1974 else
1975 {
1976 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(&pVCpu->cpum.GstCtx, &pVmcsInfo->HCPhysVirtApic);
1977 Assert(pVmcsInfo->pbVirtApic);
1978 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1979 }
1980 }
1981
1982 return VINF_SUCCESS;
1983}
1984
1985
1986/**
1987 * Free all VT-x structures for the VM.
1988 *
1989 * @returns IPRT status code.
1990 * @param pVM The cross context VM structure.
1991 */
1992static void hmR0VmxStructsFree(PVMCC pVM)
1993{
1994 hmR0VmxPagesFree(&pVM->hmr0.s.vmx.hMemObj);
1995#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1996 if (pVM->hmr0.s.vmx.fUseVmcsShadowing)
1997 {
1998 RTMemFree(pVM->hmr0.s.vmx.paShadowVmcsFields);
1999 pVM->hmr0.s.vmx.paShadowVmcsFields = NULL;
2000 RTMemFree(pVM->hmr0.s.vmx.paShadowVmcsRoFields);
2001 pVM->hmr0.s.vmx.paShadowVmcsRoFields = NULL;
2002 }
2003#endif
2004
2005 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2006 {
2007 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2008 hmR0VmxVmcsInfoFree(&pVCpu->hmr0.s.vmx.VmcsInfo, &pVCpu->hm.s.vmx.VmcsInfo);
2009#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2010 if (pVM->cpum.ro.GuestFeatures.fVmx)
2011 hmR0VmxVmcsInfoFree(&pVCpu->hmr0.s.vmx.VmcsInfoNstGst, &pVCpu->hm.s.vmx.VmcsInfoNstGst);
2012#endif
2013 }
2014}
2015
2016
2017/**
2018 * Allocate all VT-x structures for the VM.
2019 *
2020 * @returns IPRT status code.
2021 * @param pVM The cross context VM structure.
2022 *
2023 * @remarks This functions will cleanup on memory allocation failures.
2024 */
2025static int hmR0VmxStructsAlloc(PVMCC pVM)
2026{
2027 /*
2028 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
2029 * The VMCS size cannot be more than 4096 bytes.
2030 *
2031 * See Intel spec. Appendix A.1 "Basic VMX Information".
2032 */
2033 uint32_t const cbVmcs = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
2034 if (cbVmcs <= X86_PAGE_4K_SIZE)
2035 { /* likely */ }
2036 else
2037 {
2038 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
2039 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2040 }
2041
2042 /*
2043 * Allocate per-VM VT-x structures.
2044 */
2045 bool const fVirtApicAccess = RT_BOOL(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
2046 bool const fUseVmcsShadowing = pVM->hmr0.s.vmx.fUseVmcsShadowing;
2047 VMXPAGEALLOCINFO aAllocInfo[] =
2048 {
2049 { fVirtApicAccess, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysApicAccess, (PRTR0PTR)&pVM->hmr0.s.vmx.pbApicAccess },
2050 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysVmreadBitmap, &pVM->hmr0.s.vmx.pvVmreadBitmap },
2051 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysVmwriteBitmap, &pVM->hmr0.s.vmx.pvVmwriteBitmap },
2052#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2053 { true, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysScratch, (PRTR0PTR)&pVM->hmr0.s.vmx.pbScratch },
2054#endif
2055 };
2056
2057 int rc = hmR0VmxPagesAllocZ(&pVM->hmr0.s.vmx.hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
2058 if (RT_SUCCESS(rc))
2059 {
2060#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2061 /* Allocate the shadow VMCS-fields array. */
2062 if (fUseVmcsShadowing)
2063 {
2064 Assert(!pVM->hmr0.s.vmx.cShadowVmcsFields);
2065 Assert(!pVM->hmr0.s.vmx.cShadowVmcsRoFields);
2066 pVM->hmr0.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2067 pVM->hmr0.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2068 if (!pVM->hmr0.s.vmx.paShadowVmcsFields || !pVM->hmr0.s.vmx.paShadowVmcsRoFields)
2069 rc = VERR_NO_MEMORY;
2070 }
2071#endif
2072
2073 /*
2074 * Allocate per-VCPU VT-x structures.
2075 */
2076 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus && RT_SUCCESS(rc); idCpu++)
2077 {
2078 /* Allocate the guest VMCS structures. */
2079 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2080 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
2081
2082#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2083 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
2084 if (pVM->cpum.ro.GuestFeatures.fVmx && RT_SUCCESS(rc))
2085 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
2086#endif
2087 }
2088 if (RT_SUCCESS(rc))
2089 return VINF_SUCCESS;
2090 }
2091 hmR0VmxStructsFree(pVM);
2092 return rc;
2093}
2094
2095
2096/**
2097 * Pre-initializes non-zero fields in VMX structures that will be allocated.
2098 *
2099 * @param pVM The cross context VM structure.
2100 */
2101static void hmR0VmxStructsInit(PVMCC pVM)
2102{
2103 /* Paranoia. */
2104 Assert(pVM->hmr0.s.vmx.pbApicAccess == NULL);
2105#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2106 Assert(pVM->hmr0.s.vmx.pbScratch == NULL);
2107#endif
2108
2109 /*
2110 * Initialize members up-front so we can cleanup en masse on allocation failures.
2111 */
2112#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2113 pVM->hmr0.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
2114#endif
2115 pVM->hmr0.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
2116 pVM->hmr0.s.vmx.HCPhysVmreadBitmap = NIL_RTHCPHYS;
2117 pVM->hmr0.s.vmx.HCPhysVmwriteBitmap = NIL_RTHCPHYS;
2118 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2119 {
2120 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2121 hmR0VmxVmcsInfoInit(&pVCpu->hmr0.s.vmx.VmcsInfo, &pVCpu->hm.s.vmx.VmcsInfo);
2122 hmR0VmxVmcsInfoInit(&pVCpu->hmr0.s.vmx.VmcsInfoNstGst, &pVCpu->hm.s.vmx.VmcsInfoNstGst);
2123 }
2124}
2125
2126#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2127/**
2128 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2129 *
2130 * @returns @c true if the MSR is intercepted, @c false otherwise.
2131 * @param pvMsrBitmap The MSR bitmap.
2132 * @param offMsr The MSR byte offset.
2133 * @param iBit The bit offset from the byte offset.
2134 */
2135DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2136{
2137 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2138 Assert(pbMsrBitmap);
2139 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2140 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2141}
2142#endif
2143
2144/**
2145 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2146 *
2147 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2148 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2149 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2150 * the read/write access of this MSR.
2151 *
2152 * @param pVCpu The cross context virtual CPU structure.
2153 * @param pVmcsInfo The VMCS info. object.
2154 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2155 * @param idMsr The MSR value.
2156 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2157 * include both a read -and- a write permission!
2158 *
2159 * @sa CPUMGetVmxMsrPermission.
2160 * @remarks Can be called with interrupts disabled.
2161 */
2162static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2163{
2164 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2165 Assert(pbMsrBitmap);
2166 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2167
2168 /*
2169 * MSR-bitmap Layout:
2170 * Byte index MSR range Interpreted as
2171 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2172 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2173 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2174 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2175 *
2176 * A bit corresponding to an MSR within the above range causes a VM-exit
2177 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2178 * the MSR range, it always cause a VM-exit.
2179 *
2180 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2181 */
2182 uint16_t const offBitmapRead = 0;
2183 uint16_t const offBitmapWrite = 0x800;
2184 uint16_t offMsr;
2185 int32_t iBit;
2186 if (idMsr <= UINT32_C(0x00001fff))
2187 {
2188 offMsr = 0;
2189 iBit = idMsr;
2190 }
2191 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2192 {
2193 offMsr = 0x400;
2194 iBit = idMsr - UINT32_C(0xc0000000);
2195 }
2196 else
2197 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2198
2199 /*
2200 * Set the MSR read permission.
2201 */
2202 uint16_t const offMsrRead = offBitmapRead + offMsr;
2203 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2204 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2205 {
2206#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2207 bool const fClear = !fIsNstGstVmcs ? true
2208 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2209#else
2210 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2211 bool const fClear = true;
2212#endif
2213 if (fClear)
2214 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2215 }
2216 else
2217 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2218
2219 /*
2220 * Set the MSR write permission.
2221 */
2222 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2223 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2224 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2225 {
2226#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2227 bool const fClear = !fIsNstGstVmcs ? true
2228 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2229#else
2230 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2231 bool const fClear = true;
2232#endif
2233 if (fClear)
2234 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2235 }
2236 else
2237 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2238}
2239
2240
2241/**
2242 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2243 * area.
2244 *
2245 * @returns VBox status code.
2246 * @param pVCpu The cross context virtual CPU structure.
2247 * @param pVmcsInfo The VMCS info. object.
2248 * @param cMsrs The number of MSRs.
2249 */
2250static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2251{
2252 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2253 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc);
2254 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2255 {
2256 /* Commit the MSR counts to the VMCS and update the cache. */
2257 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2258 {
2259 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2260 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2261 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2262 pVmcsInfo->cEntryMsrLoad = cMsrs;
2263 pVmcsInfo->cExitMsrStore = cMsrs;
2264 pVmcsInfo->cExitMsrLoad = cMsrs;
2265 }
2266 return VINF_SUCCESS;
2267 }
2268
2269 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2270 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2271 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2272}
2273
2274
2275/**
2276 * Adds a new (or updates the value of an existing) guest/host MSR
2277 * pair to be swapped during the world-switch as part of the
2278 * auto-load/store MSR area in the VMCS.
2279 *
2280 * @returns VBox status code.
2281 * @param pVCpu The cross context virtual CPU structure.
2282 * @param pVmxTransient The VMX-transient structure.
2283 * @param idMsr The MSR.
2284 * @param uGuestMsrValue Value of the guest MSR.
2285 * @param fSetReadWrite Whether to set the guest read/write access of this
2286 * MSR (thus not causing a VM-exit).
2287 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2288 * necessary.
2289 */
2290static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2291 bool fSetReadWrite, bool fUpdateHostMsr)
2292{
2293 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2294 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2295 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2296 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2297 uint32_t i;
2298
2299 /* Paranoia. */
2300 Assert(pGuestMsrLoad);
2301
2302#ifndef DEBUG_bird
2303 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGuestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2304#endif
2305
2306 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2307 for (i = 0; i < cMsrs; i++)
2308 {
2309 if (pGuestMsrLoad[i].u32Msr == idMsr)
2310 break;
2311 }
2312
2313 bool fAdded = false;
2314 if (i == cMsrs)
2315 {
2316 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2317 ++cMsrs;
2318 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2319 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2320
2321 /* Set the guest to read/write this MSR without causing VM-exits. */
2322 if ( fSetReadWrite
2323 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2324 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2325
2326 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2327 fAdded = true;
2328 }
2329
2330 /* Update the MSR value for the newly added or already existing MSR. */
2331 pGuestMsrLoad[i].u32Msr = idMsr;
2332 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2333
2334 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2335 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2336 {
2337 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2338 pGuestMsrStore[i].u32Msr = idMsr;
2339 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2340 }
2341
2342 /* Update the corresponding slot in the host MSR area. */
2343 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2344 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2345 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2346 pHostMsr[i].u32Msr = idMsr;
2347
2348 /*
2349 * Only if the caller requests to update the host MSR value AND we've newly added the
2350 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2351 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2352 *
2353 * We do this for performance reasons since reading MSRs may be quite expensive.
2354 */
2355 if (fAdded)
2356 {
2357 if (fUpdateHostMsr)
2358 {
2359 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2360 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2361 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2362 }
2363 else
2364 {
2365 /* Someone else can do the work. */
2366 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
2367 }
2368 }
2369 return VINF_SUCCESS;
2370}
2371
2372
2373/**
2374 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2375 * auto-load/store MSR area in the VMCS.
2376 *
2377 * @returns VBox status code.
2378 * @param pVCpu The cross context virtual CPU structure.
2379 * @param pVmxTransient The VMX-transient structure.
2380 * @param idMsr The MSR.
2381 */
2382static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2383{
2384 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2385 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2386 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2387 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2388
2389#ifndef DEBUG_bird
2390 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2391#endif
2392
2393 for (uint32_t i = 0; i < cMsrs; i++)
2394 {
2395 /* Find the MSR. */
2396 if (pGuestMsrLoad[i].u32Msr == idMsr)
2397 {
2398 /*
2399 * If it's the last MSR, we only need to reduce the MSR count.
2400 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2401 */
2402 if (i < cMsrs - 1)
2403 {
2404 /* Remove it from the VM-entry MSR-load area. */
2405 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2406 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2407
2408 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2409 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2410 {
2411 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2412 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2413 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2414 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2415 }
2416
2417 /* Remove it from the VM-exit MSR-load area. */
2418 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2419 Assert(pHostMsr[i].u32Msr == idMsr);
2420 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2421 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2422 }
2423
2424 /* Reduce the count to reflect the removed MSR and bail. */
2425 --cMsrs;
2426 break;
2427 }
2428 }
2429
2430 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2431 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2432 {
2433 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2434 AssertRCReturn(rc, rc);
2435
2436 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2437 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2438 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2439
2440 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2441 return VINF_SUCCESS;
2442 }
2443
2444 return VERR_NOT_FOUND;
2445}
2446
2447
2448/**
2449 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2450 *
2451 * @returns @c true if found, @c false otherwise.
2452 * @param pVmcsInfo The VMCS info. object.
2453 * @param idMsr The MSR to find.
2454 */
2455static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2456{
2457 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2458 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2459 Assert(pMsrs);
2460 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2461 for (uint32_t i = 0; i < cMsrs; i++)
2462 {
2463 if (pMsrs[i].u32Msr == idMsr)
2464 return true;
2465 }
2466 return false;
2467}
2468
2469
2470/**
2471 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2472 *
2473 * @param pVCpu The cross context virtual CPU structure.
2474 * @param pVmcsInfo The VMCS info. object.
2475 *
2476 * @remarks No-long-jump zone!!!
2477 */
2478static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2479{
2480 RT_NOREF(pVCpu);
2481 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2482
2483 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2484 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2485 Assert(pHostMsrLoad);
2486 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2487 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2488 for (uint32_t i = 0; i < cMsrs; i++)
2489 {
2490 /*
2491 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2492 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2493 */
2494 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2495 pHostMsrLoad[i].u64Value = g_uHmVmxHostMsrEfer;
2496 else
2497 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2498 }
2499}
2500
2501
2502/**
2503 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2504 * perform lazy restoration of the host MSRs while leaving VT-x.
2505 *
2506 * @param pVCpu The cross context virtual CPU structure.
2507 *
2508 * @remarks No-long-jump zone!!!
2509 */
2510static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2511{
2512 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2513
2514 /*
2515 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2516 */
2517 if (!(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2518 {
2519 Assert(!(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2520 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2521 {
2522 pVCpu->hmr0.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2523 pVCpu->hmr0.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2524 pVCpu->hmr0.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2525 pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2526 }
2527 pVCpu->hmr0.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2528 }
2529}
2530
2531
2532/**
2533 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2534 * lazily while leaving VT-x.
2535 *
2536 * @returns true if it does, false otherwise.
2537 * @param pVCpu The cross context virtual CPU structure.
2538 * @param idMsr The MSR to check.
2539 */
2540static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2541{
2542 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2543 {
2544 switch (idMsr)
2545 {
2546 case MSR_K8_LSTAR:
2547 case MSR_K6_STAR:
2548 case MSR_K8_SF_MASK:
2549 case MSR_K8_KERNEL_GS_BASE:
2550 return true;
2551 }
2552 }
2553 return false;
2554}
2555
2556
2557/**
2558 * Loads a set of guests MSRs to allow read/passthru to the guest.
2559 *
2560 * The name of this function is slightly confusing. This function does NOT
2561 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2562 * common prefix for functions dealing with "lazy restoration" of the shared
2563 * MSRs.
2564 *
2565 * @param pVCpu The cross context virtual CPU structure.
2566 *
2567 * @remarks No-long-jump zone!!!
2568 */
2569static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2570{
2571 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2572 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2573
2574 Assert(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2575 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2576 {
2577 /*
2578 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2579 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2580 * we can skip a few MSR writes.
2581 *
2582 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2583 * guest MSR values in the guest-CPU context might be different to what's currently
2584 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2585 * CPU, see @bugref{8728}.
2586 */
2587 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2588 if ( !(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2589 && pCtx->msrKERNELGSBASE == pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase
2590 && pCtx->msrLSTAR == pVCpu->hmr0.s.vmx.u64HostMsrLStar
2591 && pCtx->msrSTAR == pVCpu->hmr0.s.vmx.u64HostMsrStar
2592 && pCtx->msrSFMASK == pVCpu->hmr0.s.vmx.u64HostMsrSfMask)
2593 {
2594#ifdef VBOX_STRICT
2595 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2596 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2597 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2598 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2599#endif
2600 }
2601 else
2602 {
2603 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2604 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2605 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2606 /* The system call flag mask register isn't as benign and accepting of all
2607 values as the above, so mask it to avoid #GP'ing on corrupted input. */
2608 Assert(!(pCtx->msrSFMASK & ~(uint64_t)UINT32_MAX));
2609 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK & UINT32_MAX);
2610 }
2611 }
2612 pVCpu->hmr0.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2613}
2614
2615
2616/**
2617 * Performs lazy restoration of the set of host MSRs if they were previously
2618 * loaded with guest MSR values.
2619 *
2620 * @param pVCpu The cross context virtual CPU structure.
2621 *
2622 * @remarks No-long-jump zone!!!
2623 * @remarks The guest MSRs should have been saved back into the guest-CPU
2624 * context by hmR0VmxImportGuestState()!!!
2625 */
2626static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2627{
2628 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2629 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2630
2631 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2632 {
2633 Assert(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2634 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2635 {
2636 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hmr0.s.vmx.u64HostMsrLStar);
2637 ASMWrMsr(MSR_K6_STAR, pVCpu->hmr0.s.vmx.u64HostMsrStar);
2638 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hmr0.s.vmx.u64HostMsrSfMask);
2639 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase);
2640 }
2641 }
2642 pVCpu->hmr0.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2643}
2644
2645
2646/**
2647 * Verifies that our cached values of the VMCS fields are all consistent with
2648 * what's actually present in the VMCS.
2649 *
2650 * @returns VBox status code.
2651 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2652 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2653 * VMCS content. HMCPU error-field is
2654 * updated, see VMX_VCI_XXX.
2655 * @param pVCpu The cross context virtual CPU structure.
2656 * @param pVmcsInfo The VMCS info. object.
2657 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2658 */
2659static int hmR0VmxCheckCachedVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2660{
2661 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2662
2663 uint32_t u32Val;
2664 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2665 AssertRC(rc);
2666 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2667 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2668 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2669 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2670
2671 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2672 AssertRC(rc);
2673 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2674 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2675 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2676 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2677
2678 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2679 AssertRC(rc);
2680 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2681 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2682 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2683 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2684
2685 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2686 AssertRC(rc);
2687 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2688 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2689 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2690 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2691
2692 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2693 {
2694 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2695 AssertRC(rc);
2696 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2697 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2698 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2699 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2700 }
2701
2702 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2703 AssertRC(rc);
2704 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2705 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2706 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2707 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2708
2709 uint64_t u64Val;
2710 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2711 AssertRC(rc);
2712 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2713 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2714 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2715 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2716
2717 NOREF(pcszVmcs);
2718 return VINF_SUCCESS;
2719}
2720
2721#ifdef VBOX_STRICT
2722
2723/**
2724 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2725 *
2726 * @param pVmcsInfo The VMCS info. object.
2727 */
2728static void hmR0VmxCheckHostEferMsr(PCVMXVMCSINFO pVmcsInfo)
2729{
2730 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2731
2732 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2733 {
2734 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2735 uint64_t const uHostEferMsrCache = g_uHmVmxHostMsrEfer;
2736 uint64_t uVmcsEferMsrVmcs;
2737 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2738 AssertRC(rc);
2739
2740 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2741 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2742 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2743 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2744 }
2745}
2746
2747
2748/**
2749 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2750 * VMCS are correct.
2751 *
2752 * @param pVCpu The cross context virtual CPU structure.
2753 * @param pVmcsInfo The VMCS info. object.
2754 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2755 */
2756static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2757{
2758 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2759
2760 /* Read the various MSR-area counts from the VMCS. */
2761 uint32_t cEntryLoadMsrs;
2762 uint32_t cExitStoreMsrs;
2763 uint32_t cExitLoadMsrs;
2764 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2765 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2766 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2767
2768 /* Verify all the MSR counts are the same. */
2769 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2770 Assert(cExitStoreMsrs == cExitLoadMsrs);
2771 uint32_t const cMsrs = cExitLoadMsrs;
2772
2773 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2774 Assert(cMsrs < VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc));
2775
2776 /* Verify the MSR counts are within the allocated page size. */
2777 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2778
2779 /* Verify the relevant contents of the MSR areas match. */
2780 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2781 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2782 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2783 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2784 for (uint32_t i = 0; i < cMsrs; i++)
2785 {
2786 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2787 if (fSeparateExitMsrStorePage)
2788 {
2789 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2790 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2791 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2792 }
2793
2794 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2795 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2796 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2797
2798 uint64_t const u64HostMsr = ASMRdMsr(pHostMsrLoad->u32Msr);
2799 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64HostMsr,
2800 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2801 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64HostMsr, cMsrs));
2802
2803 /* Verify that cached host EFER MSR matches what's loaded on the CPU. */
2804 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2805 AssertMsgReturnVoid(!fIsEferMsr || u64HostMsr == g_uHmVmxHostMsrEfer,
2806 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n", g_uHmVmxHostMsrEfer, u64HostMsr, cMsrs));
2807
2808 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2809 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2810 {
2811 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2812 if (fIsEferMsr)
2813 {
2814 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2815 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2816 }
2817 else
2818 {
2819 /* Verify LBR MSRs (used only for debugging) are intercepted. We don't passthru these MSRs to the guest yet. */
2820 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
2821 if ( pVM->hmr0.s.vmx.fLbr
2822 && ( hmR0VmxIsLbrBranchFromMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2823 || hmR0VmxIsLbrBranchToMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2824 || pGuestMsrLoad->u32Msr == pVM->hmr0.s.vmx.idLbrTosMsr))
2825 {
2826 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_EXIT_RD_WR,
2827 ("u32Msr=%#RX32 cMsrs=%u Passthru read/write for LBR MSRs!\n",
2828 pGuestMsrLoad->u32Msr, cMsrs));
2829 }
2830 else if (!fIsNstGstVmcs)
2831 {
2832 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_ALLOW_RD_WR,
2833 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2834 }
2835 else
2836 {
2837 /*
2838 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2839 * execute a nested-guest with MSR passthrough.
2840 *
2841 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2842 * allow passthrough too.
2843 */
2844 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2845 Assert(pvMsrBitmapNstGst);
2846 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2847 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2848 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2849 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2850 }
2851 }
2852 }
2853
2854 /* Move to the next MSR. */
2855 pHostMsrLoad++;
2856 pGuestMsrLoad++;
2857 pGuestMsrStore++;
2858 }
2859}
2860
2861#endif /* VBOX_STRICT */
2862
2863/**
2864 * Flushes the TLB using EPT.
2865 *
2866 * @returns VBox status code.
2867 * @param pVCpu The cross context virtual CPU structure of the calling
2868 * EMT. Can be NULL depending on @a enmTlbFlush.
2869 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2870 * enmTlbFlush.
2871 * @param enmTlbFlush Type of flush.
2872 *
2873 * @remarks Caller is responsible for making sure this function is called only
2874 * when NestedPaging is supported and providing @a enmTlbFlush that is
2875 * supported by the CPU.
2876 * @remarks Can be called with interrupts disabled.
2877 */
2878static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2879{
2880 uint64_t au64Descriptor[2];
2881 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2882 au64Descriptor[0] = 0;
2883 else
2884 {
2885 Assert(pVCpu);
2886 Assert(pVmcsInfo);
2887 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2888 }
2889 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2890
2891 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2892 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2893
2894 if ( RT_SUCCESS(rc)
2895 && pVCpu)
2896 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2897}
2898
2899
2900/**
2901 * Flushes the TLB using VPID.
2902 *
2903 * @returns VBox status code.
2904 * @param pVCpu The cross context virtual CPU structure of the calling
2905 * EMT. Can be NULL depending on @a enmTlbFlush.
2906 * @param enmTlbFlush Type of flush.
2907 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2908 * on @a enmTlbFlush).
2909 *
2910 * @remarks Can be called with interrupts disabled.
2911 */
2912static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2913{
2914 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid);
2915
2916 uint64_t au64Descriptor[2];
2917 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2918 {
2919 au64Descriptor[0] = 0;
2920 au64Descriptor[1] = 0;
2921 }
2922 else
2923 {
2924 AssertPtr(pVCpu);
2925 AssertMsg(pVCpu->hmr0.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hmr0.s.uCurrentAsid));
2926 AssertMsg(pVCpu->hmr0.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hmr0.s.uCurrentAsid));
2927 au64Descriptor[0] = pVCpu->hmr0.s.uCurrentAsid;
2928 au64Descriptor[1] = GCPtr;
2929 }
2930
2931 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2932 AssertMsg(rc == VINF_SUCCESS,
2933 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hmr0.s.uCurrentAsid : 0, GCPtr, rc));
2934
2935 if ( RT_SUCCESS(rc)
2936 && pVCpu)
2937 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2938 NOREF(rc);
2939}
2940
2941
2942/**
2943 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2944 * otherwise there is nothing really to invalidate.
2945 *
2946 * @returns VBox status code.
2947 * @param pVCpu The cross context virtual CPU structure.
2948 * @param GCVirt Guest virtual address of the page to invalidate.
2949 */
2950VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2951{
2952 AssertPtr(pVCpu);
2953 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2954
2955 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2956 {
2957 /*
2958 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2959 * the EPT case. See @bugref{6043} and @bugref{6177}.
2960 *
2961 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2962 * as this function maybe called in a loop with individual addresses.
2963 */
2964 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2965 if (pVM->hmr0.s.vmx.fVpid)
2966 {
2967 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
2968 {
2969 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2970 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2971 }
2972 else
2973 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2974 }
2975 else if (pVM->hmr0.s.fNestedPaging)
2976 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2977 }
2978
2979 return VINF_SUCCESS;
2980}
2981
2982
2983/**
2984 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2985 * case where neither EPT nor VPID is supported by the CPU.
2986 *
2987 * @param pHostCpu The HM physical-CPU structure.
2988 * @param pVCpu The cross context virtual CPU structure.
2989 *
2990 * @remarks Called with interrupts disabled.
2991 */
2992static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2993{
2994 AssertPtr(pVCpu);
2995 AssertPtr(pHostCpu);
2996
2997 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2998
2999 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3000 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3001 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3002 pVCpu->hmr0.s.fForceTLBFlush = false;
3003 return;
3004}
3005
3006
3007/**
3008 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
3009 *
3010 * @param pHostCpu The HM physical-CPU structure.
3011 * @param pVCpu The cross context virtual CPU structure.
3012 * @param pVmcsInfo The VMCS info. object.
3013 *
3014 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
3015 * nomenclature. The reason is, to avoid confusion in compare statements
3016 * since the host-CPU copies are named "ASID".
3017 *
3018 * @remarks Called with interrupts disabled.
3019 */
3020static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3021{
3022#ifdef VBOX_WITH_STATISTICS
3023 bool fTlbFlushed = false;
3024# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
3025# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
3026 if (!fTlbFlushed) \
3027 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
3028 } while (0)
3029#else
3030# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
3031# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
3032#endif
3033
3034 AssertPtr(pVCpu);
3035 AssertPtr(pHostCpu);
3036 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3037
3038 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3039 AssertMsg(pVM->hmr0.s.fNestedPaging && pVM->hmr0.s.vmx.fVpid,
3040 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
3041 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hmr0.s.fNestedPaging, pVM->hmr0.s.vmx.fVpid));
3042
3043 /*
3044 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
3045 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3046 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3047 * cannot reuse the current ASID anymore.
3048 */
3049 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3050 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3051 {
3052 ++pHostCpu->uCurrentAsid;
3053 if (pHostCpu->uCurrentAsid >= g_uHmMaxAsid)
3054 {
3055 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
3056 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3057 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3058 }
3059
3060 pVCpu->hmr0.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3061 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3062 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3063
3064 /*
3065 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
3066 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
3067 */
3068 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3069 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3070 HMVMX_SET_TAGGED_TLB_FLUSHED();
3071 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
3072 }
3073 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
3074 {
3075 /*
3076 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
3077 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
3078 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
3079 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
3080 * mappings, see @bugref{6568}.
3081 *
3082 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
3083 */
3084 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3085 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3086 HMVMX_SET_TAGGED_TLB_FLUSHED();
3087 }
3088 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3089 {
3090 /*
3091 * The nested-guest specifies its own guest-physical address to use as the APIC-access
3092 * address which requires flushing the TLB of EPT cached structures.
3093 *
3094 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
3095 */
3096 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3097 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3098 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3099 HMVMX_SET_TAGGED_TLB_FLUSHED();
3100 }
3101
3102
3103 pVCpu->hmr0.s.fForceTLBFlush = false;
3104 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
3105
3106 Assert(pVCpu->hmr0.s.idLastCpu == pHostCpu->idCpu);
3107 Assert(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes);
3108 AssertMsg(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3109 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hmr0.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3110 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < g_uHmMaxAsid,
3111 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3112 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hmr0.s.idLastCpu, pVCpu->hmr0.s.cTlbFlushes));
3113 AssertMsg(pVCpu->hmr0.s.uCurrentAsid >= 1 && pVCpu->hmr0.s.uCurrentAsid < g_uHmMaxAsid,
3114 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hmr0.s.uCurrentAsid));
3115
3116 /* Update VMCS with the VPID. */
3117 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hmr0.s.uCurrentAsid);
3118 AssertRC(rc);
3119
3120#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3121}
3122
3123
3124/**
3125 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3126 *
3127 * @param pHostCpu The HM physical-CPU structure.
3128 * @param pVCpu The cross context virtual CPU structure.
3129 * @param pVmcsInfo The VMCS info. object.
3130 *
3131 * @remarks Called with interrupts disabled.
3132 */
3133static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3134{
3135 AssertPtr(pVCpu);
3136 AssertPtr(pHostCpu);
3137 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3138 AssertMsg(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3139 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3140
3141 /*
3142 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3143 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3144 */
3145 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3146 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3147 {
3148 pVCpu->hmr0.s.fForceTLBFlush = true;
3149 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3150 }
3151
3152 /* Check for explicit TLB flushes. */
3153 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3154 {
3155 pVCpu->hmr0.s.fForceTLBFlush = true;
3156 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3157 }
3158
3159 /* Check for TLB flushes while switching to/from a nested-guest. */
3160 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3161 {
3162 pVCpu->hmr0.s.fForceTLBFlush = true;
3163 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3164 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3165 }
3166
3167 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3168 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3169
3170 if (pVCpu->hmr0.s.fForceTLBFlush)
3171 {
3172 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.enmTlbFlushEpt);
3173 pVCpu->hmr0.s.fForceTLBFlush = false;
3174 }
3175}
3176
3177
3178/**
3179 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3180 *
3181 * @param pHostCpu The HM physical-CPU structure.
3182 * @param pVCpu The cross context virtual CPU structure.
3183 *
3184 * @remarks Called with interrupts disabled.
3185 */
3186static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3187{
3188 AssertPtr(pVCpu);
3189 AssertPtr(pHostCpu);
3190 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3191 AssertMsg(pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3192 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3193
3194 /*
3195 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3196 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3197 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3198 * cannot reuse the current ASID anymore.
3199 */
3200 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3201 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3202 {
3203 pVCpu->hmr0.s.fForceTLBFlush = true;
3204 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3205 }
3206
3207 /* Check for explicit TLB flushes. */
3208 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3209 {
3210 /*
3211 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3212 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3213 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3214 * include fExplicitFlush's too) - an obscure corner case.
3215 */
3216 pVCpu->hmr0.s.fForceTLBFlush = true;
3217 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3218 }
3219
3220 /* Check for TLB flushes while switching to/from a nested-guest. */
3221 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3222 {
3223 pVCpu->hmr0.s.fForceTLBFlush = true;
3224 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3225 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3226 }
3227
3228 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3229 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3230 if (pVCpu->hmr0.s.fForceTLBFlush)
3231 {
3232 ++pHostCpu->uCurrentAsid;
3233 if (pHostCpu->uCurrentAsid >= g_uHmMaxAsid)
3234 {
3235 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3236 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3237 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3238 }
3239
3240 pVCpu->hmr0.s.fForceTLBFlush = false;
3241 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3242 pVCpu->hmr0.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3243 if (pHostCpu->fFlushAsidBeforeUse)
3244 {
3245 if (pVM->hmr0.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3246 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3247 else if (pVM->hmr0.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3248 {
3249 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3250 pHostCpu->fFlushAsidBeforeUse = false;
3251 }
3252 else
3253 {
3254 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3255 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3256 }
3257 }
3258 }
3259
3260 AssertMsg(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3261 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hmr0.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3262 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < g_uHmMaxAsid,
3263 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3264 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hmr0.s.idLastCpu, pVCpu->hmr0.s.cTlbFlushes));
3265 AssertMsg(pVCpu->hmr0.s.uCurrentAsid >= 1 && pVCpu->hmr0.s.uCurrentAsid < g_uHmMaxAsid,
3266 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hmr0.s.uCurrentAsid));
3267
3268 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hmr0.s.uCurrentAsid);
3269 AssertRC(rc);
3270}
3271
3272
3273/**
3274 * Flushes the guest TLB entry based on CPU capabilities.
3275 *
3276 * @param pHostCpu The HM physical-CPU structure.
3277 * @param pVCpu The cross context virtual CPU structure.
3278 * @param pVmcsInfo The VMCS info. object.
3279 *
3280 * @remarks Called with interrupts disabled.
3281 */
3282static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3283{
3284#ifdef HMVMX_ALWAYS_FLUSH_TLB
3285 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3286#endif
3287 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3288 switch (pVM->hmr0.s.vmx.enmTlbFlushType)
3289 {
3290 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3291 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3292 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3293 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3294 default:
3295 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3296 break;
3297 }
3298 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3299}
3300
3301
3302/**
3303 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3304 * TLB entries from the host TLB before VM-entry.
3305 *
3306 * @returns VBox status code.
3307 * @param pVM The cross context VM structure.
3308 */
3309static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3310{
3311 /*
3312 * Determine optimal flush type for nested paging.
3313 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3314 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3315 */
3316 if (pVM->hmr0.s.fNestedPaging)
3317 {
3318 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3319 {
3320 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3321 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3322 else if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3323 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3324 else
3325 {
3326 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3327 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3328 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3329 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3330 }
3331
3332 /* Make sure the write-back cacheable memory type for EPT is supported. */
3333 if (RT_UNLIKELY(!(g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3334 {
3335 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3336 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3337 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3338 }
3339
3340 /* EPT requires a page-walk length of 4. */
3341 if (RT_UNLIKELY(!(g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3342 {
3343 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3344 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3345 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3346 }
3347 }
3348 else
3349 {
3350 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3351 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3352 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3353 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3354 }
3355 }
3356
3357 /*
3358 * Determine optimal flush type for VPID.
3359 */
3360 if (pVM->hmr0.s.vmx.fVpid)
3361 {
3362 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3363 {
3364 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3365 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3366 else if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3367 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3368 else
3369 {
3370 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3371 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3372 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3373 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3374 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3375 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3376 pVM->hmr0.s.vmx.fVpid = false;
3377 }
3378 }
3379 else
3380 {
3381 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3382 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3383 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3384 pVM->hmr0.s.vmx.fVpid = false;
3385 }
3386 }
3387
3388 /*
3389 * Setup the handler for flushing tagged-TLBs.
3390 */
3391 if (pVM->hmr0.s.fNestedPaging && pVM->hmr0.s.vmx.fVpid)
3392 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3393 else if (pVM->hmr0.s.fNestedPaging)
3394 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3395 else if (pVM->hmr0.s.vmx.fVpid)
3396 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3397 else
3398 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3399
3400
3401 /*
3402 * Copy out the result to ring-3.
3403 */
3404 pVM->hm.s.ForR3.vmx.fVpid = pVM->hmr0.s.vmx.fVpid;
3405 pVM->hm.s.ForR3.vmx.enmTlbFlushType = pVM->hmr0.s.vmx.enmTlbFlushType;
3406 pVM->hm.s.ForR3.vmx.enmTlbFlushEpt = pVM->hmr0.s.vmx.enmTlbFlushEpt;
3407 pVM->hm.s.ForR3.vmx.enmTlbFlushVpid = pVM->hmr0.s.vmx.enmTlbFlushVpid;
3408 return VINF_SUCCESS;
3409}
3410
3411
3412/**
3413 * Sets up the LBR MSR ranges based on the host CPU.
3414 *
3415 * @returns VBox status code.
3416 * @param pVM The cross context VM structure.
3417 */
3418static int hmR0VmxSetupLbrMsrRange(PVMCC pVM)
3419{
3420 Assert(pVM->hmr0.s.vmx.fLbr);
3421 uint32_t idLbrFromIpMsrFirst;
3422 uint32_t idLbrFromIpMsrLast;
3423 uint32_t idLbrToIpMsrFirst;
3424 uint32_t idLbrToIpMsrLast;
3425 uint32_t idLbrTosMsr;
3426
3427 /*
3428 * Determine the LBR MSRs supported for this host CPU family and model.
3429 *
3430 * See Intel spec. 17.4.8 "LBR Stack".
3431 * See Intel "Model-Specific Registers" spec.
3432 */
3433 uint32_t const uFamilyModel = (pVM->cpum.ro.HostFeatures.uFamily << 8)
3434 | pVM->cpum.ro.HostFeatures.uModel;
3435 switch (uFamilyModel)
3436 {
3437 case 0x0f01: case 0x0f02:
3438 idLbrFromIpMsrFirst = MSR_P4_LASTBRANCH_0;
3439 idLbrFromIpMsrLast = MSR_P4_LASTBRANCH_3;
3440 idLbrToIpMsrFirst = 0x0;
3441 idLbrToIpMsrLast = 0x0;
3442 idLbrTosMsr = MSR_P4_LASTBRANCH_TOS;
3443 break;
3444
3445 case 0x065c: case 0x065f: case 0x064e: case 0x065e: case 0x068e:
3446 case 0x069e: case 0x0655: case 0x0666: case 0x067a: case 0x0667:
3447 case 0x066a: case 0x066c: case 0x067d: case 0x067e:
3448 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3449 idLbrFromIpMsrLast = MSR_LASTBRANCH_31_FROM_IP;
3450 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3451 idLbrToIpMsrLast = MSR_LASTBRANCH_31_TO_IP;
3452 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3453 break;
3454
3455 case 0x063d: case 0x0647: case 0x064f: case 0x0656: case 0x063c:
3456 case 0x0645: case 0x0646: case 0x063f: case 0x062a: case 0x062d:
3457 case 0x063a: case 0x063e: case 0x061a: case 0x061e: case 0x061f:
3458 case 0x062e: case 0x0625: case 0x062c: case 0x062f:
3459 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3460 idLbrFromIpMsrLast = MSR_LASTBRANCH_15_FROM_IP;
3461 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3462 idLbrToIpMsrLast = MSR_LASTBRANCH_15_TO_IP;
3463 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3464 break;
3465
3466 case 0x0617: case 0x061d: case 0x060f:
3467 idLbrFromIpMsrFirst = MSR_CORE2_LASTBRANCH_0_FROM_IP;
3468 idLbrFromIpMsrLast = MSR_CORE2_LASTBRANCH_3_FROM_IP;
3469 idLbrToIpMsrFirst = MSR_CORE2_LASTBRANCH_0_TO_IP;
3470 idLbrToIpMsrLast = MSR_CORE2_LASTBRANCH_3_TO_IP;
3471 idLbrTosMsr = MSR_CORE2_LASTBRANCH_TOS;
3472 break;
3473
3474 /* Atom and related microarchitectures we don't care about:
3475 case 0x0637: case 0x064a: case 0x064c: case 0x064d: case 0x065a:
3476 case 0x065d: case 0x061c: case 0x0626: case 0x0627: case 0x0635:
3477 case 0x0636: */
3478 /* All other CPUs: */
3479 default:
3480 {
3481 LogRelFunc(("Could not determine LBR stack size for the CPU model %#x\n", uFamilyModel));
3482 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_UNKNOWN;
3483 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3484 }
3485 }
3486
3487 /*
3488 * Validate.
3489 */
3490 uint32_t const cLbrStack = idLbrFromIpMsrLast - idLbrFromIpMsrFirst + 1;
3491 PCVMCPU pVCpu0 = VMCC_GET_CPU_0(pVM);
3492 AssertCompile( RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr)
3493 == RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrToIpMsr));
3494 if (cLbrStack > RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr))
3495 {
3496 LogRelFunc(("LBR stack size of the CPU (%u) exceeds our buffer size\n", cLbrStack));
3497 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_OVERFLOW;
3498 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3499 }
3500 NOREF(pVCpu0);
3501
3502 /*
3503 * Update the LBR info. to the VM struct. for use later.
3504 */
3505 pVM->hmr0.s.vmx.idLbrTosMsr = idLbrTosMsr;
3506
3507 pVM->hm.s.ForR3.vmx.idLbrFromIpMsrFirst = pVM->hmr0.s.vmx.idLbrFromIpMsrFirst = idLbrFromIpMsrFirst;
3508 pVM->hm.s.ForR3.vmx.idLbrFromIpMsrLast = pVM->hmr0.s.vmx.idLbrFromIpMsrLast = idLbrFromIpMsrLast;
3509
3510 pVM->hm.s.ForR3.vmx.idLbrToIpMsrFirst = pVM->hmr0.s.vmx.idLbrToIpMsrFirst = idLbrToIpMsrFirst;
3511 pVM->hm.s.ForR3.vmx.idLbrToIpMsrLast = pVM->hmr0.s.vmx.idLbrToIpMsrLast = idLbrToIpMsrLast;
3512 return VINF_SUCCESS;
3513}
3514
3515
3516#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3517/**
3518 * Sets up the shadow VMCS fields arrays.
3519 *
3520 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3521 * executing the guest.
3522 *
3523 * @returns VBox status code.
3524 * @param pVM The cross context VM structure.
3525 */
3526static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3527{
3528 /*
3529 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3530 * when the host does not support it.
3531 */
3532 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3533 if ( !fGstVmwriteAll
3534 || (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL))
3535 { /* likely. */ }
3536 else
3537 {
3538 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3539 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3540 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3541 }
3542
3543 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3544 uint32_t cRwFields = 0;
3545 uint32_t cRoFields = 0;
3546 for (uint32_t i = 0; i < cVmcsFields; i++)
3547 {
3548 VMXVMCSFIELD VmcsField;
3549 VmcsField.u = g_aVmcsFields[i];
3550
3551 /*
3552 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3553 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3554 * in the shadow VMCS fields array as they would be redundant.
3555 *
3556 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3557 * we must not include it in the shadow VMCS fields array. Guests attempting to
3558 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3559 * the required behavior.
3560 */
3561 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3562 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3563 {
3564 /*
3565 * Read-only fields are placed in a separate array so that while syncing shadow
3566 * VMCS fields later (which is more performance critical) we can avoid branches.
3567 *
3568 * However, if the guest can write to all fields (including read-only fields),
3569 * we treat it a as read/write field. Otherwise, writing to these fields would
3570 * cause a VMWRITE instruction error while syncing the shadow VMCS.
3571 */
3572 if ( fGstVmwriteAll
3573 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3574 pVM->hmr0.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3575 else
3576 pVM->hmr0.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3577 }
3578 }
3579
3580 /* Update the counts. */
3581 pVM->hmr0.s.vmx.cShadowVmcsFields = cRwFields;
3582 pVM->hmr0.s.vmx.cShadowVmcsRoFields = cRoFields;
3583 return VINF_SUCCESS;
3584}
3585
3586
3587/**
3588 * Sets up the VMREAD and VMWRITE bitmaps.
3589 *
3590 * @param pVM The cross context VM structure.
3591 */
3592static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3593{
3594 /*
3595 * By default, ensure guest attempts to access any VMCS fields cause VM-exits.
3596 */
3597 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3598 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hmr0.s.vmx.pvVmreadBitmap;
3599 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hmr0.s.vmx.pvVmwriteBitmap;
3600 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3601 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3602
3603 /*
3604 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3605 * VMREAD and VMWRITE bitmaps.
3606 */
3607 {
3608 uint32_t const *paShadowVmcsFields = pVM->hmr0.s.vmx.paShadowVmcsFields;
3609 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
3610 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3611 {
3612 uint32_t const uVmcsField = paShadowVmcsFields[i];
3613 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3614 Assert(uVmcsField >> 3 < cbBitmap);
3615 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3616 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3617 }
3618 }
3619
3620 /*
3621 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3622 * if the host supports VMWRITE to all supported VMCS fields.
3623 */
3624 if (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL)
3625 {
3626 uint32_t const *paShadowVmcsRoFields = pVM->hmr0.s.vmx.paShadowVmcsRoFields;
3627 uint32_t const cShadowVmcsRoFields = pVM->hmr0.s.vmx.cShadowVmcsRoFields;
3628 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3629 {
3630 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3631 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3632 Assert(uVmcsField >> 3 < cbBitmap);
3633 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3634 }
3635 }
3636}
3637#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3638
3639
3640/**
3641 * Sets up the virtual-APIC page address for the VMCS.
3642 *
3643 * @param pVmcsInfo The VMCS info. object.
3644 */
3645DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3646{
3647 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3648 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3649 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3650 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3651 AssertRC(rc);
3652}
3653
3654
3655/**
3656 * Sets up the MSR-bitmap address for the VMCS.
3657 *
3658 * @param pVmcsInfo The VMCS info. object.
3659 */
3660DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3661{
3662 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3663 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3664 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3665 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3666 AssertRC(rc);
3667}
3668
3669
3670/**
3671 * Sets up the APIC-access page address for the VMCS.
3672 *
3673 * @param pVCpu The cross context virtual CPU structure.
3674 */
3675DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3676{
3677 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysApicAccess;
3678 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3679 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3680 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3681 AssertRC(rc);
3682}
3683
3684#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3685
3686/**
3687 * Sets up the VMREAD bitmap address for the VMCS.
3688 *
3689 * @param pVCpu The cross context virtual CPU structure.
3690 */
3691DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3692{
3693 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysVmreadBitmap;
3694 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3695 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3696 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3697 AssertRC(rc);
3698}
3699
3700
3701/**
3702 * Sets up the VMWRITE bitmap address for the VMCS.
3703 *
3704 * @param pVCpu The cross context virtual CPU structure.
3705 */
3706DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3707{
3708 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysVmwriteBitmap;
3709 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3710 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3711 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3712 AssertRC(rc);
3713}
3714
3715#endif
3716
3717/**
3718 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3719 * in the VMCS.
3720 *
3721 * @returns VBox status code.
3722 * @param pVmcsInfo The VMCS info. object.
3723 */
3724DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3725{
3726 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3727 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3728 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3729
3730 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3731 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3732 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3733
3734 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3735 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3736 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3737
3738 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3739 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3740 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3741 return VINF_SUCCESS;
3742}
3743
3744
3745/**
3746 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3747 *
3748 * @param pVCpu The cross context virtual CPU structure.
3749 * @param pVmcsInfo The VMCS info. object.
3750 */
3751static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3752{
3753 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3754
3755 /*
3756 * By default, ensure guest attempts to access any MSR cause VM-exits.
3757 * This shall later be relaxed for specific MSRs as necessary.
3758 *
3759 * Note: For nested-guests, the entire bitmap will be merged prior to
3760 * executing the nested-guest using hardware-assisted VMX and hence there
3761 * is no need to perform this operation. See hmR0VmxMergeMsrBitmapNested.
3762 */
3763 Assert(pVmcsInfo->pvMsrBitmap);
3764 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
3765
3766 /*
3767 * The guest can access the following MSRs (read, write) without causing
3768 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3769 */
3770 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3771 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3772 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3773 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3774 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3775 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3776
3777 /*
3778 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3779 * associated with then. We never need to intercept access (writes need to be
3780 * executed without causing a VM-exit, reads will #GP fault anyway).
3781 *
3782 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3783 * read/write them. We swap the guest/host MSR value using the
3784 * auto-load/store MSR area.
3785 */
3786 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3787 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3788 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3789 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3790 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3791 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3792
3793 /*
3794 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3795 * required for 64-bit guests.
3796 */
3797 if (pVM->hmr0.s.fAllow64BitGuests)
3798 {
3799 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3800 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3801 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3802 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3803 }
3804
3805 /*
3806 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3807 */
3808#ifdef VBOX_STRICT
3809 Assert(pVmcsInfo->pvMsrBitmap);
3810 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3811 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3812#endif
3813}
3814
3815
3816/**
3817 * Sets up pin-based VM-execution controls in the VMCS.
3818 *
3819 * @returns VBox status code.
3820 * @param pVCpu The cross context virtual CPU structure.
3821 * @param pVmcsInfo The VMCS info. object.
3822 */
3823static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3824{
3825 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3826 uint32_t fVal = g_HmMsrs.u.vmx.PinCtls.n.allowed0; /* Bits set here must always be set. */
3827 uint32_t const fZap = g_HmMsrs.u.vmx.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3828
3829 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3830 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3831
3832 if (g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3833 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3834
3835 /* Enable the VMX-preemption timer. */
3836 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
3837 {
3838 Assert(g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3839 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3840 }
3841
3842#if 0
3843 /* Enable posted-interrupt processing. */
3844 if (pVM->hm.s.fPostedIntrs)
3845 {
3846 Assert(g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3847 Assert(g_HmMsrs.u.vmx.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3848 fVal |= VMX_PIN_CTLS_POSTED_INT;
3849 }
3850#endif
3851
3852 if ((fVal & fZap) != fVal)
3853 {
3854 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3855 g_HmMsrs.u.vmx.PinCtls.n.allowed0, fVal, fZap));
3856 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3857 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3858 }
3859
3860 /* Commit it to the VMCS and update our cache. */
3861 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3862 AssertRC(rc);
3863 pVmcsInfo->u32PinCtls = fVal;
3864
3865 return VINF_SUCCESS;
3866}
3867
3868
3869/**
3870 * Sets up secondary processor-based VM-execution controls in the VMCS.
3871 *
3872 * @returns VBox status code.
3873 * @param pVCpu The cross context virtual CPU structure.
3874 * @param pVmcsInfo The VMCS info. object.
3875 */
3876static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3877{
3878 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3879 uint32_t fVal = g_HmMsrs.u.vmx.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3880 uint32_t const fZap = g_HmMsrs.u.vmx.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3881
3882 /* WBINVD causes a VM-exit. */
3883 if (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3884 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3885
3886 /* Enable EPT (aka nested-paging). */
3887 if (pVM->hmr0.s.fNestedPaging)
3888 fVal |= VMX_PROC_CTLS2_EPT;
3889
3890 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3891 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3892 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3893 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3894 fVal |= VMX_PROC_CTLS2_INVPCID;
3895
3896 /* Enable VPID. */
3897 if (pVM->hmr0.s.vmx.fVpid)
3898 fVal |= VMX_PROC_CTLS2_VPID;
3899
3900 /* Enable unrestricted guest execution. */
3901 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
3902 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3903
3904#if 0
3905 if (pVM->hm.s.fVirtApicRegs)
3906 {
3907 /* Enable APIC-register virtualization. */
3908 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3909 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3910
3911 /* Enable virtual-interrupt delivery. */
3912 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3913 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3914 }
3915#endif
3916
3917 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3918 where the TPR shadow resides. */
3919 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3920 * done dynamically. */
3921 if (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3922 {
3923 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3924 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3925 }
3926
3927 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3928 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3929 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3930 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3931 fVal |= VMX_PROC_CTLS2_RDTSCP;
3932
3933 /* Enable Pause-Loop exiting. */
3934 if ( (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3935 && pVM->hm.s.vmx.cPleGapTicks
3936 && pVM->hm.s.vmx.cPleWindowTicks)
3937 {
3938 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3939
3940 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3941 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3942 }
3943
3944 if ((fVal & fZap) != fVal)
3945 {
3946 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3947 g_HmMsrs.u.vmx.ProcCtls2.n.allowed0, fVal, fZap));
3948 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3949 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3950 }
3951
3952 /* Commit it to the VMCS and update our cache. */
3953 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3954 AssertRC(rc);
3955 pVmcsInfo->u32ProcCtls2 = fVal;
3956
3957 return VINF_SUCCESS;
3958}
3959
3960
3961/**
3962 * Sets up processor-based VM-execution controls in the VMCS.
3963 *
3964 * @returns VBox status code.
3965 * @param pVCpu The cross context virtual CPU structure.
3966 * @param pVmcsInfo The VMCS info. object.
3967 */
3968static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3969{
3970 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3971 uint32_t fVal = g_HmMsrs.u.vmx.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3972 uint32_t const fZap = g_HmMsrs.u.vmx.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3973
3974 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3975 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3976 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3977 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3978 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3979 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3980 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3981
3982 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3983 if ( !(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3984 || (g_HmMsrs.u.vmx.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3985 {
3986 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3987 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3988 }
3989
3990 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3991 if (!pVM->hmr0.s.fNestedPaging)
3992 {
3993 Assert(!pVM->hmr0.s.vmx.fUnrestrictedGuest);
3994 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3995 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3996 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3997 }
3998
3999 /* Use TPR shadowing if supported by the CPU. */
4000 if ( PDMHasApic(pVM)
4001 && (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
4002 {
4003 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
4004 /* CR8 writes cause a VM-exit based on TPR threshold. */
4005 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
4006 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
4007 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
4008 }
4009 else
4010 {
4011 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
4012 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
4013 if (pVM->hmr0.s.fAllow64BitGuests)
4014 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
4015 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
4016 }
4017
4018 /* Use MSR-bitmaps if supported by the CPU. */
4019 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4020 {
4021 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
4022 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4023 }
4024
4025 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
4026 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
4027 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
4028
4029 if ((fVal & fZap) != fVal)
4030 {
4031 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4032 g_HmMsrs.u.vmx.ProcCtls.n.allowed0, fVal, fZap));
4033 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
4034 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4035 }
4036
4037 /* Commit it to the VMCS and update our cache. */
4038 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
4039 AssertRC(rc);
4040 pVmcsInfo->u32ProcCtls = fVal;
4041
4042 /* Set up MSR permissions that don't change through the lifetime of the VM. */
4043 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4044 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
4045
4046 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
4047 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
4048 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
4049
4050 /* Sanity check, should not really happen. */
4051 if (RT_LIKELY(!pVM->hmr0.s.vmx.fUnrestrictedGuest))
4052 { /* likely */ }
4053 else
4054 {
4055 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
4056 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4057 }
4058
4059 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
4060 return VINF_SUCCESS;
4061}
4062
4063
4064/**
4065 * Sets up miscellaneous (everything other than Pin, Processor and secondary
4066 * Processor-based VM-execution) control fields in the VMCS.
4067 *
4068 * @returns VBox status code.
4069 * @param pVCpu The cross context virtual CPU structure.
4070 * @param pVmcsInfo The VMCS info. object.
4071 */
4072static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4073{
4074#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4075 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUseVmcsShadowing)
4076 {
4077 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
4078 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
4079 }
4080#endif
4081
4082 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4083 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4084 AssertRC(rc);
4085
4086 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4087 if (RT_SUCCESS(rc))
4088 {
4089 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
4090 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
4091
4092 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
4093 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
4094
4095 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
4096 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
4097
4098 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fLbr)
4099 {
4100 rc = VMXWriteVmcsNw(VMX_VMCS64_GUEST_DEBUGCTL_FULL, MSR_IA32_DEBUGCTL_LBR);
4101 AssertRC(rc);
4102 }
4103 return VINF_SUCCESS;
4104 }
4105 else
4106 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
4107 return rc;
4108}
4109
4110
4111/**
4112 * Sets up the initial exception bitmap in the VMCS based on static conditions.
4113 *
4114 * We shall setup those exception intercepts that don't change during the
4115 * lifetime of the VM here. The rest are done dynamically while loading the
4116 * guest state.
4117 *
4118 * @param pVCpu The cross context virtual CPU structure.
4119 * @param pVmcsInfo The VMCS info. object.
4120 */
4121static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4122{
4123 /*
4124 * The following exceptions are always intercepted:
4125 *
4126 * #AC - To prevent the guest from hanging the CPU and for dealing with
4127 * split-lock detecting host configs.
4128 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
4129 * recursive #DBs can cause a CPU hang.
4130 * #PF - To sync our shadow page tables when nested-paging is not used.
4131 */
4132 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging;
4133 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
4134 | RT_BIT(X86_XCPT_DB)
4135 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
4136
4137 /* Commit it to the VMCS. */
4138 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
4139 AssertRC(rc);
4140
4141 /* Update our cache of the exception bitmap. */
4142 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
4143}
4144
4145
4146#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4147/**
4148 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
4149 *
4150 * @returns VBox status code.
4151 * @param pVmcsInfo The VMCS info. object.
4152 */
4153static int hmR0VmxSetupVmcsCtlsNested(PVMXVMCSINFO pVmcsInfo)
4154{
4155 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4156 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4157 AssertRC(rc);
4158
4159 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4160 if (RT_SUCCESS(rc))
4161 {
4162 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4163 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4164
4165 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
4166 Assert(!pVmcsInfo->u64Cr0Mask);
4167 Assert(!pVmcsInfo->u64Cr4Mask);
4168 return VINF_SUCCESS;
4169 }
4170 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
4171 return rc;
4172}
4173#endif
4174
4175
4176/**
4177 * Sets pfnStartVm to the best suited variant.
4178 *
4179 * This must be called whenever anything changes relative to the hmR0VmXStartVm
4180 * variant selection:
4181 * - pVCpu->hm.s.fLoadSaveGuestXcr0
4182 * - HM_WSF_IBPB_ENTRY in pVCpu->hmr0.s.fWorldSwitcher
4183 * - HM_WSF_IBPB_EXIT in pVCpu->hmr0.s.fWorldSwitcher
4184 * - Perhaps: CPUMIsGuestFPUStateActive() (windows only)
4185 * - Perhaps: CPUMCTX.fXStateMask (windows only)
4186 *
4187 * We currently ASSUME that neither HM_WSF_IBPB_ENTRY nor HM_WSF_IBPB_EXIT
4188 * cannot be changed at runtime.
4189 */
4190static void hmR0VmxUpdateStartVmFunction(PVMCPUCC pVCpu)
4191{
4192 static const struct CLANGWORKAROUND { PFNHMVMXSTARTVM pfn; } s_aHmR0VmxStartVmFunctions[] =
4193 {
4194 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4195 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4196 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4197 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4198 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4199 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4200 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4201 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4202 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4203 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4204 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4205 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4206 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4207 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4208 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4209 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4210 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4211 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4212 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4213 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4214 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4215 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4216 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4217 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4218 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4219 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4220 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4221 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4222 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4223 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4224 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4225 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4226 };
4227 uintptr_t const idx = (pVCpu->hmr0.s.fLoadSaveGuestXcr0 ? 1 : 0)
4228 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_IBPB_ENTRY ? 2 : 0)
4229 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_L1D_ENTRY ? 4 : 0)
4230 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_MDS_ENTRY ? 8 : 0)
4231 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_IBPB_EXIT ? 16 : 0);
4232 PFNHMVMXSTARTVM const pfnStartVm = s_aHmR0VmxStartVmFunctions[idx].pfn;
4233 if (pVCpu->hmr0.s.vmx.pfnStartVm != pfnStartVm)
4234 pVCpu->hmr0.s.vmx.pfnStartVm = pfnStartVm;
4235}
4236
4237
4238/**
4239 * Selector FNHMSVMVMRUN implementation.
4240 */
4241static DECLCALLBACK(int) hmR0VmxStartVmSelector(PVMXVMCSINFO pVmcsInfo, PVMCPUCC pVCpu, bool fResume)
4242{
4243 hmR0VmxUpdateStartVmFunction(pVCpu);
4244 return pVCpu->hmr0.s.vmx.pfnStartVm(pVmcsInfo, pVCpu, fResume);
4245}
4246
4247
4248/**
4249 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
4250 * VMX.
4251 *
4252 * @returns VBox status code.
4253 * @param pVCpu The cross context virtual CPU structure.
4254 * @param pVmcsInfo The VMCS info. object.
4255 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
4256 */
4257static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
4258{
4259 Assert(pVmcsInfo->pvVmcs);
4260 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4261
4262 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
4263 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
4264 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
4265
4266 LogFlowFunc(("\n"));
4267
4268 /*
4269 * Initialize the VMCS using VMCLEAR before loading the VMCS.
4270 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
4271 */
4272 int rc = hmR0VmxClearVmcs(pVmcsInfo);
4273 if (RT_SUCCESS(rc))
4274 {
4275 rc = hmR0VmxLoadVmcs(pVmcsInfo);
4276 if (RT_SUCCESS(rc))
4277 {
4278 /*
4279 * Initialize the hardware-assisted VMX execution handler for guest and nested-guest VMCS.
4280 * The host is always 64-bit since we no longer support 32-bit hosts.
4281 * Currently we have just a single handler for all guest modes as well, see @bugref{6208#c73}.
4282 */
4283 if (!fIsNstGstVmcs)
4284 {
4285 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
4286 if (RT_SUCCESS(rc))
4287 {
4288 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
4289 if (RT_SUCCESS(rc))
4290 {
4291 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
4292 if (RT_SUCCESS(rc))
4293 {
4294 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4295#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4296 /*
4297 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4298 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4299 * making it fit for use when VMCS shadowing is later enabled.
4300 */
4301 if (pVmcsInfo->pvShadowVmcs)
4302 {
4303 VMXVMCSREVID VmcsRevId;
4304 VmcsRevId.u = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
4305 VmcsRevId.n.fIsShadowVmcs = 1;
4306 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4307 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4308 if (RT_SUCCESS(rc))
4309 { /* likely */ }
4310 else
4311 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4312 }
4313#endif
4314 }
4315 else
4316 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4317 }
4318 else
4319 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4320 }
4321 else
4322 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4323 }
4324 else
4325 {
4326#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4327 rc = hmR0VmxSetupVmcsCtlsNested(pVmcsInfo);
4328 if (RT_SUCCESS(rc))
4329 { /* likely */ }
4330 else
4331 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4332#else
4333 AssertFailed();
4334#endif
4335 }
4336 }
4337 else
4338 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4339 }
4340 else
4341 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4342
4343 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4344 if (RT_SUCCESS(rc))
4345 {
4346 rc = hmR0VmxClearVmcs(pVmcsInfo);
4347 if (RT_SUCCESS(rc))
4348 { /* likely */ }
4349 else
4350 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4351 }
4352
4353 /*
4354 * Update the last-error record both for failures and success, so we
4355 * can propagate the status code back to ring-3 for diagnostics.
4356 */
4357 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4358 NOREF(pszVmcs);
4359 return rc;
4360}
4361
4362
4363/**
4364 * Does global VT-x initialization (called during module initialization).
4365 *
4366 * @returns VBox status code.
4367 */
4368VMMR0DECL(int) VMXR0GlobalInit(void)
4369{
4370#ifdef HMVMX_USE_FUNCTION_TABLE
4371 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_aVMExitHandlers));
4372# ifdef VBOX_STRICT
4373 for (unsigned i = 0; i < RT_ELEMENTS(g_aVMExitHandlers); i++)
4374 Assert(g_aVMExitHandlers[i].pfn);
4375# endif
4376#endif
4377 return VINF_SUCCESS;
4378}
4379
4380
4381/**
4382 * Does global VT-x termination (called during module termination).
4383 */
4384VMMR0DECL(void) VMXR0GlobalTerm()
4385{
4386 /* Nothing to do currently. */
4387}
4388
4389
4390/**
4391 * Sets up and activates VT-x on the current CPU.
4392 *
4393 * @returns VBox status code.
4394 * @param pHostCpu The HM physical-CPU structure.
4395 * @param pVM The cross context VM structure. Can be
4396 * NULL after a host resume operation.
4397 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4398 * fEnabledByHost is @c true).
4399 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4400 * @a fEnabledByHost is @c true).
4401 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4402 * enable VT-x on the host.
4403 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4404 */
4405VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4406 PCSUPHWVIRTMSRS pHwvirtMsrs)
4407{
4408 AssertPtr(pHostCpu);
4409 AssertPtr(pHwvirtMsrs);
4410 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4411
4412 /* Enable VT-x if it's not already enabled by the host. */
4413 if (!fEnabledByHost)
4414 {
4415 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4416 if (RT_FAILURE(rc))
4417 return rc;
4418 }
4419
4420 /*
4421 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4422 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4423 * invalidated when flushing by VPID.
4424 */
4425 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4426 {
4427 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4428 pHostCpu->fFlushAsidBeforeUse = false;
4429 }
4430 else
4431 pHostCpu->fFlushAsidBeforeUse = true;
4432
4433 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4434 ++pHostCpu->cTlbFlushes;
4435
4436 return VINF_SUCCESS;
4437}
4438
4439
4440/**
4441 * Deactivates VT-x on the current CPU.
4442 *
4443 * @returns VBox status code.
4444 * @param pHostCpu The HM physical-CPU structure.
4445 * @param pvCpuPage Pointer to the VMXON region.
4446 * @param HCPhysCpuPage Physical address of the VMXON region.
4447 *
4448 * @remarks This function should never be called when SUPR0EnableVTx() or
4449 * similar was used to enable VT-x on the host.
4450 */
4451VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4452{
4453 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4454
4455 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4456 return hmR0VmxLeaveRootMode(pHostCpu);
4457}
4458
4459
4460/**
4461 * Does per-VM VT-x initialization.
4462 *
4463 * @returns VBox status code.
4464 * @param pVM The cross context VM structure.
4465 */
4466VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4467{
4468 AssertPtr(pVM);
4469 LogFlowFunc(("pVM=%p\n", pVM));
4470
4471 hmR0VmxStructsInit(pVM);
4472 int rc = hmR0VmxStructsAlloc(pVM);
4473 if (RT_FAILURE(rc))
4474 {
4475 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4476 return rc;
4477 }
4478
4479 /* Setup the crash dump page. */
4480#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4481 strcpy((char *)pVM->hmr0.s.vmx.pbScratch, "SCRATCH Magic");
4482 *(uint64_t *)(pVM->hmr0.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
4483#endif
4484 return VINF_SUCCESS;
4485}
4486
4487
4488/**
4489 * Does per-VM VT-x termination.
4490 *
4491 * @returns VBox status code.
4492 * @param pVM The cross context VM structure.
4493 */
4494VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4495{
4496 AssertPtr(pVM);
4497 LogFlowFunc(("pVM=%p\n", pVM));
4498
4499#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4500 if (pVM->hmr0.s.vmx.pbScratch)
4501 RT_BZERO(pVM->hmr0.s.vmx.pbScratch, X86_PAGE_4K_SIZE);
4502#endif
4503 hmR0VmxStructsFree(pVM);
4504 return VINF_SUCCESS;
4505}
4506
4507
4508/**
4509 * Sets up the VM for execution using hardware-assisted VMX.
4510 * This function is only called once per-VM during initialization.
4511 *
4512 * @returns VBox status code.
4513 * @param pVM The cross context VM structure.
4514 */
4515VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4516{
4517 AssertPtr(pVM);
4518 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4519
4520 LogFlowFunc(("pVM=%p\n", pVM));
4521
4522 /*
4523 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4524 * without causing a #GP.
4525 */
4526 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4527 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4528 { /* likely */ }
4529 else
4530 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4531
4532 /*
4533 * Check that nested paging is supported if enabled and copy over the flag to the
4534 * ring-0 only structure.
4535 */
4536 bool const fNestedPaging = pVM->hm.s.fNestedPagingCfg;
4537 AssertReturn( !fNestedPaging
4538 || (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_EPT), /** @todo use a ring-0 copy of ProcCtls2.n.allowed1 */
4539 VERR_INCOMPATIBLE_CONFIG);
4540 pVM->hmr0.s.fNestedPaging = fNestedPaging;
4541 pVM->hmr0.s.fAllow64BitGuests = pVM->hm.s.fAllow64BitGuestsCfg;
4542
4543 /*
4544 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4545 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4546 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4547 */
4548 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuestCfg;
4549 AssertReturn( !fUnrestrictedGuest
4550 || ( (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_UNRESTRICTED_GUEST)
4551 && fNestedPaging),
4552 VERR_INCOMPATIBLE_CONFIG);
4553 if ( !fUnrestrictedGuest
4554 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4555 || !pVM->hm.s.vmx.pRealModeTSS))
4556 {
4557 LogRelFunc(("Invalid real-on-v86 state.\n"));
4558 return VERR_INTERNAL_ERROR;
4559 }
4560 pVM->hmr0.s.vmx.fUnrestrictedGuest = fUnrestrictedGuest;
4561
4562 /* Initialize these always, see hmR3InitFinalizeR0().*/
4563 pVM->hm.s.ForR3.vmx.enmTlbFlushEpt = pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4564 pVM->hm.s.ForR3.vmx.enmTlbFlushVpid = pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4565
4566 /* Setup the tagged-TLB flush handlers. */
4567 int rc = hmR0VmxSetupTaggedTlb(pVM);
4568 if (RT_FAILURE(rc))
4569 {
4570 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4571 return rc;
4572 }
4573
4574 /* Determine LBR capabilities. */
4575 pVM->hmr0.s.vmx.fLbr = pVM->hm.s.vmx.fLbrCfg;
4576 if (pVM->hmr0.s.vmx.fLbr)
4577 {
4578 rc = hmR0VmxSetupLbrMsrRange(pVM);
4579 if (RT_FAILURE(rc))
4580 {
4581 LogRelFunc(("Failed to setup LBR MSR range. rc=%Rrc\n", rc));
4582 return rc;
4583 }
4584 }
4585
4586#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4587 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4588 if (pVM->hmr0.s.vmx.fUseVmcsShadowing)
4589 {
4590 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4591 if (RT_SUCCESS(rc))
4592 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4593 else
4594 {
4595 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4596 return rc;
4597 }
4598 }
4599#endif
4600
4601 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4602 {
4603 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4604 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4605
4606 pVCpu->hmr0.s.vmx.pfnStartVm = hmR0VmxStartVmSelector;
4607
4608 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4609 if (RT_SUCCESS(rc))
4610 {
4611#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4612 if (pVM->cpum.ro.GuestFeatures.fVmx)
4613 {
4614 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4615 if (RT_SUCCESS(rc))
4616 { /* likely */ }
4617 else
4618 {
4619 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4620 return rc;
4621 }
4622 }
4623#endif
4624 }
4625 else
4626 {
4627 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4628 return rc;
4629 }
4630 }
4631
4632 return VINF_SUCCESS;
4633}
4634
4635
4636/**
4637 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4638 * the VMCS.
4639 * @returns CR4 for passing along to hmR0VmxExportHostSegmentRegs.
4640 */
4641static uint64_t hmR0VmxExportHostControlRegs(void)
4642{
4643 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4644 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4645 uint64_t uHostCr4 = ASMGetCR4();
4646 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, uHostCr4); AssertRC(rc);
4647 return uHostCr4;
4648}
4649
4650
4651/**
4652 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4653 * the host-state area in the VMCS.
4654 *
4655 * @returns VBox status code.
4656 * @param pVCpu The cross context virtual CPU structure.
4657 * @param uHostCr4 The host CR4 value.
4658 */
4659static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu, uint64_t uHostCr4)
4660{
4661 /*
4662 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4663 * will be messed up. We should -not- save the messed up state without restoring
4664 * the original host-state, see @bugref{7240}.
4665 *
4666 * This apparently can happen (most likely the FPU changes), deal with it rather than
4667 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4668 */
4669 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
4670 {
4671 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hmr0.s.vmx.fRestoreHostFlags,
4672 pVCpu->idCpu));
4673 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
4674 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
4675 }
4676
4677 /*
4678 * Get all the host info.
4679 * ASSUME it is safe to use rdfsbase and friends if the CR4.FSGSBASE bit is set
4680 * without also checking the cpuid bit.
4681 */
4682 uint32_t fRestoreHostFlags;
4683#if RT_INLINE_ASM_EXTERNAL
4684 if (uHostCr4 & X86_CR4_FSGSBASE)
4685 {
4686 hmR0VmxExportHostSegmentRegsAsmHlp(&pVCpu->hmr0.s.vmx.RestoreHost, true /*fHaveFsGsBase*/);
4687 fRestoreHostFlags = VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE;
4688 }
4689 else
4690 {
4691 hmR0VmxExportHostSegmentRegsAsmHlp(&pVCpu->hmr0.s.vmx.RestoreHost, false /*fHaveFsGsBase*/);
4692 fRestoreHostFlags = 0;
4693 }
4694 RTSEL uSelES = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelES;
4695 RTSEL uSelDS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelDS;
4696 RTSEL uSelFS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelFS;
4697 RTSEL uSelGS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelGS;
4698#else
4699 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR = ASMGetTR();
4700 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS = ASMGetSS();
4701 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS = ASMGetCS();
4702 ASMGetGDTR((PRTGDTR)&pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr);
4703 ASMGetIDTR((PRTIDTR)&pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr);
4704 if (uHostCr4 & X86_CR4_FSGSBASE)
4705 {
4706 pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase = ASMGetFSBase();
4707 pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase = ASMGetGSBase();
4708 fRestoreHostFlags = VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE;
4709 }
4710 else
4711 {
4712 pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase = ASMRdMsr(MSR_K8_FS_BASE);
4713 pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase = ASMRdMsr(MSR_K8_GS_BASE);
4714 fRestoreHostFlags = 0;
4715 }
4716 RTSEL uSelES, uSelDS, uSelFS, uSelGS;
4717 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelDS = uSelDS = ASMGetDS();
4718 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelES = uSelES = ASMGetES();
4719 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelFS = uSelFS = ASMGetFS();
4720 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelGS = uSelGS = ASMGetGS();
4721#endif
4722
4723 /*
4724 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4725 * gain VM-entry and restore them before we get preempted.
4726 *
4727 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4728 */
4729 RTSEL const uSelAll = uSelFS | uSelGS | uSelES | uSelDS;
4730 if (uSelAll & (X86_SEL_RPL | X86_SEL_LDT))
4731 {
4732 if (!(uSelAll & X86_SEL_LDT))
4733 {
4734#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_uVmcsVar) \
4735 do { \
4736 (a_uVmcsVar) = pVCpu->hmr0.s.vmx.RestoreHost.uHostSel##a_Seg; \
4737 if ((a_uVmcsVar) & X86_SEL_RPL) \
4738 { \
4739 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
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 else
4750 {
4751#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_uVmcsVar) \
4752 do { \
4753 (a_uVmcsVar) = pVCpu->hmr0.s.vmx.RestoreHost.uHostSel##a_Seg; \
4754 if ((a_uVmcsVar) & (X86_SEL_RPL | X86_SEL_LDT)) \
4755 { \
4756 if (!((a_uVmcsVar) & X86_SEL_LDT)) \
4757 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4758 else \
4759 { \
4760 uint32_t const fAttr = ASMGetSegAttr(a_uVmcsVar); \
4761 if ((fAttr & X86_DESC_P) && fAttr != UINT32_MAX) \
4762 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4763 } \
4764 (a_uVmcsVar) = 0; \
4765 } \
4766 } while (0)
4767 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4768 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4769 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4770 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4771#undef VMXLOCAL_ADJUST_HOST_SEG
4772 }
4773 }
4774
4775 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4776 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);
4777 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);
4778 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS & X86_SEL_LDT));
4779 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4780 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4781 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4782 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4783
4784 /*
4785 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4786 * them to the maximum limit (0xffff) on every VM-exit.
4787 */
4788 if (pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb != 0xffff)
4789 fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4790
4791 /*
4792 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4793 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4794 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4795 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4796 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4797 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4798 * at 0xffff on hosts where we are sure it won't cause trouble.
4799 */
4800#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4801 if (pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.cb < 0x0fff)
4802#else
4803 if (pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.cb != 0xffff)
4804#endif
4805 fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4806
4807 /*
4808 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4809 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4810 * RPL should be too in most cases.
4811 */
4812 RTSEL const uSelTR = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR;
4813 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb,
4814 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb),
4815 VERR_VMX_INVALID_HOST_STATE);
4816
4817 PCX86DESCHC pDesc = (PCX86DESCHC)(pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.uAddr + (uSelTR & X86_SEL_MASK));
4818 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4819
4820 /*
4821 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4822 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4823 * restoration if the host has something else. Task switching is not supported in 64-bit
4824 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4825 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4826 *
4827 * [1] See Intel spec. 3.5 "System Descriptor Types".
4828 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4829 */
4830 Assert(pDesc->System.u4Type == 11);
4831 if ( pDesc->System.u16LimitLow != 0x67
4832 || pDesc->System.u4LimitHigh)
4833 {
4834 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4835
4836 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4837 if (g_fHmHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4838 fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4839 if (g_fHmHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4840 {
4841 /* The GDT is read-only but the writable GDT is available. */
4842 fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4843 pVCpu->hmr0.s.vmx.RestoreHost.HostGdtrRw.cb = pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb;
4844 int rc = SUPR0GetCurrentGdtRw(&pVCpu->hmr0.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4845 AssertRCReturn(rc, rc);
4846 }
4847 }
4848
4849 pVCpu->hmr0.s.vmx.fRestoreHostFlags = fRestoreHostFlags;
4850
4851 /*
4852 * Do all the VMCS updates in one block to assist nested virtualization.
4853 */
4854 int rc;
4855 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS); AssertRC(rc);
4856 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS); AssertRC(rc);
4857 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4858 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4859 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4860 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4861 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR); AssertRC(rc);
4862 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.uAddr); AssertRC(rc);
4863 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.uAddr); AssertRC(rc);
4864 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase); AssertRC(rc);
4865 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase); AssertRC(rc);
4866 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase); AssertRC(rc);
4867
4868 return VINF_SUCCESS;
4869}
4870
4871
4872/**
4873 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4874 * host-state area of the VMCS.
4875 *
4876 * These MSRs will be automatically restored on the host after every successful
4877 * VM-exit.
4878 *
4879 * @param pVCpu The cross context virtual CPU structure.
4880 *
4881 * @remarks No-long-jump zone!!!
4882 */
4883static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4884{
4885 AssertPtr(pVCpu);
4886
4887 /*
4888 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4889 * rather than swapping them on every VM-entry.
4890 */
4891 hmR0VmxLazySaveHostMsrs(pVCpu);
4892
4893 /*
4894 * Host Sysenter MSRs.
4895 */
4896 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4897 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4898 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4899
4900 /*
4901 * Host EFER MSR.
4902 *
4903 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4904 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4905 */
4906 if (g_fHmVmxSupportsVmcsEfer)
4907 {
4908 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, g_uHmVmxHostMsrEfer);
4909 AssertRC(rc);
4910 }
4911
4912 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4913 * hmR0VmxExportGuestEntryExitCtls(). */
4914}
4915
4916
4917/**
4918 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4919 *
4920 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4921 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4922 *
4923 * @returns true if we need to load guest EFER, false otherwise.
4924 * @param pVCpu The cross context virtual CPU structure.
4925 * @param pVmxTransient The VMX-transient structure.
4926 *
4927 * @remarks Requires EFER, CR4.
4928 * @remarks No-long-jump zone!!!
4929 */
4930static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4931{
4932#ifdef HMVMX_ALWAYS_SWAP_EFER
4933 RT_NOREF2(pVCpu, pVmxTransient);
4934 return true;
4935#else
4936 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4937 uint64_t const u64HostEfer = g_uHmVmxHostMsrEfer;
4938 uint64_t const u64GuestEfer = pCtx->msrEFER;
4939
4940# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4941 /*
4942 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4943 * the nested-guest.
4944 */
4945 if ( pVmxTransient->fIsNestedGuest
4946 && ( CPUMIsGuestVmxEntryCtlsSet(pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4947 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4948 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4949 return true;
4950# else
4951 RT_NOREF(pVmxTransient);
4952#endif
4953
4954 /*
4955 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4956 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4957 */
4958 if ( CPUMIsGuestInLongModeEx(pCtx)
4959 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4960 return true;
4961
4962 /*
4963 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4964 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4965 *
4966 * See Intel spec. 4.5 "IA-32e Paging".
4967 * See Intel spec. 4.1.1 "Three Paging Modes".
4968 *
4969 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4970 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4971 */
4972 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4973 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4974 if ( (pCtx->cr4 & X86_CR4_PAE)
4975 && (pCtx->cr0 & X86_CR0_PG))
4976 {
4977 /*
4978 * If nested paging is not used, verify that the guest paging mode matches the
4979 * shadow paging mode which is/will be placed in the VMCS (which is what will
4980 * actually be used while executing the guest and not the CR4 shadow value).
4981 */
4982 AssertMsg( pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging
4983 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4984 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4985 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4986 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX,
4987 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4988 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4989 {
4990 /* Verify that the host is NX capable. */
4991 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4992 return true;
4993 }
4994 }
4995
4996 return false;
4997#endif
4998}
4999
5000
5001/**
5002 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
5003 * VMCS.
5004 *
5005 * This is typically required when the guest changes paging mode.
5006 *
5007 * @returns VBox status code.
5008 * @param pVCpu The cross context virtual CPU structure.
5009 * @param pVmxTransient The VMX-transient structure.
5010 *
5011 * @remarks Requires EFER.
5012 * @remarks No-long-jump zone!!!
5013 */
5014static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5015{
5016 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
5017 {
5018 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5019 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5020
5021 /*
5022 * VM-entry controls.
5023 */
5024 {
5025 uint32_t fVal = g_HmMsrs.u.vmx.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5026 uint32_t const fZap = g_HmMsrs.u.vmx.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5027
5028 /*
5029 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
5030 * The first VT-x capable CPUs only supported the 1-setting of this bit.
5031 *
5032 * For nested-guests, this is a mandatory VM-entry control. It's also
5033 * required because we do not want to leak host bits to the nested-guest.
5034 */
5035 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
5036
5037 /*
5038 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
5039 *
5040 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
5041 * required to get the nested-guest working with hardware-assisted VMX execution.
5042 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
5043 * can skip intercepting changes to the EFER MSR. This is why it needs to be done
5044 * here rather than while merging the guest VMCS controls.
5045 */
5046 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
5047 {
5048 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
5049 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
5050 }
5051 else
5052 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
5053
5054 /*
5055 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
5056 *
5057 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
5058 * regardless of whether the nested-guest VMCS specifies it because we are free to
5059 * load whatever MSRs we require and we do not need to modify the guest visible copy
5060 * of the VM-entry MSR load area.
5061 */
5062 if ( g_fHmVmxSupportsVmcsEfer
5063 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
5064 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
5065 else
5066 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
5067
5068 /*
5069 * The following should -not- be set (since we're not in SMM mode):
5070 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
5071 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
5072 */
5073
5074 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
5075 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
5076
5077 if ((fVal & fZap) == fVal)
5078 { /* likely */ }
5079 else
5080 {
5081 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
5082 g_HmMsrs.u.vmx.EntryCtls.n.allowed0, fVal, fZap));
5083 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
5084 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5085 }
5086
5087 /* Commit it to the VMCS. */
5088 if (pVmcsInfo->u32EntryCtls != fVal)
5089 {
5090 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
5091 AssertRC(rc);
5092 pVmcsInfo->u32EntryCtls = fVal;
5093 }
5094 }
5095
5096 /*
5097 * VM-exit controls.
5098 */
5099 {
5100 uint32_t fVal = g_HmMsrs.u.vmx.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5101 uint32_t const fZap = g_HmMsrs.u.vmx.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5102
5103 /*
5104 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
5105 * supported the 1-setting of this bit.
5106 *
5107 * For nested-guests, we set the "save debug controls" as the converse
5108 * "load debug controls" is mandatory for nested-guests anyway.
5109 */
5110 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
5111
5112 /*
5113 * Set the host long mode active (EFER.LMA) bit (which Intel calls
5114 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
5115 * host EFER.LMA and EFER.LME bit to this value. See assertion in
5116 * hmR0VmxExportHostMsrs().
5117 *
5118 * For nested-guests, we always set this bit as we do not support 32-bit
5119 * hosts.
5120 */
5121 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5122
5123 /*
5124 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
5125 *
5126 * For nested-guests, we should use the "save IA32_EFER" control if we also
5127 * used the "load IA32_EFER" control while exporting VM-entry controls.
5128 */
5129 if ( g_fHmVmxSupportsVmcsEfer
5130 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
5131 {
5132 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
5133 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
5134 }
5135
5136 /*
5137 * Enable saving of the VMX-preemption timer value on VM-exit.
5138 * For nested-guests, currently not exposed/used.
5139 */
5140 /** @todo r=bird: Measure performance hit because of this vs. always rewriting
5141 * the timer value. */
5142 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
5143 {
5144 Assert(g_HmMsrs.u.vmx.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER);
5145 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
5146 }
5147
5148 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
5149 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
5150
5151 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5152 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5153 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5154
5155 if ((fVal & fZap) == fVal)
5156 { /* likely */ }
5157 else
5158 {
5159 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5160 g_HmMsrs.u.vmx.ExitCtls.n.allowed0, fVal, fZap));
5161 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5162 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5163 }
5164
5165 /* Commit it to the VMCS. */
5166 if (pVmcsInfo->u32ExitCtls != fVal)
5167 {
5168 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5169 AssertRC(rc);
5170 pVmcsInfo->u32ExitCtls = fVal;
5171 }
5172 }
5173
5174 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5175 }
5176 return VINF_SUCCESS;
5177}
5178
5179
5180/**
5181 * Sets the TPR threshold in the VMCS.
5182 *
5183 * @param pVmcsInfo The VMCS info. object.
5184 * @param u32TprThreshold The TPR threshold (task-priority class only).
5185 */
5186DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5187{
5188 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5189 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5190 RT_NOREF(pVmcsInfo);
5191 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5192 AssertRC(rc);
5193}
5194
5195
5196/**
5197 * Exports the guest APIC TPR state into the VMCS.
5198 *
5199 * @param pVCpu The cross context virtual CPU structure.
5200 * @param pVmxTransient The VMX-transient structure.
5201 *
5202 * @remarks No-long-jump zone!!!
5203 */
5204static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5205{
5206 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5207 {
5208 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5209
5210 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5211 if (!pVmxTransient->fIsNestedGuest)
5212 {
5213 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5214 && APICIsEnabled(pVCpu))
5215 {
5216 /*
5217 * Setup TPR shadowing.
5218 */
5219 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5220 {
5221 bool fPendingIntr = false;
5222 uint8_t u8Tpr = 0;
5223 uint8_t u8PendingIntr = 0;
5224 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5225 AssertRC(rc);
5226
5227 /*
5228 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5229 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5230 * priority of the pending interrupt so we can deliver the interrupt. If there
5231 * are no interrupts pending, set threshold to 0 to not cause any
5232 * TPR-below-threshold VM-exits.
5233 */
5234 uint32_t u32TprThreshold = 0;
5235 if (fPendingIntr)
5236 {
5237 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5238 (which is the Task-Priority Class). */
5239 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5240 const uint8_t u8TprPriority = u8Tpr >> 4;
5241 if (u8PendingPriority <= u8TprPriority)
5242 u32TprThreshold = u8PendingPriority;
5243 }
5244
5245 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
5246 }
5247 }
5248 }
5249 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5250 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5251 }
5252}
5253
5254
5255/**
5256 * Gets the guest interruptibility-state and updates related force-flags.
5257 *
5258 * @returns Guest's interruptibility-state.
5259 * @param pVCpu The cross context virtual CPU structure.
5260 *
5261 * @remarks No-long-jump zone!!!
5262 */
5263static uint32_t hmR0VmxGetGuestIntrStateAndUpdateFFs(PVMCPUCC pVCpu)
5264{
5265 /*
5266 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5267 */
5268 uint32_t fIntrState = 0;
5269 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5270 {
5271 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
5272 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
5273
5274 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5275 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5276 {
5277 if (pCtx->eflags.Bits.u1IF)
5278 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5279 else
5280 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5281 }
5282 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5283 {
5284 /*
5285 * We can clear the inhibit force flag as even if we go back to the recompiler
5286 * without executing guest code in VT-x, the flag's condition to be cleared is
5287 * met and thus the cleared state is correct.
5288 */
5289 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5290 }
5291 }
5292
5293 /*
5294 * Check if we should inhibit NMI delivery.
5295 */
5296 if (CPUMIsGuestNmiBlocking(pVCpu))
5297 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5298
5299 /*
5300 * Validate.
5301 */
5302#ifdef VBOX_STRICT
5303 /* We don't support block-by-SMI yet.*/
5304 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
5305
5306 /* Block-by-STI must not be set when interrupts are disabled. */
5307 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
5308 {
5309 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5310 Assert(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_IF);
5311 }
5312#endif
5313
5314 return fIntrState;
5315}
5316
5317
5318/**
5319 * Exports the exception intercepts required for guest execution in the VMCS.
5320 *
5321 * @param pVCpu The cross context virtual CPU structure.
5322 * @param pVmxTransient The VMX-transient structure.
5323 *
5324 * @remarks No-long-jump zone!!!
5325 */
5326static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5327{
5328 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5329 {
5330 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5331 if ( !pVmxTransient->fIsNestedGuest
5332 && pVCpu->hm.s.fGIMTrapXcptUD)
5333 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5334 else
5335 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5336
5337 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5338 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5339 }
5340}
5341
5342
5343/**
5344 * Exports the guest's RIP into the guest-state area in the VMCS.
5345 *
5346 * @param pVCpu The cross context virtual CPU structure.
5347 *
5348 * @remarks No-long-jump zone!!!
5349 */
5350static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5351{
5352 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5353 {
5354 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5355
5356 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5357 AssertRC(rc);
5358
5359 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5360 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5361 }
5362}
5363
5364
5365/**
5366 * Exports the guest's RSP into the guest-state area in the VMCS.
5367 *
5368 * @param pVCpu The cross context virtual CPU structure.
5369 *
5370 * @remarks No-long-jump zone!!!
5371 */
5372static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5373{
5374 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5375 {
5376 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5377
5378 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5379 AssertRC(rc);
5380
5381 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5382 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5383 }
5384}
5385
5386
5387/**
5388 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5389 *
5390 * @param pVCpu The cross context virtual CPU structure.
5391 * @param pVmxTransient The VMX-transient structure.
5392 *
5393 * @remarks No-long-jump zone!!!
5394 */
5395static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5396{
5397 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5398 {
5399 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5400
5401 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5402 Let us assert it as such and use 32-bit VMWRITE. */
5403 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5404 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5405 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5406 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5407
5408 /*
5409 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5410 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5411 * can run the real-mode guest code under Virtual 8086 mode.
5412 */
5413 PVMXVMCSINFOSHARED pVmcsInfo = pVmxTransient->pVmcsInfo->pShared;
5414 if (pVmcsInfo->RealMode.fRealOnV86Active)
5415 {
5416 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5417 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5418 Assert(!pVmxTransient->fIsNestedGuest);
5419 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5420 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5421 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5422 }
5423
5424 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5425 AssertRC(rc);
5426
5427 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5428 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5429 }
5430}
5431
5432
5433#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5434/**
5435 * Copies the nested-guest VMCS to the shadow VMCS.
5436 *
5437 * @returns VBox status code.
5438 * @param pVCpu The cross context virtual CPU structure.
5439 * @param pVmcsInfo The VMCS info. object.
5440 *
5441 * @remarks No-long-jump zone!!!
5442 */
5443static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5444{
5445 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5446 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5447
5448 /*
5449 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5450 * current VMCS, as we may try saving guest lazy MSRs.
5451 *
5452 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5453 * calling the import VMCS code which is currently performing the guest MSR reads
5454 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5455 * and the rest of the VMX leave session machinery.
5456 */
5457 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5458
5459 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5460 if (RT_SUCCESS(rc))
5461 {
5462 /*
5463 * Copy all guest read/write VMCS fields.
5464 *
5465 * We don't check for VMWRITE failures here for performance reasons and
5466 * because they are not expected to fail, barring irrecoverable conditions
5467 * like hardware errors.
5468 */
5469 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
5470 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5471 {
5472 uint64_t u64Val;
5473 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsFields[i];
5474 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5475 VMXWriteVmcs64(uVmcsField, u64Val);
5476 }
5477
5478 /*
5479 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5480 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5481 */
5482 if (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL)
5483 {
5484 uint32_t const cShadowVmcsRoFields = pVM->hmr0.s.vmx.cShadowVmcsRoFields;
5485 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5486 {
5487 uint64_t u64Val;
5488 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsRoFields[i];
5489 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5490 VMXWriteVmcs64(uVmcsField, u64Val);
5491 }
5492 }
5493
5494 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5495 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5496 }
5497
5498 ASMSetFlags(fEFlags);
5499 return rc;
5500}
5501
5502
5503/**
5504 * Copies the shadow VMCS to the nested-guest VMCS.
5505 *
5506 * @returns VBox status code.
5507 * @param pVCpu The cross context virtual CPU structure.
5508 * @param pVmcsInfo The VMCS info. object.
5509 *
5510 * @remarks Called with interrupts disabled.
5511 */
5512static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5513{
5514 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5515 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5516 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5517
5518 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5519 if (RT_SUCCESS(rc))
5520 {
5521 /*
5522 * Copy guest read/write fields from the shadow VMCS.
5523 * Guest read-only fields cannot be modified, so no need to copy them.
5524 *
5525 * We don't check for VMREAD failures here for performance reasons and
5526 * because they are not expected to fail, barring irrecoverable conditions
5527 * like hardware errors.
5528 */
5529 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
5530 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5531 {
5532 uint64_t u64Val;
5533 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsFields[i];
5534 VMXReadVmcs64(uVmcsField, &u64Val);
5535 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5536 }
5537
5538 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5539 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5540 }
5541 return rc;
5542}
5543
5544
5545/**
5546 * Enables VMCS shadowing for the given VMCS info. object.
5547 *
5548 * @param pVmcsInfo The VMCS info. object.
5549 *
5550 * @remarks No-long-jump zone!!!
5551 */
5552static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5553{
5554 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5555 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5556 {
5557 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5558 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5559 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5560 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5561 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5562 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5563 Log4Func(("Enabled\n"));
5564 }
5565}
5566
5567
5568/**
5569 * Disables VMCS shadowing for the given VMCS info. object.
5570 *
5571 * @param pVmcsInfo The VMCS info. object.
5572 *
5573 * @remarks No-long-jump zone!!!
5574 */
5575static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5576{
5577 /*
5578 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5579 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5580 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5581 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5582 *
5583 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5584 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5585 */
5586 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5587 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5588 {
5589 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5590 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5591 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5592 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5593 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5594 Log4Func(("Disabled\n"));
5595 }
5596}
5597#endif
5598
5599
5600/**
5601 * Exports the guest hardware-virtualization state.
5602 *
5603 * @returns VBox status code.
5604 * @param pVCpu The cross context virtual CPU structure.
5605 * @param pVmxTransient The VMX-transient structure.
5606 *
5607 * @remarks No-long-jump zone!!!
5608 */
5609static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5610{
5611 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5612 {
5613#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5614 /*
5615 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5616 * VMCS shadowing.
5617 */
5618 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUseVmcsShadowing)
5619 {
5620 /*
5621 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5622 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5623 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5624 *
5625 * We check for VMX root mode here in case the guest executes VMXOFF without
5626 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5627 * not clear the current VMCS pointer.
5628 */
5629 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5630 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5631 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5632 && CPUMIsGuestVmxCurrentVmcsValid(&pVCpu->cpum.GstCtx))
5633 {
5634 /* Paranoia. */
5635 Assert(!pVmxTransient->fIsNestedGuest);
5636
5637 /*
5638 * For performance reasons, also check if the nested hypervisor's current VMCS
5639 * was newly loaded or modified before copying it to the shadow VMCS.
5640 */
5641 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5642 {
5643 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5644 AssertRCReturn(rc, rc);
5645 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5646 }
5647 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5648 }
5649 else
5650 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5651 }
5652#else
5653 NOREF(pVmxTransient);
5654#endif
5655 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5656 }
5657 return VINF_SUCCESS;
5658}
5659
5660
5661/**
5662 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5663 *
5664 * The guest FPU state is always pre-loaded hence we don't need to bother about
5665 * sharing FPU related CR0 bits between the guest and host.
5666 *
5667 * @returns VBox status code.
5668 * @param pVCpu The cross context virtual CPU structure.
5669 * @param pVmxTransient The VMX-transient structure.
5670 *
5671 * @remarks No-long-jump zone!!!
5672 */
5673static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5674{
5675 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5676 {
5677 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5678 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5679
5680 uint64_t fSetCr0 = g_HmMsrs.u.vmx.u64Cr0Fixed0;
5681 uint64_t const fZapCr0 = g_HmMsrs.u.vmx.u64Cr0Fixed1;
5682 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
5683 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5684 else
5685 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5686
5687 if (!pVmxTransient->fIsNestedGuest)
5688 {
5689 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5690 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5691 uint64_t const u64ShadowCr0 = u64GuestCr0;
5692 Assert(!RT_HI_U32(u64GuestCr0));
5693
5694 /*
5695 * Setup VT-x's view of the guest CR0.
5696 */
5697 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5698 if (pVM->hmr0.s.fNestedPaging)
5699 {
5700 if (CPUMIsGuestPagingEnabled(pVCpu))
5701 {
5702 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5703 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5704 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5705 }
5706 else
5707 {
5708 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5709 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5710 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5711 }
5712
5713 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5714 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
5715 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5716 }
5717 else
5718 {
5719 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5720 u64GuestCr0 |= X86_CR0_WP;
5721 }
5722
5723 /*
5724 * Guest FPU bits.
5725 *
5726 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5727 * using CR0.TS.
5728 *
5729 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5730 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5731 */
5732 u64GuestCr0 |= X86_CR0_NE;
5733
5734 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5735 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5736
5737 /*
5738 * Update exception intercepts.
5739 */
5740 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5741 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
5742 {
5743 Assert(PDMVmmDevHeapIsEnabled(pVM));
5744 Assert(pVM->hm.s.vmx.pRealModeTSS);
5745 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5746 }
5747 else
5748 {
5749 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5750 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5751 if (fInterceptMF)
5752 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5753 }
5754
5755 /* Additional intercepts for debugging, define these yourself explicitly. */
5756#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5757 uXcptBitmap |= 0
5758 | RT_BIT(X86_XCPT_BP)
5759 | RT_BIT(X86_XCPT_DE)
5760 | RT_BIT(X86_XCPT_NM)
5761 | RT_BIT(X86_XCPT_TS)
5762 | RT_BIT(X86_XCPT_UD)
5763 | RT_BIT(X86_XCPT_NP)
5764 | RT_BIT(X86_XCPT_SS)
5765 | RT_BIT(X86_XCPT_GP)
5766 | RT_BIT(X86_XCPT_PF)
5767 | RT_BIT(X86_XCPT_MF)
5768 ;
5769#elif defined(HMVMX_ALWAYS_TRAP_PF)
5770 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5771#endif
5772 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5773 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5774 Assert(pVM->hmr0.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5775
5776 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5777 u64GuestCr0 |= fSetCr0;
5778 u64GuestCr0 &= fZapCr0;
5779 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5780
5781 /* Commit the CR0 and related fields to the guest VMCS. */
5782 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5783 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5784 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5785 {
5786 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5787 AssertRC(rc);
5788 }
5789 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5790 {
5791 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5792 AssertRC(rc);
5793 }
5794
5795 /* Update our caches. */
5796 pVmcsInfo->u32ProcCtls = uProcCtls;
5797 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5798
5799 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5800 }
5801 else
5802 {
5803 /*
5804 * With nested-guests, we may have extended the guest/host mask here since we
5805 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5806 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5807 * originally supplied. We must copy those bits from the nested-guest CR0 into
5808 * the nested-guest CR0 read-shadow.
5809 */
5810 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5811 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5812 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(&pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5813 Assert(!RT_HI_U32(u64GuestCr0));
5814 Assert(u64GuestCr0 & X86_CR0_NE);
5815
5816 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5817 u64GuestCr0 |= fSetCr0;
5818 u64GuestCr0 &= fZapCr0;
5819 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5820
5821 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5822 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5823 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5824
5825 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5826 }
5827
5828 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5829 }
5830
5831 return VINF_SUCCESS;
5832}
5833
5834
5835/**
5836 * Exports the guest control registers (CR3, CR4) into the guest-state area
5837 * in the VMCS.
5838 *
5839 * @returns VBox strict status code.
5840 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5841 * without unrestricted guest access and the VMMDev is not presently
5842 * mapped (e.g. EFI32).
5843 *
5844 * @param pVCpu The cross context virtual CPU structure.
5845 * @param pVmxTransient The VMX-transient structure.
5846 *
5847 * @remarks No-long-jump zone!!!
5848 */
5849static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5850{
5851 int rc = VINF_SUCCESS;
5852 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5853
5854 /*
5855 * Guest CR2.
5856 * It's always loaded in the assembler code. Nothing to do here.
5857 */
5858
5859 /*
5860 * Guest CR3.
5861 */
5862 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5863 {
5864 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5865
5866 if (pVM->hmr0.s.fNestedPaging)
5867 {
5868 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5869 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5870
5871 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5872 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5873 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5874 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5875
5876 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5877 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5878 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5879
5880 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5881 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5882 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5883 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5884 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5885 || (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5886 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5887
5888 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5889 AssertRC(rc);
5890
5891 uint64_t u64GuestCr3;
5892 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5893 if ( pVM->hmr0.s.vmx.fUnrestrictedGuest
5894 || CPUMIsGuestPagingEnabledEx(pCtx))
5895 {
5896 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5897 if (CPUMIsGuestInPAEModeEx(pCtx))
5898 {
5899 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5900 AssertRC(rc);
5901 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5902 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5903 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5904 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5905 }
5906
5907 /*
5908 * The guest's view of its CR3 is unblemished with nested paging when the
5909 * guest is using paging or we have unrestricted guest execution to handle
5910 * the guest when it's not using paging.
5911 */
5912 u64GuestCr3 = pCtx->cr3;
5913 }
5914 else
5915 {
5916 /*
5917 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5918 * thinks it accesses physical memory directly, we use our identity-mapped
5919 * page table to map guest-linear to guest-physical addresses. EPT takes care
5920 * of translating it to host-physical addresses.
5921 */
5922 RTGCPHYS GCPhys;
5923 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5924
5925 /* We obtain it here every time as the guest could have relocated this PCI region. */
5926 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5927 if (RT_SUCCESS(rc))
5928 { /* likely */ }
5929 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5930 {
5931 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5932 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5933 }
5934 else
5935 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5936
5937 u64GuestCr3 = GCPhys;
5938 }
5939
5940 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5941 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5942 AssertRC(rc);
5943 }
5944 else
5945 {
5946 Assert(!pVmxTransient->fIsNestedGuest);
5947 /* Non-nested paging case, just use the hypervisor's CR3. */
5948 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5949
5950 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5951 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5952 AssertRC(rc);
5953 }
5954
5955 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5956 }
5957
5958 /*
5959 * Guest CR4.
5960 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5961 */
5962 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5963 {
5964 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5965 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5966
5967 uint64_t const fSetCr4 = g_HmMsrs.u.vmx.u64Cr4Fixed0;
5968 uint64_t const fZapCr4 = g_HmMsrs.u.vmx.u64Cr4Fixed1;
5969
5970 /*
5971 * With nested-guests, we may have extended the guest/host mask here (since we
5972 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5973 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5974 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5975 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5976 */
5977 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5978 uint64_t u64GuestCr4 = pCtx->cr4;
5979 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5980 ? pCtx->cr4
5981 : CPUMGetGuestVmxMaskedCr4(pCtx, pVmcsInfo->u64Cr4Mask);
5982 Assert(!RT_HI_U32(u64GuestCr4));
5983
5984 /*
5985 * Setup VT-x's view of the guest CR4.
5986 *
5987 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5988 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5989 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5990 *
5991 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5992 */
5993 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
5994 {
5995 Assert(pVM->hm.s.vmx.pRealModeTSS);
5996 Assert(PDMVmmDevHeapIsEnabled(pVM));
5997 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5998 }
5999
6000 if (pVM->hmr0.s.fNestedPaging)
6001 {
6002 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
6003 && !pVM->hmr0.s.vmx.fUnrestrictedGuest)
6004 {
6005 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
6006 u64GuestCr4 |= X86_CR4_PSE;
6007 /* Our identity mapping is a 32-bit page directory. */
6008 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
6009 }
6010 /* else use guest CR4.*/
6011 }
6012 else
6013 {
6014 Assert(!pVmxTransient->fIsNestedGuest);
6015
6016 /*
6017 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
6018 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
6019 */
6020 switch (pVCpu->hm.s.enmShadowMode)
6021 {
6022 case PGMMODE_REAL: /* Real-mode. */
6023 case PGMMODE_PROTECTED: /* Protected mode without paging. */
6024 case PGMMODE_32_BIT: /* 32-bit paging. */
6025 {
6026 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
6027 break;
6028 }
6029
6030 case PGMMODE_PAE: /* PAE paging. */
6031 case PGMMODE_PAE_NX: /* PAE paging with NX. */
6032 {
6033 u64GuestCr4 |= X86_CR4_PAE;
6034 break;
6035 }
6036
6037 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
6038 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
6039 {
6040#ifdef VBOX_WITH_64_BITS_GUESTS
6041 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
6042 Assert(u64GuestCr4 & X86_CR4_PAE);
6043 break;
6044#endif
6045 }
6046 default:
6047 AssertFailed();
6048 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6049 }
6050 }
6051
6052 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
6053 u64GuestCr4 |= fSetCr4;
6054 u64GuestCr4 &= fZapCr4;
6055
6056 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
6057 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
6058 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
6059
6060 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
6061 bool const fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
6062 if (fLoadSaveGuestXcr0 != pVCpu->hmr0.s.fLoadSaveGuestXcr0)
6063 {
6064 pVCpu->hmr0.s.fLoadSaveGuestXcr0 = fLoadSaveGuestXcr0;
6065 hmR0VmxUpdateStartVmFunction(pVCpu);
6066 }
6067
6068 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
6069
6070 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
6071 }
6072 return rc;
6073}
6074
6075
6076/**
6077 * Exports the guest debug registers into the guest-state area in the VMCS.
6078 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
6079 *
6080 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
6081 *
6082 * @returns VBox status code.
6083 * @param pVCpu The cross context virtual CPU structure.
6084 * @param pVmxTransient The VMX-transient structure.
6085 *
6086 * @remarks No-long-jump zone!!!
6087 */
6088static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6089{
6090 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
6091
6092 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
6093 * stepping. */
6094 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6095 if (pVmxTransient->fIsNestedGuest)
6096 {
6097 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
6098 AssertRC(rc);
6099
6100 /*
6101 * We don't want to always intercept MOV DRx for nested-guests as it causes
6102 * problems when the nested hypervisor isn't intercepting them, see @bugref{10080}.
6103 * Instead, they are strictly only requested when the nested hypervisor intercepts
6104 * them -- handled while merging VMCS controls.
6105 *
6106 * If neither the outer nor the nested-hypervisor is intercepting MOV DRx,
6107 * then the nested-guest debug state should be actively loaded on the host so that
6108 * nested-guest reads its own debug registers without causing VM-exits.
6109 */
6110 if ( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT)
6111 && !CPUMIsGuestDebugStateActive(pVCpu))
6112 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6113 return VINF_SUCCESS;
6114 }
6115
6116#ifdef VBOX_STRICT
6117 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
6118 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
6119 {
6120 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
6121 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
6122 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
6123 }
6124#endif
6125
6126 bool fSteppingDB = false;
6127 bool fInterceptMovDRx = false;
6128 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6129 if (pVCpu->hm.s.fSingleInstruction)
6130 {
6131 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
6132 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
6133 {
6134 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
6135 Assert(fSteppingDB == false);
6136 }
6137 else
6138 {
6139 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
6140 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
6141 pVCpu->hmr0.s.fClearTrapFlag = true;
6142 fSteppingDB = true;
6143 }
6144 }
6145
6146 uint64_t u64GuestDr7;
6147 if ( fSteppingDB
6148 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
6149 {
6150 /*
6151 * Use the combined guest and host DRx values found in the hypervisor register set
6152 * because the hypervisor debugger has breakpoints active or someone is single stepping
6153 * on the host side without a monitor trap flag.
6154 *
6155 * Note! DBGF expects a clean DR6 state before executing guest code.
6156 */
6157 if (!CPUMIsHyperDebugStateActive(pVCpu))
6158 {
6159 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6160 Assert(CPUMIsHyperDebugStateActive(pVCpu));
6161 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
6162 }
6163
6164 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6165 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
6166 pVCpu->hmr0.s.fUsingHyperDR7 = true;
6167 fInterceptMovDRx = true;
6168 }
6169 else
6170 {
6171 /*
6172 * If the guest has enabled debug registers, we need to load them prior to
6173 * executing guest code so they'll trigger at the right time.
6174 */
6175 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
6176 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6177 {
6178 if (!CPUMIsGuestDebugStateActive(pVCpu))
6179 {
6180 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6181 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6182 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6183 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6184 }
6185 Assert(!fInterceptMovDRx);
6186 }
6187 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6188 {
6189 /*
6190 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6191 * must intercept #DB in order to maintain a correct DR6 guest value, and
6192 * because we need to intercept it to prevent nested #DBs from hanging the
6193 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6194 */
6195 fInterceptMovDRx = true;
6196 }
6197
6198 /* Update DR7 with the actual guest value. */
6199 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6200 pVCpu->hmr0.s.fUsingHyperDR7 = false;
6201 }
6202
6203 if (fInterceptMovDRx)
6204 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6205 else
6206 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6207
6208 /*
6209 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6210 * monitor-trap flag and update our cache.
6211 */
6212 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6213 {
6214 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6215 AssertRC(rc);
6216 pVmcsInfo->u32ProcCtls = uProcCtls;
6217 }
6218
6219 /*
6220 * Update guest DR7.
6221 */
6222 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
6223 AssertRC(rc);
6224
6225 /*
6226 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6227 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6228 *
6229 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6230 */
6231 if (fSteppingDB)
6232 {
6233 Assert(pVCpu->hm.s.fSingleInstruction);
6234 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6235
6236 uint32_t fIntrState = 0;
6237 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6238 AssertRC(rc);
6239
6240 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6241 {
6242 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6243 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6244 AssertRC(rc);
6245 }
6246 }
6247
6248 return VINF_SUCCESS;
6249}
6250
6251
6252#ifdef VBOX_STRICT
6253/**
6254 * Strict function to validate segment registers.
6255 *
6256 * @param pVCpu The cross context virtual CPU structure.
6257 * @param pVmcsInfo The VMCS info. object.
6258 *
6259 * @remarks Will import guest CR0 on strict builds during validation of
6260 * segments.
6261 */
6262static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
6263{
6264 /*
6265 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6266 *
6267 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6268 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6269 * unusable bit and doesn't change the guest-context value.
6270 */
6271 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6272 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6273 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6274 if ( !pVM->hmr0.s.vmx.fUnrestrictedGuest
6275 && ( !CPUMIsGuestInRealModeEx(pCtx)
6276 && !CPUMIsGuestInV86ModeEx(pCtx)))
6277 {
6278 /* Protected mode checks */
6279 /* CS */
6280 Assert(pCtx->cs.Attr.n.u1Present);
6281 Assert(!(pCtx->cs.Attr.u & 0xf00));
6282 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6283 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6284 || !(pCtx->cs.Attr.n.u1Granularity));
6285 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6286 || (pCtx->cs.Attr.n.u1Granularity));
6287 /* CS cannot be loaded with NULL in protected mode. */
6288 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6289 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6290 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6291 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6292 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6293 else
6294 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6295 /* SS */
6296 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6297 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6298 if ( !(pCtx->cr0 & X86_CR0_PE)
6299 || pCtx->cs.Attr.n.u4Type == 3)
6300 {
6301 Assert(!pCtx->ss.Attr.n.u2Dpl);
6302 }
6303 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6304 {
6305 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6306 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6307 Assert(pCtx->ss.Attr.n.u1Present);
6308 Assert(!(pCtx->ss.Attr.u & 0xf00));
6309 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6310 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6311 || !(pCtx->ss.Attr.n.u1Granularity));
6312 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6313 || (pCtx->ss.Attr.n.u1Granularity));
6314 }
6315 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6316 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6317 {
6318 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6319 Assert(pCtx->ds.Attr.n.u1Present);
6320 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6321 Assert(!(pCtx->ds.Attr.u & 0xf00));
6322 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6323 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6324 || !(pCtx->ds.Attr.n.u1Granularity));
6325 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6326 || (pCtx->ds.Attr.n.u1Granularity));
6327 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6328 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6329 }
6330 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6331 {
6332 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6333 Assert(pCtx->es.Attr.n.u1Present);
6334 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6335 Assert(!(pCtx->es.Attr.u & 0xf00));
6336 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6337 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6338 || !(pCtx->es.Attr.n.u1Granularity));
6339 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6340 || (pCtx->es.Attr.n.u1Granularity));
6341 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6342 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6343 }
6344 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6345 {
6346 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6347 Assert(pCtx->fs.Attr.n.u1Present);
6348 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6349 Assert(!(pCtx->fs.Attr.u & 0xf00));
6350 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6351 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6352 || !(pCtx->fs.Attr.n.u1Granularity));
6353 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6354 || (pCtx->fs.Attr.n.u1Granularity));
6355 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6356 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6357 }
6358 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6359 {
6360 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6361 Assert(pCtx->gs.Attr.n.u1Present);
6362 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6363 Assert(!(pCtx->gs.Attr.u & 0xf00));
6364 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6365 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6366 || !(pCtx->gs.Attr.n.u1Granularity));
6367 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6368 || (pCtx->gs.Attr.n.u1Granularity));
6369 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6370 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6371 }
6372 /* 64-bit capable CPUs. */
6373 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6374 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6375 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6376 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6377 }
6378 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6379 || ( CPUMIsGuestInRealModeEx(pCtx)
6380 && !pVM->hmr0.s.vmx.fUnrestrictedGuest))
6381 {
6382 /* Real and v86 mode checks. */
6383 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6384 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6385 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
6386 {
6387 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6388 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6389 }
6390 else
6391 {
6392 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6393 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6394 }
6395
6396 /* CS */
6397 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6398 Assert(pCtx->cs.u32Limit == 0xffff);
6399 Assert(u32CSAttr == 0xf3);
6400 /* SS */
6401 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6402 Assert(pCtx->ss.u32Limit == 0xffff);
6403 Assert(u32SSAttr == 0xf3);
6404 /* DS */
6405 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6406 Assert(pCtx->ds.u32Limit == 0xffff);
6407 Assert(u32DSAttr == 0xf3);
6408 /* ES */
6409 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6410 Assert(pCtx->es.u32Limit == 0xffff);
6411 Assert(u32ESAttr == 0xf3);
6412 /* FS */
6413 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6414 Assert(pCtx->fs.u32Limit == 0xffff);
6415 Assert(u32FSAttr == 0xf3);
6416 /* GS */
6417 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6418 Assert(pCtx->gs.u32Limit == 0xffff);
6419 Assert(u32GSAttr == 0xf3);
6420 /* 64-bit capable CPUs. */
6421 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6422 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6423 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6424 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6425 }
6426}
6427#endif /* VBOX_STRICT */
6428
6429
6430/**
6431 * Exports a guest segment register into the guest-state area in the VMCS.
6432 *
6433 * @returns VBox status code.
6434 * @param pVCpu The cross context virtual CPU structure.
6435 * @param pVmcsInfo The VMCS info. object.
6436 * @param iSegReg The segment register number (X86_SREG_XXX).
6437 * @param pSelReg Pointer to the segment selector.
6438 *
6439 * @remarks No-long-jump zone!!!
6440 */
6441static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint32_t iSegReg, PCCPUMSELREG pSelReg)
6442{
6443 Assert(iSegReg < X86_SREG_COUNT);
6444
6445 uint32_t u32Access = pSelReg->Attr.u;
6446 if (!pVmcsInfo->pShared->RealMode.fRealOnV86Active)
6447 {
6448 /*
6449 * The way to differentiate between whether this is really a null selector or was just
6450 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6451 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6452 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6453 * NULL selectors loaded in protected-mode have their attribute as 0.
6454 */
6455 if (u32Access)
6456 { }
6457 else
6458 u32Access = X86DESCATTR_UNUSABLE;
6459 }
6460 else
6461 {
6462 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6463 u32Access = 0xf3;
6464 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6465 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6466 RT_NOREF_PV(pVCpu);
6467 }
6468
6469 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6470 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6471 ("Access bit not set for usable segment. %.2s sel=%#x attr %#x\n", "ESCSSSDSFSGS" + iSegReg * 2, pSelReg, pSelReg->Attr.u));
6472
6473 /*
6474 * Commit it to the VMCS.
6475 */
6476 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]);
6477 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]);
6478 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
6479 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]);
6480 int rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), pSelReg->Sel); AssertRC(rc);
6481 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), pSelReg->u32Limit); AssertRC(rc);
6482 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), pSelReg->u64Base); AssertRC(rc);
6483 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), u32Access); AssertRC(rc);
6484 return VINF_SUCCESS;
6485}
6486
6487
6488/**
6489 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6490 * area in the VMCS.
6491 *
6492 * @returns VBox status code.
6493 * @param pVCpu The cross context virtual CPU structure.
6494 * @param pVmxTransient The VMX-transient structure.
6495 *
6496 * @remarks Will import guest CR0 on strict builds during validation of
6497 * segments.
6498 * @remarks No-long-jump zone!!!
6499 */
6500static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6501{
6502 int rc = VERR_INTERNAL_ERROR_5;
6503 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6504 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6505 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6506 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
6507
6508 /*
6509 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6510 */
6511 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6512 {
6513 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6514 {
6515 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6516 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6517 pVmcsInfoShared->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6518 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6519 AssertRC(rc);
6520 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6521 }
6522
6523 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6524 {
6525 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6526 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6527 pVmcsInfoShared->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6528 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6529 AssertRC(rc);
6530 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6531 }
6532
6533 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6534 {
6535 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6536 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6537 pVmcsInfoShared->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6538 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6539 AssertRC(rc);
6540 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6541 }
6542
6543 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6544 {
6545 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6546 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6547 pVmcsInfoShared->RealMode.AttrES.u = pCtx->es.Attr.u;
6548 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6549 AssertRC(rc);
6550 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6551 }
6552
6553 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6554 {
6555 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6556 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6557 pVmcsInfoShared->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6558 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6559 AssertRC(rc);
6560 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6561 }
6562
6563 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6564 {
6565 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6566 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6567 pVmcsInfoShared->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6568 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6569 AssertRC(rc);
6570 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6571 }
6572
6573#ifdef VBOX_STRICT
6574 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6575#endif
6576 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6577 pCtx->cs.Attr.u));
6578 }
6579
6580 /*
6581 * Guest TR.
6582 */
6583 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6584 {
6585 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6586
6587 /*
6588 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6589 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6590 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6591 */
6592 uint16_t u16Sel;
6593 uint32_t u32Limit;
6594 uint64_t u64Base;
6595 uint32_t u32AccessRights;
6596 if (!pVmcsInfoShared->RealMode.fRealOnV86Active)
6597 {
6598 u16Sel = pCtx->tr.Sel;
6599 u32Limit = pCtx->tr.u32Limit;
6600 u64Base = pCtx->tr.u64Base;
6601 u32AccessRights = pCtx->tr.Attr.u;
6602 }
6603 else
6604 {
6605 Assert(!pVmxTransient->fIsNestedGuest);
6606 Assert(pVM->hm.s.vmx.pRealModeTSS);
6607 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6608
6609 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6610 RTGCPHYS GCPhys;
6611 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6612 AssertRCReturn(rc, rc);
6613
6614 X86DESCATTR DescAttr;
6615 DescAttr.u = 0;
6616 DescAttr.n.u1Present = 1;
6617 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6618
6619 u16Sel = 0;
6620 u32Limit = HM_VTX_TSS_SIZE;
6621 u64Base = GCPhys;
6622 u32AccessRights = DescAttr.u;
6623 }
6624
6625 /* Validate. */
6626 Assert(!(u16Sel & RT_BIT(2)));
6627 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6628 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6629 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6630 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6631 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6632 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6633 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6634 Assert( (u32Limit & 0xfff) == 0xfff
6635 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6636 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6637 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6638
6639 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6640 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6641 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6642 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6643
6644 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6645 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6646 }
6647
6648 /*
6649 * Guest GDTR.
6650 */
6651 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6652 {
6653 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6654
6655 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6656 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6657
6658 /* Validate. */
6659 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6660
6661 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6662 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6663 }
6664
6665 /*
6666 * Guest LDTR.
6667 */
6668 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6669 {
6670 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6671
6672 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6673 uint32_t u32Access;
6674 if ( !pVmxTransient->fIsNestedGuest
6675 && !pCtx->ldtr.Attr.u)
6676 u32Access = X86DESCATTR_UNUSABLE;
6677 else
6678 u32Access = pCtx->ldtr.Attr.u;
6679
6680 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6681 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6682 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6683 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6684
6685 /* Validate. */
6686 if (!(u32Access & X86DESCATTR_UNUSABLE))
6687 {
6688 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6689 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6690 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6691 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6692 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6693 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6694 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6695 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6696 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6697 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6698 }
6699
6700 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6701 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6702 }
6703
6704 /*
6705 * Guest IDTR.
6706 */
6707 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6708 {
6709 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6710
6711 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6712 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6713
6714 /* Validate. */
6715 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6716
6717 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6718 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6719 }
6720
6721 return VINF_SUCCESS;
6722}
6723
6724
6725/**
6726 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6727 * areas.
6728 *
6729 * These MSRs will automatically be loaded to the host CPU on every successful
6730 * VM-entry and stored from the host CPU on every successful VM-exit.
6731 *
6732 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6733 * actual host MSR values are not- updated here for performance reasons. See
6734 * hmR0VmxExportHostMsrs().
6735 *
6736 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6737 *
6738 * @returns VBox status code.
6739 * @param pVCpu The cross context virtual CPU structure.
6740 * @param pVmxTransient The VMX-transient structure.
6741 *
6742 * @remarks No-long-jump zone!!!
6743 */
6744static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6745{
6746 AssertPtr(pVCpu);
6747 AssertPtr(pVmxTransient);
6748
6749 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6750 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6751
6752 /*
6753 * MSRs that we use the auto-load/store MSR area in the VMCS.
6754 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6755 * nothing to do here. The host MSR values are updated when it's safe in
6756 * hmR0VmxLazySaveHostMsrs().
6757 *
6758 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6759 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6760 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6761 * for any MSR that are not part of the lazy MSRs so we do not need to place
6762 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6763 */
6764 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6765 {
6766 /* No auto-load/store MSRs currently. */
6767 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6768 }
6769
6770 /*
6771 * Guest Sysenter MSRs.
6772 */
6773 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6774 {
6775 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6776
6777 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6778 {
6779 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6780 AssertRC(rc);
6781 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6782 }
6783
6784 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6785 {
6786 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6787 AssertRC(rc);
6788 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6789 }
6790
6791 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6792 {
6793 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6794 AssertRC(rc);
6795 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6796 }
6797 }
6798
6799 /*
6800 * Guest/host EFER MSR.
6801 */
6802 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6803 {
6804 /* Whether we are using the VMCS to swap the EFER MSR must have been
6805 determined earlier while exporting VM-entry/VM-exit controls. */
6806 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6807 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6808
6809 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6810 {
6811 /*
6812 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6813 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6814 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6815 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6816 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6817 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6818 * during VM-entry.
6819 */
6820 uint64_t uGuestEferMsr = pCtx->msrEFER;
6821 if (!pVM->hmr0.s.vmx.fUnrestrictedGuest)
6822 {
6823 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6824 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6825 else
6826 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6827 }
6828
6829 /*
6830 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6831 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6832 */
6833 if (g_fHmVmxSupportsVmcsEfer)
6834 {
6835 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6836 AssertRC(rc);
6837 }
6838 else
6839 {
6840 /*
6841 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6842 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6843 */
6844 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6845 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6846 AssertRCReturn(rc, rc);
6847 }
6848
6849 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6850 }
6851 else if (!g_fHmVmxSupportsVmcsEfer)
6852 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6853
6854 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6855 }
6856
6857 /*
6858 * Other MSRs.
6859 */
6860 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6861 {
6862 /* Speculation Control (R/W). */
6863 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6864 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6865 {
6866 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6867 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6868 AssertRCReturn(rc, rc);
6869 }
6870
6871 /* Last Branch Record. */
6872 if (pVM->hmr0.s.vmx.fLbr)
6873 {
6874 PVMXVMCSINFOSHARED const pVmcsInfoShared = pVmxTransient->pVmcsInfo->pShared;
6875 uint32_t const idFromIpMsrStart = pVM->hmr0.s.vmx.idLbrFromIpMsrFirst;
6876 uint32_t const idToIpMsrStart = pVM->hmr0.s.vmx.idLbrToIpMsrFirst;
6877 uint32_t const cLbrStack = pVM->hmr0.s.vmx.idLbrFromIpMsrLast - pVM->hmr0.s.vmx.idLbrFromIpMsrFirst + 1;
6878 Assert(cLbrStack <= 32);
6879 for (uint32_t i = 0; i < cLbrStack; i++)
6880 {
6881 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idFromIpMsrStart + i,
6882 pVmcsInfoShared->au64LbrFromIpMsr[i],
6883 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6884 AssertRCReturn(rc, rc);
6885
6886 /* Some CPUs don't have a Branch-To-IP MSR (P4 and related Xeons). */
6887 if (idToIpMsrStart != 0)
6888 {
6889 rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idToIpMsrStart + i,
6890 pVmcsInfoShared->au64LbrToIpMsr[i],
6891 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6892 AssertRCReturn(rc, rc);
6893 }
6894 }
6895
6896 /* Add LBR top-of-stack MSR (which contains the index to the most recent record). */
6897 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, pVM->hmr0.s.vmx.idLbrTosMsr,
6898 pVmcsInfoShared->u64LbrTosMsr, false /* fSetReadWrite */,
6899 false /* fUpdateHostMsr */);
6900 AssertRCReturn(rc, rc);
6901 }
6902
6903 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6904 }
6905
6906 return VINF_SUCCESS;
6907}
6908
6909
6910/**
6911 * Wrapper for running the guest code in VT-x.
6912 *
6913 * @returns VBox status code, no informational status codes.
6914 * @param pVCpu The cross context virtual CPU structure.
6915 * @param pVmxTransient The VMX-transient structure.
6916 *
6917 * @remarks No-long-jump zone!!!
6918 */
6919DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6920{
6921 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6922 pVCpu->cpum.GstCtx.fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6923
6924 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6925 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6926#ifdef VBOX_WITH_STATISTICS
6927 if (fResumeVM)
6928 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxVmResume);
6929 else
6930 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxVmLaunch);
6931#endif
6932 int rc = pVCpu->hmr0.s.vmx.pfnStartVm(pVmcsInfo, pVCpu, fResumeVM);
6933 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6934 return rc;
6935}
6936
6937
6938/**
6939 * Reports world-switch error and dumps some useful debug info.
6940 *
6941 * @param pVCpu The cross context virtual CPU structure.
6942 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6943 * @param pVmxTransient The VMX-transient structure (only
6944 * exitReason updated).
6945 */
6946static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6947{
6948 Assert(pVCpu);
6949 Assert(pVmxTransient);
6950 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6951
6952 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6953 switch (rcVMRun)
6954 {
6955 case VERR_VMX_INVALID_VMXON_PTR:
6956 AssertFailed();
6957 break;
6958 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6959 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6960 {
6961 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6962 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6963 AssertRC(rc);
6964 hmR0VmxReadExitQualVmcs(pVmxTransient);
6965
6966 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hmr0.s.idEnteredCpu;
6967 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6968 Cannot do it here as we may have been long preempted. */
6969
6970#ifdef VBOX_STRICT
6971 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6972 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6973 pVmxTransient->uExitReason));
6974 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6975 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6976 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6977 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6978 else
6979 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6980 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6981 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6982
6983 static struct
6984 {
6985 /** Name of the field to log. */
6986 const char *pszName;
6987 /** The VMCS field. */
6988 uint32_t uVmcsField;
6989 /** Whether host support of this field needs to be checked. */
6990 bool fCheckSupport;
6991 } const s_aVmcsFields[] =
6992 {
6993 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6994 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6995 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6996 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6997 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6998 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6999 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
7000 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
7001 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
7002 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
7003 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
7004 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
7005 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
7006 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
7007 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
7008 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
7009 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
7010 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
7011 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
7012 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
7013 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
7014 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
7015 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
7016 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
7017 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
7018 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
7019 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
7020 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
7021 /* The order of selector fields below are fixed! */
7022 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
7023 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
7024 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
7025 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
7026 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
7027 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
7028 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
7029 /* End of ordered selector fields. */
7030 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
7031 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
7032 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
7033 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
7034 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
7035 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
7036 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
7037 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
7038 };
7039
7040 RTGDTR HostGdtr;
7041 ASMGetGDTR(&HostGdtr);
7042
7043 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
7044 for (uint32_t i = 0; i < cVmcsFields; i++)
7045 {
7046 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
7047
7048 bool fSupported;
7049 if (!s_aVmcsFields[i].fCheckSupport)
7050 fSupported = true;
7051 else
7052 {
7053 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7054 switch (uVmcsField)
7055 {
7056 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hmr0.s.fNestedPaging; break;
7057 case VMX_VMCS16_VPID: fSupported = pVM->hmr0.s.vmx.fVpid; break;
7058 case VMX_VMCS32_CTRL_PROC_EXEC2:
7059 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
7060 break;
7061 default:
7062 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
7063 }
7064 }
7065
7066 if (fSupported)
7067 {
7068 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
7069 switch (uWidth)
7070 {
7071 case VMX_VMCSFIELD_WIDTH_16BIT:
7072 {
7073 uint16_t u16Val;
7074 rc = VMXReadVmcs16(uVmcsField, &u16Val);
7075 AssertRC(rc);
7076 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
7077
7078 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
7079 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
7080 {
7081 if (u16Val < HostGdtr.cbGdt)
7082 {
7083 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
7084 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
7085 "Host FS", "Host GS", "Host TR" };
7086 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
7087 Assert(idxSel < RT_ELEMENTS(s_apszSel));
7088 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
7089 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
7090 }
7091 else
7092 Log4((" Selector value exceeds GDT limit!\n"));
7093 }
7094 break;
7095 }
7096
7097 case VMX_VMCSFIELD_WIDTH_32BIT:
7098 {
7099 uint32_t u32Val;
7100 rc = VMXReadVmcs32(uVmcsField, &u32Val);
7101 AssertRC(rc);
7102 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
7103 break;
7104 }
7105
7106 case VMX_VMCSFIELD_WIDTH_64BIT:
7107 case VMX_VMCSFIELD_WIDTH_NATURAL:
7108 {
7109 uint64_t u64Val;
7110 rc = VMXReadVmcs64(uVmcsField, &u64Val);
7111 AssertRC(rc);
7112 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
7113 break;
7114 }
7115 }
7116 }
7117 }
7118
7119 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
7120 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
7121 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
7122 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
7123 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
7124 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
7125#endif /* VBOX_STRICT */
7126 break;
7127 }
7128
7129 default:
7130 /* Impossible */
7131 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
7132 break;
7133 }
7134}
7135
7136
7137/**
7138 * Sets up the usage of TSC-offsetting and updates the VMCS.
7139 *
7140 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
7141 * VMX-preemption timer.
7142 *
7143 * @returns VBox status code.
7144 * @param pVCpu The cross context virtual CPU structure.
7145 * @param pVmxTransient The VMX-transient structure.
7146 * @param idCurrentCpu The current CPU number.
7147 *
7148 * @remarks No-long-jump zone!!!
7149 */
7150static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, RTCPUID idCurrentCpu)
7151{
7152 bool fOffsettedTsc;
7153 bool fParavirtTsc;
7154 uint64_t uTscOffset;
7155 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7156 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7157
7158 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
7159 {
7160 /* The TMCpuTickGetDeadlineAndTscOffset function is expensive (calling it on
7161 every entry slowed down the bs2-test1 CPUID testcase by ~33% (on an 10980xe). */
7162 uint64_t cTicksToDeadline;
7163 if ( idCurrentCpu == pVCpu->hmr0.s.idLastCpu
7164 && TMVirtualSyncIsCurrentDeadlineVersion(pVM, pVCpu->hmr0.s.vmx.uTscDeadlineVersion))
7165 {
7166 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatVmxPreemptionReusingDeadline);
7167 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7168 cTicksToDeadline = pVCpu->hmr0.s.vmx.uTscDeadline - SUPReadTsc();
7169 if ((int64_t)cTicksToDeadline > 0)
7170 { /* hopefully */ }
7171 else
7172 {
7173 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatVmxPreemptionReusingDeadlineExpired);
7174 cTicksToDeadline = 0;
7175 }
7176 }
7177 else
7178 {
7179 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatVmxPreemptionRecalcingDeadline);
7180 cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc,
7181 &pVCpu->hmr0.s.vmx.uTscDeadline,
7182 &pVCpu->hmr0.s.vmx.uTscDeadlineVersion);
7183 pVCpu->hmr0.s.vmx.uTscDeadline += cTicksToDeadline;
7184 if (cTicksToDeadline >= 128)
7185 { /* hopefully */ }
7186 else
7187 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatVmxPreemptionRecalcingDeadlineExpired);
7188 }
7189
7190 /* Make sure the returned values have sane upper and lower boundaries. */
7191 uint64_t const u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7192 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second, 15.625ms. */ /** @todo r=bird: Once real+virtual timers move to separate thread, we can raise the upper limit (16ms isn't much). ASSUMES working poke cpu function. */
7193 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 32678); /* 1/32768th of a second, ~30us. */
7194 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7195
7196 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7197 * preemption timers here. We probably need to clamp the preemption timer,
7198 * after converting the timer value to the host. */
7199 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7200 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7201 AssertRC(rc);
7202 }
7203 else
7204 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7205
7206 if (fParavirtTsc)
7207 {
7208 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7209 information before every VM-entry, hence disable it for performance sake. */
7210#if 0
7211 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7212 AssertRC(rc);
7213#endif
7214 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7215 }
7216
7217 if ( fOffsettedTsc
7218 && RT_LIKELY(!pVCpu->hmr0.s.fDebugWantRdTscExit))
7219 {
7220 if (pVmxTransient->fIsNestedGuest)
7221 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7222 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
7223 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7224 }
7225 else
7226 {
7227 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7228 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7229 }
7230}
7231
7232
7233/**
7234 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7235 * VM-exit interruption info type.
7236 *
7237 * @returns The IEM exception flags.
7238 * @param uVector The event vector.
7239 * @param uVmxEventType The VMX event type.
7240 *
7241 * @remarks This function currently only constructs flags required for
7242 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7243 * and CR2 aspects of an exception are not included).
7244 */
7245static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7246{
7247 uint32_t fIemXcptFlags;
7248 switch (uVmxEventType)
7249 {
7250 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7251 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7252 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7253 break;
7254
7255 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7256 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7257 break;
7258
7259 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7260 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7261 break;
7262
7263 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7264 {
7265 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7266 if (uVector == X86_XCPT_BP)
7267 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7268 else if (uVector == X86_XCPT_OF)
7269 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7270 else
7271 {
7272 fIemXcptFlags = 0;
7273 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7274 }
7275 break;
7276 }
7277
7278 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7279 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7280 break;
7281
7282 default:
7283 fIemXcptFlags = 0;
7284 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7285 break;
7286 }
7287 return fIemXcptFlags;
7288}
7289
7290
7291/**
7292 * Sets an event as a pending event to be injected into the guest.
7293 *
7294 * @param pVCpu The cross context virtual CPU structure.
7295 * @param u32IntInfo The VM-entry interruption-information field.
7296 * @param cbInstr The VM-entry instruction length in bytes (for
7297 * software interrupts, exceptions and privileged
7298 * software exceptions).
7299 * @param u32ErrCode The VM-entry exception error code.
7300 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7301 * page-fault.
7302 */
7303DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7304 RTGCUINTPTR GCPtrFaultAddress)
7305{
7306 Assert(!pVCpu->hm.s.Event.fPending);
7307 pVCpu->hm.s.Event.fPending = true;
7308 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7309 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7310 pVCpu->hm.s.Event.cbInstr = cbInstr;
7311 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7312}
7313
7314
7315/**
7316 * Sets an external interrupt as pending-for-injection into the VM.
7317 *
7318 * @param pVCpu The cross context virtual CPU structure.
7319 * @param u8Interrupt The external interrupt vector.
7320 */
7321DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
7322{
7323 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7324 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7325 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7326 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7327 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7328}
7329
7330
7331/**
7332 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7333 *
7334 * @param pVCpu The cross context virtual CPU structure.
7335 */
7336DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
7337{
7338 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7339 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7340 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7341 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7342 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7343}
7344
7345
7346/**
7347 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7348 *
7349 * @param pVCpu The cross context virtual CPU structure.
7350 */
7351DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
7352{
7353 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7354 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7355 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7356 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7357 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7358}
7359
7360
7361/**
7362 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7363 *
7364 * @param pVCpu The cross context virtual CPU structure.
7365 */
7366DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
7367{
7368 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7369 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7370 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7371 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7372 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7373}
7374
7375
7376/**
7377 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7378 *
7379 * @param pVCpu The cross context virtual CPU structure.
7380 */
7381DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
7382{
7383 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7384 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7385 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7386 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7387 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7388}
7389
7390
7391#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7392/**
7393 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7394 *
7395 * @param pVCpu The cross context virtual CPU structure.
7396 * @param u32ErrCode The error code for the general-protection exception.
7397 */
7398DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7399{
7400 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7401 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7402 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7403 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7404 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7405}
7406
7407
7408/**
7409 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7410 *
7411 * @param pVCpu The cross context virtual CPU structure.
7412 * @param u32ErrCode The error code for the stack exception.
7413 */
7414DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7415{
7416 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7417 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7418 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7419 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7420 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7421}
7422#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7423
7424
7425/**
7426 * Fixes up attributes for the specified segment register.
7427 *
7428 * @param pVCpu The cross context virtual CPU structure.
7429 * @param pSelReg The segment register that needs fixing.
7430 * @param pszRegName The register name (for logging and assertions).
7431 */
7432static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, const char *pszRegName)
7433{
7434 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7435
7436 /*
7437 * If VT-x marks the segment as unusable, most other bits remain undefined:
7438 * - For CS the L, D and G bits have meaning.
7439 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7440 * - For the remaining data segments no bits are defined.
7441 *
7442 * The present bit and the unusable bit has been observed to be set at the
7443 * same time (the selector was supposed to be invalid as we started executing
7444 * a V8086 interrupt in ring-0).
7445 *
7446 * What should be important for the rest of the VBox code, is that the P bit is
7447 * cleared. Some of the other VBox code recognizes the unusable bit, but
7448 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7449 * safe side here, we'll strip off P and other bits we don't care about. If
7450 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7451 *
7452 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7453 */
7454#ifdef VBOX_STRICT
7455 uint32_t const uAttr = pSelReg->Attr.u;
7456#endif
7457
7458 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7459 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7460 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7461
7462#ifdef VBOX_STRICT
7463 VMMRZCallRing3Disable(pVCpu);
7464 Log4Func(("Unusable %s: sel=%#x attr=%#x -> %#x\n", pszRegName, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7465# ifdef DEBUG_bird
7466 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7467 ("%s: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7468 pszRegName, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7469# endif
7470 VMMRZCallRing3Enable(pVCpu);
7471 NOREF(uAttr);
7472#endif
7473 RT_NOREF2(pVCpu, pszRegName);
7474}
7475
7476
7477/**
7478 * Imports a guest segment register from the current VMCS into the guest-CPU
7479 * context.
7480 *
7481 * @param pVCpu The cross context virtual CPU structure.
7482 * @param iSegReg The segment register number (X86_SREG_XXX).
7483 *
7484 * @remarks Called with interrupts and/or preemption disabled.
7485 */
7486static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint32_t iSegReg)
7487{
7488 Assert(iSegReg < X86_SREG_COUNT);
7489 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]);
7490 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]);
7491 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
7492 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]);
7493
7494 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7495
7496 uint16_t u16Sel;
7497 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), &u16Sel); AssertRC(rc);
7498 pSelReg->Sel = u16Sel;
7499 pSelReg->ValidSel = u16Sel;
7500
7501 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), &pSelReg->u32Limit); AssertRC(rc);
7502 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), &pSelReg->u64Base); AssertRC(rc);
7503
7504 uint32_t u32Attr;
7505 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), &u32Attr); AssertRC(rc);
7506 pSelReg->Attr.u = u32Attr;
7507 if (u32Attr & X86DESCATTR_UNUSABLE)
7508 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, "ES\0CS\0SS\0DS\0FS\0GS" + iSegReg * 3);
7509
7510 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7511}
7512
7513
7514/**
7515 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7516 *
7517 * @param pVCpu The cross context virtual CPU structure.
7518 *
7519 * @remarks Called with interrupts and/or preemption disabled.
7520 */
7521static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7522{
7523 uint16_t u16Sel;
7524 uint64_t u64Base;
7525 uint32_t u32Limit, u32Attr;
7526 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7527 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7528 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7529 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7530
7531 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7532 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7533 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7534 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7535 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7536 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7537 if (u32Attr & X86DESCATTR_UNUSABLE)
7538 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, "LDTR");
7539}
7540
7541
7542/**
7543 * Imports the guest TR from the current VMCS into the guest-CPU context.
7544 *
7545 * @param pVCpu The cross context virtual CPU structure.
7546 *
7547 * @remarks Called with interrupts and/or preemption disabled.
7548 */
7549static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7550{
7551 uint16_t u16Sel;
7552 uint64_t u64Base;
7553 uint32_t u32Limit, u32Attr;
7554 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7555 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7556 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7557 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7558
7559 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7560 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7561 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7562 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7563 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7564 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7565 /* TR is the only selector that can never be unusable. */
7566 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7567}
7568
7569
7570/**
7571 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7572 *
7573 * @param pVCpu The cross context virtual CPU structure.
7574 *
7575 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7576 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7577 * instead!!!
7578 */
7579static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7580{
7581 uint64_t u64Val;
7582 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7583 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7584 {
7585 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7586 AssertRC(rc);
7587
7588 pCtx->rip = u64Val;
7589 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7590 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7591 }
7592}
7593
7594
7595/**
7596 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7597 *
7598 * @param pVCpu The cross context virtual CPU structure.
7599 * @param pVmcsInfo The VMCS info. object.
7600 *
7601 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7602 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7603 * instead!!!
7604 */
7605static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7606{
7607 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7608 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7609 {
7610 uint64_t u64Val;
7611 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7612 AssertRC(rc);
7613
7614 pCtx->rflags.u64 = u64Val;
7615 PCVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7616 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
7617 {
7618 pCtx->eflags.Bits.u1VM = 0;
7619 pCtx->eflags.Bits.u2IOPL = pVmcsInfoShared->RealMode.Eflags.Bits.u2IOPL;
7620 }
7621 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7622 }
7623}
7624
7625
7626/**
7627 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7628 * context.
7629 *
7630 * @param pVCpu The cross context virtual CPU structure.
7631 * @param pVmcsInfo The VMCS info. object.
7632 *
7633 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7634 * do not log!
7635 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7636 * instead!!!
7637 */
7638static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7639{
7640 uint32_t u32Val;
7641 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7642 if (!u32Val)
7643 {
7644 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7645 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7646 CPUMSetGuestNmiBlocking(pVCpu, false);
7647 }
7648 else
7649 {
7650 /*
7651 * We must import RIP here to set our EM interrupt-inhibited state.
7652 * We also import RFLAGS as our code that evaluates pending interrupts
7653 * before VM-entry requires it.
7654 */
7655 hmR0VmxImportGuestRip(pVCpu);
7656 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7657
7658 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7659 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7660 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7661 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7662
7663 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7664 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7665 }
7666}
7667
7668
7669/**
7670 * Worker for VMXR0ImportStateOnDemand.
7671 *
7672 * @returns VBox status code.
7673 * @param pVCpu The cross context virtual CPU structure.
7674 * @param pVmcsInfo The VMCS info. object.
7675 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7676 */
7677static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7678{
7679 int rc = VINF_SUCCESS;
7680 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7681 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7682 uint32_t u32Val;
7683
7684 /*
7685 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7686 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7687 * neither are other host platforms.
7688 *
7689 * Committing this temporarily as it prevents BSOD.
7690 *
7691 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7692 */
7693#ifdef RT_OS_WINDOWS
7694 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7695 return VERR_HM_IPE_1;
7696#endif
7697
7698 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7699
7700 /*
7701 * We disable interrupts to make the updating of the state and in particular
7702 * the fExtrn modification atomic wrt to preemption hooks.
7703 */
7704 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7705
7706 fWhat &= pCtx->fExtrn;
7707 if (fWhat)
7708 {
7709 do
7710 {
7711 if (fWhat & CPUMCTX_EXTRN_RIP)
7712 hmR0VmxImportGuestRip(pVCpu);
7713
7714 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7715 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7716
7717 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7718 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7719
7720 if (fWhat & CPUMCTX_EXTRN_RSP)
7721 {
7722 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7723 AssertRC(rc);
7724 }
7725
7726 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7727 {
7728 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7729 bool const fRealOnV86Active = pVmcsInfoShared->RealMode.fRealOnV86Active;
7730 if (fWhat & CPUMCTX_EXTRN_CS)
7731 {
7732 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7733 hmR0VmxImportGuestRip(pVCpu);
7734 if (fRealOnV86Active)
7735 pCtx->cs.Attr.u = pVmcsInfoShared->RealMode.AttrCS.u;
7736 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7737 }
7738 if (fWhat & CPUMCTX_EXTRN_SS)
7739 {
7740 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7741 if (fRealOnV86Active)
7742 pCtx->ss.Attr.u = pVmcsInfoShared->RealMode.AttrSS.u;
7743 }
7744 if (fWhat & CPUMCTX_EXTRN_DS)
7745 {
7746 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7747 if (fRealOnV86Active)
7748 pCtx->ds.Attr.u = pVmcsInfoShared->RealMode.AttrDS.u;
7749 }
7750 if (fWhat & CPUMCTX_EXTRN_ES)
7751 {
7752 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7753 if (fRealOnV86Active)
7754 pCtx->es.Attr.u = pVmcsInfoShared->RealMode.AttrES.u;
7755 }
7756 if (fWhat & CPUMCTX_EXTRN_FS)
7757 {
7758 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7759 if (fRealOnV86Active)
7760 pCtx->fs.Attr.u = pVmcsInfoShared->RealMode.AttrFS.u;
7761 }
7762 if (fWhat & CPUMCTX_EXTRN_GS)
7763 {
7764 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7765 if (fRealOnV86Active)
7766 pCtx->gs.Attr.u = pVmcsInfoShared->RealMode.AttrGS.u;
7767 }
7768 }
7769
7770 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7771 {
7772 if (fWhat & CPUMCTX_EXTRN_LDTR)
7773 hmR0VmxImportGuestLdtr(pVCpu);
7774
7775 if (fWhat & CPUMCTX_EXTRN_GDTR)
7776 {
7777 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7778 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7779 pCtx->gdtr.cbGdt = u32Val;
7780 }
7781
7782 /* Guest IDTR. */
7783 if (fWhat & CPUMCTX_EXTRN_IDTR)
7784 {
7785 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7786 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7787 pCtx->idtr.cbIdt = u32Val;
7788 }
7789
7790 /* Guest TR. */
7791 if (fWhat & CPUMCTX_EXTRN_TR)
7792 {
7793 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7794 don't need to import that one. */
7795 if (!pVmcsInfo->pShared->RealMode.fRealOnV86Active)
7796 hmR0VmxImportGuestTr(pVCpu);
7797 }
7798 }
7799
7800 if (fWhat & CPUMCTX_EXTRN_DR7)
7801 {
7802 if (!pVCpu->hmr0.s.fUsingHyperDR7)
7803 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7804 }
7805
7806 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7807 {
7808 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7809 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7810 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7811 pCtx->SysEnter.cs = u32Val;
7812 }
7813
7814 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7815 {
7816 if ( pVM->hmr0.s.fAllow64BitGuests
7817 && (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7818 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7819 }
7820
7821 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7822 {
7823 if ( pVM->hmr0.s.fAllow64BitGuests
7824 && (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7825 {
7826 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7827 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7828 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7829 }
7830 }
7831
7832 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7833 {
7834 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7835 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7836 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7837 Assert(pMsrs);
7838 Assert(cMsrs <= VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc));
7839 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7840 for (uint32_t i = 0; i < cMsrs; i++)
7841 {
7842 uint32_t const idMsr = pMsrs[i].u32Msr;
7843 switch (idMsr)
7844 {
7845 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7846 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7847 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7848 default:
7849 {
7850 uint32_t idxLbrMsr;
7851 if (pVM->hmr0.s.vmx.fLbr)
7852 {
7853 if (hmR0VmxIsLbrBranchFromMsr(pVM, idMsr, &idxLbrMsr))
7854 {
7855 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfoShared->au64LbrFromIpMsr));
7856 pVmcsInfoShared->au64LbrFromIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7857 break;
7858 }
7859 if (hmR0VmxIsLbrBranchToMsr(pVM, idMsr, &idxLbrMsr))
7860 {
7861 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfoShared->au64LbrFromIpMsr));
7862 pVmcsInfoShared->au64LbrToIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7863 break;
7864 }
7865 if (idMsr == pVM->hmr0.s.vmx.idLbrTosMsr)
7866 {
7867 pVmcsInfoShared->u64LbrTosMsr = pMsrs[i].u64Value;
7868 break;
7869 }
7870 /* Fallthru (no break) */
7871 }
7872 pCtx->fExtrn = 0;
7873 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7874 ASMSetFlags(fEFlags);
7875 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7876 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7877 }
7878 }
7879 }
7880 }
7881
7882 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7883 {
7884 if (fWhat & CPUMCTX_EXTRN_CR0)
7885 {
7886 uint64_t u64Cr0;
7887 uint64_t u64Shadow;
7888 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7889 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7890#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7891 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7892 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7893#else
7894 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7895 {
7896 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7897 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7898 }
7899 else
7900 {
7901 /*
7902 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7903 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7904 * re-construct CR0. See @bugref{9180#c95} for details.
7905 */
7906 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
7907 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7908 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7909 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7910 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7911 }
7912#endif
7913 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7914 CPUMSetGuestCR0(pVCpu, u64Cr0);
7915 VMMRZCallRing3Enable(pVCpu);
7916 }
7917
7918 if (fWhat & CPUMCTX_EXTRN_CR4)
7919 {
7920 uint64_t u64Cr4;
7921 uint64_t u64Shadow;
7922 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7923 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7924#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7925 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7926 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7927#else
7928 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7929 {
7930 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7931 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7932 }
7933 else
7934 {
7935 /*
7936 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7937 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7938 * re-construct CR4. See @bugref{9180#c95} for details.
7939 */
7940 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
7941 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7942 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7943 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7944 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7945 }
7946#endif
7947 pCtx->cr4 = u64Cr4;
7948 }
7949
7950 if (fWhat & CPUMCTX_EXTRN_CR3)
7951 {
7952 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7953 if ( pVM->hmr0.s.vmx.fUnrestrictedGuest
7954 || ( pVM->hmr0.s.fNestedPaging
7955 && CPUMIsGuestPagingEnabledEx(pCtx)))
7956 {
7957 uint64_t u64Cr3;
7958 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7959 if (pCtx->cr3 != u64Cr3)
7960 {
7961 pCtx->cr3 = u64Cr3;
7962 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7963 }
7964
7965 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7966 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7967 if (CPUMIsGuestInPAEModeEx(pCtx))
7968 {
7969 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7970 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7971 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7972 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7973 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7974 }
7975 }
7976 }
7977 }
7978
7979#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7980 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7981 {
7982 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7983 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7984 {
7985 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7986 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7987 if (RT_SUCCESS(rc))
7988 { /* likely */ }
7989 else
7990 break;
7991 }
7992 }
7993#endif
7994 } while (0);
7995
7996 if (RT_SUCCESS(rc))
7997 {
7998 /* Update fExtrn. */
7999 pCtx->fExtrn &= ~fWhat;
8000
8001 /* If everything has been imported, clear the HM keeper bit. */
8002 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
8003 {
8004 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
8005 Assert(!pCtx->fExtrn);
8006 }
8007 }
8008 }
8009 else
8010 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
8011
8012 /*
8013 * Restore interrupts.
8014 */
8015 ASMSetFlags(fEFlags);
8016
8017 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
8018
8019 if (RT_SUCCESS(rc))
8020 { /* likely */ }
8021 else
8022 return rc;
8023
8024 /*
8025 * Honor any pending CR3 updates.
8026 *
8027 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
8028 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
8029 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
8030 *
8031 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
8032 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
8033 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
8034 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
8035 *
8036 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
8037 */
8038 if (VMMRZCallRing3IsEnabled(pVCpu))
8039 {
8040 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
8041 {
8042 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
8043 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
8044 }
8045
8046 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
8047 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
8048
8049 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
8050 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
8051 }
8052
8053 return VINF_SUCCESS;
8054}
8055
8056
8057/**
8058 * Saves the guest state from the VMCS into the guest-CPU context.
8059 *
8060 * @returns VBox status code.
8061 * @param pVCpu The cross context virtual CPU structure.
8062 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
8063 */
8064VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
8065{
8066 AssertPtr(pVCpu);
8067 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8068 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
8069}
8070
8071
8072/**
8073 * Check per-VM and per-VCPU force flag actions that require us to go back to
8074 * ring-3 for one reason or another.
8075 *
8076 * @returns Strict VBox status code (i.e. informational status codes too)
8077 * @retval VINF_SUCCESS if we don't have any actions that require going back to
8078 * ring-3.
8079 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
8080 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
8081 * interrupts)
8082 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
8083 * all EMTs to be in ring-3.
8084 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
8085 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
8086 * to the EM loop.
8087 *
8088 * @param pVCpu The cross context virtual CPU structure.
8089 * @param pVmxTransient The VMX-transient structure.
8090 * @param fStepping Whether we are single-stepping the guest using the
8091 * hypervisor debugger.
8092 *
8093 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
8094 * is no longer in VMX non-root mode.
8095 */
8096static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, bool fStepping)
8097{
8098 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8099
8100 /*
8101 * Update pending interrupts into the APIC's IRR.
8102 */
8103 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
8104 APICUpdatePendingInterrupts(pVCpu);
8105
8106 /*
8107 * Anything pending? Should be more likely than not if we're doing a good job.
8108 */
8109 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8110 if ( !fStepping
8111 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
8112 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
8113 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
8114 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
8115 return VINF_SUCCESS;
8116
8117 /* Pending PGM C3 sync. */
8118 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
8119 {
8120 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8121 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
8122 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
8123 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
8124 if (rcStrict != VINF_SUCCESS)
8125 {
8126 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
8127 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
8128 return rcStrict;
8129 }
8130 }
8131
8132 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
8133 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
8134 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
8135 {
8136 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
8137 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
8138 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
8139 return rc;
8140 }
8141
8142 /* Pending VM request packets, such as hardware interrupts. */
8143 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
8144 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
8145 {
8146 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
8147 Log4Func(("Pending VM request forcing us back to ring-3\n"));
8148 return VINF_EM_PENDING_REQUEST;
8149 }
8150
8151 /* Pending PGM pool flushes. */
8152 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
8153 {
8154 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
8155 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
8156 return VINF_PGM_POOL_FLUSH_PENDING;
8157 }
8158
8159 /* Pending DMA requests. */
8160 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
8161 {
8162 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
8163 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
8164 return VINF_EM_RAW_TO_R3;
8165 }
8166
8167#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8168 /*
8169 * Pending nested-guest events.
8170 *
8171 * Please note the priority of these events are specified and important.
8172 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
8173 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
8174 */
8175 if (pVmxTransient->fIsNestedGuest)
8176 {
8177 /* Pending nested-guest APIC-write. */
8178 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
8179 {
8180 Log4Func(("Pending nested-guest APIC-write\n"));
8181 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
8182 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8183 return rcStrict;
8184 }
8185
8186 /* Pending nested-guest monitor-trap flag (MTF). */
8187 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
8188 {
8189 Log4Func(("Pending nested-guest MTF\n"));
8190 VBOXSTRICTRC rcStrict = IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */);
8191 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8192 return rcStrict;
8193 }
8194
8195 /* Pending nested-guest VMX-preemption timer expired. */
8196 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
8197 {
8198 Log4Func(("Pending nested-guest preempt timer\n"));
8199 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitPreemptTimer(pVCpu);
8200 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8201 return rcStrict;
8202 }
8203 }
8204#else
8205 NOREF(pVmxTransient);
8206#endif
8207
8208 return VINF_SUCCESS;
8209}
8210
8211
8212/**
8213 * Converts any TRPM trap into a pending HM event. This is typically used when
8214 * entering from ring-3 (not longjmp returns).
8215 *
8216 * @param pVCpu The cross context virtual CPU structure.
8217 */
8218static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
8219{
8220 Assert(TRPMHasTrap(pVCpu));
8221 Assert(!pVCpu->hm.s.Event.fPending);
8222
8223 uint8_t uVector;
8224 TRPMEVENT enmTrpmEvent;
8225 uint32_t uErrCode;
8226 RTGCUINTPTR GCPtrFaultAddress;
8227 uint8_t cbInstr;
8228 bool fIcebp;
8229
8230 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
8231 AssertRC(rc);
8232
8233 uint32_t u32IntInfo;
8234 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8235 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
8236
8237 rc = TRPMResetTrap(pVCpu);
8238 AssertRC(rc);
8239 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8240 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8241
8242 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8243}
8244
8245
8246/**
8247 * Converts the pending HM event into a TRPM trap.
8248 *
8249 * @param pVCpu The cross context virtual CPU structure.
8250 */
8251static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
8252{
8253 Assert(pVCpu->hm.s.Event.fPending);
8254
8255 /* If a trap was already pending, we did something wrong! */
8256 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8257
8258 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8259 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8260 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8261
8262 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8263
8264 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8265 AssertRC(rc);
8266
8267 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8268 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8269
8270 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8271 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8272 else
8273 {
8274 uint8_t const uVectorType = VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo);
8275 switch (uVectorType)
8276 {
8277 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
8278 TRPMSetTrapDueToIcebp(pVCpu);
8279 RT_FALL_THRU();
8280 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
8281 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
8282 {
8283 AssertMsg( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
8284 || ( uVector == X86_XCPT_BP /* INT3 */
8285 || uVector == X86_XCPT_OF /* INTO */
8286 || uVector == X86_XCPT_DB /* INT1 (ICEBP) */),
8287 ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uVectorType));
8288 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8289 break;
8290 }
8291 }
8292 }
8293
8294 /* We're now done converting the pending event. */
8295 pVCpu->hm.s.Event.fPending = false;
8296}
8297
8298
8299/**
8300 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8301 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8302 *
8303 * @param pVmcsInfo The VMCS info. object.
8304 */
8305static void hmR0VmxSetIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8306{
8307 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8308 {
8309 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8310 {
8311 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8312 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8313 AssertRC(rc);
8314 }
8315 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8316}
8317
8318
8319/**
8320 * Clears the interrupt-window exiting control in the VMCS.
8321 *
8322 * @param pVmcsInfo The VMCS info. object.
8323 */
8324DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8325{
8326 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8327 {
8328 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8329 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8330 AssertRC(rc);
8331 }
8332}
8333
8334
8335/**
8336 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8337 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8338 *
8339 * @param pVmcsInfo The VMCS info. object.
8340 */
8341static void hmR0VmxSetNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8342{
8343 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8344 {
8345 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8346 {
8347 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8348 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8349 AssertRC(rc);
8350 Log4Func(("Setup NMI-window exiting\n"));
8351 }
8352 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8353}
8354
8355
8356/**
8357 * Clears the NMI-window exiting control in the VMCS.
8358 *
8359 * @param pVmcsInfo The VMCS info. object.
8360 */
8361DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8362{
8363 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8364 {
8365 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8366 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8367 AssertRC(rc);
8368 }
8369}
8370
8371
8372/**
8373 * Does the necessary state syncing before returning to ring-3 for any reason
8374 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8375 *
8376 * @returns VBox status code.
8377 * @param pVCpu The cross context virtual CPU structure.
8378 * @param fImportState Whether to import the guest state from the VMCS back
8379 * to the guest-CPU context.
8380 *
8381 * @remarks No-long-jmp zone!!!
8382 */
8383static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
8384{
8385 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8386 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8387
8388 RTCPUID const idCpu = RTMpCpuId();
8389 Log4Func(("HostCpuId=%u\n", idCpu));
8390
8391 /*
8392 * !!! IMPORTANT !!!
8393 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
8394 */
8395
8396 /* Save the guest state if necessary. */
8397 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8398 if (fImportState)
8399 {
8400 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8401 AssertRCReturn(rc, rc);
8402 }
8403
8404 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8405 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8406 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8407
8408 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8409#ifdef VBOX_STRICT
8410 if (CPUMIsHyperDebugStateActive(pVCpu))
8411 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8412#endif
8413 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8414 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
8415 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
8416
8417 /* Restore host-state bits that VT-x only restores partially. */
8418 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
8419 {
8420 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hmr0.s.vmx.fRestoreHostFlags, idCpu));
8421 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
8422 }
8423 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
8424
8425 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8426 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8427 {
8428 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8429 if (!fImportState)
8430 {
8431 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8432 AssertRCReturn(rc, rc);
8433 }
8434 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8435 Assert(!pVCpu->hmr0.s.vmx.fLazyMsrs);
8436 }
8437 else
8438 pVCpu->hmr0.s.vmx.fLazyMsrs = 0;
8439
8440 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8441 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
8442
8443 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8444 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8445 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8446 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8447 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8448 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8449 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8450 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8451 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8452 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8453
8454 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8455
8456 /** @todo This partially defeats the purpose of having preemption hooks.
8457 * The problem is, deregistering the hooks should be moved to a place that
8458 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8459 * context.
8460 */
8461 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8462 AssertRCReturn(rc, rc);
8463
8464#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8465 /*
8466 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8467 * clear a shadow VMCS before allowing that VMCS to become active on another
8468 * logical processor. We may or may not be importing guest state which clears
8469 * it, so cover for it here.
8470 *
8471 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8472 */
8473 if ( pVmcsInfo->pvShadowVmcs
8474 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8475 {
8476 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8477 AssertRCReturn(rc, rc);
8478 }
8479
8480 /*
8481 * Flag that we need to re-export the host state if we switch to this VMCS before
8482 * executing guest or nested-guest code.
8483 */
8484 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8485#endif
8486
8487 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8488 NOREF(idCpu);
8489 return VINF_SUCCESS;
8490}
8491
8492
8493/**
8494 * Leaves the VT-x session.
8495 *
8496 * @returns VBox status code.
8497 * @param pVCpu The cross context virtual CPU structure.
8498 *
8499 * @remarks No-long-jmp zone!!!
8500 */
8501static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8502{
8503 HM_DISABLE_PREEMPT(pVCpu);
8504 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8505 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8506 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8507
8508 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8509 and done this from the VMXR0ThreadCtxCallback(). */
8510 if (!pVCpu->hmr0.s.fLeaveDone)
8511 {
8512 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8513 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8514 pVCpu->hmr0.s.fLeaveDone = true;
8515 }
8516 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8517
8518 /*
8519 * !!! IMPORTANT !!!
8520 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8521 */
8522
8523 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8524 /** @todo Deregistering here means we need to VMCLEAR always
8525 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8526 * for calling VMMR0ThreadCtxHookDisable here! */
8527 VMMR0ThreadCtxHookDisable(pVCpu);
8528
8529 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8530 int rc = HMR0LeaveCpu(pVCpu);
8531 HM_RESTORE_PREEMPT();
8532 return rc;
8533}
8534
8535
8536/**
8537 * Does the necessary state syncing before doing a longjmp to ring-3.
8538 *
8539 * @returns VBox status code.
8540 * @param pVCpu The cross context virtual CPU structure.
8541 *
8542 * @remarks No-long-jmp zone!!!
8543 */
8544DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8545{
8546 return hmR0VmxLeaveSession(pVCpu);
8547}
8548
8549
8550/**
8551 * Take necessary actions before going back to ring-3.
8552 *
8553 * An action requires us to go back to ring-3. This function does the necessary
8554 * steps before we can safely return to ring-3. This is not the same as longjmps
8555 * to ring-3, this is voluntary and prepares the guest so it may continue
8556 * executing outside HM (recompiler/IEM).
8557 *
8558 * @returns VBox status code.
8559 * @param pVCpu The cross context virtual CPU structure.
8560 * @param rcExit The reason for exiting to ring-3. Can be
8561 * VINF_VMM_UNKNOWN_RING3_CALL.
8562 */
8563static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8564{
8565 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8566
8567 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8568 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8569 {
8570 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8571 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8572 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hmr0.s.idEnteredCpu;
8573 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8574 }
8575
8576 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8577 VMMRZCallRing3Disable(pVCpu);
8578 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8579
8580 /*
8581 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8582 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8583 *
8584 * This is because execution may continue from ring-3 and we would need to inject
8585 * the event from there (hence place it back in TRPM).
8586 */
8587 if (pVCpu->hm.s.Event.fPending)
8588 {
8589 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8590 Assert(!pVCpu->hm.s.Event.fPending);
8591
8592 /* Clear the events from the VMCS. */
8593 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc);
8594 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0); AssertRC(rc);
8595 }
8596#ifdef VBOX_STRICT
8597 /*
8598 * We check for rcExit here since for errors like VERR_VMX_UNABLE_TO_START_VM (which are
8599 * fatal), we don't care about verifying duplicate injection of events. Errors like
8600 * VERR_EM_INTERPRET are converted to their VINF_* counterparts -prior- to calling this
8601 * function so those should and will be checked below.
8602 */
8603 else if (RT_SUCCESS(rcExit))
8604 {
8605 /*
8606 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8607 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8608 * occasionally, see @bugref{9180#c42}.
8609 *
8610 * However, if the VM-entry failed, any VM entry-interruption info. field would
8611 * be left unmodified as the event would not have been injected to the guest. In
8612 * such cases, don't assert, we're not going to continue guest execution anyway.
8613 */
8614 uint32_t uExitReason;
8615 uint32_t uEntryIntInfo;
8616 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8617 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8618 AssertRC(rc);
8619 AssertMsg(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo),
8620 ("uExitReason=%#RX32 uEntryIntInfo=%#RX32 rcExit=%d\n", uExitReason, uEntryIntInfo, VBOXSTRICTRC_VAL(rcExit)));
8621 }
8622#endif
8623
8624 /*
8625 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8626 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8627 * (e.g. TPR below threshold).
8628 */
8629 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8630 {
8631 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8632 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8633 }
8634
8635 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8636 and if we're injecting an event we should have a TRPM trap pending. */
8637 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8638#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8639 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8640#endif
8641
8642 /* Save guest state and restore host state bits. */
8643 int rc = hmR0VmxLeaveSession(pVCpu);
8644 AssertRCReturn(rc, rc);
8645 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8646
8647 /* Thread-context hooks are unregistered at this point!!! */
8648 /* Ring-3 callback notifications are unregistered at this point!!! */
8649
8650 /* Sync recompiler state. */
8651 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8652 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8653 | CPUM_CHANGED_LDTR
8654 | CPUM_CHANGED_GDTR
8655 | CPUM_CHANGED_IDTR
8656 | CPUM_CHANGED_TR
8657 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8658 if ( pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging
8659 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8660 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8661
8662 Assert(!pVCpu->hmr0.s.fClearTrapFlag);
8663
8664 /* Update the exit-to-ring 3 reason. */
8665 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8666
8667 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8668 if ( rcExit != VINF_EM_RAW_INTERRUPT
8669 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8670 {
8671 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8672 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8673 }
8674
8675 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8676 VMMRZCallRing3Enable(pVCpu);
8677 return rc;
8678}
8679
8680
8681/**
8682 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8683 * longjump to ring-3 and possibly get preempted.
8684 *
8685 * @returns VBox status code.
8686 * @param pVCpu The cross context virtual CPU structure.
8687 * @param enmOperation The operation causing the ring-3 longjump.
8688 */
8689VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8690{
8691 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8692 {
8693 /*
8694 * !!! IMPORTANT !!!
8695 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8696 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8697 */
8698 VMMRZCallRing3RemoveNotification(pVCpu);
8699 VMMRZCallRing3Disable(pVCpu);
8700 HM_DISABLE_PREEMPT(pVCpu);
8701
8702 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8703 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8704 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8705 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8706
8707 /* Restore host-state bits that VT-x only restores partially. */
8708 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
8709 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
8710 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
8711
8712 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8713 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8714 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8715
8716 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8717 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
8718 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8719
8720 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8721 cleared as part of importing the guest state above. */
8722 hmR0VmxClearVmcs(pVmcsInfo);
8723
8724 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8725 VMMR0ThreadCtxHookDisable(pVCpu);
8726
8727 /* Leave HM context. This takes care of local init (term). */
8728 HMR0LeaveCpu(pVCpu);
8729 HM_RESTORE_PREEMPT();
8730 return VINF_SUCCESS;
8731 }
8732
8733 Assert(pVCpu);
8734 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8735 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8736
8737 VMMRZCallRing3Disable(pVCpu);
8738 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8739
8740 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8741
8742 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8743 AssertRCReturn(rc, rc);
8744
8745 VMMRZCallRing3Enable(pVCpu);
8746 return VINF_SUCCESS;
8747}
8748
8749
8750/**
8751 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8752 * stack.
8753 *
8754 * @returns Strict VBox status code (i.e. informational status codes too).
8755 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8756 * @param pVCpu The cross context virtual CPU structure.
8757 * @param uValue The value to push to the guest stack.
8758 */
8759static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8760{
8761 /*
8762 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8763 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8764 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8765 */
8766 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8767 if (pCtx->sp == 1)
8768 return VINF_EM_RESET;
8769 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8770 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8771 AssertRC(rc);
8772 return rc;
8773}
8774
8775
8776/**
8777 * Injects an event into the guest upon VM-entry by updating the relevant fields
8778 * in the VM-entry area in the VMCS.
8779 *
8780 * @returns Strict VBox status code (i.e. informational status codes too).
8781 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8782 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8783 *
8784 * @param pVCpu The cross context virtual CPU structure.
8785 * @param pVmxTransient The VMX-transient structure.
8786 * @param pEvent The event being injected.
8787 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8788 * will be updated if necessary. This cannot not be NULL.
8789 * @param fStepping Whether we're single-stepping guest execution and should
8790 * return VINF_EM_DBG_STEPPED if the event is injected
8791 * directly (registers modified by us, not by hardware on
8792 * VM-entry).
8793 */
8794static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8795 uint32_t *pfIntrState)
8796{
8797 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8798 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8799 Assert(pfIntrState);
8800
8801 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8802 uint32_t u32IntInfo = pEvent->u64IntInfo;
8803 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8804 uint32_t const cbInstr = pEvent->cbInstr;
8805 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8806 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8807 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8808
8809#ifdef VBOX_STRICT
8810 /*
8811 * Validate the error-code-valid bit for hardware exceptions.
8812 * No error codes for exceptions in real-mode.
8813 *
8814 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8815 */
8816 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8817 && !CPUMIsGuestInRealModeEx(pCtx))
8818 {
8819 switch (uVector)
8820 {
8821 case X86_XCPT_PF:
8822 case X86_XCPT_DF:
8823 case X86_XCPT_TS:
8824 case X86_XCPT_NP:
8825 case X86_XCPT_SS:
8826 case X86_XCPT_GP:
8827 case X86_XCPT_AC:
8828 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8829 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8830 RT_FALL_THRU();
8831 default:
8832 break;
8833 }
8834 }
8835
8836 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8837 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8838 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8839#endif
8840
8841 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8842 || uIntType == VMX_EXIT_INT_INFO_TYPE_NMI
8843 || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT
8844 || uIntType == VMX_EXIT_INT_INFO_TYPE_SW_XCPT)
8845 {
8846 Assert(uVector <= X86_XCPT_LAST);
8847 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_NMI || uVector == X86_XCPT_NMI);
8848 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT || uVector == X86_XCPT_DB);
8849 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedXcptsR0[uVector]);
8850 }
8851 else
8852 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8853
8854 /*
8855 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8856 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8857 * interrupt handler in the (real-mode) guest.
8858 *
8859 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8860 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8861 */
8862 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8863 {
8864 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest)
8865 {
8866 /*
8867 * For CPUs with unrestricted guest execution enabled and with the guest
8868 * in real-mode, we must not set the deliver-error-code bit.
8869 *
8870 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8871 */
8872 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8873 }
8874 else
8875 {
8876 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8877 Assert(PDMVmmDevHeapIsEnabled(pVM));
8878 Assert(pVM->hm.s.vmx.pRealModeTSS);
8879 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8880
8881 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8882 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8883 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8884 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8885 AssertRCReturn(rc2, rc2);
8886
8887 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8888 size_t const cbIdtEntry = sizeof(X86IDTR16);
8889 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8890 {
8891 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8892 if (uVector == X86_XCPT_DF)
8893 return VINF_EM_RESET;
8894
8895 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8896 No error codes for exceptions in real-mode. */
8897 if (uVector == X86_XCPT_GP)
8898 {
8899 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8900 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8901 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8902 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8903 HMEVENT EventXcptDf;
8904 RT_ZERO(EventXcptDf);
8905 EventXcptDf.u64IntInfo = uXcptDfInfo;
8906 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8907 }
8908
8909 /*
8910 * If we're injecting an event with no valid IDT entry, inject a #GP.
8911 * No error codes for exceptions in real-mode.
8912 *
8913 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8914 */
8915 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8916 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8917 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8918 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8919 HMEVENT EventXcptGp;
8920 RT_ZERO(EventXcptGp);
8921 EventXcptGp.u64IntInfo = uXcptGpInfo;
8922 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8923 }
8924
8925 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8926 uint16_t uGuestIp = pCtx->ip;
8927 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8928 {
8929 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8930 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8931 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8932 }
8933 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8934 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8935
8936 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8937 X86IDTR16 IdtEntry;
8938 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8939 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8940 AssertRCReturn(rc2, rc2);
8941
8942 /* Construct the stack frame for the interrupt/exception handler. */
8943 VBOXSTRICTRC rcStrict;
8944 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8945 if (rcStrict == VINF_SUCCESS)
8946 {
8947 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8948 if (rcStrict == VINF_SUCCESS)
8949 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8950 }
8951
8952 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8953 if (rcStrict == VINF_SUCCESS)
8954 {
8955 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8956 pCtx->rip = IdtEntry.offSel;
8957 pCtx->cs.Sel = IdtEntry.uSel;
8958 pCtx->cs.ValidSel = IdtEntry.uSel;
8959 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8960 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8961 && uVector == X86_XCPT_PF)
8962 pCtx->cr2 = GCPtrFault;
8963
8964 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8965 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8966 | HM_CHANGED_GUEST_RSP);
8967
8968 /*
8969 * If we delivered a hardware exception (other than an NMI) and if there was
8970 * block-by-STI in effect, we should clear it.
8971 */
8972 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8973 {
8974 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8975 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8976 Log4Func(("Clearing inhibition due to STI\n"));
8977 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8978 }
8979
8980 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8981 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8982
8983 /*
8984 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8985 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8986 */
8987 pVCpu->hm.s.Event.fPending = false;
8988
8989 /*
8990 * If we eventually support nested-guest execution without unrestricted guest execution,
8991 * we should set fInterceptEvents here.
8992 */
8993 Assert(!pVmxTransient->fIsNestedGuest);
8994
8995 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8996 if (fStepping)
8997 rcStrict = VINF_EM_DBG_STEPPED;
8998 }
8999 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
9000 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
9001 return rcStrict;
9002 }
9003 }
9004
9005 /*
9006 * Validate.
9007 */
9008 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
9009 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
9010
9011 /*
9012 * Inject the event into the VMCS.
9013 */
9014 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
9015 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
9016 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
9017 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
9018 AssertRC(rc);
9019
9020 /*
9021 * Update guest CR2 if this is a page-fault.
9022 */
9023 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
9024 pCtx->cr2 = GCPtrFault;
9025
9026 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
9027 return VINF_SUCCESS;
9028}
9029
9030
9031/**
9032 * Evaluates the event to be delivered to the guest and sets it as the pending
9033 * event.
9034 *
9035 * Toggling of interrupt force-flags here is safe since we update TRPM on premature
9036 * exits to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must
9037 * NOT restore these force-flags.
9038 *
9039 * @returns Strict VBox status code (i.e. informational status codes too).
9040 * @param pVCpu The cross context virtual CPU structure.
9041 * @param pVmxTransient The VMX-transient structure.
9042 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
9043 */
9044static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
9045{
9046 Assert(pfIntrState);
9047 Assert(!TRPMHasTrap(pVCpu));
9048
9049 /*
9050 * Compute/update guest-interruptibility state related FFs.
9051 * The FFs will be used below while evaluating events to be injected.
9052 */
9053 *pfIntrState = hmR0VmxGetGuestIntrStateAndUpdateFFs(pVCpu);
9054
9055 /*
9056 * Evaluate if a new event needs to be injected.
9057 * An event that's already pending has already performed all necessary checks.
9058 */
9059 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9060 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
9061 if ( !pVCpu->hm.s.Event.fPending
9062 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
9063 {
9064 /** @todo SMI. SMIs take priority over NMIs. */
9065
9066 /*
9067 * NMIs.
9068 * NMIs take priority over external interrupts.
9069 */
9070 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9071 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
9072 {
9073 /*
9074 * For a guest, the FF always indicates the guest's ability to receive an NMI.
9075 *
9076 * For a nested-guest, the FF always indicates the outer guest's ability to
9077 * receive an NMI while the guest-interruptibility state bit depends on whether
9078 * the nested-hypervisor is using virtual-NMIs.
9079 */
9080 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
9081 {
9082#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9083 if ( fIsNestedGuest
9084 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_NMI_EXIT))
9085 return IEMExecVmxVmexitXcptNmi(pVCpu);
9086#endif
9087 hmR0VmxSetPendingXcptNmi(pVCpu);
9088 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
9089 Log4Func(("NMI pending injection\n"));
9090
9091 /* We've injected the NMI, bail. */
9092 return VINF_SUCCESS;
9093 }
9094 else if (!fIsNestedGuest)
9095 hmR0VmxSetNmiWindowExitVmcs(pVmcsInfo);
9096 }
9097
9098 /*
9099 * External interrupts (PIC/APIC).
9100 * Once PDMGetInterrupt() returns a valid interrupt we -must- deliver it.
9101 * We cannot re-request the interrupt from the controller again.
9102 */
9103 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9104 && !pVCpu->hm.s.fSingleInstruction)
9105 {
9106 Assert(!DBGFIsStepping(pVCpu));
9107 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
9108 AssertRC(rc);
9109
9110 /*
9111 * We must not check EFLAGS directly when executing a nested-guest, use
9112 * CPUMIsGuestPhysIntrEnabled() instead as EFLAGS.IF does not control the blocking of
9113 * external interrupts when "External interrupt exiting" is set. This fixes a nasty
9114 * SMP hang while executing nested-guest VCPUs on spinlocks which aren't rescued by
9115 * other VM-exits (like a preemption timer), see @bugref{9562#c18}.
9116 *
9117 * See Intel spec. 25.4.1 "Event Blocking".
9118 */
9119 if (CPUMIsGuestPhysIntrEnabled(pVCpu))
9120 {
9121#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9122 if ( fIsNestedGuest
9123 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9124 {
9125 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
9126 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9127 return rcStrict;
9128 }
9129#endif
9130 uint8_t u8Interrupt;
9131 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9132 if (RT_SUCCESS(rc))
9133 {
9134#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9135 if ( fIsNestedGuest
9136 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9137 {
9138 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9139 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
9140 return rcStrict;
9141 }
9142#endif
9143 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9144 Log4Func(("External interrupt (%#x) pending injection\n", u8Interrupt));
9145 }
9146 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9147 {
9148 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9149
9150 if ( !fIsNestedGuest
9151 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9152 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
9153 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
9154
9155 /*
9156 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9157 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9158 * need to re-set this force-flag here.
9159 */
9160 }
9161 else
9162 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9163
9164 /* We've injected the interrupt or taken necessary action, bail. */
9165 return VINF_SUCCESS;
9166 }
9167 if (!fIsNestedGuest)
9168 hmR0VmxSetIntWindowExitVmcs(pVmcsInfo);
9169 }
9170 }
9171 else if (!fIsNestedGuest)
9172 {
9173 /*
9174 * An event is being injected or we are in an interrupt shadow. Check if another event is
9175 * pending. If so, instruct VT-x to cause a VM-exit as soon as the guest is ready to accept
9176 * the pending event.
9177 */
9178 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
9179 hmR0VmxSetNmiWindowExitVmcs(pVmcsInfo);
9180 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9181 && !pVCpu->hm.s.fSingleInstruction)
9182 hmR0VmxSetIntWindowExitVmcs(pVmcsInfo);
9183 }
9184 /* else: for nested-guests, NMI/interrupt-window exiting will be picked up when merging VMCS controls. */
9185
9186 return VINF_SUCCESS;
9187}
9188
9189
9190/**
9191 * Injects any pending events into the guest if the guest is in a state to
9192 * receive them.
9193 *
9194 * @returns Strict VBox status code (i.e. informational status codes too).
9195 * @param pVCpu The cross context virtual CPU structure.
9196 * @param pVmxTransient The VMX-transient structure.
9197 * @param fIntrState The VT-x guest-interruptibility state.
9198 * @param fStepping Whether we are single-stepping the guest using the
9199 * hypervisor debugger and should return
9200 * VINF_EM_DBG_STEPPED if the event was dispatched
9201 * directly.
9202 */
9203static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9204{
9205 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9206 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9207
9208#ifdef VBOX_STRICT
9209 /*
9210 * Verify guest-interruptibility state.
9211 *
9212 * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
9213 * since injecting an event may modify the interruptibility state and we must thus always
9214 * use fIntrState.
9215 */
9216 {
9217 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9218 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9219 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9220 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9221 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9222 Assert(!TRPMHasTrap(pVCpu));
9223 NOREF(fBlockMovSS); NOREF(fBlockSti);
9224 }
9225#endif
9226
9227 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9228 if (pVCpu->hm.s.Event.fPending)
9229 {
9230 /*
9231 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9232 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9233 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9234 *
9235 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9236 */
9237 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9238#ifdef VBOX_STRICT
9239 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9240 {
9241 Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9242 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9243 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9244 }
9245 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9246 {
9247 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
9248 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9249 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9250 }
9251#endif
9252 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9253 uIntType));
9254
9255 /*
9256 * Inject the event and get any changes to the guest-interruptibility state.
9257 *
9258 * The guest-interruptibility state may need to be updated if we inject the event
9259 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9260 */
9261 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9262 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9263
9264 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9265 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9266 else
9267 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9268 }
9269
9270 /*
9271 * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
9272 * is an interrupt shadow (block-by-STI or block-by-MOV SS).
9273 */
9274 if ( (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9275 && !pVmxTransient->fIsNestedGuest)
9276 {
9277 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
9278
9279 if (!pVCpu->hm.s.fSingleInstruction)
9280 {
9281 /*
9282 * Set or clear the BS bit depending on whether the trap flag is active or not. We need
9283 * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
9284 */
9285 Assert(!DBGFIsStepping(pVCpu));
9286 uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
9287 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
9288 AssertRC(rc);
9289 }
9290 else
9291 {
9292 /*
9293 * We must not deliver a debug exception when single-stepping over STI/Mov-SS in the
9294 * hypervisor debugger using EFLAGS.TF but rather clear interrupt inhibition. However,
9295 * we take care of this case in hmR0VmxExportSharedDebugState and also the case if
9296 * we use MTF, so just make sure it's called before executing guest-code.
9297 */
9298 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR_MASK);
9299 }
9300 }
9301 /* else: for nested-guest currently handling while merging controls. */
9302
9303 /*
9304 * Finally, update the guest-interruptibility state.
9305 *
9306 * This is required for the real-on-v86 software interrupt injection, for
9307 * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
9308 */
9309 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9310 AssertRC(rc);
9311
9312 /*
9313 * There's no need to clear the VM-entry interruption-information field here if we're not
9314 * injecting anything. VT-x clears the valid bit on every VM-exit.
9315 *
9316 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9317 */
9318
9319 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9320 return rcStrict;
9321}
9322
9323
9324/**
9325 * Enters the VT-x session.
9326 *
9327 * @returns VBox status code.
9328 * @param pVCpu The cross context virtual CPU structure.
9329 */
9330VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
9331{
9332 AssertPtr(pVCpu);
9333 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9334 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9335
9336 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9337 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9338 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9339
9340#ifdef VBOX_STRICT
9341 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9342 RTCCUINTREG uHostCr4 = ASMGetCR4();
9343 if (!(uHostCr4 & X86_CR4_VMXE))
9344 {
9345 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9346 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9347 }
9348#endif
9349
9350 /*
9351 * Do the EMT scheduled L1D and MDS flush here if needed.
9352 */
9353 if (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_L1D_SCHED)
9354 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9355 else if (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_MDS_SCHED)
9356 hmR0MdsClear();
9357
9358 /*
9359 * Load the appropriate VMCS as the current and active one.
9360 */
9361 PVMXVMCSINFO pVmcsInfo;
9362 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9363 if (!fInNestedGuestMode)
9364 pVmcsInfo = &pVCpu->hmr0.s.vmx.VmcsInfo;
9365 else
9366 pVmcsInfo = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
9367 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9368 if (RT_SUCCESS(rc))
9369 {
9370 pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9371 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcsCopyForRing3 = fInNestedGuestMode;
9372 pVCpu->hmr0.s.fLeaveDone = false;
9373 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9374 }
9375 return rc;
9376}
9377
9378
9379/**
9380 * The thread-context callback.
9381 *
9382 * This is used together with RTThreadCtxHookCreate() on platforms which
9383 * supports it, and directly from VMMR0EmtPrepareForBlocking() and
9384 * VMMR0EmtResumeAfterBlocking() on platforms which don't.
9385 *
9386 * @param enmEvent The thread-context event.
9387 * @param pVCpu The cross context virtual CPU structure.
9388 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9389 * @thread EMT(pVCpu)
9390 */
9391VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
9392{
9393 AssertPtr(pVCpu);
9394 RT_NOREF1(fGlobalInit);
9395
9396 switch (enmEvent)
9397 {
9398 case RTTHREADCTXEVENT_OUT:
9399 {
9400 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9401 VMCPU_ASSERT_EMT(pVCpu);
9402
9403 /* No longjmps (logger flushes, locks) in this fragile context. */
9404 VMMRZCallRing3Disable(pVCpu);
9405 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9406
9407 /* Restore host-state (FPU, debug etc.) */
9408 if (!pVCpu->hmr0.s.fLeaveDone)
9409 {
9410 /*
9411 * Do -not- import the guest-state here as we might already be in the middle of importing
9412 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9413 */
9414 hmR0VmxLeave(pVCpu, false /* fImportState */);
9415 pVCpu->hmr0.s.fLeaveDone = true;
9416 }
9417
9418 /* Leave HM context, takes care of local init (term). */
9419 int rc = HMR0LeaveCpu(pVCpu);
9420 AssertRC(rc);
9421
9422 /* Restore longjmp state. */
9423 VMMRZCallRing3Enable(pVCpu);
9424 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9425 break;
9426 }
9427
9428 case RTTHREADCTXEVENT_IN:
9429 {
9430 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9431 VMCPU_ASSERT_EMT(pVCpu);
9432
9433 /* Do the EMT scheduled L1D and MDS flush here if needed. */
9434 if (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_L1D_SCHED)
9435 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9436 else if (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_MDS_SCHED)
9437 hmR0MdsClear();
9438
9439 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9440 VMMRZCallRing3Disable(pVCpu);
9441 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9442
9443 /* Initialize the bare minimum state required for HM. This takes care of
9444 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9445 int rc = hmR0EnterCpu(pVCpu);
9446 AssertRC(rc);
9447 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9448 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9449
9450 /* Load the active VMCS as the current one. */
9451 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9452 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9453 AssertRC(rc);
9454 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9455 pVCpu->hmr0.s.fLeaveDone = false;
9456
9457 /* Restore longjmp state. */
9458 VMMRZCallRing3Enable(pVCpu);
9459 break;
9460 }
9461
9462 default:
9463 break;
9464 }
9465}
9466
9467
9468/**
9469 * Exports the host state into the VMCS host-state area.
9470 * Sets up the VM-exit MSR-load area.
9471 *
9472 * The CPU state will be loaded from these fields on every successful VM-exit.
9473 *
9474 * @returns VBox status code.
9475 * @param pVCpu The cross context virtual CPU structure.
9476 *
9477 * @remarks No-long-jump zone!!!
9478 */
9479static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
9480{
9481 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9482
9483 int rc = VINF_SUCCESS;
9484 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9485 {
9486 uint64_t uHostCr4 = hmR0VmxExportHostControlRegs();
9487
9488 rc = hmR0VmxExportHostSegmentRegs(pVCpu, uHostCr4);
9489 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9490
9491 hmR0VmxExportHostMsrs(pVCpu);
9492
9493 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9494 }
9495 return rc;
9496}
9497
9498
9499/**
9500 * Saves the host state in the VMCS host-state.
9501 *
9502 * @returns VBox status code.
9503 * @param pVCpu The cross context virtual CPU structure.
9504 *
9505 * @remarks No-long-jump zone!!!
9506 */
9507VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
9508{
9509 AssertPtr(pVCpu);
9510 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9511
9512 /*
9513 * Export the host state here while entering HM context.
9514 * When thread-context hooks are used, we might get preempted and have to re-save the host
9515 * state but most of the time we won't be, so do it here before we disable interrupts.
9516 */
9517 return hmR0VmxExportHostState(pVCpu);
9518}
9519
9520
9521/**
9522 * Exports the guest state into the VMCS guest-state area.
9523 *
9524 * The will typically be done before VM-entry when the guest-CPU state and the
9525 * VMCS state may potentially be out of sync.
9526 *
9527 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9528 * VM-entry controls.
9529 * Sets up the appropriate VMX non-root function to execute guest code based on
9530 * the guest CPU mode.
9531 *
9532 * @returns VBox strict status code.
9533 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9534 * without unrestricted guest execution and the VMMDev is not presently
9535 * mapped (e.g. EFI32).
9536 *
9537 * @param pVCpu The cross context virtual CPU structure.
9538 * @param pVmxTransient The VMX-transient structure.
9539 *
9540 * @remarks No-long-jump zone!!!
9541 */
9542static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9543{
9544 AssertPtr(pVCpu);
9545 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9546 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9547
9548 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9549
9550 /*
9551 * Determine real-on-v86 mode.
9552 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9553 */
9554 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmxTransient->pVmcsInfo->pShared;
9555 if ( pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest
9556 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9557 pVmcsInfoShared->RealMode.fRealOnV86Active = false;
9558 else
9559 {
9560 Assert(!pVmxTransient->fIsNestedGuest);
9561 pVmcsInfoShared->RealMode.fRealOnV86Active = true;
9562 }
9563
9564 /*
9565 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9566 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9567 */
9568 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9569 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9570
9571 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9572 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9573
9574 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9575 if (rcStrict == VINF_SUCCESS)
9576 { /* likely */ }
9577 else
9578 {
9579 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9580 return rcStrict;
9581 }
9582
9583 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9584 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9585
9586 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9587 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9588
9589 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9590 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9591 hmR0VmxExportGuestRip(pVCpu);
9592 hmR0VmxExportGuestRsp(pVCpu);
9593 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9594
9595 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9596 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9597
9598 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9599 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9600 | HM_CHANGED_GUEST_CR2
9601 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9602 | HM_CHANGED_GUEST_X87
9603 | HM_CHANGED_GUEST_SSE_AVX
9604 | HM_CHANGED_GUEST_OTHER_XSAVE
9605 | HM_CHANGED_GUEST_XCRx
9606 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9607 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9608 | HM_CHANGED_GUEST_TSC_AUX
9609 | HM_CHANGED_GUEST_OTHER_MSRS
9610 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9611
9612 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9613 return rc;
9614}
9615
9616
9617/**
9618 * Exports the state shared between the host and guest into the VMCS.
9619 *
9620 * @param pVCpu The cross context virtual CPU structure.
9621 * @param pVmxTransient The VMX-transient structure.
9622 *
9623 * @remarks No-long-jump zone!!!
9624 */
9625static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9626{
9627 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9628 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9629
9630 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9631 {
9632 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9633 AssertRC(rc);
9634 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9635
9636 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9637 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9638 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9639 }
9640
9641 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9642 {
9643 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9644 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9645 }
9646
9647 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9648 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9649}
9650
9651
9652/**
9653 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9654 *
9655 * @returns Strict VBox status code (i.e. informational status codes too).
9656 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9657 * without unrestricted guest execution and the VMMDev is not presently
9658 * mapped (e.g. EFI32).
9659 *
9660 * @param pVCpu The cross context virtual CPU structure.
9661 * @param pVmxTransient The VMX-transient structure.
9662 *
9663 * @remarks No-long-jump zone!!!
9664 */
9665static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9666{
9667 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9668 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9669 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9670
9671#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9672 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9673#endif
9674
9675 /*
9676 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9677 * changes. First try to export only these without going through all other changed-flag checks.
9678 */
9679 VBOXSTRICTRC rcStrict;
9680 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9681 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9682 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9683
9684 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9685 if ( (fCtxChanged & fMinimalMask)
9686 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9687 {
9688 hmR0VmxExportGuestRip(pVCpu);
9689 hmR0VmxExportGuestRsp(pVCpu);
9690 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9691 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9692 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9693 }
9694 /* If anything else also changed, go through the full export routine and export as required. */
9695 else if (fCtxChanged & fCtxMask)
9696 {
9697 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9698 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9699 { /* likely */}
9700 else
9701 {
9702 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9703 VBOXSTRICTRC_VAL(rcStrict)));
9704 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9705 return rcStrict;
9706 }
9707 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9708 }
9709 /* Nothing changed, nothing to load here. */
9710 else
9711 rcStrict = VINF_SUCCESS;
9712
9713#ifdef VBOX_STRICT
9714 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9715 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9716 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9717#endif
9718 return rcStrict;
9719}
9720
9721
9722/**
9723 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9724 * and update error record fields accordingly.
9725 *
9726 * @returns VMX_IGS_* error codes.
9727 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9728 * wrong with the guest state.
9729 *
9730 * @param pVCpu The cross context virtual CPU structure.
9731 * @param pVmcsInfo The VMCS info. object.
9732 *
9733 * @remarks This function assumes our cache of the VMCS controls
9734 * are valid, i.e. hmR0VmxCheckCachedVmcsCtls() succeeded.
9735 */
9736static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9737{
9738#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9739#define HMVMX_CHECK_BREAK(expr, err) do { \
9740 if (!(expr)) { uError = (err); break; } \
9741 } while (0)
9742
9743 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9744 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9745 uint32_t uError = VMX_IGS_ERROR;
9746 uint32_t u32IntrState = 0;
9747 bool const fUnrestrictedGuest = pVM->hmr0.s.vmx.fUnrestrictedGuest;
9748 do
9749 {
9750 int rc;
9751
9752 /*
9753 * Guest-interruptibility state.
9754 *
9755 * Read this first so that any check that fails prior to those that actually
9756 * require the guest-interruptibility state would still reflect the correct
9757 * VMCS value and avoids causing further confusion.
9758 */
9759 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9760 AssertRC(rc);
9761
9762 uint32_t u32Val;
9763 uint64_t u64Val;
9764
9765 /*
9766 * CR0.
9767 */
9768 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9769 uint64_t fSetCr0 = (g_HmMsrs.u.vmx.u64Cr0Fixed0 & g_HmMsrs.u.vmx.u64Cr0Fixed1);
9770 uint64_t const fZapCr0 = (g_HmMsrs.u.vmx.u64Cr0Fixed0 | g_HmMsrs.u.vmx.u64Cr0Fixed1);
9771 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9772 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9773 if (fUnrestrictedGuest)
9774 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9775
9776 uint64_t u64GuestCr0;
9777 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9778 AssertRC(rc);
9779 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9780 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9781 if ( !fUnrestrictedGuest
9782 && (u64GuestCr0 & X86_CR0_PG)
9783 && !(u64GuestCr0 & X86_CR0_PE))
9784 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9785
9786 /*
9787 * CR4.
9788 */
9789 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9790 uint64_t const fSetCr4 = (g_HmMsrs.u.vmx.u64Cr4Fixed0 & g_HmMsrs.u.vmx.u64Cr4Fixed1);
9791 uint64_t const fZapCr4 = (g_HmMsrs.u.vmx.u64Cr4Fixed0 | g_HmMsrs.u.vmx.u64Cr4Fixed1);
9792
9793 uint64_t u64GuestCr4;
9794 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9795 AssertRC(rc);
9796 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9797 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9798
9799 /*
9800 * IA32_DEBUGCTL MSR.
9801 */
9802 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9803 AssertRC(rc);
9804 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9805 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9806 {
9807 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9808 }
9809 uint64_t u64DebugCtlMsr = u64Val;
9810
9811#ifdef VBOX_STRICT
9812 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9813 AssertRC(rc);
9814 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9815#endif
9816 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9817
9818 /*
9819 * RIP and RFLAGS.
9820 */
9821 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9822 AssertRC(rc);
9823 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9824 if ( !fLongModeGuest
9825 || !pCtx->cs.Attr.n.u1Long)
9826 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9827 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9828 * must be identical if the "IA-32e mode guest" VM-entry
9829 * control is 1 and CS.L is 1. No check applies if the
9830 * CPU supports 64 linear-address bits. */
9831
9832 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9833 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9834 AssertRC(rc);
9835 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9836 VMX_IGS_RFLAGS_RESERVED);
9837 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9838 uint32_t const u32Eflags = u64Val;
9839
9840 if ( fLongModeGuest
9841 || ( fUnrestrictedGuest
9842 && !(u64GuestCr0 & X86_CR0_PE)))
9843 {
9844 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9845 }
9846
9847 uint32_t u32EntryInfo;
9848 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9849 AssertRC(rc);
9850 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9851 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9852
9853 /*
9854 * 64-bit checks.
9855 */
9856 if (fLongModeGuest)
9857 {
9858 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9859 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9860 }
9861
9862 if ( !fLongModeGuest
9863 && (u64GuestCr4 & X86_CR4_PCIDE))
9864 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9865
9866 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9867 * 51:32 beyond the processor's physical-address width are 0. */
9868
9869 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9870 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9871 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9872
9873 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9874 AssertRC(rc);
9875 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9876
9877 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9878 AssertRC(rc);
9879 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9880
9881 /*
9882 * PERF_GLOBAL MSR.
9883 */
9884 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9885 {
9886 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9887 AssertRC(rc);
9888 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9889 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9890 }
9891
9892 /*
9893 * PAT MSR.
9894 */
9895 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9896 {
9897 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9898 AssertRC(rc);
9899 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9900 for (unsigned i = 0; i < 8; i++)
9901 {
9902 uint8_t u8Val = (u64Val & 0xff);
9903 if ( u8Val != 0 /* UC */
9904 && u8Val != 1 /* WC */
9905 && u8Val != 4 /* WT */
9906 && u8Val != 5 /* WP */
9907 && u8Val != 6 /* WB */
9908 && u8Val != 7 /* UC- */)
9909 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9910 u64Val >>= 8;
9911 }
9912 }
9913
9914 /*
9915 * EFER MSR.
9916 */
9917 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9918 {
9919 Assert(g_fHmVmxSupportsVmcsEfer);
9920 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9921 AssertRC(rc);
9922 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9923 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9924 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9925 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9926 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9927 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9928 * iemVmxVmentryCheckGuestState(). */
9929 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9930 || !(u64GuestCr0 & X86_CR0_PG)
9931 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9932 VMX_IGS_EFER_LMA_LME_MISMATCH);
9933 }
9934
9935 /*
9936 * Segment registers.
9937 */
9938 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9939 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9940 if (!(u32Eflags & X86_EFL_VM))
9941 {
9942 /* CS */
9943 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9944 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9945 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9946 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9947 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9948 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9949 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9950 /* CS cannot be loaded with NULL in protected mode. */
9951 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9952 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9953 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9954 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9955 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9956 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9957 else if (fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9958 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9959 else
9960 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9961
9962 /* SS */
9963 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9964 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9965 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9966 if ( !(pCtx->cr0 & X86_CR0_PE)
9967 || pCtx->cs.Attr.n.u4Type == 3)
9968 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9969
9970 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9971 {
9972 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9973 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9974 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9975 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9976 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9977 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9978 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9979 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9980 }
9981
9982 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9983 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9984 {
9985 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9986 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9987 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9988 || pCtx->ds.Attr.n.u4Type > 11
9989 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9990 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9991 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9992 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9993 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9994 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9995 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9996 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9997 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9998 }
9999 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
10000 {
10001 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
10002 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
10003 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10004 || pCtx->es.Attr.n.u4Type > 11
10005 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10006 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
10007 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
10008 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
10009 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10010 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
10011 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10012 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10013 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
10014 }
10015 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
10016 {
10017 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
10018 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
10019 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10020 || pCtx->fs.Attr.n.u4Type > 11
10021 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
10022 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
10023 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
10024 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
10025 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10026 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
10027 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10028 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10029 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
10030 }
10031 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
10032 {
10033 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
10034 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
10035 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10036 || pCtx->gs.Attr.n.u4Type > 11
10037 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
10038 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
10039 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
10040 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
10041 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10042 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
10043 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10044 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10045 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
10046 }
10047 /* 64-bit capable CPUs. */
10048 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10049 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10050 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10051 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10052 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10053 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10054 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10055 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10056 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10057 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10058 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10059 }
10060 else
10061 {
10062 /* V86 mode checks. */
10063 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
10064 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
10065 {
10066 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
10067 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
10068 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
10069 }
10070 else
10071 {
10072 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
10073 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
10074 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
10075 }
10076
10077 /* CS */
10078 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10079 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10080 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10081 /* SS */
10082 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10083 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10084 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10085 /* DS */
10086 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10087 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10088 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10089 /* ES */
10090 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10091 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10092 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10093 /* FS */
10094 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10095 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10096 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10097 /* GS */
10098 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10099 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10100 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10101 /* 64-bit capable CPUs. */
10102 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10103 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10104 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10105 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10106 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10107 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10108 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10109 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10110 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10111 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10112 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10113 }
10114
10115 /*
10116 * TR.
10117 */
10118 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10119 /* 64-bit capable CPUs. */
10120 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10121 if (fLongModeGuest)
10122 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10123 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10124 else
10125 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10126 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10127 VMX_IGS_TR_ATTR_TYPE_INVALID);
10128 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10129 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10130 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10131 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10132 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10133 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10134 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10135 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10136
10137 /*
10138 * GDTR and IDTR (64-bit capable checks).
10139 */
10140 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10141 AssertRC(rc);
10142 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10143
10144 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10145 AssertRC(rc);
10146 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10147
10148 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10149 AssertRC(rc);
10150 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10151
10152 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10153 AssertRC(rc);
10154 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10155
10156 /*
10157 * Guest Non-Register State.
10158 */
10159 /* Activity State. */
10160 uint32_t u32ActivityState;
10161 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10162 AssertRC(rc);
10163 HMVMX_CHECK_BREAK( !u32ActivityState
10164 || (u32ActivityState & RT_BF_GET(g_HmMsrs.u.vmx.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10165 VMX_IGS_ACTIVITY_STATE_INVALID);
10166 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10167 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10168
10169 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10170 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10171 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10172
10173 /** @todo Activity state and injecting interrupts. Left as a todo since we
10174 * currently don't use activity states but ACTIVE. */
10175
10176 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10177 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10178
10179 /* Guest interruptibility-state. */
10180 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10181 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10182 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10183 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10184 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10185 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10186 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10187 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10188 {
10189 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10190 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10191 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10192 }
10193 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10194 {
10195 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10196 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10197 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10198 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10199 }
10200 /** @todo Assumes the processor is not in SMM. */
10201 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10202 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10203 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10204 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10205 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10206 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10207 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10208 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10209
10210 /* Pending debug exceptions. */
10211 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10212 AssertRC(rc);
10213 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10214 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10215 u32Val = u64Val; /* For pending debug exceptions checks below. */
10216
10217 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10218 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10219 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10220 {
10221 if ( (u32Eflags & X86_EFL_TF)
10222 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10223 {
10224 /* Bit 14 is PendingDebug.BS. */
10225 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10226 }
10227 if ( !(u32Eflags & X86_EFL_TF)
10228 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10229 {
10230 /* Bit 14 is PendingDebug.BS. */
10231 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10232 }
10233 }
10234
10235 /* VMCS link pointer. */
10236 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10237 AssertRC(rc);
10238 if (u64Val != UINT64_C(0xffffffffffffffff))
10239 {
10240 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10241 /** @todo Bits beyond the processor's physical-address width MBZ. */
10242 /** @todo SMM checks. */
10243 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10244 Assert(pVmcsInfo->pvShadowVmcs);
10245 VMXVMCSREVID VmcsRevId;
10246 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10247 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID),
10248 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10249 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10250 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10251 }
10252
10253 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10254 * not using nested paging? */
10255 if ( pVM->hmr0.s.fNestedPaging
10256 && !fLongModeGuest
10257 && CPUMIsGuestInPAEModeEx(pCtx))
10258 {
10259 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10260 AssertRC(rc);
10261 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10262
10263 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10264 AssertRC(rc);
10265 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10266
10267 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10268 AssertRC(rc);
10269 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10270
10271 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10272 AssertRC(rc);
10273 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10274 }
10275
10276 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10277 if (uError == VMX_IGS_ERROR)
10278 uError = VMX_IGS_REASON_NOT_FOUND;
10279 } while (0);
10280
10281 pVCpu->hm.s.u32HMError = uError;
10282 pVCpu->hm.s.vmx.LastError.u32GuestIntrState = u32IntrState;
10283 return uError;
10284
10285#undef HMVMX_ERROR_BREAK
10286#undef HMVMX_CHECK_BREAK
10287}
10288
10289
10290/**
10291 * Map the APIC-access page for virtualizing APIC accesses.
10292 *
10293 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10294 * this not done as part of exporting guest state, see @bugref{8721}.
10295 *
10296 * @returns VBox status code.
10297 * @param pVCpu The cross context virtual CPU structure.
10298 */
10299static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
10300{
10301 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10302 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10303
10304 Assert(PDMHasApic(pVM));
10305 Assert(u64MsrApicBase);
10306
10307 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10308 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10309
10310 /* Unalias the existing mapping. */
10311 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10312 AssertRCReturn(rc, rc);
10313
10314 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10315 Assert(pVM->hmr0.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10316 rc = IOMR0MmioMapMmioHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hmr0.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10317 AssertRCReturn(rc, rc);
10318
10319 /* Update the per-VCPU cache of the APIC base MSR. */
10320 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10321 return VINF_SUCCESS;
10322}
10323
10324
10325/**
10326 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10327 * CPU.
10328 *
10329 * @param idCpu The ID for the CPU the function is called on.
10330 * @param pvUser1 Null, not used.
10331 * @param pvUser2 Null, not used.
10332 */
10333static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10334{
10335 RT_NOREF3(idCpu, pvUser1, pvUser2);
10336 VMXDispatchHostNmi();
10337}
10338
10339
10340/**
10341 * Dispatching an NMI on the host CPU that received it.
10342 *
10343 * @returns VBox status code.
10344 * @param pVCpu The cross context virtual CPU structure.
10345 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10346 * executing when receiving the host NMI in VMX non-root
10347 * operation.
10348 */
10349static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
10350{
10351 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
10352 Assert(idCpu != NIL_RTCPUID);
10353
10354 /*
10355 * We don't want to delay dispatching the NMI any more than we have to. However,
10356 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10357 * after executing guest or nested-guest code for the following reasons:
10358 *
10359 * - We would need to perform VMREADs with interrupts disabled and is orders of
10360 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
10361 * supported by the host hypervisor.
10362 *
10363 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10364 * longer period of time just for handling an edge case like host NMIs which do
10365 * not occur nearly as frequently as other VM-exits.
10366 *
10367 * Let's cover the most likely scenario first. Check if we are on the target CPU
10368 * and dispatch the NMI right away. This should be much faster than calling into
10369 * RTMpOnSpecific() machinery.
10370 */
10371 bool fDispatched = false;
10372 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10373 if (idCpu == RTMpCpuId())
10374 {
10375 VMXDispatchHostNmi();
10376 fDispatched = true;
10377 }
10378 ASMSetFlags(fEFlags);
10379 if (fDispatched)
10380 {
10381 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10382 return VINF_SUCCESS;
10383 }
10384
10385 /*
10386 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10387 * there should be no race or recursion even if we are unlucky enough to be preempted
10388 * (to the target CPU) without dispatching the host NMI above.
10389 */
10390 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10391 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10392}
10393
10394
10395#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10396/**
10397 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10398 * nested-guest using hardware-assisted VMX.
10399 *
10400 * @param pVCpu The cross context virtual CPU structure.
10401 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10402 * @param pVmcsInfoGst The guest VMCS info. object.
10403 */
10404static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10405{
10406 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10407 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10408 Assert(pu64MsrBitmap);
10409
10410 /*
10411 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10412 * MSR that is intercepted by the guest is also intercepted while executing the
10413 * nested-guest using hardware-assisted VMX.
10414 *
10415 * Note! If the nested-guest is not using an MSR bitmap, every MSR must cause a
10416 * nested-guest VM-exit even if the outer guest is not intercepting some
10417 * MSRs. We cannot assume the caller has initialized the nested-guest
10418 * MSR bitmap in this case.
10419 *
10420 * The nested hypervisor may also switch whether it uses MSR bitmaps for
10421 * each of its VM-entry, hence initializing it once per-VM while setting
10422 * up the nested-guest VMCS is not sufficient.
10423 */
10424 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10425 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10426 {
10427 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10428 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10429 Assert(pu64MsrBitmapNstGst);
10430 Assert(pu64MsrBitmapGst);
10431
10432 /** @todo Detect and use EVEX.POR? */
10433 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10434 for (uint32_t i = 0; i < cFrags; i++)
10435 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10436 }
10437 else
10438 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10439}
10440
10441
10442/**
10443 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10444 * hardware-assisted VMX execution of the nested-guest.
10445 *
10446 * For a guest, we don't modify these controls once we set up the VMCS and hence
10447 * this function is never called.
10448 *
10449 * For nested-guests since the nested hypervisor provides these controls on every
10450 * nested-guest VM-entry and could potentially change them everytime we need to
10451 * merge them before every nested-guest VM-entry.
10452 *
10453 * @returns VBox status code.
10454 * @param pVCpu The cross context virtual CPU structure.
10455 */
10456static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
10457{
10458 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10459 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
10460 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10461 Assert(pVmcsNstGst);
10462
10463 /*
10464 * Merge the controls with the requirements of the guest VMCS.
10465 *
10466 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10467 * VMCS with the features supported by the physical CPU as it's already done by the
10468 * VMLAUNCH/VMRESUME instruction emulation.
10469 *
10470 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10471 * derived from the VMX features supported by the physical CPU.
10472 */
10473
10474 /* Pin-based VM-execution controls. */
10475 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10476
10477 /* Processor-based VM-execution controls. */
10478 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10479 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10480 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10481 | VMX_PROC_CTLS_MOV_DR_EXIT
10482 | VMX_PROC_CTLS_USE_TPR_SHADOW
10483 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10484
10485 /* Secondary processor-based VM-execution controls. */
10486 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10487 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10488 | VMX_PROC_CTLS2_INVPCID
10489 | VMX_PROC_CTLS2_VMCS_SHADOWING
10490 | VMX_PROC_CTLS2_RDTSCP
10491 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10492 | VMX_PROC_CTLS2_APIC_REG_VIRT
10493 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10494 | VMX_PROC_CTLS2_VMFUNC));
10495
10496 /*
10497 * VM-entry controls:
10498 * These controls contains state that depends on the nested-guest state (primarily
10499 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10500 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
10501 * properly continue executing the nested-guest if the EFER MSR changes but does not
10502 * cause a nested-guest VM-exits.
10503 *
10504 * VM-exit controls:
10505 * These controls specify the host state on return. We cannot use the controls from
10506 * the nested hypervisor state as is as it would contain the guest state rather than
10507 * the host state. Since the host state is subject to change (e.g. preemption, trips
10508 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10509 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10510 *
10511 * VM-entry MSR-load:
10512 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10513 * context by the VMLAUNCH/VMRESUME instruction emulation.
10514 *
10515 * VM-exit MSR-store:
10516 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10517 * back into the VM-exit MSR-store area.
10518 *
10519 * VM-exit MSR-load areas:
10520 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10521 * can entirely ignore what the nested hypervisor wants to load here.
10522 */
10523
10524 /*
10525 * Exception bitmap.
10526 *
10527 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10528 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10529 * code more flexible if intercepting exceptions become more dynamic in the future we do
10530 * it as part of exporting the nested-guest state.
10531 */
10532 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10533
10534 /*
10535 * CR0/CR4 guest/host mask.
10536 *
10537 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10538 * cause VM-exits, so we need to merge them here.
10539 */
10540 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10541 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10542
10543 /*
10544 * Page-fault error-code mask and match.
10545 *
10546 * Although we require unrestricted guest execution (and thereby nested-paging) for
10547 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10548 * normally intercept #PFs, it might intercept them for debugging purposes.
10549 *
10550 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10551 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10552 */
10553 uint32_t u32XcptPFMask;
10554 uint32_t u32XcptPFMatch;
10555 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10556 {
10557 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10558 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10559 }
10560 else
10561 {
10562 u32XcptPFMask = 0;
10563 u32XcptPFMatch = 0;
10564 }
10565
10566 /*
10567 * Pause-Loop exiting.
10568 */
10569 /** @todo r=bird: given that both pVM->hm.s.vmx.cPleGapTicks and
10570 * pVM->hm.s.vmx.cPleWindowTicks defaults to zero, I cannot see how
10571 * this will work... */
10572 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10573 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10574
10575 /*
10576 * Pending debug exceptions.
10577 * Currently just copy whatever the nested-guest provides us.
10578 */
10579 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10580
10581 /*
10582 * I/O Bitmap.
10583 *
10584 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10585 * intercept all I/O port accesses.
10586 */
10587 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10588 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10589
10590 /*
10591 * VMCS shadowing.
10592 *
10593 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10594 * enabled while executing the nested-guest.
10595 */
10596 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10597
10598 /*
10599 * APIC-access page.
10600 */
10601 RTHCPHYS HCPhysApicAccess;
10602 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10603 {
10604 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10605 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10606
10607 /** @todo NSTVMX: This is not really correct but currently is required to make
10608 * things work. We need to re-enable the page handler when we fallback to
10609 * IEM execution of the nested-guest! */
10610 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10611
10612 void *pvPage;
10613 PGMPAGEMAPLOCK PgLockApicAccess;
10614 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10615 if (RT_SUCCESS(rc))
10616 {
10617 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10618 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10619
10620 /** @todo Handle proper releasing of page-mapping lock later. */
10621 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10622 }
10623 else
10624 return rc;
10625 }
10626 else
10627 HCPhysApicAccess = 0;
10628
10629 /*
10630 * Virtual-APIC page and TPR threshold.
10631 */
10632 RTHCPHYS HCPhysVirtApic;
10633 uint32_t u32TprThreshold;
10634 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10635 {
10636 Assert(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10637 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10638
10639 void *pvPage;
10640 PGMPAGEMAPLOCK PgLockVirtApic;
10641 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10642 if (RT_SUCCESS(rc))
10643 {
10644 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10645 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10646
10647 /** @todo Handle proper releasing of page-mapping lock later. */
10648 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10649 }
10650 else
10651 return rc;
10652
10653 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10654 }
10655 else
10656 {
10657 HCPhysVirtApic = 0;
10658 u32TprThreshold = 0;
10659
10660 /*
10661 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10662 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10663 * be taken care of by EPT/shadow paging.
10664 */
10665 if (pVM->hmr0.s.fAllow64BitGuests)
10666 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10667 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10668 }
10669
10670 /*
10671 * Validate basic assumptions.
10672 */
10673 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
10674 Assert(pVM->hmr0.s.vmx.fUnrestrictedGuest);
10675 Assert(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10676 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10677
10678 /*
10679 * Commit it to the nested-guest VMCS.
10680 */
10681 int rc = VINF_SUCCESS;
10682 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10683 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10684 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10685 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10686 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10687 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10688 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10689 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10690 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10691 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10692 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10693 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10694 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10695 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10696 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10697 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10698 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10699 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10700 {
10701 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10702 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10703 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10704 }
10705 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10706 {
10707 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10708 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10709 }
10710 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10711 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10712 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10713 AssertRC(rc);
10714
10715 /*
10716 * Update the nested-guest VMCS cache.
10717 */
10718 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10719 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10720 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10721 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10722 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10723 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10724 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10725 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10726 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10727
10728 /*
10729 * We need to flush the TLB if we are switching the APIC-access page address.
10730 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10731 */
10732 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10733 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10734
10735 /*
10736 * MSR bitmap.
10737 *
10738 * The MSR bitmap address has already been initialized while setting up the nested-guest
10739 * VMCS, here we need to merge the MSR bitmaps.
10740 */
10741 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10742 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10743
10744 return VINF_SUCCESS;
10745}
10746#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10747
10748
10749/**
10750 * Does the preparations before executing guest code in VT-x.
10751 *
10752 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10753 * recompiler/IEM. We must be cautious what we do here regarding committing
10754 * guest-state information into the VMCS assuming we assuredly execute the
10755 * guest in VT-x mode.
10756 *
10757 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10758 * the common-state (TRPM/forceflags), we must undo those changes so that the
10759 * recompiler/IEM can (and should) use them when it resumes guest execution.
10760 * Otherwise such operations must be done when we can no longer exit to ring-3.
10761 *
10762 * @returns Strict VBox status code (i.e. informational status codes too).
10763 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10764 * have been disabled.
10765 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10766 * pending events).
10767 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10768 * double-fault into the guest.
10769 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10770 * dispatched directly.
10771 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10772 *
10773 * @param pVCpu The cross context virtual CPU structure.
10774 * @param pVmxTransient The VMX-transient structure.
10775 * @param fStepping Whether we are single-stepping the guest in the
10776 * hypervisor debugger. Makes us ignore some of the reasons
10777 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10778 * if event dispatching took place.
10779 */
10780static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10781{
10782 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10783
10784 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10785
10786#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10787 if (pVmxTransient->fIsNestedGuest)
10788 {
10789 RT_NOREF2(pVCpu, fStepping);
10790 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10791 return VINF_EM_RESCHEDULE_REM;
10792 }
10793#endif
10794
10795 /*
10796 * Check and process force flag actions, some of which might require us to go back to ring-3.
10797 */
10798 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, pVmxTransient, fStepping);
10799 if (rcStrict == VINF_SUCCESS)
10800 {
10801 /* FFs don't get set all the time. */
10802#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10803 if ( pVmxTransient->fIsNestedGuest
10804 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10805 {
10806 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10807 return VINF_VMX_VMEXIT;
10808 }
10809#endif
10810 }
10811 else
10812 return rcStrict;
10813
10814 /*
10815 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10816 */
10817 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10818 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10819 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10820 && PDMHasApic(pVM))
10821 {
10822 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10823 AssertRCReturn(rc, rc);
10824 }
10825
10826#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10827 /*
10828 * Merge guest VMCS controls with the nested-guest VMCS controls.
10829 *
10830 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10831 * saved state), we should be okay with merging controls as we initialize the
10832 * guest VMCS controls as part of VM setup phase.
10833 */
10834 if ( pVmxTransient->fIsNestedGuest
10835 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10836 {
10837 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10838 AssertRCReturn(rc, rc);
10839 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10840 }
10841#endif
10842
10843 /*
10844 * Evaluate events to be injected into the guest.
10845 *
10846 * Events in TRPM can be injected without inspecting the guest state.
10847 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10848 * guest to cause a VM-exit the next time they are ready to receive the event.
10849 */
10850 if (TRPMHasTrap(pVCpu))
10851 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10852
10853 uint32_t fIntrState;
10854 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10855
10856#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10857 /*
10858 * While evaluating pending events if something failed (unlikely) or if we were
10859 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10860 */
10861 if (rcStrict != VINF_SUCCESS)
10862 return rcStrict;
10863 if ( pVmxTransient->fIsNestedGuest
10864 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10865 {
10866 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10867 return VINF_VMX_VMEXIT;
10868 }
10869#else
10870 Assert(rcStrict == VINF_SUCCESS);
10871#endif
10872
10873 /*
10874 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10875 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10876 * also result in triple-faulting the VM.
10877 *
10878 * With nested-guests, the above does not apply since unrestricted guest execution is a
10879 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10880 */
10881 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10882 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10883 { /* likely */ }
10884 else
10885 {
10886 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10887 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10888 return rcStrict;
10889 }
10890
10891 /*
10892 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10893 * import CR3 themselves. We will need to update them here, as even as late as the above
10894 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10895 * the below force flags to be set.
10896 */
10897 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10898 {
10899 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10900 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10901 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10902 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10903 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10904 }
10905 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10906 {
10907 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10908 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10909 }
10910
10911#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10912 /* Paranoia. */
10913 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10914#endif
10915
10916 /*
10917 * No longjmps to ring-3 from this point on!!!
10918 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10919 * This also disables flushing of the R0-logger instance (if any).
10920 */
10921 VMMRZCallRing3Disable(pVCpu);
10922
10923 /*
10924 * Export the guest state bits.
10925 *
10926 * We cannot perform longjmps while loading the guest state because we do not preserve the
10927 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10928 * CPU migration.
10929 *
10930 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10931 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10932 */
10933 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10934 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10935 { /* likely */ }
10936 else
10937 {
10938 VMMRZCallRing3Enable(pVCpu);
10939 return rcStrict;
10940 }
10941
10942 /*
10943 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10944 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10945 * preemption disabled for a while. Since this is purely to aid the
10946 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10947 * disable interrupt on NT.
10948 *
10949 * We need to check for force-flags that could've possible been altered since we last
10950 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10951 * see @bugref{6398}).
10952 *
10953 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10954 * to ring-3 before executing guest code.
10955 */
10956 pVmxTransient->fEFlags = ASMIntDisableFlags();
10957
10958 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10959 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10960 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10961 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10962 {
10963 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10964 {
10965#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10966 /*
10967 * If we are executing a nested-guest make sure that we should intercept subsequent
10968 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10969 * the VM-exit instruction emulation happy.
10970 */
10971 if (pVmxTransient->fIsNestedGuest)
10972 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10973#endif
10974
10975 /*
10976 * We've injected any pending events. This is really the point of no return (to ring-3).
10977 *
10978 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10979 * returns from this function, so do -not- enable them here.
10980 */
10981 pVCpu->hm.s.Event.fPending = false;
10982 return VINF_SUCCESS;
10983 }
10984
10985 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10986 rcStrict = VINF_EM_RAW_INTERRUPT;
10987 }
10988 else
10989 {
10990 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10991 rcStrict = VINF_EM_RAW_TO_R3;
10992 }
10993
10994 ASMSetFlags(pVmxTransient->fEFlags);
10995 VMMRZCallRing3Enable(pVCpu);
10996
10997 return rcStrict;
10998}
10999
11000
11001/**
11002 * Final preparations before executing guest code using hardware-assisted VMX.
11003 *
11004 * We can no longer get preempted to a different host CPU and there are no returns
11005 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
11006 * failures), this function is not intended to fail sans unrecoverable hardware
11007 * errors.
11008 *
11009 * @param pVCpu The cross context virtual CPU structure.
11010 * @param pVmxTransient The VMX-transient structure.
11011 *
11012 * @remarks Called with preemption disabled.
11013 * @remarks No-long-jump zone!!!
11014 */
11015static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
11016{
11017 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11018 Assert(VMMR0IsLogFlushDisabled(pVCpu));
11019 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
11020 Assert(!pVCpu->hm.s.Event.fPending);
11021
11022 /*
11023 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
11024 */
11025 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11026 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
11027
11028 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11029 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11030 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
11031 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
11032
11033 if (!CPUMIsGuestFPUStateActive(pVCpu))
11034 {
11035 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11036 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
11037 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
11038 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11039 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
11040 }
11041
11042 /*
11043 * Re-export the host state bits as we may've been preempted (only happens when
11044 * thread-context hooks are used or when the VM start function changes) or if
11045 * the host CR0 is modified while loading the guest FPU state above.
11046 *
11047 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
11048 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
11049 * see @bugref{8432}.
11050 *
11051 * This may also happen when switching to/from a nested-guest VMCS without leaving
11052 * ring-0.
11053 */
11054 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
11055 {
11056 hmR0VmxExportHostState(pVCpu);
11057 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
11058 }
11059 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
11060
11061 /*
11062 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
11063 */
11064 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
11065 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
11066 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
11067
11068 /*
11069 * Store status of the shared guest/host debug state at the time of VM-entry.
11070 */
11071 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
11072 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11073
11074 /*
11075 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11076 * more than one conditional check. The post-run side of our code shall determine
11077 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11078 */
11079 if (pVmcsInfo->pbVirtApic)
11080 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11081
11082 /*
11083 * Update the host MSRs values in the VM-exit MSR-load area.
11084 */
11085 if (!pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs)
11086 {
11087 if (pVmcsInfo->cExitMsrLoad > 0)
11088 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11089 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = true;
11090 }
11091
11092 /*
11093 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11094 * VMX-preemption timer based on the next virtual sync clock deadline.
11095 */
11096 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11097 || idCurrentCpu != pVCpu->hmr0.s.idLastCpu)
11098 {
11099 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient, idCurrentCpu);
11100 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11101 }
11102
11103 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11104 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11105 if (!fIsRdtscIntercepted)
11106 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11107 else
11108 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11109
11110 ASMAtomicUoWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11111 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11112 Assert(idCurrentCpu == pVCpu->hmr0.s.idLastCpu);
11113 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
11114 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
11115 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
11116
11117 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11118
11119 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11120 as we're about to start executing the guest. */
11121
11122 /*
11123 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11124 *
11125 * This is done this late as updating the TSC offsetting/preemption timer above
11126 * figures out if we can skip intercepting RDTSCP by calculating the number of
11127 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11128 */
11129 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11130 && !fIsRdtscIntercepted)
11131 {
11132 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11133
11134 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11135 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11136 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11137 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11138 AssertRC(rc);
11139 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11140 pVmxTransient->fRemoveTscAuxMsr = true;
11141 }
11142
11143#ifdef VBOX_STRICT
11144 Assert(pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs);
11145 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11146 hmR0VmxCheckHostEferMsr(pVmcsInfo);
11147 AssertRC(hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11148#endif
11149
11150#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11151 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11152 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11153 * see @bugref{9180#c54}. */
11154 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11155 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11156 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11157#endif
11158}
11159
11160
11161/**
11162 * First C routine invoked after running guest code using hardware-assisted VMX.
11163 *
11164 * @param pVCpu The cross context virtual CPU structure.
11165 * @param pVmxTransient The VMX-transient structure.
11166 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11167 *
11168 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11169 *
11170 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11171 * unconditionally when it is safe to do so.
11172 */
11173static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11174{
11175 ASMAtomicUoWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11176 ASMAtomicIncU32(&pVCpu->hmr0.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11177 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11178 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11179 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11180 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11181
11182 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11183 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11184 {
11185 uint64_t uGstTsc;
11186 if (!pVmxTransient->fIsNestedGuest)
11187 uGstTsc = pVCpu->hmr0.s.uTscExit + pVmcsInfo->u64TscOffset;
11188 else
11189 {
11190 uint64_t const uNstGstTsc = pVCpu->hmr0.s.uTscExit + pVmcsInfo->u64TscOffset;
11191 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11192 }
11193 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11194 }
11195
11196 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11197 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu, pVCpu->hmr0.s.uTscExit); /* Notify TM that the guest is no longer running. */
11198 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11199
11200 pVCpu->hmr0.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11201 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11202#ifdef VBOX_STRICT
11203 hmR0VmxCheckHostEferMsr(pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11204#endif
11205 Assert(!ASMIntAreEnabled());
11206 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11207 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11208
11209#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11210 /*
11211 * Clean all the VMCS fields in the transient structure before reading
11212 * anything from the VMCS.
11213 */
11214 pVmxTransient->uExitReason = 0;
11215 pVmxTransient->uExitIntErrorCode = 0;
11216 pVmxTransient->uExitQual = 0;
11217 pVmxTransient->uGuestLinearAddr = 0;
11218 pVmxTransient->uExitIntInfo = 0;
11219 pVmxTransient->cbExitInstr = 0;
11220 pVmxTransient->ExitInstrInfo.u = 0;
11221 pVmxTransient->uEntryIntInfo = 0;
11222 pVmxTransient->uEntryXcptErrorCode = 0;
11223 pVmxTransient->cbEntryInstr = 0;
11224 pVmxTransient->uIdtVectoringInfo = 0;
11225 pVmxTransient->uIdtVectoringErrorCode = 0;
11226#endif
11227
11228 /*
11229 * Save the basic VM-exit reason and check if the VM-entry failed.
11230 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11231 */
11232 uint32_t uExitReason;
11233 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11234 AssertRC(rc);
11235 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11236 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11237
11238 /*
11239 * Log the VM-exit before logging anything else as otherwise it might be a
11240 * tad confusing what happens before and after the world-switch.
11241 */
11242 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11243
11244 /*
11245 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11246 * bitmap permissions, if it was added before VM-entry.
11247 */
11248 if (pVmxTransient->fRemoveTscAuxMsr)
11249 {
11250 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11251 pVmxTransient->fRemoveTscAuxMsr = false;
11252 }
11253
11254 /*
11255 * Check if VMLAUNCH/VMRESUME succeeded.
11256 * If this failed, we cause a guru meditation and cease further execution.
11257 *
11258 * However, if we are executing a nested-guest we might fail if we use the
11259 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11260 */
11261 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11262 {
11263 /*
11264 * Update the VM-exit history array here even if the VM-entry failed due to:
11265 * - Invalid guest state.
11266 * - MSR loading.
11267 * - Machine-check event.
11268 *
11269 * In any of the above cases we will still have a "valid" VM-exit reason
11270 * despite @a fVMEntryFailed being false.
11271 *
11272 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11273 *
11274 * Note! We don't have CS or RIP at this point. Will probably address that later
11275 * by amending the history entry added here.
11276 */
11277 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11278 UINT64_MAX, pVCpu->hmr0.s.uTscExit);
11279
11280 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11281 {
11282 VMMRZCallRing3Enable(pVCpu);
11283
11284 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11285 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11286
11287#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
11288 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
11289#endif
11290
11291 /*
11292 * Import the guest-interruptibility state always as we need it while evaluating
11293 * injecting events on re-entry.
11294 *
11295 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11296 * checking for real-mode while exporting the state because all bits that cause
11297 * mode changes wrt CR0 are intercepted.
11298 */
11299 uint64_t const fImportMask = CPUMCTX_EXTRN_HM_VMX_INT_STATE
11300#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11301 | HMVMX_CPUMCTX_EXTRN_ALL
11302#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11303 | CPUMCTX_EXTRN_RFLAGS
11304#endif
11305 ;
11306 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImportMask);
11307 AssertRC(rc);
11308
11309 /*
11310 * Sync the TPR shadow with our APIC state.
11311 */
11312 if ( !pVmxTransient->fIsNestedGuest
11313 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
11314 {
11315 Assert(pVmcsInfo->pbVirtApic);
11316 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11317 {
11318 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11319 AssertRC(rc);
11320 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11321 }
11322 }
11323
11324 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11325 Assert( pVmxTransient->fWasGuestDebugStateActive == false
11326 || pVmxTransient->fWasHyperDebugStateActive == false);
11327 return;
11328 }
11329 }
11330#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11331 else if (pVmxTransient->fIsNestedGuest)
11332 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11333#endif
11334 else
11335 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11336
11337 VMMRZCallRing3Enable(pVCpu);
11338}
11339
11340
11341/**
11342 * Runs the guest code using hardware-assisted VMX the normal way.
11343 *
11344 * @returns VBox status code.
11345 * @param pVCpu The cross context virtual CPU structure.
11346 * @param pcLoops Pointer to the number of executed loops.
11347 */
11348static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
11349{
11350 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
11351 Assert(pcLoops);
11352 Assert(*pcLoops <= cMaxResumeLoops);
11353 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11354
11355#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11356 /*
11357 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11358 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11359 * guest VMCS while entering the VMX ring-0 session.
11360 */
11361 if (pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
11362 {
11363 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11364 if (RT_SUCCESS(rc))
11365 { /* likely */ }
11366 else
11367 {
11368 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11369 return rc;
11370 }
11371 }
11372#endif
11373
11374 VMXTRANSIENT VmxTransient;
11375 RT_ZERO(VmxTransient);
11376 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11377
11378 /* Paranoia. */
11379 Assert(VmxTransient.pVmcsInfo == &pVCpu->hmr0.s.vmx.VmcsInfo);
11380
11381 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11382 for (;;)
11383 {
11384 Assert(!HMR0SuspendPending());
11385 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11386 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11387
11388 /*
11389 * Preparatory work for running nested-guest code, this may force us to
11390 * return to ring-3.
11391 *
11392 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11393 */
11394 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11395 if (rcStrict != VINF_SUCCESS)
11396 break;
11397
11398 /* Interrupts are disabled at this point! */
11399 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11400 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11401 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11402 /* Interrupts are re-enabled at this point! */
11403
11404 /*
11405 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11406 */
11407 if (RT_SUCCESS(rcRun))
11408 { /* very likely */ }
11409 else
11410 {
11411 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11412 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11413 return rcRun;
11414 }
11415
11416 /*
11417 * Profile the VM-exit.
11418 */
11419 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11420 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11421 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11422 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11423 HMVMX_START_EXIT_DISPATCH_PROF();
11424
11425 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11426
11427 /*
11428 * Handle the VM-exit.
11429 */
11430#ifdef HMVMX_USE_FUNCTION_TABLE
11431 rcStrict = g_aVMExitHandlers[VmxTransient.uExitReason].pfn(pVCpu, &VmxTransient);
11432#else
11433 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11434#endif
11435 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11436 if (rcStrict == VINF_SUCCESS)
11437 {
11438 if (++(*pcLoops) <= cMaxResumeLoops)
11439 continue;
11440 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11441 rcStrict = VINF_EM_RAW_INTERRUPT;
11442 }
11443 break;
11444 }
11445
11446 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11447 return rcStrict;
11448}
11449
11450
11451#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11452/**
11453 * Runs the nested-guest code using hardware-assisted VMX.
11454 *
11455 * @returns VBox status code.
11456 * @param pVCpu The cross context virtual CPU structure.
11457 * @param pcLoops Pointer to the number of executed loops.
11458 *
11459 * @sa hmR0VmxRunGuestCodeNormal.
11460 */
11461static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
11462{
11463 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
11464 Assert(pcLoops);
11465 Assert(*pcLoops <= cMaxResumeLoops);
11466 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11467
11468 /*
11469 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11470 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11471 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11472 */
11473 if (!pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
11474 {
11475 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11476 if (RT_SUCCESS(rc))
11477 { /* likely */ }
11478 else
11479 {
11480 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11481 return rc;
11482 }
11483 }
11484
11485 VMXTRANSIENT VmxTransient;
11486 RT_ZERO(VmxTransient);
11487 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11488 VmxTransient.fIsNestedGuest = true;
11489
11490 /* Paranoia. */
11491 Assert(VmxTransient.pVmcsInfo == &pVCpu->hmr0.s.vmx.VmcsInfoNstGst);
11492
11493 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11494 for (;;)
11495 {
11496 Assert(!HMR0SuspendPending());
11497 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11498 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11499
11500 /*
11501 * Preparatory work for running guest code, this may force us to
11502 * return to ring-3.
11503 *
11504 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11505 */
11506 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11507 if (rcStrict != VINF_SUCCESS)
11508 break;
11509
11510 /* Interrupts are disabled at this point! */
11511 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11512 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11513 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11514 /* Interrupts are re-enabled at this point! */
11515
11516 /*
11517 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11518 */
11519 if (RT_SUCCESS(rcRun))
11520 { /* very likely */ }
11521 else
11522 {
11523 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11524 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11525 return rcRun;
11526 }
11527
11528 /*
11529 * Profile the VM-exit.
11530 */
11531 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11532 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11533 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11534 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11535 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11536 HMVMX_START_EXIT_DISPATCH_PROF();
11537
11538 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11539
11540 /*
11541 * Handle the VM-exit.
11542 */
11543 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11544 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11545 if (rcStrict == VINF_SUCCESS)
11546 {
11547 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11548 {
11549 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11550 rcStrict = VINF_VMX_VMEXIT;
11551 }
11552 else
11553 {
11554 if (++(*pcLoops) <= cMaxResumeLoops)
11555 continue;
11556 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11557 rcStrict = VINF_EM_RAW_INTERRUPT;
11558 }
11559 }
11560 else
11561 Assert(rcStrict != VINF_VMX_VMEXIT);
11562 break;
11563 }
11564
11565 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11566 return rcStrict;
11567}
11568#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11569
11570
11571/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11572 * probes.
11573 *
11574 * The following few functions and associated structure contains the bloat
11575 * necessary for providing detailed debug events and dtrace probes as well as
11576 * reliable host side single stepping. This works on the principle of
11577 * "subclassing" the normal execution loop and workers. We replace the loop
11578 * method completely and override selected helpers to add necessary adjustments
11579 * to their core operation.
11580 *
11581 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11582 * any performance for debug and analysis features.
11583 *
11584 * @{
11585 */
11586
11587/**
11588 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11589 * the debug run loop.
11590 */
11591typedef struct VMXRUNDBGSTATE
11592{
11593 /** The RIP we started executing at. This is for detecting that we stepped. */
11594 uint64_t uRipStart;
11595 /** The CS we started executing with. */
11596 uint16_t uCsStart;
11597
11598 /** Whether we've actually modified the 1st execution control field. */
11599 bool fModifiedProcCtls : 1;
11600 /** Whether we've actually modified the 2nd execution control field. */
11601 bool fModifiedProcCtls2 : 1;
11602 /** Whether we've actually modified the exception bitmap. */
11603 bool fModifiedXcptBitmap : 1;
11604
11605 /** We desire the modified the CR0 mask to be cleared. */
11606 bool fClearCr0Mask : 1;
11607 /** We desire the modified the CR4 mask to be cleared. */
11608 bool fClearCr4Mask : 1;
11609 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11610 uint32_t fCpe1Extra;
11611 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11612 uint32_t fCpe1Unwanted;
11613 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11614 uint32_t fCpe2Extra;
11615 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11616 uint32_t bmXcptExtra;
11617 /** The sequence number of the Dtrace provider settings the state was
11618 * configured against. */
11619 uint32_t uDtraceSettingsSeqNo;
11620 /** VM-exits to check (one bit per VM-exit). */
11621 uint32_t bmExitsToCheck[3];
11622
11623 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11624 uint32_t fProcCtlsInitial;
11625 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11626 uint32_t fProcCtls2Initial;
11627 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11628 uint32_t bmXcptInitial;
11629} VMXRUNDBGSTATE;
11630AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11631typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11632
11633
11634/**
11635 * Initializes the VMXRUNDBGSTATE structure.
11636 *
11637 * @param pVCpu The cross context virtual CPU structure of the
11638 * calling EMT.
11639 * @param pVmxTransient The VMX-transient structure.
11640 * @param pDbgState The debug state to initialize.
11641 */
11642static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11643{
11644 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11645 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11646
11647 pDbgState->fModifiedProcCtls = false;
11648 pDbgState->fModifiedProcCtls2 = false;
11649 pDbgState->fModifiedXcptBitmap = false;
11650 pDbgState->fClearCr0Mask = false;
11651 pDbgState->fClearCr4Mask = false;
11652 pDbgState->fCpe1Extra = 0;
11653 pDbgState->fCpe1Unwanted = 0;
11654 pDbgState->fCpe2Extra = 0;
11655 pDbgState->bmXcptExtra = 0;
11656 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11657 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11658 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11659}
11660
11661
11662/**
11663 * Updates the VMSC fields with changes requested by @a pDbgState.
11664 *
11665 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11666 * immediately before executing guest code, i.e. when interrupts are disabled.
11667 * We don't check status codes here as we cannot easily assert or return in the
11668 * latter case.
11669 *
11670 * @param pVCpu The cross context virtual CPU structure.
11671 * @param pVmxTransient The VMX-transient structure.
11672 * @param pDbgState The debug state.
11673 */
11674static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11675{
11676 /*
11677 * Ensure desired flags in VMCS control fields are set.
11678 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11679 *
11680 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11681 * there should be no stale data in pCtx at this point.
11682 */
11683 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11684 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11685 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11686 {
11687 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11688 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11689 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11690 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11691 pDbgState->fModifiedProcCtls = true;
11692 }
11693
11694 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11695 {
11696 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11697 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11698 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11699 pDbgState->fModifiedProcCtls2 = true;
11700 }
11701
11702 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11703 {
11704 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11705 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11706 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11707 pDbgState->fModifiedXcptBitmap = true;
11708 }
11709
11710 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11711 {
11712 pVmcsInfo->u64Cr0Mask = 0;
11713 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11714 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11715 }
11716
11717 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11718 {
11719 pVmcsInfo->u64Cr4Mask = 0;
11720 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11721 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11722 }
11723
11724 NOREF(pVCpu);
11725}
11726
11727
11728/**
11729 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11730 * re-entry next time around.
11731 *
11732 * @returns Strict VBox status code (i.e. informational status codes too).
11733 * @param pVCpu The cross context virtual CPU structure.
11734 * @param pVmxTransient The VMX-transient structure.
11735 * @param pDbgState The debug state.
11736 * @param rcStrict The return code from executing the guest using single
11737 * stepping.
11738 */
11739static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11740 VBOXSTRICTRC rcStrict)
11741{
11742 /*
11743 * Restore VM-exit control settings as we may not reenter this function the
11744 * next time around.
11745 */
11746 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11747
11748 /* We reload the initial value, trigger what we can of recalculations the
11749 next time around. From the looks of things, that's all that's required atm. */
11750 if (pDbgState->fModifiedProcCtls)
11751 {
11752 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11753 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11754 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11755 AssertRC(rc2);
11756 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11757 }
11758
11759 /* We're currently the only ones messing with this one, so just restore the
11760 cached value and reload the field. */
11761 if ( pDbgState->fModifiedProcCtls2
11762 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11763 {
11764 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11765 AssertRC(rc2);
11766 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11767 }
11768
11769 /* If we've modified the exception bitmap, we restore it and trigger
11770 reloading and partial recalculation the next time around. */
11771 if (pDbgState->fModifiedXcptBitmap)
11772 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11773
11774 return rcStrict;
11775}
11776
11777
11778/**
11779 * Configures VM-exit controls for current DBGF and DTrace settings.
11780 *
11781 * This updates @a pDbgState and the VMCS execution control fields to reflect
11782 * the necessary VM-exits demanded by DBGF and DTrace.
11783 *
11784 * @param pVCpu The cross context virtual CPU structure.
11785 * @param pVmxTransient The VMX-transient structure. May update
11786 * fUpdatedTscOffsettingAndPreemptTimer.
11787 * @param pDbgState The debug state.
11788 */
11789static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11790{
11791 /*
11792 * Take down the dtrace serial number so we can spot changes.
11793 */
11794 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11795 ASMCompilerBarrier();
11796
11797 /*
11798 * We'll rebuild most of the middle block of data members (holding the
11799 * current settings) as we go along here, so start by clearing it all.
11800 */
11801 pDbgState->bmXcptExtra = 0;
11802 pDbgState->fCpe1Extra = 0;
11803 pDbgState->fCpe1Unwanted = 0;
11804 pDbgState->fCpe2Extra = 0;
11805 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11806 pDbgState->bmExitsToCheck[i] = 0;
11807
11808 /*
11809 * Software interrupts (INT XXh) - no idea how to trigger these...
11810 */
11811 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11812 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11813 || VBOXVMM_INT_SOFTWARE_ENABLED())
11814 {
11815 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11816 }
11817
11818 /*
11819 * INT3 breakpoints - triggered by #BP exceptions.
11820 */
11821 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11822 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11823
11824 /*
11825 * Exception bitmap and XCPT events+probes.
11826 */
11827 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11828 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11829 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11830
11831 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11832 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11833 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11834 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11835 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11836 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11837 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11838 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11839 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11840 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11841 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11842 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11843 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11844 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11845 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11846 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11847 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11848 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11849
11850 if (pDbgState->bmXcptExtra)
11851 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11852
11853 /*
11854 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11855 *
11856 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11857 * So, when adding/changing/removing please don't forget to update it.
11858 *
11859 * Some of the macros are picking up local variables to save horizontal space,
11860 * (being able to see it in a table is the lesser evil here).
11861 */
11862#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11863 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11864 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11865#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11866 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11867 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11868 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11869 } else do { } while (0)
11870#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11871 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11872 { \
11873 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11874 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11875 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11876 } else do { } while (0)
11877#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11878 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11879 { \
11880 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11881 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11882 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11883 } else do { } while (0)
11884#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11885 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11886 { \
11887 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11888 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11889 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11890 } else do { } while (0)
11891
11892 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11893 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11894 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11895 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11896 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11897
11898 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11899 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11900 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11901 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11902 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11903 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11904 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11905 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11906 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11907 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11908 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11909 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11910 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11911 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11912 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11913 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11914 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11915 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11916 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11917 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11918 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11919 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11920 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11921 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11922 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11923 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11924 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11925 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11926 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11927 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11928 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11929 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11930 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11931 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11932 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11933 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11934
11935 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11936 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11937 {
11938 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11939 | CPUMCTX_EXTRN_APIC_TPR);
11940 AssertRC(rc);
11941
11942#if 0 /** @todo fix me */
11943 pDbgState->fClearCr0Mask = true;
11944 pDbgState->fClearCr4Mask = true;
11945#endif
11946 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11947 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11948 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11949 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11950 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11951 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11952 require clearing here and in the loop if we start using it. */
11953 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11954 }
11955 else
11956 {
11957 if (pDbgState->fClearCr0Mask)
11958 {
11959 pDbgState->fClearCr0Mask = false;
11960 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11961 }
11962 if (pDbgState->fClearCr4Mask)
11963 {
11964 pDbgState->fClearCr4Mask = false;
11965 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11966 }
11967 }
11968 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11969 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11970
11971 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11972 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11973 {
11974 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11975 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11976 }
11977 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11978 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11979
11980 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11981 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11982 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11983 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11984 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11985 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11986 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11987 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11988#if 0 /** @todo too slow, fix handler. */
11989 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11990#endif
11991 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11992
11993 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11994 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11995 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11996 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11997 {
11998 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11999 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
12000 }
12001 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12002 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12003 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12004 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12005
12006 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
12007 || IS_EITHER_ENABLED(pVM, INSTR_STR)
12008 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
12009 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
12010 {
12011 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12012 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
12013 }
12014 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
12015 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
12016 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
12017 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
12018
12019 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
12020 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
12021 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
12022 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
12023 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
12024 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
12025 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
12026 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
12027 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
12028 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
12029 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
12030 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
12031 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
12032 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
12033 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
12034 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
12035 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
12036 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
12037 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
12038 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
12039 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
12040 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
12041
12042#undef IS_EITHER_ENABLED
12043#undef SET_ONLY_XBM_IF_EITHER_EN
12044#undef SET_CPE1_XBM_IF_EITHER_EN
12045#undef SET_CPEU_XBM_IF_EITHER_EN
12046#undef SET_CPE2_XBM_IF_EITHER_EN
12047
12048 /*
12049 * Sanitize the control stuff.
12050 */
12051 pDbgState->fCpe2Extra &= g_HmMsrs.u.vmx.ProcCtls2.n.allowed1;
12052 if (pDbgState->fCpe2Extra)
12053 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
12054 pDbgState->fCpe1Extra &= g_HmMsrs.u.vmx.ProcCtls.n.allowed1;
12055 pDbgState->fCpe1Unwanted &= ~g_HmMsrs.u.vmx.ProcCtls.n.allowed0;
12056 if (pVCpu->hmr0.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
12057 {
12058 pVCpu->hmr0.s.fDebugWantRdTscExit ^= true;
12059 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
12060 }
12061
12062 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
12063 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
12064 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
12065 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
12066}
12067
12068
12069/**
12070 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
12071 * appropriate.
12072 *
12073 * The caller has checked the VM-exit against the
12074 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12075 * already, so we don't have to do that either.
12076 *
12077 * @returns Strict VBox status code (i.e. informational status codes too).
12078 * @param pVCpu The cross context virtual CPU structure.
12079 * @param pVmxTransient The VMX-transient structure.
12080 * @param uExitReason The VM-exit reason.
12081 *
12082 * @remarks The name of this function is displayed by dtrace, so keep it short
12083 * and to the point. No longer than 33 chars long, please.
12084 */
12085static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12086{
12087 /*
12088 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12089 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12090 *
12091 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12092 * does. Must add/change/remove both places. Same ordering, please.
12093 *
12094 * Added/removed events must also be reflected in the next section
12095 * where we dispatch dtrace events.
12096 */
12097 bool fDtrace1 = false;
12098 bool fDtrace2 = false;
12099 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12100 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12101 uint32_t uEventArg = 0;
12102#define SET_EXIT(a_EventSubName) \
12103 do { \
12104 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12105 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12106 } while (0)
12107#define SET_BOTH(a_EventSubName) \
12108 do { \
12109 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12110 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12111 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12112 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12113 } while (0)
12114 switch (uExitReason)
12115 {
12116 case VMX_EXIT_MTF:
12117 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12118
12119 case VMX_EXIT_XCPT_OR_NMI:
12120 {
12121 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12122 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12123 {
12124 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12125 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12126 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12127 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12128 {
12129 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12130 {
12131 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12132 uEventArg = pVmxTransient->uExitIntErrorCode;
12133 }
12134 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12135 switch (enmEvent1)
12136 {
12137 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12138 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12139 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12140 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12141 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12142 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12143 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12144 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12145 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12146 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12147 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12148 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12149 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12150 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12151 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12152 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12153 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12154 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12155 default: break;
12156 }
12157 }
12158 else
12159 AssertFailed();
12160 break;
12161
12162 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12163 uEventArg = idxVector;
12164 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12165 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12166 break;
12167 }
12168 break;
12169 }
12170
12171 case VMX_EXIT_TRIPLE_FAULT:
12172 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12173 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12174 break;
12175 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12176 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12177 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12178 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12179 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12180
12181 /* Instruction specific VM-exits: */
12182 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12183 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12184 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12185 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12186 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12187 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12188 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12189 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12190 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12191 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12192 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12193 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12194 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12195 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12196 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12197 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12198 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12199 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12200 case VMX_EXIT_MOV_CRX:
12201 hmR0VmxReadExitQualVmcs(pVmxTransient);
12202 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12203 SET_BOTH(CRX_READ);
12204 else
12205 SET_BOTH(CRX_WRITE);
12206 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12207 break;
12208 case VMX_EXIT_MOV_DRX:
12209 hmR0VmxReadExitQualVmcs(pVmxTransient);
12210 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12211 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12212 SET_BOTH(DRX_READ);
12213 else
12214 SET_BOTH(DRX_WRITE);
12215 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12216 break;
12217 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12218 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12219 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12220 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12221 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12222 case VMX_EXIT_GDTR_IDTR_ACCESS:
12223 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12224 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12225 {
12226 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12227 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12228 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12229 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12230 }
12231 break;
12232
12233 case VMX_EXIT_LDTR_TR_ACCESS:
12234 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12235 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12236 {
12237 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12238 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12239 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12240 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12241 }
12242 break;
12243
12244 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12245 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12246 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12247 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12248 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12249 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12250 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12251 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12252 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12253 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12254 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12255
12256 /* Events that aren't relevant at this point. */
12257 case VMX_EXIT_EXT_INT:
12258 case VMX_EXIT_INT_WINDOW:
12259 case VMX_EXIT_NMI_WINDOW:
12260 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12261 case VMX_EXIT_PREEMPT_TIMER:
12262 case VMX_EXIT_IO_INSTR:
12263 break;
12264
12265 /* Errors and unexpected events. */
12266 case VMX_EXIT_INIT_SIGNAL:
12267 case VMX_EXIT_SIPI:
12268 case VMX_EXIT_IO_SMI:
12269 case VMX_EXIT_SMI:
12270 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12271 case VMX_EXIT_ERR_MSR_LOAD:
12272 case VMX_EXIT_ERR_MACHINE_CHECK:
12273 case VMX_EXIT_PML_FULL:
12274 case VMX_EXIT_VIRTUALIZED_EOI:
12275 break;
12276
12277 default:
12278 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12279 break;
12280 }
12281#undef SET_BOTH
12282#undef SET_EXIT
12283
12284 /*
12285 * Dtrace tracepoints go first. We do them here at once so we don't
12286 * have to copy the guest state saving and stuff a few dozen times.
12287 * Down side is that we've got to repeat the switch, though this time
12288 * we use enmEvent since the probes are a subset of what DBGF does.
12289 */
12290 if (fDtrace1 || fDtrace2)
12291 {
12292 hmR0VmxReadExitQualVmcs(pVmxTransient);
12293 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12294 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12295 switch (enmEvent1)
12296 {
12297 /** @todo consider which extra parameters would be helpful for each probe. */
12298 case DBGFEVENT_END: break;
12299 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12300 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12301 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12302 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12303 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12304 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12305 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12306 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12307 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12308 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12309 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12310 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12311 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12312 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12313 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12314 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12315 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12316 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12317 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12318 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12319 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12320 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12321 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12322 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12323 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12324 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12325 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12326 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12327 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12328 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12329 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12330 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12331 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12332 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12333 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12334 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12335 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12336 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12337 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12338 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12339 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12340 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12341 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12342 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12343 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12344 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12345 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12346 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12347 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12348 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12349 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12350 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12351 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12352 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12353 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12354 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12355 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12356 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12357 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12358 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12359 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12360 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12361 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12362 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12363 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12364 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12365 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12366 }
12367 switch (enmEvent2)
12368 {
12369 /** @todo consider which extra parameters would be helpful for each probe. */
12370 case DBGFEVENT_END: break;
12371 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12372 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12373 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12374 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12375 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12376 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12377 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12378 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12379 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12380 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12381 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12382 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12383 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12384 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12385 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12386 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12387 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12388 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12389 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12390 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12391 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12392 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12393 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12394 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12395 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12396 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12397 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12398 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12399 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12400 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12401 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12402 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12403 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12404 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12405 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12406 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12407 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12408 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12409 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12410 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12411 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12412 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12413 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12414 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12415 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12416 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12417 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12418 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12419 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12420 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12421 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12422 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12423 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12424 }
12425 }
12426
12427 /*
12428 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12429 * the DBGF call will do a full check).
12430 *
12431 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12432 * Note! If we have to events, we prioritize the first, i.e. the instruction
12433 * one, in order to avoid event nesting.
12434 */
12435 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
12436 if ( enmEvent1 != DBGFEVENT_END
12437 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12438 {
12439 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12440 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12441 if (rcStrict != VINF_SUCCESS)
12442 return rcStrict;
12443 }
12444 else if ( enmEvent2 != DBGFEVENT_END
12445 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12446 {
12447 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12448 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12449 if (rcStrict != VINF_SUCCESS)
12450 return rcStrict;
12451 }
12452
12453 return VINF_SUCCESS;
12454}
12455
12456
12457/**
12458 * Single-stepping VM-exit filtering.
12459 *
12460 * This is preprocessing the VM-exits and deciding whether we've gotten far
12461 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12462 * handling is performed.
12463 *
12464 * @returns Strict VBox status code (i.e. informational status codes too).
12465 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12466 * @param pVmxTransient The VMX-transient structure.
12467 * @param pDbgState The debug state.
12468 */
12469DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12470{
12471 /*
12472 * Expensive (saves context) generic dtrace VM-exit probe.
12473 */
12474 uint32_t const uExitReason = pVmxTransient->uExitReason;
12475 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12476 { /* more likely */ }
12477 else
12478 {
12479 hmR0VmxReadExitQualVmcs(pVmxTransient);
12480 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12481 AssertRC(rc);
12482 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12483 }
12484
12485 /*
12486 * Check for host NMI, just to get that out of the way.
12487 */
12488 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12489 { /* normally likely */ }
12490 else
12491 {
12492 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12493 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12494 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12495 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12496 }
12497
12498 /*
12499 * Check for single stepping event if we're stepping.
12500 */
12501 if (pVCpu->hm.s.fSingleInstruction)
12502 {
12503 switch (uExitReason)
12504 {
12505 case VMX_EXIT_MTF:
12506 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12507
12508 /* Various events: */
12509 case VMX_EXIT_XCPT_OR_NMI:
12510 case VMX_EXIT_EXT_INT:
12511 case VMX_EXIT_TRIPLE_FAULT:
12512 case VMX_EXIT_INT_WINDOW:
12513 case VMX_EXIT_NMI_WINDOW:
12514 case VMX_EXIT_TASK_SWITCH:
12515 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12516 case VMX_EXIT_APIC_ACCESS:
12517 case VMX_EXIT_EPT_VIOLATION:
12518 case VMX_EXIT_EPT_MISCONFIG:
12519 case VMX_EXIT_PREEMPT_TIMER:
12520
12521 /* Instruction specific VM-exits: */
12522 case VMX_EXIT_CPUID:
12523 case VMX_EXIT_GETSEC:
12524 case VMX_EXIT_HLT:
12525 case VMX_EXIT_INVD:
12526 case VMX_EXIT_INVLPG:
12527 case VMX_EXIT_RDPMC:
12528 case VMX_EXIT_RDTSC:
12529 case VMX_EXIT_RSM:
12530 case VMX_EXIT_VMCALL:
12531 case VMX_EXIT_VMCLEAR:
12532 case VMX_EXIT_VMLAUNCH:
12533 case VMX_EXIT_VMPTRLD:
12534 case VMX_EXIT_VMPTRST:
12535 case VMX_EXIT_VMREAD:
12536 case VMX_EXIT_VMRESUME:
12537 case VMX_EXIT_VMWRITE:
12538 case VMX_EXIT_VMXOFF:
12539 case VMX_EXIT_VMXON:
12540 case VMX_EXIT_MOV_CRX:
12541 case VMX_EXIT_MOV_DRX:
12542 case VMX_EXIT_IO_INSTR:
12543 case VMX_EXIT_RDMSR:
12544 case VMX_EXIT_WRMSR:
12545 case VMX_EXIT_MWAIT:
12546 case VMX_EXIT_MONITOR:
12547 case VMX_EXIT_PAUSE:
12548 case VMX_EXIT_GDTR_IDTR_ACCESS:
12549 case VMX_EXIT_LDTR_TR_ACCESS:
12550 case VMX_EXIT_INVEPT:
12551 case VMX_EXIT_RDTSCP:
12552 case VMX_EXIT_INVVPID:
12553 case VMX_EXIT_WBINVD:
12554 case VMX_EXIT_XSETBV:
12555 case VMX_EXIT_RDRAND:
12556 case VMX_EXIT_INVPCID:
12557 case VMX_EXIT_VMFUNC:
12558 case VMX_EXIT_RDSEED:
12559 case VMX_EXIT_XSAVES:
12560 case VMX_EXIT_XRSTORS:
12561 {
12562 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12563 AssertRCReturn(rc, rc);
12564 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12565 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12566 return VINF_EM_DBG_STEPPED;
12567 break;
12568 }
12569
12570 /* Errors and unexpected events: */
12571 case VMX_EXIT_INIT_SIGNAL:
12572 case VMX_EXIT_SIPI:
12573 case VMX_EXIT_IO_SMI:
12574 case VMX_EXIT_SMI:
12575 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12576 case VMX_EXIT_ERR_MSR_LOAD:
12577 case VMX_EXIT_ERR_MACHINE_CHECK:
12578 case VMX_EXIT_PML_FULL:
12579 case VMX_EXIT_VIRTUALIZED_EOI:
12580 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12581 break;
12582
12583 default:
12584 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12585 break;
12586 }
12587 }
12588
12589 /*
12590 * Check for debugger event breakpoints and dtrace probes.
12591 */
12592 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12593 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12594 {
12595 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12596 if (rcStrict != VINF_SUCCESS)
12597 return rcStrict;
12598 }
12599
12600 /*
12601 * Normal processing.
12602 */
12603#ifdef HMVMX_USE_FUNCTION_TABLE
12604 return g_aVMExitHandlers[uExitReason].pfn(pVCpu, pVmxTransient);
12605#else
12606 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12607#endif
12608}
12609
12610
12611/**
12612 * Single steps guest code using hardware-assisted VMX.
12613 *
12614 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12615 * but single-stepping through the hypervisor debugger.
12616 *
12617 * @returns Strict VBox status code (i.e. informational status codes too).
12618 * @param pVCpu The cross context virtual CPU structure.
12619 * @param pcLoops Pointer to the number of executed loops.
12620 *
12621 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12622 */
12623static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12624{
12625 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
12626 Assert(pcLoops);
12627 Assert(*pcLoops <= cMaxResumeLoops);
12628
12629 VMXTRANSIENT VmxTransient;
12630 RT_ZERO(VmxTransient);
12631 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12632
12633 /* Set HMCPU indicators. */
12634 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12635 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12636 pVCpu->hmr0.s.fDebugWantRdTscExit = false;
12637 pVCpu->hmr0.s.fUsingDebugLoop = true;
12638
12639 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12640 VMXRUNDBGSTATE DbgState;
12641 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12642 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12643
12644 /*
12645 * The loop.
12646 */
12647 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12648 for (;;)
12649 {
12650 Assert(!HMR0SuspendPending());
12651 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12652 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12653 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12654
12655 /* Set up VM-execution controls the next two can respond to. */
12656 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12657
12658 /*
12659 * Preparatory work for running guest code, this may force us to
12660 * return to ring-3.
12661 *
12662 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12663 */
12664 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12665 if (rcStrict != VINF_SUCCESS)
12666 break;
12667
12668 /* Interrupts are disabled at this point! */
12669 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12670
12671 /* Override any obnoxious code in the above two calls. */
12672 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12673
12674 /*
12675 * Finally execute the guest.
12676 */
12677 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12678
12679 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12680 /* Interrupts are re-enabled at this point! */
12681
12682 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12683 if (RT_SUCCESS(rcRun))
12684 { /* very likely */ }
12685 else
12686 {
12687 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12688 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12689 return rcRun;
12690 }
12691
12692 /* Profile the VM-exit. */
12693 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12694 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12695 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12696 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12697 HMVMX_START_EXIT_DISPATCH_PROF();
12698
12699 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12700
12701 /*
12702 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12703 */
12704 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12705 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12706 if (rcStrict != VINF_SUCCESS)
12707 break;
12708 if (++(*pcLoops) > cMaxResumeLoops)
12709 {
12710 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12711 rcStrict = VINF_EM_RAW_INTERRUPT;
12712 break;
12713 }
12714
12715 /*
12716 * Stepping: Did the RIP change, if so, consider it a single step.
12717 * Otherwise, make sure one of the TFs gets set.
12718 */
12719 if (fStepping)
12720 {
12721 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12722 AssertRC(rc);
12723 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12724 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12725 {
12726 rcStrict = VINF_EM_DBG_STEPPED;
12727 break;
12728 }
12729 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12730 }
12731
12732 /*
12733 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12734 */
12735 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12736 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12737
12738 /* Restore all controls applied by hmR0VmxPreRunGuestDebugStateApply above. */
12739 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12740 Assert(rcStrict == VINF_SUCCESS);
12741 }
12742
12743 /*
12744 * Clear the X86_EFL_TF if necessary.
12745 */
12746 if (pVCpu->hmr0.s.fClearTrapFlag)
12747 {
12748 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12749 AssertRC(rc);
12750 pVCpu->hmr0.s.fClearTrapFlag = false;
12751 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12752 }
12753 /** @todo there seems to be issues with the resume flag when the monitor trap
12754 * flag is pending without being used. Seen early in bios init when
12755 * accessing APIC page in protected mode. */
12756
12757 /* Restore HMCPU indicators. */
12758 pVCpu->hmr0.s.fUsingDebugLoop = false;
12759 pVCpu->hmr0.s.fDebugWantRdTscExit = false;
12760 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12761
12762 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12763 return rcStrict;
12764}
12765
12766
12767/** @} */
12768
12769
12770/**
12771 * Checks if any expensive dtrace probes are enabled and we should go to the
12772 * debug loop.
12773 *
12774 * @returns true if we should use debug loop, false if not.
12775 */
12776static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12777{
12778 /* It's probably faster to OR the raw 32-bit counter variables together.
12779 Since the variables are in an array and the probes are next to one
12780 another (more or less), we have good locality. So, better read
12781 eight-nine cache lines ever time and only have one conditional, than
12782 128+ conditionals, right? */
12783 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12784 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12785 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12786 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12787 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12788 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12789 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12790 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12791 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12792 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12793 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12794 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12795 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12796 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12797 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12798 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12799 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12800 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12801 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12802 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12803 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12804 ) != 0
12805 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12806 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12807 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12808 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12809 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12810 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12811 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12812 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12813 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12814 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12815 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12816 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12817 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12818 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12819 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12820 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12821 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12822 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12823 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12824 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12825 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12826 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12827 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12828 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12829 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12830 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12831 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12832 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12833 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12834 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12835 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12836 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12837 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12838 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12839 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12840 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12841 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12842 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12843 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12844 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12845 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12846 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12847 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12848 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12849 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12850 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12851 ) != 0
12852 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12853 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12854 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12855 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12856 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12857 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12858 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12859 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12860 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12861 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12862 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12863 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12864 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12865 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12866 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12867 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12868 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12869 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12870 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12871 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12872 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12873 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12874 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12875 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12876 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12877 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12878 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12879 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12880 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12881 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12882 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12883 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12884 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12885 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12886 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12887 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12888 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12889 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12890 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12891 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12892 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12893 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12894 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12895 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12896 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12897 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12898 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12899 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12900 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12901 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12902 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12903 ) != 0;
12904}
12905
12906
12907/**
12908 * Runs the guest using hardware-assisted VMX.
12909 *
12910 * @returns Strict VBox status code (i.e. informational status codes too).
12911 * @param pVCpu The cross context virtual CPU structure.
12912 */
12913VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12914{
12915 AssertPtr(pVCpu);
12916 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12917 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12918 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12919 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12920
12921 VBOXSTRICTRC rcStrict;
12922 uint32_t cLoops = 0;
12923 for (;;)
12924 {
12925#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12926 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12927#else
12928 NOREF(pCtx);
12929 bool const fInNestedGuestMode = false;
12930#endif
12931 if (!fInNestedGuestMode)
12932 {
12933 if ( !pVCpu->hm.s.fUseDebugLoop
12934 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12935 && !DBGFIsStepping(pVCpu)
12936 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12937 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12938 else
12939 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12940 }
12941#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12942 else
12943 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12944
12945 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12946 {
12947 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12948 continue;
12949 }
12950 if (rcStrict == VINF_VMX_VMEXIT)
12951 {
12952 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12953 continue;
12954 }
12955#endif
12956 break;
12957 }
12958
12959 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12960 switch (rcLoop)
12961 {
12962 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12963 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12964 }
12965
12966 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12967 if (RT_FAILURE(rc2))
12968 {
12969 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12970 rcStrict = rc2;
12971 }
12972 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12973 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12974 return rcStrict;
12975}
12976
12977
12978#ifndef HMVMX_USE_FUNCTION_TABLE
12979/**
12980 * Handles a guest VM-exit from hardware-assisted VMX execution.
12981 *
12982 * @returns Strict VBox status code (i.e. informational status codes too).
12983 * @param pVCpu The cross context virtual CPU structure.
12984 * @param pVmxTransient The VMX-transient structure.
12985 */
12986DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12987{
12988#ifdef DEBUG_ramshankar
12989# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12990 do { \
12991 if (a_fSave != 0) \
12992 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12993 VBOXSTRICTRC rcStrict = a_CallExpr; \
12994 if (a_fSave != 0) \
12995 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12996 return rcStrict; \
12997 } while (0)
12998#else
12999# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
13000#endif
13001 uint32_t const uExitReason = pVmxTransient->uExitReason;
13002 switch (uExitReason)
13003 {
13004 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
13005 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
13006 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
13007 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
13008 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
13009 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
13010 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
13011 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
13012 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
13013 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
13014 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
13015 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
13016 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
13017 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
13018 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
13019 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
13020 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
13021 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
13022 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
13023 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
13024 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
13025 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
13026 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
13027 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
13028 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
13029 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
13030 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
13031 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
13032 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
13033 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
13034#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13035 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
13036 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
13037 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
13038 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
13039 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
13040 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
13041 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
13042 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
13043 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
13044 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
13045 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
13046#else
13047 case VMX_EXIT_VMCLEAR:
13048 case VMX_EXIT_VMLAUNCH:
13049 case VMX_EXIT_VMPTRLD:
13050 case VMX_EXIT_VMPTRST:
13051 case VMX_EXIT_VMREAD:
13052 case VMX_EXIT_VMRESUME:
13053 case VMX_EXIT_VMWRITE:
13054 case VMX_EXIT_VMXOFF:
13055 case VMX_EXIT_VMXON:
13056 case VMX_EXIT_INVVPID:
13057 case VMX_EXIT_INVEPT:
13058 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
13059#endif
13060
13061 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
13062 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
13063 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
13064
13065 case VMX_EXIT_INIT_SIGNAL:
13066 case VMX_EXIT_SIPI:
13067 case VMX_EXIT_IO_SMI:
13068 case VMX_EXIT_SMI:
13069 case VMX_EXIT_ERR_MSR_LOAD:
13070 case VMX_EXIT_ERR_MACHINE_CHECK:
13071 case VMX_EXIT_PML_FULL:
13072 case VMX_EXIT_VIRTUALIZED_EOI:
13073 case VMX_EXIT_GDTR_IDTR_ACCESS:
13074 case VMX_EXIT_LDTR_TR_ACCESS:
13075 case VMX_EXIT_APIC_WRITE:
13076 case VMX_EXIT_RDRAND:
13077 case VMX_EXIT_RSM:
13078 case VMX_EXIT_VMFUNC:
13079 case VMX_EXIT_ENCLS:
13080 case VMX_EXIT_RDSEED:
13081 case VMX_EXIT_XSAVES:
13082 case VMX_EXIT_XRSTORS:
13083 case VMX_EXIT_UMWAIT:
13084 case VMX_EXIT_TPAUSE:
13085 default:
13086 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13087 }
13088#undef VMEXIT_CALL_RET
13089}
13090#endif /* !HMVMX_USE_FUNCTION_TABLE */
13091
13092
13093#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13094/**
13095 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13096 *
13097 * @returns Strict VBox status code (i.e. informational status codes too).
13098 * @param pVCpu The cross context virtual CPU structure.
13099 * @param pVmxTransient The VMX-transient structure.
13100 */
13101DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13102{
13103 uint32_t const uExitReason = pVmxTransient->uExitReason;
13104 switch (uExitReason)
13105 {
13106 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13107 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13108 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13109 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13110 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13111
13112 /*
13113 * We shouldn't direct host physical interrupts to the nested-guest.
13114 */
13115 case VMX_EXIT_EXT_INT:
13116 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13117
13118 /*
13119 * Instructions that cause VM-exits unconditionally or the condition is
13120 * always is taken solely from the nested hypervisor (meaning if the VM-exit
13121 * happens, it's guaranteed to be a nested-guest VM-exit).
13122 *
13123 * - Provides VM-exit instruction length ONLY.
13124 */
13125 case VMX_EXIT_CPUID: /* Unconditional. */
13126 case VMX_EXIT_VMCALL:
13127 case VMX_EXIT_GETSEC:
13128 case VMX_EXIT_INVD:
13129 case VMX_EXIT_XSETBV:
13130 case VMX_EXIT_VMLAUNCH:
13131 case VMX_EXIT_VMRESUME:
13132 case VMX_EXIT_VMXOFF:
13133 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
13134 case VMX_EXIT_VMFUNC:
13135 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13136
13137 /*
13138 * Instructions that cause VM-exits unconditionally or the condition is
13139 * always is taken solely from the nested hypervisor (meaning if the VM-exit
13140 * happens, it's guaranteed to be a nested-guest VM-exit).
13141 *
13142 * - Provides VM-exit instruction length.
13143 * - Provides VM-exit information.
13144 * - Optionally provides Exit qualification.
13145 *
13146 * Since Exit qualification is 0 for all VM-exits where it is not
13147 * applicable, reading and passing it to the guest should produce
13148 * defined behavior.
13149 *
13150 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13151 */
13152 case VMX_EXIT_INVEPT: /* Unconditional. */
13153 case VMX_EXIT_INVVPID:
13154 case VMX_EXIT_VMCLEAR:
13155 case VMX_EXIT_VMPTRLD:
13156 case VMX_EXIT_VMPTRST:
13157 case VMX_EXIT_VMXON:
13158 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
13159 case VMX_EXIT_LDTR_TR_ACCESS:
13160 case VMX_EXIT_RDRAND:
13161 case VMX_EXIT_RDSEED:
13162 case VMX_EXIT_XSAVES:
13163 case VMX_EXIT_XRSTORS:
13164 case VMX_EXIT_UMWAIT:
13165 case VMX_EXIT_TPAUSE:
13166 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13167
13168 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13169 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13170 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13171 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13172 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13173 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13174 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13175 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13176 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13177 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13178 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13179 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13180 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13181 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13182 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13183 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13184 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13185 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13186 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13187
13188 case VMX_EXIT_PREEMPT_TIMER:
13189 {
13190 /** @todo NSTVMX: Preempt timer. */
13191 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13192 }
13193
13194 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13195 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13196
13197 case VMX_EXIT_VMREAD:
13198 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13199
13200 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13201 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13202
13203 case VMX_EXIT_INIT_SIGNAL:
13204 case VMX_EXIT_SIPI:
13205 case VMX_EXIT_IO_SMI:
13206 case VMX_EXIT_SMI:
13207 case VMX_EXIT_ERR_MSR_LOAD:
13208 case VMX_EXIT_ERR_MACHINE_CHECK:
13209 case VMX_EXIT_PML_FULL:
13210 case VMX_EXIT_RSM:
13211 default:
13212 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13213 }
13214}
13215#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13216
13217
13218/** @name VM-exit helpers.
13219 * @{
13220 */
13221/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13222/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13223/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13224
13225/** Macro for VM-exits called unexpectedly. */
13226#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13227 do { \
13228 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13229 return VERR_VMX_UNEXPECTED_EXIT; \
13230 } while (0)
13231
13232#ifdef VBOX_STRICT
13233/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13234# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13235 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13236
13237# define HMVMX_ASSERT_PREEMPT_CPUID() \
13238 do { \
13239 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13240 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13241 } while (0)
13242
13243# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13244 do { \
13245 AssertPtr((a_pVCpu)); \
13246 AssertPtr((a_pVmxTransient)); \
13247 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13248 Assert((a_pVmxTransient)->pVmcsInfo); \
13249 Assert(ASMIntAreEnabled()); \
13250 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13251 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13252 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13253 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13254 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13255 HMVMX_ASSERT_PREEMPT_CPUID(); \
13256 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13257 } while (0)
13258
13259# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13260 do { \
13261 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13262 Assert((a_pVmxTransient)->fIsNestedGuest); \
13263 } while (0)
13264
13265# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13266 do { \
13267 Log4Func(("\n")); \
13268 } while (0)
13269#else
13270# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13271 do { \
13272 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13273 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13274 } while (0)
13275
13276# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13277 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13278
13279# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13280#endif
13281
13282#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13283/** Macro that does the necessary privilege checks and intercepted VM-exits for
13284 * guests that attempted to execute a VMX instruction. */
13285# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13286 do \
13287 { \
13288 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13289 if (rcStrictTmp == VINF_SUCCESS) \
13290 { /* likely */ } \
13291 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13292 { \
13293 Assert((a_pVCpu)->hm.s.Event.fPending); \
13294 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13295 return VINF_SUCCESS; \
13296 } \
13297 else \
13298 { \
13299 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13300 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13301 } \
13302 } while (0)
13303
13304/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13305# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13306 do \
13307 { \
13308 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13309 (a_pGCPtrEffAddr)); \
13310 if (rcStrictTmp == VINF_SUCCESS) \
13311 { /* likely */ } \
13312 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13313 { \
13314 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13315 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13316 NOREF(uXcptTmp); \
13317 return VINF_SUCCESS; \
13318 } \
13319 else \
13320 { \
13321 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13322 return rcStrictTmp; \
13323 } \
13324 } while (0)
13325#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13326
13327
13328/**
13329 * Advances the guest RIP by the specified number of bytes.
13330 *
13331 * @param pVCpu The cross context virtual CPU structure.
13332 * @param cbInstr Number of bytes to advance the RIP by.
13333 *
13334 * @remarks No-long-jump zone!!!
13335 */
13336DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
13337{
13338 /* Advance the RIP. */
13339 pVCpu->cpum.GstCtx.rip += cbInstr;
13340 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13341
13342 /* Update interrupt inhibition. */
13343 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13344 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13345 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13346}
13347
13348
13349/**
13350 * Advances the guest RIP after reading it from the VMCS.
13351 *
13352 * @returns VBox status code, no informational status codes.
13353 * @param pVCpu The cross context virtual CPU structure.
13354 * @param pVmxTransient The VMX-transient structure.
13355 *
13356 * @remarks No-long-jump zone!!!
13357 */
13358static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13359{
13360 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13361 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13362 AssertRCReturn(rc, rc);
13363
13364 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
13365 return VINF_SUCCESS;
13366}
13367
13368
13369/**
13370 * Handle a condition that occurred while delivering an event through the guest or
13371 * nested-guest IDT.
13372 *
13373 * @returns Strict VBox status code (i.e. informational status codes too).
13374 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13375 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13376 * to continue execution of the guest which will delivery the \#DF.
13377 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13378 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13379 *
13380 * @param pVCpu The cross context virtual CPU structure.
13381 * @param pVmxTransient The VMX-transient structure.
13382 *
13383 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13384 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13385 * is due to an EPT violation, PML full or SPP-related event.
13386 *
13387 * @remarks No-long-jump zone!!!
13388 */
13389static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13390{
13391 Assert(!pVCpu->hm.s.Event.fPending);
13392 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13393 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13394 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13395 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13396 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13397
13398 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13399 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13400 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13401 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13402 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13403 {
13404 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13405 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13406
13407 /*
13408 * If the event was a software interrupt (generated with INT n) or a software exception
13409 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13410 * can handle the VM-exit and continue guest execution which will re-execute the
13411 * instruction rather than re-injecting the exception, as that can cause premature
13412 * trips to ring-3 before injection and involve TRPM which currently has no way of
13413 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13414 * the problem).
13415 */
13416 IEMXCPTRAISE enmRaise;
13417 IEMXCPTRAISEINFO fRaiseInfo;
13418 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13419 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13420 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13421 {
13422 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13423 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13424 }
13425 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13426 {
13427 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13428 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13429 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13430
13431 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13432 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13433
13434 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13435
13436 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13437 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13438 {
13439 pVmxTransient->fVectoringPF = true;
13440 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13441 }
13442 }
13443 else
13444 {
13445 /*
13446 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13447 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13448 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13449 */
13450 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13451 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13452 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13453 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13454 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13455 }
13456
13457 /*
13458 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13459 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13460 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13461 * subsequent VM-entry would fail, see @bugref{7445}.
13462 *
13463 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13464 */
13465 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13466 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13467 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13468 && CPUMIsGuestNmiBlocking(pVCpu))
13469 {
13470 CPUMSetGuestNmiBlocking(pVCpu, false);
13471 }
13472
13473 switch (enmRaise)
13474 {
13475 case IEMXCPTRAISE_CURRENT_XCPT:
13476 {
13477 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13478 Assert(rcStrict == VINF_SUCCESS);
13479 break;
13480 }
13481
13482 case IEMXCPTRAISE_PREV_EVENT:
13483 {
13484 uint32_t u32ErrCode;
13485 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13486 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13487 else
13488 u32ErrCode = 0;
13489
13490 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13491 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13492 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13493 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13494
13495 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13496 pVCpu->hm.s.Event.u32ErrCode));
13497 Assert(rcStrict == VINF_SUCCESS);
13498 break;
13499 }
13500
13501 case IEMXCPTRAISE_REEXEC_INSTR:
13502 Assert(rcStrict == VINF_SUCCESS);
13503 break;
13504
13505 case IEMXCPTRAISE_DOUBLE_FAULT:
13506 {
13507 /*
13508 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13509 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13510 */
13511 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13512 {
13513 pVmxTransient->fVectoringDoublePF = true;
13514 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13515 pVCpu->cpum.GstCtx.cr2));
13516 rcStrict = VINF_SUCCESS;
13517 }
13518 else
13519 {
13520 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13521 hmR0VmxSetPendingXcptDF(pVCpu);
13522 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13523 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13524 rcStrict = VINF_HM_DOUBLE_FAULT;
13525 }
13526 break;
13527 }
13528
13529 case IEMXCPTRAISE_TRIPLE_FAULT:
13530 {
13531 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13532 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13533 rcStrict = VINF_EM_RESET;
13534 break;
13535 }
13536
13537 case IEMXCPTRAISE_CPU_HANG:
13538 {
13539 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13540 rcStrict = VERR_EM_GUEST_CPU_HANG;
13541 break;
13542 }
13543
13544 default:
13545 {
13546 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13547 rcStrict = VERR_VMX_IPE_2;
13548 break;
13549 }
13550 }
13551 }
13552 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13553 && !CPUMIsGuestNmiBlocking(pVCpu))
13554 {
13555 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13556 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13557 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13558 {
13559 /*
13560 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13561 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13562 * that virtual NMIs remain blocked until the IRET execution is completed.
13563 *
13564 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13565 */
13566 CPUMSetGuestNmiBlocking(pVCpu, true);
13567 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13568 }
13569 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13570 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13571 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13572 {
13573 /*
13574 * Execution of IRET caused an EPT violation, page-modification log-full event or
13575 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13576 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13577 * that virtual NMIs remain blocked until the IRET execution is completed.
13578 *
13579 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13580 */
13581 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13582 {
13583 CPUMSetGuestNmiBlocking(pVCpu, true);
13584 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13585 }
13586 }
13587 }
13588
13589 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13590 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13591 return rcStrict;
13592}
13593
13594
13595#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13596/**
13597 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13598 * guest attempting to execute a VMX instruction.
13599 *
13600 * @returns Strict VBox status code (i.e. informational status codes too).
13601 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13602 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13603 *
13604 * @param pVCpu The cross context virtual CPU structure.
13605 * @param uExitReason The VM-exit reason.
13606 *
13607 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13608 * @remarks No-long-jump zone!!!
13609 */
13610static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13611{
13612 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13613 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13614
13615 /*
13616 * The physical CPU would have already checked the CPU mode/code segment.
13617 * We shall just assert here for paranoia.
13618 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13619 */
13620 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13621 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13622 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13623
13624 if (uExitReason == VMX_EXIT_VMXON)
13625 {
13626 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13627
13628 /*
13629 * We check CR4.VMXE because it is required to be always set while in VMX operation
13630 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13631 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13632 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13633 */
13634 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13635 {
13636 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13637 hmR0VmxSetPendingXcptUD(pVCpu);
13638 return VINF_HM_PENDING_XCPT;
13639 }
13640 }
13641 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13642 {
13643 /*
13644 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13645 * (other than VMXON), we need to raise a #UD.
13646 */
13647 Log4Func(("Not in VMX root mode -> #UD\n"));
13648 hmR0VmxSetPendingXcptUD(pVCpu);
13649 return VINF_HM_PENDING_XCPT;
13650 }
13651
13652 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13653 return VINF_SUCCESS;
13654}
13655
13656
13657/**
13658 * Decodes the memory operand of an instruction that caused a VM-exit.
13659 *
13660 * The Exit qualification field provides the displacement field for memory
13661 * operand instructions, if any.
13662 *
13663 * @returns Strict VBox status code (i.e. informational status codes too).
13664 * @retval VINF_SUCCESS if the operand was successfully decoded.
13665 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13666 * operand.
13667 * @param pVCpu The cross context virtual CPU structure.
13668 * @param uExitInstrInfo The VM-exit instruction information field.
13669 * @param enmMemAccess The memory operand's access type (read or write).
13670 * @param GCPtrDisp The instruction displacement field, if any. For
13671 * RIP-relative addressing pass RIP + displacement here.
13672 * @param pGCPtrMem Where to store the effective destination memory address.
13673 *
13674 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13675 * virtual-8086 mode hence skips those checks while verifying if the
13676 * segment is valid.
13677 */
13678static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13679 PRTGCPTR pGCPtrMem)
13680{
13681 Assert(pGCPtrMem);
13682 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13683 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13684 | CPUMCTX_EXTRN_CR0);
13685
13686 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13687 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13688 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13689
13690 VMXEXITINSTRINFO ExitInstrInfo;
13691 ExitInstrInfo.u = uExitInstrInfo;
13692 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13693 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13694 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13695 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13696 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13697 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13698 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13699 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13700 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13701
13702 /*
13703 * Validate instruction information.
13704 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13705 */
13706 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13707 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13708 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13709 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13710 AssertLogRelMsgReturn(fIsMemOperand,
13711 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13712
13713 /*
13714 * Compute the complete effective address.
13715 *
13716 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13717 * See AMD spec. 4.5.2 "Segment Registers".
13718 */
13719 RTGCPTR GCPtrMem = GCPtrDisp;
13720 if (fBaseRegValid)
13721 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13722 if (fIdxRegValid)
13723 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13724
13725 RTGCPTR const GCPtrOff = GCPtrMem;
13726 if ( !fIsLongMode
13727 || iSegReg >= X86_SREG_FS)
13728 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13729 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13730
13731 /*
13732 * Validate effective address.
13733 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13734 */
13735 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13736 Assert(cbAccess > 0);
13737 if (fIsLongMode)
13738 {
13739 if (X86_IS_CANONICAL(GCPtrMem))
13740 {
13741 *pGCPtrMem = GCPtrMem;
13742 return VINF_SUCCESS;
13743 }
13744
13745 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13746 * "Data Limit Checks in 64-bit Mode". */
13747 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13748 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13749 return VINF_HM_PENDING_XCPT;
13750 }
13751
13752 /*
13753 * This is a watered down version of iemMemApplySegment().
13754 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13755 * and segment CPL/DPL checks are skipped.
13756 */
13757 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13758 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13759 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13760
13761 /* Check if the segment is present and usable. */
13762 if ( pSel->Attr.n.u1Present
13763 && !pSel->Attr.n.u1Unusable)
13764 {
13765 Assert(pSel->Attr.n.u1DescType);
13766 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13767 {
13768 /* Check permissions for the data segment. */
13769 if ( enmMemAccess == VMXMEMACCESS_WRITE
13770 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13771 {
13772 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13773 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13774 return VINF_HM_PENDING_XCPT;
13775 }
13776
13777 /* Check limits if it's a normal data segment. */
13778 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13779 {
13780 if ( GCPtrFirst32 > pSel->u32Limit
13781 || GCPtrLast32 > pSel->u32Limit)
13782 {
13783 Log4Func(("Data segment limit exceeded. "
13784 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13785 GCPtrLast32, pSel->u32Limit));
13786 if (iSegReg == X86_SREG_SS)
13787 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13788 else
13789 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13790 return VINF_HM_PENDING_XCPT;
13791 }
13792 }
13793 else
13794 {
13795 /* Check limits if it's an expand-down data segment.
13796 Note! The upper boundary is defined by the B bit, not the G bit! */
13797 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13798 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13799 {
13800 Log4Func(("Expand-down data segment limit exceeded. "
13801 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13802 GCPtrLast32, pSel->u32Limit));
13803 if (iSegReg == X86_SREG_SS)
13804 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13805 else
13806 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13807 return VINF_HM_PENDING_XCPT;
13808 }
13809 }
13810 }
13811 else
13812 {
13813 /* Check permissions for the code segment. */
13814 if ( enmMemAccess == VMXMEMACCESS_WRITE
13815 || ( enmMemAccess == VMXMEMACCESS_READ
13816 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13817 {
13818 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13819 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13820 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13821 return VINF_HM_PENDING_XCPT;
13822 }
13823
13824 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13825 if ( GCPtrFirst32 > pSel->u32Limit
13826 || GCPtrLast32 > pSel->u32Limit)
13827 {
13828 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13829 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13830 if (iSegReg == X86_SREG_SS)
13831 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13832 else
13833 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13834 return VINF_HM_PENDING_XCPT;
13835 }
13836 }
13837 }
13838 else
13839 {
13840 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13841 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13842 return VINF_HM_PENDING_XCPT;
13843 }
13844
13845 *pGCPtrMem = GCPtrMem;
13846 return VINF_SUCCESS;
13847}
13848#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13849
13850
13851/**
13852 * VM-exit helper for LMSW.
13853 */
13854static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13855{
13856 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13857 AssertRCReturn(rc, rc);
13858
13859 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13860 AssertMsg( rcStrict == VINF_SUCCESS
13861 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13862
13863 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13864 if (rcStrict == VINF_IEM_RAISED_XCPT)
13865 {
13866 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13867 rcStrict = VINF_SUCCESS;
13868 }
13869
13870 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13871 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13872 return rcStrict;
13873}
13874
13875
13876/**
13877 * VM-exit helper for CLTS.
13878 */
13879static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13880{
13881 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13882 AssertRCReturn(rc, rc);
13883
13884 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13885 AssertMsg( rcStrict == VINF_SUCCESS
13886 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13887
13888 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13889 if (rcStrict == VINF_IEM_RAISED_XCPT)
13890 {
13891 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13892 rcStrict = VINF_SUCCESS;
13893 }
13894
13895 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13896 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13897 return rcStrict;
13898}
13899
13900
13901/**
13902 * VM-exit helper for MOV from CRx (CRx read).
13903 */
13904static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13905{
13906 Assert(iCrReg < 16);
13907 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13908
13909 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13910 AssertRCReturn(rc, rc);
13911
13912 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13913 AssertMsg( rcStrict == VINF_SUCCESS
13914 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13915
13916 if (iGReg == X86_GREG_xSP)
13917 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13918 else
13919 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13920#ifdef VBOX_WITH_STATISTICS
13921 switch (iCrReg)
13922 {
13923 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13924 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13925 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13926 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13927 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13928 }
13929#endif
13930 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13931 return rcStrict;
13932}
13933
13934
13935/**
13936 * VM-exit helper for MOV to CRx (CRx write).
13937 */
13938static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13939{
13940 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13941 AssertRCReturn(rc, rc);
13942
13943 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13944 AssertMsg( rcStrict == VINF_SUCCESS
13945 || rcStrict == VINF_IEM_RAISED_XCPT
13946 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13947
13948 switch (iCrReg)
13949 {
13950 case 0:
13951 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13952 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13953 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13954 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13955 break;
13956
13957 case 2:
13958 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13959 /* Nothing to do here, CR2 it's not part of the VMCS. */
13960 break;
13961
13962 case 3:
13963 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13964 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13965 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13966 break;
13967
13968 case 4:
13969 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13970 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13971 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13972 pVCpu->cpum.GstCtx.cr4, pVCpu->hmr0.s.fLoadSaveGuestXcr0));
13973 break;
13974
13975 case 8:
13976 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13977 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13978 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13979 break;
13980
13981 default:
13982 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13983 break;
13984 }
13985
13986 if (rcStrict == VINF_IEM_RAISED_XCPT)
13987 {
13988 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13989 rcStrict = VINF_SUCCESS;
13990 }
13991 return rcStrict;
13992}
13993
13994
13995/**
13996 * VM-exit exception handler for \#PF (Page-fault exception).
13997 *
13998 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13999 */
14000static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14001{
14002 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14003 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14004 hmR0VmxReadExitQualVmcs(pVmxTransient);
14005
14006 if (!pVM->hmr0.s.fNestedPaging)
14007 { /* likely */ }
14008 else
14009 {
14010#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
14011 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hmr0.s.fUsingDebugLoop);
14012#endif
14013 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
14014 if (!pVmxTransient->fVectoringDoublePF)
14015 {
14016 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14017 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
14018 }
14019 else
14020 {
14021 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14022 Assert(!pVmxTransient->fIsNestedGuest);
14023 hmR0VmxSetPendingXcptDF(pVCpu);
14024 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
14025 }
14026 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14027 return VINF_SUCCESS;
14028 }
14029
14030 Assert(!pVmxTransient->fIsNestedGuest);
14031
14032 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
14033 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
14034 if (pVmxTransient->fVectoringPF)
14035 {
14036 Assert(pVCpu->hm.s.Event.fPending);
14037 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14038 }
14039
14040 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14041 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14042 AssertRCReturn(rc, rc);
14043
14044 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
14045 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
14046
14047 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
14048 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
14049
14050 Log4Func(("#PF: rc=%Rrc\n", rc));
14051 if (rc == VINF_SUCCESS)
14052 {
14053 /*
14054 * This is typically a shadow page table sync or a MMIO instruction. But we may have
14055 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
14056 */
14057 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14058 TRPMResetTrap(pVCpu);
14059 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
14060 return rc;
14061 }
14062
14063 if (rc == VINF_EM_RAW_GUEST_TRAP)
14064 {
14065 if (!pVmxTransient->fVectoringDoublePF)
14066 {
14067 /* It's a guest page fault and needs to be reflected to the guest. */
14068 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
14069 TRPMResetTrap(pVCpu);
14070 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
14071 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14072 uGstErrorCode, pVmxTransient->uExitQual);
14073 }
14074 else
14075 {
14076 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14077 TRPMResetTrap(pVCpu);
14078 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14079 hmR0VmxSetPendingXcptDF(pVCpu);
14080 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14081 }
14082
14083 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14084 return VINF_SUCCESS;
14085 }
14086
14087 TRPMResetTrap(pVCpu);
14088 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14089 return rc;
14090}
14091
14092
14093/**
14094 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14095 *
14096 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14097 */
14098static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14099{
14100 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14101 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14102
14103 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14104 AssertRCReturn(rc, rc);
14105
14106 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14107 {
14108 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14109 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14110
14111 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14112 * provides VM-exit instruction length. If this causes problem later,
14113 * disassemble the instruction like it's done on AMD-V. */
14114 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14115 AssertRCReturn(rc2, rc2);
14116 return rc;
14117 }
14118
14119 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
14120 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14121 return VINF_SUCCESS;
14122}
14123
14124
14125/**
14126 * VM-exit exception handler for \#BP (Breakpoint exception).
14127 *
14128 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14129 */
14130static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14131{
14132 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14133 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14134
14135 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14136 AssertRCReturn(rc, rc);
14137
14138 if (!pVmxTransient->fIsNestedGuest)
14139 rc = DBGFTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
14140 else
14141 rc = VINF_EM_RAW_GUEST_TRAP;
14142
14143 if (rc == VINF_EM_RAW_GUEST_TRAP)
14144 {
14145 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14146 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14147 rc = VINF_SUCCESS;
14148 }
14149
14150 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
14151 return rc;
14152}
14153
14154
14155/**
14156 * VM-exit exception handler for \#AC (Alignment-check exception).
14157 *
14158 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14159 */
14160static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14161{
14162 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14163
14164 /*
14165 * Detect #ACs caused by host having enabled split-lock detection.
14166 * Emulate such instructions.
14167 */
14168 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo,
14169 CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS);
14170 AssertRCReturn(rc, rc);
14171 /** @todo detect split lock in cpu feature? */
14172 if ( /* 1. If 486-style alignment checks aren't enabled, then this must be a split-lock exception */
14173 !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_AM)
14174 /* 2. #AC cannot happen in rings 0-2 except for split-lock detection. */
14175 || CPUMGetGuestCPL(pVCpu) != 3
14176 /* 3. When the EFLAGS.AC != 0 this can only be a split-lock case. */
14177 || !(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_AC) )
14178 {
14179 /*
14180 * Check for debug/trace events and import state accordingly.
14181 */
14182 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitGuestACSplitLock);
14183 PVMCC pVM = pVCpu->pVMR0;
14184 if ( !DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_VMX_SPLIT_LOCK)
14185 && !VBOXVMM_VMX_SPLIT_LOCK_ENABLED())
14186 {
14187 if (pVM->cCpus == 1)
14188 {
14189#if 0 /** @todo r=bird: This is potentially wrong. Might have to just do a whole state sync above and mark everything changed to be safe... */
14190 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14191#else
14192 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14193#endif
14194 AssertRCReturn(rc, rc);
14195 }
14196 }
14197 else
14198 {
14199 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14200 AssertRCReturn(rc, rc);
14201
14202 VBOXVMM_XCPT_DF(pVCpu, &pVCpu->cpum.GstCtx);
14203
14204 if (DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_VMX_SPLIT_LOCK))
14205 {
14206 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, DBGFEVENT_VMX_SPLIT_LOCK, DBGFEVENTCTX_HM, 0);
14207 if (rcStrict != VINF_SUCCESS)
14208 return rcStrict;
14209 }
14210 }
14211
14212 /*
14213 * Emulate the instruction.
14214 *
14215 * We have to ignore the LOCK prefix here as we must not retrigger the
14216 * detection on the host. This isn't all that satisfactory, though...
14217 */
14218 if (pVM->cCpus == 1)
14219 {
14220 Log8Func(("cs:rip=%#04x:%#RX64 rflags=%#RX64 cr0=%#RX64 split-lock #AC\n", pVCpu->cpum.GstCtx.cs.Sel,
14221 pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.rflags, pVCpu->cpum.GstCtx.cr0));
14222
14223 /** @todo For SMP configs we should do a rendezvous here. */
14224 VBOXSTRICTRC rcStrict = IEMExecOneIgnoreLock(pVCpu);
14225 if (rcStrict == VINF_SUCCESS)
14226#if 0 /** @todo r=bird: This is potentially wrong. Might have to just do a whole state sync above and mark everything changed to be safe... */
14227 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
14228 HM_CHANGED_GUEST_RIP
14229 | HM_CHANGED_GUEST_RFLAGS
14230 | HM_CHANGED_GUEST_GPRS_MASK
14231 | HM_CHANGED_GUEST_CS
14232 | HM_CHANGED_GUEST_SS);
14233#else
14234 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14235#endif
14236 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14237 {
14238 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14239 rcStrict = VINF_SUCCESS;
14240 }
14241 return rcStrict;
14242 }
14243 Log8Func(("cs:rip=%#04x:%#RX64 rflags=%#RX64 cr0=%#RX64 split-lock #AC -> VINF_EM_EMULATE_SPLIT_LOCK\n",
14244 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.rflags, pVCpu->cpum.GstCtx.cr0));
14245 return VINF_EM_EMULATE_SPLIT_LOCK;
14246 }
14247
14248 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14249 Log8Func(("cs:rip=%#04x:%#RX64 rflags=%#RX64 cr0=%#RX64 cpl=%d -> #AC\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14250 pVCpu->cpum.GstCtx.rflags, pVCpu->cpum.GstCtx.cr0, CPUMGetGuestCPL(pVCpu) ));
14251
14252 /* Re-inject it. We'll detect any nesting before getting here. */
14253 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14254 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14255 return VINF_SUCCESS;
14256}
14257
14258
14259/**
14260 * VM-exit exception handler for \#DB (Debug exception).
14261 *
14262 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14263 */
14264static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14265{
14266 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14267 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14268
14269 /*
14270 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14271 */
14272 hmR0VmxReadExitQualVmcs(pVmxTransient);
14273
14274 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14275 uint64_t const uDR6 = X86_DR6_INIT_VAL
14276 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14277 | X86_DR6_BD | X86_DR6_BS));
14278
14279 int rc;
14280 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14281 if (!pVmxTransient->fIsNestedGuest)
14282 {
14283 rc = DBGFTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14284
14285 /*
14286 * Prevents stepping twice over the same instruction when the guest is stepping using
14287 * EFLAGS.TF and the hypervisor debugger is stepping using MTF.
14288 * Testcase: DOSQEMM, break (using "ba x 1") at cs:rip 0x70:0x774 and step (using "t").
14289 */
14290 if ( rc == VINF_EM_DBG_STEPPED
14291 && (pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MONITOR_TRAP_FLAG))
14292 {
14293 Assert(pVCpu->hm.s.fSingleInstruction);
14294 rc = VINF_EM_RAW_GUEST_TRAP;
14295 }
14296 }
14297 else
14298 rc = VINF_EM_RAW_GUEST_TRAP;
14299 Log6Func(("rc=%Rrc\n", rc));
14300 if (rc == VINF_EM_RAW_GUEST_TRAP)
14301 {
14302 /*
14303 * The exception was for the guest. Update DR6, DR7.GD and
14304 * IA32_DEBUGCTL.LBR before forwarding it.
14305 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14306 */
14307 VMMRZCallRing3Disable(pVCpu);
14308 HM_DISABLE_PREEMPT(pVCpu);
14309
14310 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14311 pCtx->dr[6] |= uDR6;
14312 if (CPUMIsGuestDebugStateActive(pVCpu))
14313 ASMSetDR6(pCtx->dr[6]);
14314
14315 HM_RESTORE_PREEMPT();
14316 VMMRZCallRing3Enable(pVCpu);
14317
14318 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14319 AssertRCReturn(rc, rc);
14320
14321 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14322 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
14323
14324 /* Paranoia. */
14325 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
14326 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14327
14328 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
14329 AssertRC(rc);
14330
14331 /*
14332 * Raise #DB in the guest.
14333 *
14334 * It is important to reflect exactly what the VM-exit gave us (preserving the
14335 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14336 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14337 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14338 *
14339 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14340 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14341 */
14342 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14343 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14344 return VINF_SUCCESS;
14345 }
14346
14347 /*
14348 * Not a guest trap, must be a hypervisor related debug event then.
14349 * Update DR6 in case someone is interested in it.
14350 */
14351 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14352 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14353 CPUMSetHyperDR6(pVCpu, uDR6);
14354
14355 return rc;
14356}
14357
14358
14359/**
14360 * Hacks its way around the lovely mesa driver's backdoor accesses.
14361 *
14362 * @sa hmR0SvmHandleMesaDrvGp.
14363 */
14364static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14365{
14366 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14367 RT_NOREF(pCtx);
14368
14369 /* For now we'll just skip the instruction. */
14370 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14371}
14372
14373
14374/**
14375 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14376 * backdoor logging w/o checking what it is running inside.
14377 *
14378 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14379 * backdoor port and magic numbers loaded in registers.
14380 *
14381 * @returns true if it is, false if it isn't.
14382 * @sa hmR0SvmIsMesaDrvGp.
14383 */
14384DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14385{
14386 /* 0xed: IN eAX,dx */
14387 uint8_t abInstr[1];
14388 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
14389 return false;
14390
14391 /* Check that it is #GP(0). */
14392 if (pVmxTransient->uExitIntErrorCode != 0)
14393 return false;
14394
14395 /* Check magic and port. */
14396 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14397 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14398 if (pCtx->rax != UINT32_C(0x564d5868))
14399 return false;
14400 if (pCtx->dx != UINT32_C(0x5658))
14401 return false;
14402
14403 /* Flat ring-3 CS. */
14404 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14405 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14406 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14407 if (pCtx->cs.Attr.n.u2Dpl != 3)
14408 return false;
14409 if (pCtx->cs.u64Base != 0)
14410 return false;
14411
14412 /* Check opcode. */
14413 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14414 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14415 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14416 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14417 if (RT_FAILURE(rc))
14418 return false;
14419 if (abInstr[0] != 0xed)
14420 return false;
14421
14422 return true;
14423}
14424
14425
14426/**
14427 * VM-exit exception handler for \#GP (General-protection exception).
14428 *
14429 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14430 */
14431static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14432{
14433 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14434 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14435
14436 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14437 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14438 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
14439 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
14440 { /* likely */ }
14441 else
14442 {
14443#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14444 Assert(pVCpu->hmr0.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14445#endif
14446 /*
14447 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14448 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14449 */
14450 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14451 AssertRCReturn(rc, rc);
14452 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14453 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14454
14455 if ( pVmxTransient->fIsNestedGuest
14456 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14457 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14458 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14459 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14460 else
14461 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14462 return rc;
14463 }
14464
14465 Assert(CPUMIsGuestInRealModeEx(pCtx));
14466 Assert(!pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest);
14467 Assert(!pVmxTransient->fIsNestedGuest);
14468
14469 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14470 AssertRCReturn(rc, rc);
14471
14472 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14473 if (rcStrict == VINF_SUCCESS)
14474 {
14475 if (!CPUMIsGuestInRealModeEx(pCtx))
14476 {
14477 /*
14478 * The guest is no longer in real-mode, check if we can continue executing the
14479 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14480 */
14481 pVmcsInfoShared->RealMode.fRealOnV86Active = false;
14482 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
14483 {
14484 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14485 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14486 }
14487 else
14488 {
14489 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14490 rcStrict = VINF_EM_RESCHEDULE;
14491 }
14492 }
14493 else
14494 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14495 }
14496 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14497 {
14498 rcStrict = VINF_SUCCESS;
14499 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14500 }
14501 return VBOXSTRICTRC_VAL(rcStrict);
14502}
14503
14504
14505/**
14506 * VM-exit exception handler wrapper for all other exceptions that are not handled
14507 * by a specific handler.
14508 *
14509 * This simply re-injects the exception back into the VM without any special
14510 * processing.
14511 *
14512 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14513 */
14514static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14515{
14516 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14517
14518#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14519 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14520 AssertMsg(pVCpu->hmr0.s.fUsingDebugLoop || pVmcsInfo->pShared->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14521 ("uVector=%#x u32XcptBitmap=%#X32\n",
14522 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14523 NOREF(pVmcsInfo);
14524#endif
14525
14526 /*
14527 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14528 * would have been handled while checking exits due to event delivery.
14529 */
14530 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14531
14532#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14533 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14534 AssertRCReturn(rc, rc);
14535 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14536#endif
14537
14538#ifdef VBOX_WITH_STATISTICS
14539 switch (uVector)
14540 {
14541 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14542 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14543 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14544 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14545 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14546 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14547 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14548 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14549 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14550 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14551 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14552 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14553 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14554 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14555 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14556 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14557 default:
14558 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14559 break;
14560 }
14561#endif
14562
14563 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14564 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14565 NOREF(uVector);
14566
14567 /* Re-inject the original exception into the guest. */
14568 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14569 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14570 return VINF_SUCCESS;
14571}
14572
14573
14574/**
14575 * VM-exit exception handler for all exceptions (except NMIs!).
14576 *
14577 * @remarks This may be called for both guests and nested-guests. Take care to not
14578 * make assumptions and avoid doing anything that is not relevant when
14579 * executing a nested-guest (e.g., Mesa driver hacks).
14580 */
14581static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14582{
14583 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14584
14585 /*
14586 * If this VM-exit occurred while delivering an event through the guest IDT, take
14587 * action based on the return code and additional hints (e.g. for page-faults)
14588 * that will be updated in the VMX transient structure.
14589 */
14590 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14591 if (rcStrict == VINF_SUCCESS)
14592 {
14593 /*
14594 * If an exception caused a VM-exit due to delivery of an event, the original
14595 * event may have to be re-injected into the guest. We shall reinject it and
14596 * continue guest execution. However, page-fault is a complicated case and
14597 * needs additional processing done in hmR0VmxExitXcptPF().
14598 */
14599 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14600 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14601 if ( !pVCpu->hm.s.Event.fPending
14602 || uVector == X86_XCPT_PF)
14603 {
14604 switch (uVector)
14605 {
14606 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14607 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14608 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14609 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14610 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14611 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14612 default:
14613 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14614 }
14615 }
14616 /* else: inject pending event before resuming guest execution. */
14617 }
14618 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14619 {
14620 Assert(pVCpu->hm.s.Event.fPending);
14621 rcStrict = VINF_SUCCESS;
14622 }
14623
14624 return rcStrict;
14625}
14626/** @} */
14627
14628
14629/** @name VM-exit handlers.
14630 * @{
14631 */
14632/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14633/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14634/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14635
14636/**
14637 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14638 */
14639HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14640{
14641 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14642 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14643 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14644 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14645 return VINF_SUCCESS;
14646 return VINF_EM_RAW_INTERRUPT;
14647}
14648
14649
14650/**
14651 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14652 * VM-exit.
14653 */
14654HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14655{
14656 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14657 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14658
14659 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14660
14661 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14662 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14663 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14664
14665 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14666 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14667 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14668 NOREF(pVmcsInfo);
14669
14670 VBOXSTRICTRC rcStrict;
14671 switch (uExitIntType)
14672 {
14673 /*
14674 * Host physical NMIs:
14675 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14676 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14677 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14678 *
14679 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14680 * See Intel spec. 27.5.5 "Updating Non-Register State".
14681 */
14682 case VMX_EXIT_INT_INFO_TYPE_NMI:
14683 {
14684 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14685 break;
14686 }
14687
14688 /*
14689 * Privileged software exceptions (#DB from ICEBP),
14690 * Software exceptions (#BP and #OF),
14691 * Hardware exceptions:
14692 * Process the required exceptions and resume guest execution if possible.
14693 */
14694 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14695 Assert(uVector == X86_XCPT_DB);
14696 RT_FALL_THRU();
14697 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14698 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14699 RT_FALL_THRU();
14700 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14701 {
14702 NOREF(uVector);
14703 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14704 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14705 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14706 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14707
14708 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14709 break;
14710 }
14711
14712 default:
14713 {
14714 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14715 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14716 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14717 break;
14718 }
14719 }
14720
14721 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14722 return rcStrict;
14723}
14724
14725
14726/**
14727 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14728 */
14729HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14730{
14731 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14732
14733 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14734 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14735 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14736
14737 /* Evaluate and deliver pending events and resume guest execution. */
14738 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14739 return VINF_SUCCESS;
14740}
14741
14742
14743/**
14744 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14745 */
14746HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14747{
14748 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14749
14750 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14751 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14752 {
14753 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14754 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14755 }
14756
14757 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14758
14759 /*
14760 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14761 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14762 */
14763 uint32_t fIntrState;
14764 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14765 AssertRC(rc);
14766 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14767 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14768 {
14769 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14770 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14771
14772 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14773 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14774 AssertRC(rc);
14775 }
14776
14777 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14778 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14779
14780 /* Evaluate and deliver pending events and resume guest execution. */
14781 return VINF_SUCCESS;
14782}
14783
14784
14785/**
14786 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14787 */
14788HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14789{
14790 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14791 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14792}
14793
14794
14795/**
14796 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14797 */
14798HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14799{
14800 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14801 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14802}
14803
14804
14805/**
14806 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14807 */
14808HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14809{
14810 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14811
14812 /*
14813 * Get the state we need and update the exit history entry.
14814 */
14815 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14816 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14817
14818 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14819 AssertRCReturn(rc, rc);
14820
14821 VBOXSTRICTRC rcStrict;
14822 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14823 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14824 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14825 if (!pExitRec)
14826 {
14827 /*
14828 * Regular CPUID instruction execution.
14829 */
14830 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14831 if (rcStrict == VINF_SUCCESS)
14832 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14833 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14834 {
14835 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14836 rcStrict = VINF_SUCCESS;
14837 }
14838 }
14839 else
14840 {
14841 /*
14842 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14843 */
14844 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14845 AssertRCReturn(rc2, rc2);
14846
14847 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14848 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14849
14850 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14851 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14852
14853 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14854 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14855 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14856 }
14857 return rcStrict;
14858}
14859
14860
14861/**
14862 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14863 */
14864HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14865{
14866 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14867
14868 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14869 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14870 AssertRCReturn(rc, rc);
14871
14872 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14873 return VINF_EM_RAW_EMULATE_INSTR;
14874
14875 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14876 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14877}
14878
14879
14880/**
14881 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14882 */
14883HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14884{
14885 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14886
14887 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14888 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14889 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14890 AssertRCReturn(rc, rc);
14891
14892 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14893 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14894 {
14895 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14896 we must reset offsetting on VM-entry. See @bugref{6634}. */
14897 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14898 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14899 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14900 }
14901 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14902 {
14903 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14904 rcStrict = VINF_SUCCESS;
14905 }
14906 return rcStrict;
14907}
14908
14909
14910/**
14911 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14912 */
14913HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14914{
14915 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14916
14917 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14918 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14919 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14920 AssertRCReturn(rc, rc);
14921
14922 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14923 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14924 {
14925 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14926 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14927 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14928 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14929 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14930 }
14931 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14932 {
14933 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14934 rcStrict = VINF_SUCCESS;
14935 }
14936 return rcStrict;
14937}
14938
14939
14940/**
14941 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14942 */
14943HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14944{
14945 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14946
14947 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14948 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14949 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14950 AssertRCReturn(rc, rc);
14951
14952 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14953 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14954 if (RT_LIKELY(rc == VINF_SUCCESS))
14955 {
14956 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14957 Assert(pVmxTransient->cbExitInstr == 2);
14958 }
14959 else
14960 {
14961 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14962 rc = VERR_EM_INTERPRETER;
14963 }
14964 return rc;
14965}
14966
14967
14968/**
14969 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14970 */
14971HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14972{
14973 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14974
14975 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14976 if (EMAreHypercallInstructionsEnabled(pVCpu))
14977 {
14978 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14979 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14980 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14981 AssertRCReturn(rc, rc);
14982
14983 /* Perform the hypercall. */
14984 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14985 if (rcStrict == VINF_SUCCESS)
14986 {
14987 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14988 AssertRCReturn(rc, rc);
14989 }
14990 else
14991 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14992 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14993 || RT_FAILURE(rcStrict));
14994
14995 /* If the hypercall changes anything other than guest's general-purpose registers,
14996 we would need to reload the guest changed bits here before VM-entry. */
14997 }
14998 else
14999 Log4Func(("Hypercalls not enabled\n"));
15000
15001 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
15002 if (RT_FAILURE(rcStrict))
15003 {
15004 hmR0VmxSetPendingXcptUD(pVCpu);
15005 rcStrict = VINF_SUCCESS;
15006 }
15007
15008 return rcStrict;
15009}
15010
15011
15012/**
15013 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
15014 */
15015HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15016{
15017 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15018 Assert(!pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging || pVCpu->hmr0.s.fUsingDebugLoop);
15019
15020 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15021 hmR0VmxReadExitQualVmcs(pVmxTransient);
15022 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15023 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15024 AssertRCReturn(rc, rc);
15025
15026 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
15027
15028 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
15029 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15030 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15031 {
15032 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15033 rcStrict = VINF_SUCCESS;
15034 }
15035 else
15036 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
15037 VBOXSTRICTRC_VAL(rcStrict)));
15038 return rcStrict;
15039}
15040
15041
15042/**
15043 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
15044 */
15045HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15046{
15047 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15048
15049 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15050 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15051 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
15052 AssertRCReturn(rc, rc);
15053
15054 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
15055 if (rcStrict == VINF_SUCCESS)
15056 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15057 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15058 {
15059 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15060 rcStrict = VINF_SUCCESS;
15061 }
15062
15063 return rcStrict;
15064}
15065
15066
15067/**
15068 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
15069 */
15070HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15071{
15072 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15073
15074 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15075 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15076 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15077 AssertRCReturn(rc, rc);
15078
15079 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
15080 if (RT_SUCCESS(rcStrict))
15081 {
15082 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15083 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
15084 rcStrict = VINF_SUCCESS;
15085 }
15086
15087 return rcStrict;
15088}
15089
15090
15091/**
15092 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
15093 * VM-exit.
15094 */
15095HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15096{
15097 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15098 return VINF_EM_RESET;
15099}
15100
15101
15102/**
15103 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
15104 */
15105HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15106{
15107 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15108
15109 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15110 AssertRCReturn(rc, rc);
15111
15112 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
15113 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
15114 rc = VINF_SUCCESS;
15115 else
15116 rc = VINF_EM_HALT;
15117
15118 if (rc != VINF_SUCCESS)
15119 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
15120 return rc;
15121}
15122
15123
15124/**
15125 * VM-exit handler for instructions that result in a \#UD exception delivered to
15126 * the guest.
15127 */
15128HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15129{
15130 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15131 hmR0VmxSetPendingXcptUD(pVCpu);
15132 return VINF_SUCCESS;
15133}
15134
15135
15136/**
15137 * VM-exit handler for expiry of the VMX-preemption timer.
15138 */
15139HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15140{
15141 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15142
15143 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
15144 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15145Log12(("hmR0VmxExitPreemptTimer:\n"));
15146
15147 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
15148 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15149 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
15150 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
15151 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
15152}
15153
15154
15155/**
15156 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
15157 */
15158HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15159{
15160 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15161
15162 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15163 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15164 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15165 AssertRCReturn(rc, rc);
15166
15167 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
15168 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15169 : HM_CHANGED_RAISED_XCPT_MASK);
15170
15171 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15172 bool const fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15173 if (fLoadSaveGuestXcr0 != pVCpu->hmr0.s.fLoadSaveGuestXcr0)
15174 {
15175 pVCpu->hmr0.s.fLoadSaveGuestXcr0 = fLoadSaveGuestXcr0;
15176 hmR0VmxUpdateStartVmFunction(pVCpu);
15177 }
15178
15179 return rcStrict;
15180}
15181
15182
15183/**
15184 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15185 */
15186HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15187{
15188 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15189
15190 /** @todo Enable the new code after finding a reliably guest test-case. */
15191#if 1
15192 return VERR_EM_INTERPRETER;
15193#else
15194 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15195 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15196 hmR0VmxReadExitQualVmcs(pVmxTransient);
15197 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15198 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15199 AssertRCReturn(rc, rc);
15200
15201 /* Paranoia. Ensure this has a memory operand. */
15202 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
15203
15204 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
15205 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
15206 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
15207 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
15208
15209 RTGCPTR GCPtrDesc;
15210 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
15211
15212 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
15213 GCPtrDesc, uType);
15214 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15215 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15216 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15217 {
15218 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15219 rcStrict = VINF_SUCCESS;
15220 }
15221 return rcStrict;
15222#endif
15223}
15224
15225
15226/**
15227 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15228 * VM-exit.
15229 */
15230HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15231{
15232 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15233 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15234 AssertRCReturn(rc, rc);
15235
15236 rc = hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15237 if (RT_FAILURE(rc))
15238 return rc;
15239
15240 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15241 NOREF(uInvalidReason);
15242
15243#ifdef VBOX_STRICT
15244 uint32_t fIntrState;
15245 uint64_t u64Val;
15246 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15247 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15248 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15249
15250 Log4(("uInvalidReason %u\n", uInvalidReason));
15251 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15252 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15253 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15254
15255 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
15256 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15257 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
15258 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
15259 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
15260 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
15261 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
15262 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
15263 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
15264 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
15265 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
15266 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
15267 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging)
15268 {
15269 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15270 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15271 }
15272 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
15273#endif
15274
15275 return VERR_VMX_INVALID_GUEST_STATE;
15276}
15277
15278/**
15279 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15280 */
15281HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15282{
15283 /*
15284 * Cumulative notes of all recognized but unexpected VM-exits.
15285 *
15286 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
15287 * nested-paging is used.
15288 *
15289 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15290 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15291 * this function (and thereby stop VM execution) for handling such instructions.
15292 *
15293 *
15294 * VMX_EXIT_INIT_SIGNAL:
15295 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15296 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15297 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15298 *
15299 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15300 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15301 * See Intel spec. "23.8 Restrictions on VMX operation".
15302 *
15303 * VMX_EXIT_SIPI:
15304 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15305 * activity state is used. We don't make use of it as our guests don't have direct
15306 * access to the host local APIC.
15307 *
15308 * See Intel spec. 25.3 "Other Causes of VM-exits".
15309 *
15310 * VMX_EXIT_IO_SMI:
15311 * VMX_EXIT_SMI:
15312 * This can only happen if we support dual-monitor treatment of SMI, which can be
15313 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15314 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15315 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15316 *
15317 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15318 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15319 *
15320 * VMX_EXIT_ERR_MSR_LOAD:
15321 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15322 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15323 * execution.
15324 *
15325 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15326 *
15327 * VMX_EXIT_ERR_MACHINE_CHECK:
15328 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15329 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15330 * #MC exception abort class exception is raised. We thus cannot assume a
15331 * reasonable chance of continuing any sort of execution and we bail.
15332 *
15333 * See Intel spec. 15.1 "Machine-check Architecture".
15334 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15335 *
15336 * VMX_EXIT_PML_FULL:
15337 * VMX_EXIT_VIRTUALIZED_EOI:
15338 * VMX_EXIT_APIC_WRITE:
15339 * We do not currently support any of these features and thus they are all unexpected
15340 * VM-exits.
15341 *
15342 * VMX_EXIT_GDTR_IDTR_ACCESS:
15343 * VMX_EXIT_LDTR_TR_ACCESS:
15344 * VMX_EXIT_RDRAND:
15345 * VMX_EXIT_RSM:
15346 * VMX_EXIT_VMFUNC:
15347 * VMX_EXIT_ENCLS:
15348 * VMX_EXIT_RDSEED:
15349 * VMX_EXIT_XSAVES:
15350 * VMX_EXIT_XRSTORS:
15351 * VMX_EXIT_UMWAIT:
15352 * VMX_EXIT_TPAUSE:
15353 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15354 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15355 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15356 *
15357 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15358 */
15359 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15360 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15361 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15362}
15363
15364
15365/**
15366 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15367 */
15368HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15369{
15370 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15371
15372 /** @todo Optimize this: We currently drag in the whole MSR state
15373 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15374 * MSRs required. That would require changes to IEM and possibly CPUM too.
15375 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15376 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15377 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15378 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15379 switch (idMsr)
15380 {
15381 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15382 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15383 }
15384
15385 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15386 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15387 AssertRCReturn(rc, rc);
15388
15389 Log4Func(("ecx=%#RX32\n", idMsr));
15390
15391#ifdef VBOX_STRICT
15392 Assert(!pVmxTransient->fIsNestedGuest);
15393 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15394 {
15395 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15396 && idMsr != MSR_K6_EFER)
15397 {
15398 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15399 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15400 }
15401 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15402 {
15403 Assert(pVmcsInfo->pvMsrBitmap);
15404 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15405 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15406 {
15407 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15408 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15409 }
15410 }
15411 }
15412#endif
15413
15414 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
15415 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15416 if (rcStrict == VINF_SUCCESS)
15417 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15418 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15419 {
15420 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15421 rcStrict = VINF_SUCCESS;
15422 }
15423 else
15424 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ || rcStrict == VINF_EM_TRIPLE_FAULT,
15425 ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15426
15427 return rcStrict;
15428}
15429
15430
15431/**
15432 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15433 */
15434HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15435{
15436 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15437
15438 /** @todo Optimize this: We currently drag in the whole MSR state
15439 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15440 * MSRs required. That would require changes to IEM and possibly CPUM too.
15441 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15442 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15443 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15444
15445 /*
15446 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15447 * Although we don't need to fetch the base as it will be overwritten shortly, while
15448 * loading guest-state we would also load the entire segment register including limit
15449 * and attributes and thus we need to load them here.
15450 */
15451 switch (idMsr)
15452 {
15453 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15454 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15455 }
15456
15457 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15458 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15459 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15460 AssertRCReturn(rc, rc);
15461
15462 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15463
15464 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
15465 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15466
15467 if (rcStrict == VINF_SUCCESS)
15468 {
15469 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15470
15471 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15472 if ( idMsr == MSR_IA32_APICBASE
15473 || ( idMsr >= MSR_IA32_X2APIC_START
15474 && idMsr <= MSR_IA32_X2APIC_END))
15475 {
15476 /*
15477 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15478 * When full APIC register virtualization is implemented we'll have to make
15479 * sure APIC state is saved from the VMCS before IEM changes it.
15480 */
15481 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15482 }
15483 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15484 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15485 else if (idMsr == MSR_K6_EFER)
15486 {
15487 /*
15488 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15489 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15490 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15491 */
15492 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15493 }
15494
15495 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15496 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15497 {
15498 switch (idMsr)
15499 {
15500 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15501 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15502 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15503 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15504 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15505 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15506 default:
15507 {
15508 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15509 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15510 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15511 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15512 break;
15513 }
15514 }
15515 }
15516#ifdef VBOX_STRICT
15517 else
15518 {
15519 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15520 switch (idMsr)
15521 {
15522 case MSR_IA32_SYSENTER_CS:
15523 case MSR_IA32_SYSENTER_EIP:
15524 case MSR_IA32_SYSENTER_ESP:
15525 case MSR_K8_FS_BASE:
15526 case MSR_K8_GS_BASE:
15527 {
15528 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15529 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15530 }
15531
15532 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15533 default:
15534 {
15535 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15536 {
15537 /* EFER MSR writes are always intercepted. */
15538 if (idMsr != MSR_K6_EFER)
15539 {
15540 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15541 idMsr));
15542 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15543 }
15544 }
15545
15546 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15547 {
15548 Assert(pVmcsInfo->pvMsrBitmap);
15549 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15550 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15551 {
15552 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15553 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15554 }
15555 }
15556 break;
15557 }
15558 }
15559 }
15560#endif /* VBOX_STRICT */
15561 }
15562 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15563 {
15564 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15565 rcStrict = VINF_SUCCESS;
15566 }
15567 else
15568 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE || rcStrict == VINF_EM_TRIPLE_FAULT,
15569 ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15570
15571 return rcStrict;
15572}
15573
15574
15575/**
15576 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15577 */
15578HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15579{
15580 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15581
15582 /** @todo The guest has likely hit a contended spinlock. We might want to
15583 * poke a schedule different guest VCPU. */
15584 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15585 if (RT_SUCCESS(rc))
15586 return VINF_EM_RAW_INTERRUPT;
15587
15588 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15589 return rc;
15590}
15591
15592
15593/**
15594 * VM-exit handler for when the TPR value is lowered below the specified
15595 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15596 */
15597HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15598{
15599 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15600 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15601
15602 /*
15603 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15604 * We'll re-evaluate pending interrupts and inject them before the next VM
15605 * entry so we can just continue execution here.
15606 */
15607 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15608 return VINF_SUCCESS;
15609}
15610
15611
15612/**
15613 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15614 * VM-exit.
15615 *
15616 * @retval VINF_SUCCESS when guest execution can continue.
15617 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15618 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15619 * incompatible guest state for VMX execution (real-on-v86 case).
15620 */
15621HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15622{
15623 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15624 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15625
15626 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15627 hmR0VmxReadExitQualVmcs(pVmxTransient);
15628 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15629
15630 VBOXSTRICTRC rcStrict;
15631 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15632 uint64_t const uExitQual = pVmxTransient->uExitQual;
15633 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15634 switch (uAccessType)
15635 {
15636 /*
15637 * MOV to CRx.
15638 */
15639 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15640 {
15641 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15642 AssertRCReturn(rc, rc);
15643
15644 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15645 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15646 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15647 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15648
15649 /*
15650 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15651 * - When nested paging isn't used.
15652 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15653 * - We are executing in the VM debug loop.
15654 */
15655 Assert( iCrReg != 3
15656 || !pVM->hmr0.s.fNestedPaging
15657 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15658 || pVCpu->hmr0.s.fUsingDebugLoop);
15659
15660 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15661 Assert( iCrReg != 8
15662 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15663
15664 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15665 AssertMsg( rcStrict == VINF_SUCCESS
15666 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15667
15668 /*
15669 * This is a kludge for handling switches back to real mode when we try to use
15670 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15671 * deal with special selector values, so we have to return to ring-3 and run
15672 * there till the selector values are V86 mode compatible.
15673 *
15674 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15675 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15676 * this function.
15677 */
15678 if ( iCrReg == 0
15679 && rcStrict == VINF_SUCCESS
15680 && !pVM->hmr0.s.vmx.fUnrestrictedGuest
15681 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15682 && (uOldCr0 & X86_CR0_PE)
15683 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15684 {
15685 /** @todo Check selectors rather than returning all the time. */
15686 Assert(!pVmxTransient->fIsNestedGuest);
15687 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15688 rcStrict = VINF_EM_RESCHEDULE_REM;
15689 }
15690 break;
15691 }
15692
15693 /*
15694 * MOV from CRx.
15695 */
15696 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15697 {
15698 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15699 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15700
15701 /*
15702 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15703 * - When nested paging isn't used.
15704 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15705 * - We are executing in the VM debug loop.
15706 */
15707 Assert( iCrReg != 3
15708 || !pVM->hmr0.s.fNestedPaging
15709 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15710 || pVCpu->hmr0.s.fLeaveDone);
15711
15712 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15713 Assert( iCrReg != 8
15714 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15715
15716 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15717 break;
15718 }
15719
15720 /*
15721 * CLTS (Clear Task-Switch Flag in CR0).
15722 */
15723 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15724 {
15725 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15726 break;
15727 }
15728
15729 /*
15730 * LMSW (Load Machine-Status Word into CR0).
15731 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15732 */
15733 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15734 {
15735 RTGCPTR GCPtrEffDst;
15736 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15737 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15738 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15739 if (fMemOperand)
15740 {
15741 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15742 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15743 }
15744 else
15745 GCPtrEffDst = NIL_RTGCPTR;
15746 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15747 break;
15748 }
15749
15750 default:
15751 {
15752 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15753 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15754 }
15755 }
15756
15757 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15758 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15759 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15760
15761 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15762 NOREF(pVM);
15763 return rcStrict;
15764}
15765
15766
15767/**
15768 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15769 * VM-exit.
15770 */
15771HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15772{
15773 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15774 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15775
15776 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15777 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15778 hmR0VmxReadExitQualVmcs(pVmxTransient);
15779 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15780 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15781 | CPUMCTX_EXTRN_EFER);
15782 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15783 AssertRCReturn(rc, rc);
15784
15785 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15786 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15787 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15788 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15789 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15790 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15791 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15792 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15793
15794 /*
15795 * Update exit history to see if this exit can be optimized.
15796 */
15797 VBOXSTRICTRC rcStrict;
15798 PCEMEXITREC pExitRec = NULL;
15799 if ( !fGstStepping
15800 && !fDbgStepping)
15801 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15802 !fIOString
15803 ? !fIOWrite
15804 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15805 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15806 : !fIOWrite
15807 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15808 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15809 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15810 if (!pExitRec)
15811 {
15812 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15813 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15814
15815 uint32_t const cbValue = s_aIOSizes[uIOSize];
15816 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15817 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15818 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15819 if (fIOString)
15820 {
15821 /*
15822 * INS/OUTS - I/O String instruction.
15823 *
15824 * Use instruction-information if available, otherwise fall back on
15825 * interpreting the instruction.
15826 */
15827 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15828 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15829 bool const fInsOutsInfo = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15830 if (fInsOutsInfo)
15831 {
15832 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15833 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15834 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15835 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15836 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15837 if (fIOWrite)
15838 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15839 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15840 else
15841 {
15842 /*
15843 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15844 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15845 * See Intel Instruction spec. for "INS".
15846 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15847 */
15848 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15849 }
15850 }
15851 else
15852 rcStrict = IEMExecOne(pVCpu);
15853
15854 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15855 fUpdateRipAlready = true;
15856 }
15857 else
15858 {
15859 /*
15860 * IN/OUT - I/O instruction.
15861 */
15862 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15863 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15864 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15865 if (fIOWrite)
15866 {
15867 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15868 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15869 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15870 && !pCtx->eflags.Bits.u1TF)
15871 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15872 }
15873 else
15874 {
15875 uint32_t u32Result = 0;
15876 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15877 if (IOM_SUCCESS(rcStrict))
15878 {
15879 /* Save result of I/O IN instr. in AL/AX/EAX. */
15880 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15881 }
15882 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15883 && !pCtx->eflags.Bits.u1TF)
15884 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15885 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15886 }
15887 }
15888
15889 if (IOM_SUCCESS(rcStrict))
15890 {
15891 if (!fUpdateRipAlready)
15892 {
15893 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15894 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15895 }
15896
15897 /*
15898 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15899 * while booting Fedora 17 64-bit guest.
15900 *
15901 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15902 */
15903 if (fIOString)
15904 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15905
15906 /*
15907 * If any I/O breakpoints are armed, we need to check if one triggered
15908 * and take appropriate action.
15909 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15910 */
15911 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15912 AssertRCReturn(rc, rc);
15913
15914 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15915 * execution engines about whether hyper BPs and such are pending. */
15916 uint32_t const uDr7 = pCtx->dr[7];
15917 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15918 && X86_DR7_ANY_RW_IO(uDr7)
15919 && (pCtx->cr4 & X86_CR4_DE))
15920 || DBGFBpIsHwIoArmed(pVM)))
15921 {
15922 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15923
15924 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15925 VMMRZCallRing3Disable(pVCpu);
15926 HM_DISABLE_PREEMPT(pVCpu);
15927
15928 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15929
15930 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15931 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15932 {
15933 /* Raise #DB. */
15934 if (fIsGuestDbgActive)
15935 ASMSetDR6(pCtx->dr[6]);
15936 if (pCtx->dr[7] != uDr7)
15937 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15938
15939 hmR0VmxSetPendingXcptDB(pVCpu);
15940 }
15941 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15942 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15943 else if ( rcStrict2 != VINF_SUCCESS
15944 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15945 rcStrict = rcStrict2;
15946 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15947
15948 HM_RESTORE_PREEMPT();
15949 VMMRZCallRing3Enable(pVCpu);
15950 }
15951 }
15952
15953#ifdef VBOX_STRICT
15954 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15955 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15956 Assert(!fIOWrite);
15957 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15958 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15959 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15960 Assert(fIOWrite);
15961 else
15962 {
15963# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15964 * statuses, that the VMM device and some others may return. See
15965 * IOM_SUCCESS() for guidance. */
15966 AssertMsg( RT_FAILURE(rcStrict)
15967 || rcStrict == VINF_SUCCESS
15968 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15969 || rcStrict == VINF_EM_DBG_BREAKPOINT
15970 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15971 || rcStrict == VINF_EM_RAW_TO_R3
15972 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15973# endif
15974 }
15975#endif
15976 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15977 }
15978 else
15979 {
15980 /*
15981 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15982 */
15983 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15984 AssertRCReturn(rc2, rc2);
15985 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15986 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15987 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15988 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15989 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15990 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15991
15992 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15993 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15994
15995 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15996 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15997 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15998 }
15999 return rcStrict;
16000}
16001
16002
16003/**
16004 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
16005 * VM-exit.
16006 */
16007HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16008{
16009 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16010
16011 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
16012 hmR0VmxReadExitQualVmcs(pVmxTransient);
16013 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
16014 {
16015 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16016 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16017 {
16018 uint32_t uErrCode;
16019 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
16020 {
16021 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16022 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
16023 }
16024 else
16025 uErrCode = 0;
16026
16027 RTGCUINTPTR GCPtrFaultAddress;
16028 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
16029 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
16030 else
16031 GCPtrFaultAddress = 0;
16032
16033 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16034
16035 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
16036 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
16037
16038 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
16039 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
16040 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16041 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16042 }
16043 }
16044
16045 /* Fall back to the interpreter to emulate the task-switch. */
16046 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16047 return VERR_EM_INTERPRETER;
16048}
16049
16050
16051/**
16052 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
16053 */
16054HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16055{
16056 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16057
16058 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16059 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
16060 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16061 AssertRC(rc);
16062 return VINF_EM_DBG_STEPPED;
16063}
16064
16065
16066/**
16067 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
16068 */
16069HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16070{
16071 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16072 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
16073
16074 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16075 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16076 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16077 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16078 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16079
16080 /*
16081 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16082 */
16083 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16084 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16085 {
16086 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
16087 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
16088 {
16089 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16090 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16091 }
16092 }
16093 else
16094 {
16095 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16096 return rcStrict;
16097 }
16098
16099 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
16100 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16101 hmR0VmxReadExitQualVmcs(pVmxTransient);
16102 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16103 AssertRCReturn(rc, rc);
16104
16105 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
16106 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
16107 switch (uAccessType)
16108 {
16109 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
16110 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
16111 {
16112 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
16113 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
16114 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
16115
16116 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
16117 GCPhys &= PAGE_BASE_GC_MASK;
16118 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
16119 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
16120 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
16121
16122 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
16123 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
16124 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16125 if ( rcStrict == VINF_SUCCESS
16126 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16127 || rcStrict == VERR_PAGE_NOT_PRESENT)
16128 {
16129 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16130 | HM_CHANGED_GUEST_APIC_TPR);
16131 rcStrict = VINF_SUCCESS;
16132 }
16133 break;
16134 }
16135
16136 default:
16137 {
16138 Log4Func(("uAccessType=%#x\n", uAccessType));
16139 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
16140 break;
16141 }
16142 }
16143
16144 if (rcStrict != VINF_SUCCESS)
16145 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
16146 return rcStrict;
16147}
16148
16149
16150/**
16151 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
16152 * VM-exit.
16153 */
16154HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16155{
16156 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16157 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16158
16159 /*
16160 * We might also get this VM-exit if the nested-guest isn't intercepting MOV DRx accesses.
16161 * In such a case, rather than disabling MOV DRx intercepts and resuming execution, we
16162 * must emulate the MOV DRx access.
16163 */
16164 if (!pVmxTransient->fIsNestedGuest)
16165 {
16166 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16167 if (pVmxTransient->fWasGuestDebugStateActive)
16168 {
16169 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16170 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16171 }
16172
16173 if ( !pVCpu->hm.s.fSingleInstruction
16174 && !pVmxTransient->fWasHyperDebugStateActive)
16175 {
16176 Assert(!DBGFIsStepping(pVCpu));
16177 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16178
16179 /* Don't intercept MOV DRx any more. */
16180 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16181 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16182 AssertRC(rc);
16183
16184 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16185 VMMRZCallRing3Disable(pVCpu);
16186 HM_DISABLE_PREEMPT(pVCpu);
16187
16188 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16189 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16190 Assert(CPUMIsGuestDebugStateActive(pVCpu));
16191
16192 HM_RESTORE_PREEMPT();
16193 VMMRZCallRing3Enable(pVCpu);
16194
16195#ifdef VBOX_WITH_STATISTICS
16196 hmR0VmxReadExitQualVmcs(pVmxTransient);
16197 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16198 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16199 else
16200 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16201#endif
16202 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16203 return VINF_SUCCESS;
16204 }
16205 }
16206
16207 /*
16208 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16209 * The EFER MSR is always up-to-date.
16210 * Update the segment registers and DR7 from the CPU.
16211 */
16212 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16213 hmR0VmxReadExitQualVmcs(pVmxTransient);
16214 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16215 AssertRCReturn(rc, rc);
16216 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16217
16218 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16219 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16220 {
16221 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16222 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16223 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16224 if (RT_SUCCESS(rc))
16225 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16226 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16227 }
16228 else
16229 {
16230 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16231 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16232 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16233 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16234 }
16235
16236 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16237 if (RT_SUCCESS(rc))
16238 {
16239 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16240 AssertRCReturn(rc2, rc2);
16241 return VINF_SUCCESS;
16242 }
16243 return rc;
16244}
16245
16246
16247/**
16248 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16249 * Conditional VM-exit.
16250 */
16251HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16252{
16253 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16254 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16255
16256 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16257 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16258 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16259 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16260 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16261
16262 /*
16263 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16264 */
16265 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16266 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16267 {
16268 /*
16269 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16270 * instruction emulation to inject the original event. Otherwise, injecting the original event
16271 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
16272 */
16273 if (!pVCpu->hm.s.Event.fPending)
16274 { /* likely */ }
16275 else
16276 {
16277 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16278#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16279 /** @todo NSTVMX: Think about how this should be handled. */
16280 if (pVmxTransient->fIsNestedGuest)
16281 return VERR_VMX_IPE_3;
16282#endif
16283 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16284 }
16285 }
16286 else
16287 {
16288 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16289 return rcStrict;
16290 }
16291
16292 /*
16293 * Get sufficient state and update the exit history entry.
16294 */
16295 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16296 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16297 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16298 AssertRCReturn(rc, rc);
16299
16300 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16301 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16302 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16303 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16304 if (!pExitRec)
16305 {
16306 /*
16307 * If we succeed, resume guest execution.
16308 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16309 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16310 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16311 * weird case. See @bugref{6043}.
16312 */
16313 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16314 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16315/** @todo bird: We can probably just go straight to IOM here and assume that
16316 * it's MMIO, then fall back on PGM if that hunch didn't work out so
16317 * well. However, we need to address that aliasing workarounds that
16318 * PGMR0Trap0eHandlerNPMisconfig implements. So, some care is needed.
16319 *
16320 * Might also be interesting to see if we can get this done more or
16321 * less locklessly inside IOM. Need to consider the lookup table
16322 * updating and use a bit more carefully first (or do all updates via
16323 * rendezvous) */
16324 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16325 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16326 if ( rcStrict == VINF_SUCCESS
16327 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16328 || rcStrict == VERR_PAGE_NOT_PRESENT)
16329 {
16330 /* Successfully handled MMIO operation. */
16331 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16332 | HM_CHANGED_GUEST_APIC_TPR);
16333 rcStrict = VINF_SUCCESS;
16334 }
16335 }
16336 else
16337 {
16338 /*
16339 * Frequent exit or something needing probing. Call EMHistoryExec.
16340 */
16341 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16342 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16343
16344 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16345 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16346
16347 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16348 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16349 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16350 }
16351 return rcStrict;
16352}
16353
16354
16355/**
16356 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16357 * VM-exit.
16358 */
16359HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16360{
16361 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16362 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16363
16364 hmR0VmxReadExitQualVmcs(pVmxTransient);
16365 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16366 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16367 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16368 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16369 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16370
16371 /*
16372 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16373 */
16374 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16375 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16376 {
16377 /*
16378 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16379 * we shall resolve the nested #PF and re-inject the original event.
16380 */
16381 if (pVCpu->hm.s.Event.fPending)
16382 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16383 }
16384 else
16385 {
16386 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16387 return rcStrict;
16388 }
16389
16390 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16391 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16392 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16393 AssertRCReturn(rc, rc);
16394
16395 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16396 uint64_t const uExitQual = pVmxTransient->uExitQual;
16397 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16398
16399 RTGCUINT uErrorCode = 0;
16400 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16401 uErrorCode |= X86_TRAP_PF_ID;
16402 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16403 uErrorCode |= X86_TRAP_PF_RW;
16404 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16405 uErrorCode |= X86_TRAP_PF_P;
16406
16407 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16408 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16409 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16410
16411 /*
16412 * Handle the pagefault trap for the nested shadow table.
16413 */
16414 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16415 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16416 TRPMResetTrap(pVCpu);
16417
16418 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16419 if ( rcStrict == VINF_SUCCESS
16420 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16421 || rcStrict == VERR_PAGE_NOT_PRESENT)
16422 {
16423 /* Successfully synced our nested page tables. */
16424 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16425 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16426 return VINF_SUCCESS;
16427 }
16428
16429 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16430 return rcStrict;
16431}
16432
16433
16434#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16435/**
16436 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16437 */
16438HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16439{
16440 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16441
16442 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16443 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16444 hmR0VmxReadExitQualVmcs(pVmxTransient);
16445 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16446 | CPUMCTX_EXTRN_HWVIRT
16447 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16448 AssertRCReturn(rc, rc);
16449
16450 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16451
16452 VMXVEXITINFO ExitInfo;
16453 RT_ZERO(ExitInfo);
16454 ExitInfo.uReason = pVmxTransient->uExitReason;
16455 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16456 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16457 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16458 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16459
16460 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16461 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16462 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16463 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16464 {
16465 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16466 rcStrict = VINF_SUCCESS;
16467 }
16468 return rcStrict;
16469}
16470
16471
16472/**
16473 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16474 */
16475HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16476{
16477 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16478
16479 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16480 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16481 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16482 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16483 AssertRCReturn(rc, rc);
16484
16485 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16486
16487 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16488 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
16489 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16490 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16491 {
16492 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16493 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16494 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16495 }
16496 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16497 return rcStrict;
16498}
16499
16500
16501/**
16502 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16503 */
16504HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16505{
16506 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16507
16508 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16509 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16510 hmR0VmxReadExitQualVmcs(pVmxTransient);
16511 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16512 | CPUMCTX_EXTRN_HWVIRT
16513 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16514 AssertRCReturn(rc, rc);
16515
16516 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16517
16518 VMXVEXITINFO ExitInfo;
16519 RT_ZERO(ExitInfo);
16520 ExitInfo.uReason = pVmxTransient->uExitReason;
16521 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16522 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16523 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16524 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16525
16526 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16527 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16528 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16529 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16530 {
16531 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16532 rcStrict = VINF_SUCCESS;
16533 }
16534 return rcStrict;
16535}
16536
16537
16538/**
16539 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16540 */
16541HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16542{
16543 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16544
16545 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16546 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16547 hmR0VmxReadExitQualVmcs(pVmxTransient);
16548 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16549 | CPUMCTX_EXTRN_HWVIRT
16550 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16551 AssertRCReturn(rc, rc);
16552
16553 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16554
16555 VMXVEXITINFO ExitInfo;
16556 RT_ZERO(ExitInfo);
16557 ExitInfo.uReason = pVmxTransient->uExitReason;
16558 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16559 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16560 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16561 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16562
16563 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16564 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16565 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16566 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16567 {
16568 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16569 rcStrict = VINF_SUCCESS;
16570 }
16571 return rcStrict;
16572}
16573
16574
16575/**
16576 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16577 */
16578HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16579{
16580 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16581
16582 /*
16583 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16584 * thus might not need to import the shadow VMCS state, it's safer just in case
16585 * code elsewhere dares look at unsynced VMCS fields.
16586 */
16587 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16588 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16589 hmR0VmxReadExitQualVmcs(pVmxTransient);
16590 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16591 | CPUMCTX_EXTRN_HWVIRT
16592 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16593 AssertRCReturn(rc, rc);
16594
16595 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16596
16597 VMXVEXITINFO ExitInfo;
16598 RT_ZERO(ExitInfo);
16599 ExitInfo.uReason = pVmxTransient->uExitReason;
16600 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16601 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16602 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16603 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16604 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16605
16606 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16607 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16608 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16609 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16610 {
16611 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16612 rcStrict = VINF_SUCCESS;
16613 }
16614 return rcStrict;
16615}
16616
16617
16618/**
16619 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16620 */
16621HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16622{
16623 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16624
16625 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16626 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16627 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16628 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16629 AssertRCReturn(rc, rc);
16630
16631 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16632
16633 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16634 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16635 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16636 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16637 {
16638 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16639 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16640 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16641 }
16642 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16643 return rcStrict;
16644}
16645
16646
16647/**
16648 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16649 */
16650HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16651{
16652 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16653
16654 /*
16655 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16656 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16657 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16658 */
16659 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16660 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16661 hmR0VmxReadExitQualVmcs(pVmxTransient);
16662 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16663 | CPUMCTX_EXTRN_HWVIRT
16664 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16665 AssertRCReturn(rc, rc);
16666
16667 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16668
16669 VMXVEXITINFO ExitInfo;
16670 RT_ZERO(ExitInfo);
16671 ExitInfo.uReason = pVmxTransient->uExitReason;
16672 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16673 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16674 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16675 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16676 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16677
16678 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16679 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16680 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16681 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16682 {
16683 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16684 rcStrict = VINF_SUCCESS;
16685 }
16686 return rcStrict;
16687}
16688
16689
16690/**
16691 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16692 */
16693HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16694{
16695 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16696
16697 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16698 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16699 | CPUMCTX_EXTRN_HWVIRT
16700 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16701 AssertRCReturn(rc, rc);
16702
16703 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16704
16705 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16706 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16707 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16708 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16709 {
16710 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16711 rcStrict = VINF_SUCCESS;
16712 }
16713 return rcStrict;
16714}
16715
16716
16717/**
16718 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16719 */
16720HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16721{
16722 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16723
16724 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16725 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16726 hmR0VmxReadExitQualVmcs(pVmxTransient);
16727 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16728 | CPUMCTX_EXTRN_HWVIRT
16729 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16730 AssertRCReturn(rc, rc);
16731
16732 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16733
16734 VMXVEXITINFO ExitInfo;
16735 RT_ZERO(ExitInfo);
16736 ExitInfo.uReason = pVmxTransient->uExitReason;
16737 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16738 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16739 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16740 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16741
16742 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16743 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16744 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16745 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16746 {
16747 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16748 rcStrict = VINF_SUCCESS;
16749 }
16750 return rcStrict;
16751}
16752
16753
16754/**
16755 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16756 */
16757HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16758{
16759 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16760
16761 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16762 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16763 hmR0VmxReadExitQualVmcs(pVmxTransient);
16764 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16765 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16766 AssertRCReturn(rc, rc);
16767
16768 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16769
16770 VMXVEXITINFO ExitInfo;
16771 RT_ZERO(ExitInfo);
16772 ExitInfo.uReason = pVmxTransient->uExitReason;
16773 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16774 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16775 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16776 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16777
16778 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16779 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16780 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16781 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16782 {
16783 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16784 rcStrict = VINF_SUCCESS;
16785 }
16786 return rcStrict;
16787}
16788#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16789/** @} */
16790
16791
16792#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16793/** @name Nested-guest VM-exit handlers.
16794 * @{
16795 */
16796/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16797/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16798/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16799
16800/**
16801 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16802 * Conditional VM-exit.
16803 */
16804HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16805{
16806 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16807
16808 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16809
16810 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16811 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16812 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16813
16814 switch (uExitIntType)
16815 {
16816 /*
16817 * Physical NMIs:
16818 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16819 */
16820 case VMX_EXIT_INT_INFO_TYPE_NMI:
16821 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16822
16823 /*
16824 * Hardware exceptions,
16825 * Software exceptions,
16826 * Privileged software exceptions:
16827 * Figure out if the exception must be delivered to the guest or the nested-guest.
16828 */
16829 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16830 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16831 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16832 {
16833 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16834 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16835 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16836 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16837
16838 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16839 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16840 pVmxTransient->uExitIntErrorCode);
16841 if (fIntercept)
16842 {
16843 /* Exit qualification is required for debug and page-fault exceptions. */
16844 hmR0VmxReadExitQualVmcs(pVmxTransient);
16845
16846 /*
16847 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16848 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16849 * length. However, if delivery of a software interrupt, software exception or privileged
16850 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16851 */
16852 VMXVEXITINFO ExitInfo;
16853 RT_ZERO(ExitInfo);
16854 ExitInfo.uReason = pVmxTransient->uExitReason;
16855 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16856 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16857
16858 VMXVEXITEVENTINFO ExitEventInfo;
16859 RT_ZERO(ExitEventInfo);
16860 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16861 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16862 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16863 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16864
16865#ifdef DEBUG_ramshankar
16866 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16867 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16868 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16869 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16870 {
16871 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16872 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16873 }
16874#endif
16875 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16876 }
16877
16878 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16879 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16880 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16881 }
16882
16883 /*
16884 * Software interrupts:
16885 * VM-exits cannot be caused by software interrupts.
16886 *
16887 * External interrupts:
16888 * This should only happen when "acknowledge external interrupts on VM-exit"
16889 * control is set. However, we never set this when executing a guest or
16890 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16891 * the guest.
16892 */
16893 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16894 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16895 default:
16896 {
16897 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16898 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16899 }
16900 }
16901}
16902
16903
16904/**
16905 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16906 * Unconditional VM-exit.
16907 */
16908HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16909{
16910 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16911 return IEMExecVmxVmexitTripleFault(pVCpu);
16912}
16913
16914
16915/**
16916 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16917 */
16918HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16919{
16920 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16921
16922 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16923 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16924 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16925}
16926
16927
16928/**
16929 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16930 */
16931HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16932{
16933 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16934
16935 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16936 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16937 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16938}
16939
16940
16941/**
16942 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16943 * Unconditional VM-exit.
16944 */
16945HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16946{
16947 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16948
16949 hmR0VmxReadExitQualVmcs(pVmxTransient);
16950 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16951 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16952 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16953
16954 VMXVEXITINFO ExitInfo;
16955 RT_ZERO(ExitInfo);
16956 ExitInfo.uReason = pVmxTransient->uExitReason;
16957 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16958 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16959
16960 VMXVEXITEVENTINFO ExitEventInfo;
16961 RT_ZERO(ExitEventInfo);
16962 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16963 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16964 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16965}
16966
16967
16968/**
16969 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16970 */
16971HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16972{
16973 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16974
16975 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16976 {
16977 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16978 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16979 }
16980 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16981}
16982
16983
16984/**
16985 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16986 */
16987HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16988{
16989 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16990
16991 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16992 {
16993 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16994 hmR0VmxReadExitQualVmcs(pVmxTransient);
16995
16996 VMXVEXITINFO ExitInfo;
16997 RT_ZERO(ExitInfo);
16998 ExitInfo.uReason = pVmxTransient->uExitReason;
16999 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17000 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17001 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17002 }
17003 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
17004}
17005
17006
17007/**
17008 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
17009 */
17010HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17011{
17012 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17013
17014 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
17015 {
17016 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17017 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17018 }
17019 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
17020}
17021
17022
17023/**
17024 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
17025 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
17026 */
17027HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17028{
17029 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17030
17031 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
17032 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
17033
17034 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17035
17036 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
17037 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17038 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17039
17040 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
17041 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
17042 u64VmcsField &= UINT64_C(0xffffffff);
17043
17044 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
17045 {
17046 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17047 hmR0VmxReadExitQualVmcs(pVmxTransient);
17048
17049 VMXVEXITINFO ExitInfo;
17050 RT_ZERO(ExitInfo);
17051 ExitInfo.uReason = pVmxTransient->uExitReason;
17052 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17053 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17054 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17055 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17056 }
17057
17058 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
17059 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
17060 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
17061}
17062
17063
17064/**
17065 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
17066 */
17067HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17068{
17069 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17070
17071 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17072 {
17073 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17074 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17075 }
17076
17077 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
17078}
17079
17080
17081/**
17082 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
17083 * Conditional VM-exit.
17084 */
17085HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17086{
17087 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17088
17089 hmR0VmxReadExitQualVmcs(pVmxTransient);
17090 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17091
17092 VBOXSTRICTRC rcStrict;
17093 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
17094 switch (uAccessType)
17095 {
17096 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
17097 {
17098 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17099 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17100 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17101 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17102
17103 bool fIntercept;
17104 switch (iCrReg)
17105 {
17106 case 0:
17107 case 4:
17108 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(&pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
17109 break;
17110
17111 case 3:
17112 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
17113 break;
17114
17115 case 8:
17116 fIntercept = CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
17117 break;
17118
17119 default:
17120 fIntercept = false;
17121 break;
17122 }
17123 if (fIntercept)
17124 {
17125 VMXVEXITINFO ExitInfo;
17126 RT_ZERO(ExitInfo);
17127 ExitInfo.uReason = pVmxTransient->uExitReason;
17128 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17129 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17130 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17131 }
17132 else
17133 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
17134 break;
17135 }
17136
17137 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
17138 {
17139 /*
17140 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
17141 * CR2 reads do not cause a VM-exit.
17142 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
17143 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
17144 */
17145 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17146 if ( iCrReg == 3
17147 || iCrReg == 8)
17148 {
17149 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
17150 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
17151 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
17152 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uIntercept))
17153 {
17154 VMXVEXITINFO ExitInfo;
17155 RT_ZERO(ExitInfo);
17156 ExitInfo.uReason = pVmxTransient->uExitReason;
17157 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17158 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17159 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17160 }
17161 else
17162 {
17163 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17164 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
17165 }
17166 }
17167 else
17168 {
17169 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17170 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17171 }
17172 break;
17173 }
17174
17175 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17176 {
17177 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17178 Assert(pVmcsNstGst);
17179 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17180 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17181 if ( (uGstHostMask & X86_CR0_TS)
17182 && (uReadShadow & X86_CR0_TS))
17183 {
17184 VMXVEXITINFO ExitInfo;
17185 RT_ZERO(ExitInfo);
17186 ExitInfo.uReason = pVmxTransient->uExitReason;
17187 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17188 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17189 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17190 }
17191 else
17192 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
17193 break;
17194 }
17195
17196 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17197 {
17198 RTGCPTR GCPtrEffDst;
17199 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17200 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17201 if (fMemOperand)
17202 {
17203 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17204 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17205 }
17206 else
17207 GCPtrEffDst = NIL_RTGCPTR;
17208
17209 if (CPUMIsGuestVmxLmswInterceptSet(&pVCpu->cpum.GstCtx, uNewMsw))
17210 {
17211 VMXVEXITINFO ExitInfo;
17212 RT_ZERO(ExitInfo);
17213 ExitInfo.uReason = pVmxTransient->uExitReason;
17214 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17215 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17216 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17217 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17218 }
17219 else
17220 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
17221 break;
17222 }
17223
17224 default:
17225 {
17226 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17227 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17228 }
17229 }
17230
17231 if (rcStrict == VINF_IEM_RAISED_XCPT)
17232 {
17233 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17234 rcStrict = VINF_SUCCESS;
17235 }
17236 return rcStrict;
17237}
17238
17239
17240/**
17241 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17242 * Conditional VM-exit.
17243 */
17244HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17245{
17246 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17247
17248 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17249 {
17250 hmR0VmxReadExitQualVmcs(pVmxTransient);
17251 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17252
17253 VMXVEXITINFO ExitInfo;
17254 RT_ZERO(ExitInfo);
17255 ExitInfo.uReason = pVmxTransient->uExitReason;
17256 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17257 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17258 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17259 }
17260 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17261}
17262
17263
17264/**
17265 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17266 * Conditional VM-exit.
17267 */
17268HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17269{
17270 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17271
17272 hmR0VmxReadExitQualVmcs(pVmxTransient);
17273
17274 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17275 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17276 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17277
17278 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17279 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17280 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17281 {
17282 /*
17283 * IN/OUT instruction:
17284 * - Provides VM-exit instruction length.
17285 *
17286 * INS/OUTS instruction:
17287 * - Provides VM-exit instruction length.
17288 * - Provides Guest-linear address.
17289 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17290 */
17291 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
17292 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17293
17294 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17295 pVmxTransient->ExitInstrInfo.u = 0;
17296 pVmxTransient->uGuestLinearAddr = 0;
17297
17298 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17299 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17300 if (fIOString)
17301 {
17302 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17303 if (fVmxInsOutsInfo)
17304 {
17305 Assert(RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17306 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17307 }
17308 }
17309
17310 VMXVEXITINFO ExitInfo;
17311 RT_ZERO(ExitInfo);
17312 ExitInfo.uReason = pVmxTransient->uExitReason;
17313 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17314 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17315 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17316 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17317 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17318 }
17319 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17320}
17321
17322
17323/**
17324 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17325 */
17326HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17327{
17328 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17329
17330 uint32_t fMsrpm;
17331 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17332 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17333 else
17334 fMsrpm = VMXMSRPM_EXIT_RD;
17335
17336 if (fMsrpm & VMXMSRPM_EXIT_RD)
17337 {
17338 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17339 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17340 }
17341 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17342}
17343
17344
17345/**
17346 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17347 */
17348HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17349{
17350 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17351
17352 uint32_t fMsrpm;
17353 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17354 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17355 else
17356 fMsrpm = VMXMSRPM_EXIT_WR;
17357
17358 if (fMsrpm & VMXMSRPM_EXIT_WR)
17359 {
17360 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17361 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17362 }
17363 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17364}
17365
17366
17367/**
17368 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17369 */
17370HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17371{
17372 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17373
17374 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17375 {
17376 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17377 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17378 }
17379 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17380}
17381
17382
17383/**
17384 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17385 * VM-exit.
17386 */
17387HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17388{
17389 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17390
17391 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17392 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17393 VMXVEXITINFO ExitInfo;
17394 RT_ZERO(ExitInfo);
17395 ExitInfo.uReason = pVmxTransient->uExitReason;
17396 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17397 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17398}
17399
17400
17401/**
17402 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17403 */
17404HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17405{
17406 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17407
17408 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17409 {
17410 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17411 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17412 }
17413 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17414}
17415
17416
17417/**
17418 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17419 */
17420HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17421{
17422 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17423
17424 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17425 * PAUSE when executing a nested-guest? If it does not, we would not need
17426 * to check for the intercepts here. Just call VM-exit... */
17427
17428 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17429 if ( CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17430 || CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17431 {
17432 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17433 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17434 }
17435 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17436}
17437
17438
17439/**
17440 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17441 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17442 */
17443HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17444{
17445 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17446
17447 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17448 {
17449 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17450 VMXVEXITINFO ExitInfo;
17451 RT_ZERO(ExitInfo);
17452 ExitInfo.uReason = pVmxTransient->uExitReason;
17453 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17454 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17455 }
17456 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17457}
17458
17459
17460/**
17461 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17462 * VM-exit.
17463 */
17464HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17465{
17466 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17467
17468 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17469 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17470 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17471 hmR0VmxReadExitQualVmcs(pVmxTransient);
17472
17473 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17474
17475 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
17476 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
17477
17478 VMXVEXITINFO ExitInfo;
17479 RT_ZERO(ExitInfo);
17480 ExitInfo.uReason = pVmxTransient->uExitReason;
17481 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17482 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17483
17484 VMXVEXITEVENTINFO ExitEventInfo;
17485 RT_ZERO(ExitEventInfo);
17486 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17487 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17488 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17489}
17490
17491
17492/**
17493 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17494 * Conditional VM-exit.
17495 */
17496HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17497{
17498 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17499
17500 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17501 hmR0VmxReadExitQualVmcs(pVmxTransient);
17502 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17503}
17504
17505
17506/**
17507 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17508 * Conditional VM-exit.
17509 */
17510HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17511{
17512 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17513
17514 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17515 hmR0VmxReadExitQualVmcs(pVmxTransient);
17516 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17517}
17518
17519
17520/**
17521 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17522 */
17523HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17524{
17525 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17526
17527 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17528 {
17529 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17530 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17531 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17532 }
17533 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17534}
17535
17536
17537/**
17538 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17539 */
17540HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17541{
17542 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17543
17544 if (CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17545 {
17546 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17547 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17548 }
17549 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17550}
17551
17552
17553/**
17554 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17555 */
17556HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17557{
17558 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17559
17560 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17561 {
17562 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17563 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17564 hmR0VmxReadExitQualVmcs(pVmxTransient);
17565 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17566
17567 VMXVEXITINFO ExitInfo;
17568 RT_ZERO(ExitInfo);
17569 ExitInfo.uReason = pVmxTransient->uExitReason;
17570 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17571 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17572 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17573 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17574 }
17575 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17576}
17577
17578
17579/**
17580 * Nested-guest VM-exit handler for invalid-guest state
17581 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17582 */
17583HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17584{
17585 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17586
17587 /*
17588 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17589 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17590 * Handle it like it's in an invalid guest state of the outer guest.
17591 *
17592 * When the fast path is implemented, this should be changed to cause the corresponding
17593 * nested-guest VM-exit.
17594 */
17595 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17596}
17597
17598
17599/**
17600 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17601 * and only provide the instruction length.
17602 *
17603 * Unconditional VM-exit.
17604 */
17605HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17606{
17607 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17608
17609#ifdef VBOX_STRICT
17610 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17611 switch (pVmxTransient->uExitReason)
17612 {
17613 case VMX_EXIT_ENCLS:
17614 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17615 break;
17616
17617 case VMX_EXIT_VMFUNC:
17618 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_VMFUNC));
17619 break;
17620 }
17621#endif
17622
17623 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17624 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17625}
17626
17627
17628/**
17629 * Nested-guest VM-exit handler for instructions that provide instruction length as
17630 * well as more information.
17631 *
17632 * Unconditional VM-exit.
17633 */
17634HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17635{
17636 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17637
17638#ifdef VBOX_STRICT
17639 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17640 switch (pVmxTransient->uExitReason)
17641 {
17642 case VMX_EXIT_GDTR_IDTR_ACCESS:
17643 case VMX_EXIT_LDTR_TR_ACCESS:
17644 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17645 break;
17646
17647 case VMX_EXIT_RDRAND:
17648 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17649 break;
17650
17651 case VMX_EXIT_RDSEED:
17652 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17653 break;
17654
17655 case VMX_EXIT_XSAVES:
17656 case VMX_EXIT_XRSTORS:
17657 /** @todo NSTVMX: Verify XSS-bitmap. */
17658 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17659 break;
17660
17661 case VMX_EXIT_UMWAIT:
17662 case VMX_EXIT_TPAUSE:
17663 Assert(CPUMIsGuestVmxProcCtlsSet(pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17664 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17665 break;
17666 }
17667#endif
17668
17669 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17670 hmR0VmxReadExitQualVmcs(pVmxTransient);
17671 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17672
17673 VMXVEXITINFO ExitInfo;
17674 RT_ZERO(ExitInfo);
17675 ExitInfo.uReason = pVmxTransient->uExitReason;
17676 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17677 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17678 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17679 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17680}
17681
17682/** @} */
17683#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17684
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