VirtualBox

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

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

VMM/HMVMXR0: Fix assertion with exception bitmaps by restoring debug state in the inner loop itself.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 721.7 KB
Line 
1/* $Id: HMVMXR0.cpp 85765 2020-08-14 11:35:19Z 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)->hm.s.idEnteredCpu == RTMpCpuId(), \
165 ("Illegal migration! Entered on CPU %u Current %u\n", \
166 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
167
168/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
169 * context. */
170#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
171 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
172 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
173
174/** Log the VM-exit reason with an easily visible marker to identify it in a
175 * potential sea of logging data. */
176#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
177 do { \
178 Log4(("VM-exit: vcpu[%RU32] %85s -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-\n", (a_pVCpu)->idCpu, \
179 HMGetVmxExitName(a_uExitReason))); \
180 } while (0) \
181
182
183/*********************************************************************************************************************************
184* Structures and Typedefs *
185*********************************************************************************************************************************/
186/**
187 * VMX per-VCPU transient state.
188 *
189 * A state structure for holding miscellaneous information across
190 * VMX non-root operation and restored after the transition.
191 *
192 * Note: The members are ordered and aligned such that the most
193 * frequently used ones (in the guest execution loop) fall within
194 * the first cache line.
195 */
196typedef struct VMXTRANSIENT
197{
198 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
199 uint32_t fVmcsFieldsRead;
200 /** The guest's TPR value used for TPR shadowing. */
201 uint8_t u8GuestTpr;
202 uint8_t abAlignment0[3];
203
204 /** Whether the VM-exit was caused by a page-fault during delivery of an
205 * external interrupt or NMI. */
206 bool fVectoringPF;
207 /** Whether the VM-exit was caused by a page-fault during delivery of a
208 * contributory exception or a page-fault. */
209 bool fVectoringDoublePF;
210 /** Whether the VM-entry failed or not. */
211 bool fVMEntryFailed;
212 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
213 * area after VM-exit. */
214 bool fRemoveTscAuxMsr;
215 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
216 bool fUpdatedTscOffsettingAndPreemptTimer;
217 /** Whether we are currently executing a nested-guest. */
218 bool fIsNestedGuest;
219 /** Whether the guest debug state was active at the time of VM-exit. */
220 bool fWasGuestDebugStateActive;
221 /** Whether the hyper debug state was active at the time of VM-exit. */
222 bool fWasHyperDebugStateActive;
223
224 /** The basic VM-exit reason. */
225 uint32_t uExitReason;
226 /** The VM-exit interruption error code. */
227 uint32_t uExitIntErrorCode;
228
229 /** The host's rflags/eflags. */
230 RTCCUINTREG fEFlags;
231
232 /** The VM-exit exit code qualification. */
233 uint64_t uExitQual;
234
235 /** The VMCS info. object. */
236 PVMXVMCSINFO pVmcsInfo;
237
238 /** The VM-exit interruption-information field. */
239 uint32_t uExitIntInfo;
240 /** The VM-exit instruction-length field. */
241 uint32_t cbExitInstr;
242
243 /** The VM-exit instruction-information field. */
244 VMXEXITINSTRINFO ExitInstrInfo;
245 /** IDT-vectoring information field. */
246 uint32_t uIdtVectoringInfo;
247
248 /** IDT-vectoring error code. */
249 uint32_t uIdtVectoringErrorCode;
250 uint32_t u32Alignment0;
251
252 /** The Guest-linear address. */
253 uint64_t uGuestLinearAddr;
254
255 /** The Guest-physical address. */
256 uint64_t uGuestPhysicalAddr;
257
258 /** The Guest pending-debug exceptions. */
259 uint64_t uGuestPendingDbgXcpts;
260
261 /** The VM-entry interruption-information field. */
262 uint32_t uEntryIntInfo;
263 /** The VM-entry exception error code field. */
264 uint32_t uEntryXcptErrorCode;
265
266 /** The VM-entry instruction length field. */
267 uint32_t cbEntryInstr;
268} VMXTRANSIENT;
269AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, fVmcsFieldsRead, 8);
271AssertCompileMemberAlignment(VMXTRANSIENT, fVectoringPF, 8);
272AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, 8);
273AssertCompileMemberAlignment(VMXTRANSIENT, fEFlags, 8);
274AssertCompileMemberAlignment(VMXTRANSIENT, uExitQual, 8);
275AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, 8);
276AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, 8);
277AssertCompileMemberAlignment(VMXTRANSIENT, ExitInstrInfo, 8);
278AssertCompileMemberAlignment(VMXTRANSIENT, uIdtVectoringErrorCode, 8);
279AssertCompileMemberAlignment(VMXTRANSIENT, uGuestLinearAddr, 8);
280AssertCompileMemberAlignment(VMXTRANSIENT, uGuestPhysicalAddr, 8);
281AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, 8);
282AssertCompileMemberAlignment(VMXTRANSIENT, cbEntryInstr, 8);
283/** Pointer to VMX transient state. */
284typedef VMXTRANSIENT *PVMXTRANSIENT;
285/** Pointer to a const VMX transient state. */
286typedef const VMXTRANSIENT *PCVMXTRANSIENT;
287
288/**
289 * VMX page allocation information.
290 */
291typedef struct
292{
293 uint32_t fValid; /**< Whether to allocate this page (e.g, based on a CPU feature). */
294 uint32_t uPadding0; /**< Padding to ensure array of these structs are aligned to a multiple of 8. */
295 PRTHCPHYS pHCPhys; /**< Where to store the host-physical address of the allocation. */
296 PRTR0PTR ppVirt; /**< Where to store the host-virtual address of the allocation. */
297} VMXPAGEALLOCINFO;
298/** Pointer to VMX page-allocation info. */
299typedef VMXPAGEALLOCINFO *PVMXPAGEALLOCINFO;
300/** Pointer to a const VMX page-allocation info. */
301typedef const VMXPAGEALLOCINFO *PCVMXPAGEALLOCINFO;
302AssertCompileSizeAlignment(VMXPAGEALLOCINFO, 8);
303
304/**
305 * Memory operand read or write access.
306 */
307typedef enum VMXMEMACCESS
308{
309 VMXMEMACCESS_READ = 0,
310 VMXMEMACCESS_WRITE = 1
311} VMXMEMACCESS;
312
313/**
314 * VMX VM-exit handler.
315 *
316 * @returns Strict VBox status code (i.e. informational status codes too).
317 * @param pVCpu The cross context virtual CPU structure.
318 * @param pVmxTransient The VMX-transient structure.
319 */
320#ifndef HMVMX_USE_FUNCTION_TABLE
321typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
322#else
323typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNVMXEXITHANDLER,(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient));
324/** Pointer to VM-exit handler. */
325typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
326#endif
327
328/**
329 * VMX VM-exit handler, non-strict status code.
330 *
331 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
332 *
333 * @returns VBox status code, no informational status code returned.
334 * @param pVCpu The cross context virtual CPU structure.
335 * @param pVmxTransient The VMX-transient structure.
336 *
337 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
338 * use of that status code will be replaced with VINF_EM_SOMETHING
339 * later when switching over to IEM.
340 */
341#ifndef HMVMX_USE_FUNCTION_TABLE
342typedef int FNVMXEXITHANDLERNSRC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
343#else
344typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
345#endif
346
347
348/*********************************************************************************************************************************
349* Internal Functions *
350*********************************************************************************************************************************/
351#ifndef HMVMX_USE_FUNCTION_TABLE
352DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
353# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
354# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
355#else
356# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
357# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
358#endif
359#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
360DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
361#endif
362
363static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
364
365/** @name VM-exit handler prototypes.
366 * @{
367 */
368static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
369static FNVMXEXITHANDLER hmR0VmxExitExtInt;
370static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
371static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
372static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
373static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
374static FNVMXEXITHANDLER hmR0VmxExitCpuid;
375static FNVMXEXITHANDLER hmR0VmxExitGetsec;
376static FNVMXEXITHANDLER hmR0VmxExitHlt;
377static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
378static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
379static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
380static FNVMXEXITHANDLER hmR0VmxExitVmcall;
381#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
382static FNVMXEXITHANDLER hmR0VmxExitVmclear;
383static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
384static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
385static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
386static FNVMXEXITHANDLER hmR0VmxExitVmread;
387static FNVMXEXITHANDLER hmR0VmxExitVmresume;
388static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
389static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
390static FNVMXEXITHANDLER hmR0VmxExitVmxon;
391static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
392#endif
393static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
394static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
395static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
396static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
397static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
398static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
399static FNVMXEXITHANDLER hmR0VmxExitMwait;
400static FNVMXEXITHANDLER hmR0VmxExitMtf;
401static FNVMXEXITHANDLER hmR0VmxExitMonitor;
402static FNVMXEXITHANDLER hmR0VmxExitPause;
403static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
404static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
405static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
406static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
407static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
408static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
409static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
410static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
411static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
412static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
413static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
414static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
415/** @} */
416
417#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
418/** @name Nested-guest VM-exit handler prototypes.
419 * @{
420 */
421static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
422static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
423static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
424static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
425static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
426static FNVMXEXITHANDLER hmR0VmxExitHltNested;
427static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
428static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
429static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
430static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
431static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
432static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
433static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
434static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
435static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
436static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
437static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
438static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
439static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
440static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
441static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
442static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
443static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
444static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
445static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
446static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
447static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
448static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
449static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
450/** @} */
451#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
452
453
454/*********************************************************************************************************************************
455* Global Variables *
456*********************************************************************************************************************************/
457#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
458/**
459 * Array of all VMCS fields.
460 * Any fields added to the VT-x spec. should be added here.
461 *
462 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
463 * of nested-guests.
464 */
465static const uint32_t g_aVmcsFields[] =
466{
467 /* 16-bit control fields. */
468 VMX_VMCS16_VPID,
469 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
470 VMX_VMCS16_EPTP_INDEX,
471
472 /* 16-bit guest-state fields. */
473 VMX_VMCS16_GUEST_ES_SEL,
474 VMX_VMCS16_GUEST_CS_SEL,
475 VMX_VMCS16_GUEST_SS_SEL,
476 VMX_VMCS16_GUEST_DS_SEL,
477 VMX_VMCS16_GUEST_FS_SEL,
478 VMX_VMCS16_GUEST_GS_SEL,
479 VMX_VMCS16_GUEST_LDTR_SEL,
480 VMX_VMCS16_GUEST_TR_SEL,
481 VMX_VMCS16_GUEST_INTR_STATUS,
482 VMX_VMCS16_GUEST_PML_INDEX,
483
484 /* 16-bits host-state fields. */
485 VMX_VMCS16_HOST_ES_SEL,
486 VMX_VMCS16_HOST_CS_SEL,
487 VMX_VMCS16_HOST_SS_SEL,
488 VMX_VMCS16_HOST_DS_SEL,
489 VMX_VMCS16_HOST_FS_SEL,
490 VMX_VMCS16_HOST_GS_SEL,
491 VMX_VMCS16_HOST_TR_SEL,
492
493 /* 64-bit control fields. */
494 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
495 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
496 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
497 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
498 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
499 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
500 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
501 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
502 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
503 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
504 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
505 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
506 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
507 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
508 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
509 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
510 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
511 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
512 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
513 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
514 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
515 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
516 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
517 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
518 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
519 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
520 VMX_VMCS64_CTRL_EPTP_FULL,
521 VMX_VMCS64_CTRL_EPTP_HIGH,
522 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
523 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
524 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
525 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
526 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
527 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
528 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
529 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
530 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
531 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
532 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
533 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
534 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
535 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
536 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
537 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
538 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
539 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
540 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
541 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
542 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
543 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
544
545 /* 64-bit read-only data fields. */
546 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
547 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
548
549 /* 64-bit guest-state fields. */
550 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
551 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
552 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
553 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
554 VMX_VMCS64_GUEST_PAT_FULL,
555 VMX_VMCS64_GUEST_PAT_HIGH,
556 VMX_VMCS64_GUEST_EFER_FULL,
557 VMX_VMCS64_GUEST_EFER_HIGH,
558 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
559 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
560 VMX_VMCS64_GUEST_PDPTE0_FULL,
561 VMX_VMCS64_GUEST_PDPTE0_HIGH,
562 VMX_VMCS64_GUEST_PDPTE1_FULL,
563 VMX_VMCS64_GUEST_PDPTE1_HIGH,
564 VMX_VMCS64_GUEST_PDPTE2_FULL,
565 VMX_VMCS64_GUEST_PDPTE2_HIGH,
566 VMX_VMCS64_GUEST_PDPTE3_FULL,
567 VMX_VMCS64_GUEST_PDPTE3_HIGH,
568 VMX_VMCS64_GUEST_BNDCFGS_FULL,
569 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
570
571 /* 64-bit host-state fields. */
572 VMX_VMCS64_HOST_PAT_FULL,
573 VMX_VMCS64_HOST_PAT_HIGH,
574 VMX_VMCS64_HOST_EFER_FULL,
575 VMX_VMCS64_HOST_EFER_HIGH,
576 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
577 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
578
579 /* 32-bit control fields. */
580 VMX_VMCS32_CTRL_PIN_EXEC,
581 VMX_VMCS32_CTRL_PROC_EXEC,
582 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
583 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
584 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
585 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
586 VMX_VMCS32_CTRL_EXIT,
587 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
588 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
589 VMX_VMCS32_CTRL_ENTRY,
590 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
591 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
592 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
593 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
594 VMX_VMCS32_CTRL_TPR_THRESHOLD,
595 VMX_VMCS32_CTRL_PROC_EXEC2,
596 VMX_VMCS32_CTRL_PLE_GAP,
597 VMX_VMCS32_CTRL_PLE_WINDOW,
598
599 /* 32-bits read-only fields. */
600 VMX_VMCS32_RO_VM_INSTR_ERROR,
601 VMX_VMCS32_RO_EXIT_REASON,
602 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
603 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
604 VMX_VMCS32_RO_IDT_VECTORING_INFO,
605 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
606 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
607 VMX_VMCS32_RO_EXIT_INSTR_INFO,
608
609 /* 32-bit guest-state fields. */
610 VMX_VMCS32_GUEST_ES_LIMIT,
611 VMX_VMCS32_GUEST_CS_LIMIT,
612 VMX_VMCS32_GUEST_SS_LIMIT,
613 VMX_VMCS32_GUEST_DS_LIMIT,
614 VMX_VMCS32_GUEST_FS_LIMIT,
615 VMX_VMCS32_GUEST_GS_LIMIT,
616 VMX_VMCS32_GUEST_LDTR_LIMIT,
617 VMX_VMCS32_GUEST_TR_LIMIT,
618 VMX_VMCS32_GUEST_GDTR_LIMIT,
619 VMX_VMCS32_GUEST_IDTR_LIMIT,
620 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
621 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
622 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
623 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
624 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
625 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
626 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
627 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
628 VMX_VMCS32_GUEST_INT_STATE,
629 VMX_VMCS32_GUEST_ACTIVITY_STATE,
630 VMX_VMCS32_GUEST_SMBASE,
631 VMX_VMCS32_GUEST_SYSENTER_CS,
632 VMX_VMCS32_PREEMPT_TIMER_VALUE,
633
634 /* 32-bit host-state fields. */
635 VMX_VMCS32_HOST_SYSENTER_CS,
636
637 /* Natural-width control fields. */
638 VMX_VMCS_CTRL_CR0_MASK,
639 VMX_VMCS_CTRL_CR4_MASK,
640 VMX_VMCS_CTRL_CR0_READ_SHADOW,
641 VMX_VMCS_CTRL_CR4_READ_SHADOW,
642 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
643 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
644 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
645 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
646
647 /* Natural-width read-only data fields. */
648 VMX_VMCS_RO_EXIT_QUALIFICATION,
649 VMX_VMCS_RO_IO_RCX,
650 VMX_VMCS_RO_IO_RSI,
651 VMX_VMCS_RO_IO_RDI,
652 VMX_VMCS_RO_IO_RIP,
653 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
654
655 /* Natural-width guest-state field */
656 VMX_VMCS_GUEST_CR0,
657 VMX_VMCS_GUEST_CR3,
658 VMX_VMCS_GUEST_CR4,
659 VMX_VMCS_GUEST_ES_BASE,
660 VMX_VMCS_GUEST_CS_BASE,
661 VMX_VMCS_GUEST_SS_BASE,
662 VMX_VMCS_GUEST_DS_BASE,
663 VMX_VMCS_GUEST_FS_BASE,
664 VMX_VMCS_GUEST_GS_BASE,
665 VMX_VMCS_GUEST_LDTR_BASE,
666 VMX_VMCS_GUEST_TR_BASE,
667 VMX_VMCS_GUEST_GDTR_BASE,
668 VMX_VMCS_GUEST_IDTR_BASE,
669 VMX_VMCS_GUEST_DR7,
670 VMX_VMCS_GUEST_RSP,
671 VMX_VMCS_GUEST_RIP,
672 VMX_VMCS_GUEST_RFLAGS,
673 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
674 VMX_VMCS_GUEST_SYSENTER_ESP,
675 VMX_VMCS_GUEST_SYSENTER_EIP,
676
677 /* Natural-width host-state fields */
678 VMX_VMCS_HOST_CR0,
679 VMX_VMCS_HOST_CR3,
680 VMX_VMCS_HOST_CR4,
681 VMX_VMCS_HOST_FS_BASE,
682 VMX_VMCS_HOST_GS_BASE,
683 VMX_VMCS_HOST_TR_BASE,
684 VMX_VMCS_HOST_GDTR_BASE,
685 VMX_VMCS_HOST_IDTR_BASE,
686 VMX_VMCS_HOST_SYSENTER_ESP,
687 VMX_VMCS_HOST_SYSENTER_EIP,
688 VMX_VMCS_HOST_RSP,
689 VMX_VMCS_HOST_RIP
690};
691#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
692
693static const uint32_t g_aVmcsSegBase[] =
694{
695 VMX_VMCS_GUEST_ES_BASE,
696 VMX_VMCS_GUEST_CS_BASE,
697 VMX_VMCS_GUEST_SS_BASE,
698 VMX_VMCS_GUEST_DS_BASE,
699 VMX_VMCS_GUEST_FS_BASE,
700 VMX_VMCS_GUEST_GS_BASE
701};
702static const uint32_t g_aVmcsSegSel[] =
703{
704 VMX_VMCS16_GUEST_ES_SEL,
705 VMX_VMCS16_GUEST_CS_SEL,
706 VMX_VMCS16_GUEST_SS_SEL,
707 VMX_VMCS16_GUEST_DS_SEL,
708 VMX_VMCS16_GUEST_FS_SEL,
709 VMX_VMCS16_GUEST_GS_SEL
710};
711static const uint32_t g_aVmcsSegLimit[] =
712{
713 VMX_VMCS32_GUEST_ES_LIMIT,
714 VMX_VMCS32_GUEST_CS_LIMIT,
715 VMX_VMCS32_GUEST_SS_LIMIT,
716 VMX_VMCS32_GUEST_DS_LIMIT,
717 VMX_VMCS32_GUEST_FS_LIMIT,
718 VMX_VMCS32_GUEST_GS_LIMIT
719};
720static const uint32_t g_aVmcsSegAttr[] =
721{
722 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
723 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
724 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
725 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
726 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
727 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
728};
729AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
730AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
731AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
732AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
733
734#ifdef HMVMX_USE_FUNCTION_TABLE
735/**
736 * VMX_EXIT dispatch table.
737 */
738static const struct CLANG11NOTHROWWEIRDNESS { PFNVMXEXITHANDLER pfn; } g_aVMExitHandlers[VMX_EXIT_MAX + 1] =
739{
740 /* 0 VMX_EXIT_XCPT_OR_NMI */ { hmR0VmxExitXcptOrNmi },
741 /* 1 VMX_EXIT_EXT_INT */ { hmR0VmxExitExtInt },
742 /* 2 VMX_EXIT_TRIPLE_FAULT */ { hmR0VmxExitTripleFault },
743 /* 3 VMX_EXIT_INIT_SIGNAL */ { hmR0VmxExitErrUnexpected },
744 /* 4 VMX_EXIT_SIPI */ { hmR0VmxExitErrUnexpected },
745 /* 5 VMX_EXIT_IO_SMI */ { hmR0VmxExitErrUnexpected },
746 /* 6 VMX_EXIT_SMI */ { hmR0VmxExitErrUnexpected },
747 /* 7 VMX_EXIT_INT_WINDOW */ { hmR0VmxExitIntWindow },
748 /* 8 VMX_EXIT_NMI_WINDOW */ { hmR0VmxExitNmiWindow },
749 /* 9 VMX_EXIT_TASK_SWITCH */ { hmR0VmxExitTaskSwitch },
750 /* 10 VMX_EXIT_CPUID */ { hmR0VmxExitCpuid },
751 /* 11 VMX_EXIT_GETSEC */ { hmR0VmxExitGetsec },
752 /* 12 VMX_EXIT_HLT */ { hmR0VmxExitHlt },
753 /* 13 VMX_EXIT_INVD */ { hmR0VmxExitInvd },
754 /* 14 VMX_EXIT_INVLPG */ { hmR0VmxExitInvlpg },
755 /* 15 VMX_EXIT_RDPMC */ { hmR0VmxExitRdpmc },
756 /* 16 VMX_EXIT_RDTSC */ { hmR0VmxExitRdtsc },
757 /* 17 VMX_EXIT_RSM */ { hmR0VmxExitErrUnexpected },
758 /* 18 VMX_EXIT_VMCALL */ { hmR0VmxExitVmcall },
759#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
760 /* 19 VMX_EXIT_VMCLEAR */ { hmR0VmxExitVmclear },
761 /* 20 VMX_EXIT_VMLAUNCH */ { hmR0VmxExitVmlaunch },
762 /* 21 VMX_EXIT_VMPTRLD */ { hmR0VmxExitVmptrld },
763 /* 22 VMX_EXIT_VMPTRST */ { hmR0VmxExitVmptrst },
764 /* 23 VMX_EXIT_VMREAD */ { hmR0VmxExitVmread },
765 /* 24 VMX_EXIT_VMRESUME */ { hmR0VmxExitVmresume },
766 /* 25 VMX_EXIT_VMWRITE */ { hmR0VmxExitVmwrite },
767 /* 26 VMX_EXIT_VMXOFF */ { hmR0VmxExitVmxoff },
768 /* 27 VMX_EXIT_VMXON */ { hmR0VmxExitVmxon },
769#else
770 /* 19 VMX_EXIT_VMCLEAR */ { hmR0VmxExitSetPendingXcptUD },
771 /* 20 VMX_EXIT_VMLAUNCH */ { hmR0VmxExitSetPendingXcptUD },
772 /* 21 VMX_EXIT_VMPTRLD */ { hmR0VmxExitSetPendingXcptUD },
773 /* 22 VMX_EXIT_VMPTRST */ { hmR0VmxExitSetPendingXcptUD },
774 /* 23 VMX_EXIT_VMREAD */ { hmR0VmxExitSetPendingXcptUD },
775 /* 24 VMX_EXIT_VMRESUME */ { hmR0VmxExitSetPendingXcptUD },
776 /* 25 VMX_EXIT_VMWRITE */ { hmR0VmxExitSetPendingXcptUD },
777 /* 26 VMX_EXIT_VMXOFF */ { hmR0VmxExitSetPendingXcptUD },
778 /* 27 VMX_EXIT_VMXON */ { hmR0VmxExitSetPendingXcptUD },
779#endif
780 /* 28 VMX_EXIT_MOV_CRX */ { hmR0VmxExitMovCRx },
781 /* 29 VMX_EXIT_MOV_DRX */ { hmR0VmxExitMovDRx },
782 /* 30 VMX_EXIT_IO_INSTR */ { hmR0VmxExitIoInstr },
783 /* 31 VMX_EXIT_RDMSR */ { hmR0VmxExitRdmsr },
784 /* 32 VMX_EXIT_WRMSR */ { hmR0VmxExitWrmsr },
785 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ { hmR0VmxExitErrInvalidGuestState },
786 /* 34 VMX_EXIT_ERR_MSR_LOAD */ { hmR0VmxExitErrUnexpected },
787 /* 35 UNDEFINED */ { hmR0VmxExitErrUnexpected },
788 /* 36 VMX_EXIT_MWAIT */ { hmR0VmxExitMwait },
789 /* 37 VMX_EXIT_MTF */ { hmR0VmxExitMtf },
790 /* 38 UNDEFINED */ { hmR0VmxExitErrUnexpected },
791 /* 39 VMX_EXIT_MONITOR */ { hmR0VmxExitMonitor },
792 /* 40 VMX_EXIT_PAUSE */ { hmR0VmxExitPause },
793 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ { hmR0VmxExitErrUnexpected },
794 /* 42 UNDEFINED */ { hmR0VmxExitErrUnexpected },
795 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ { hmR0VmxExitTprBelowThreshold },
796 /* 44 VMX_EXIT_APIC_ACCESS */ { hmR0VmxExitApicAccess },
797 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ { hmR0VmxExitErrUnexpected },
798 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ { hmR0VmxExitErrUnexpected },
799 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ { hmR0VmxExitErrUnexpected },
800 /* 48 VMX_EXIT_EPT_VIOLATION */ { hmR0VmxExitEptViolation },
801 /* 49 VMX_EXIT_EPT_MISCONFIG */ { hmR0VmxExitEptMisconfig },
802 /* 50 VMX_EXIT_INVEPT */ { hmR0VmxExitSetPendingXcptUD },
803 /* 51 VMX_EXIT_RDTSCP */ { hmR0VmxExitRdtscp },
804 /* 52 VMX_EXIT_PREEMPT_TIMER */ { hmR0VmxExitPreemptTimer },
805#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
806 /* 53 VMX_EXIT_INVVPID */ { hmR0VmxExitInvvpid },
807#else
808 /* 53 VMX_EXIT_INVVPID */ { hmR0VmxExitSetPendingXcptUD },
809#endif
810 /* 54 VMX_EXIT_WBINVD */ { hmR0VmxExitWbinvd },
811 /* 55 VMX_EXIT_XSETBV */ { hmR0VmxExitXsetbv },
812 /* 56 VMX_EXIT_APIC_WRITE */ { hmR0VmxExitErrUnexpected },
813 /* 57 VMX_EXIT_RDRAND */ { hmR0VmxExitErrUnexpected },
814 /* 58 VMX_EXIT_INVPCID */ { hmR0VmxExitInvpcid },
815 /* 59 VMX_EXIT_VMFUNC */ { hmR0VmxExitErrUnexpected },
816 /* 60 VMX_EXIT_ENCLS */ { hmR0VmxExitErrUnexpected },
817 /* 61 VMX_EXIT_RDSEED */ { hmR0VmxExitErrUnexpected },
818 /* 62 VMX_EXIT_PML_FULL */ { hmR0VmxExitErrUnexpected },
819 /* 63 VMX_EXIT_XSAVES */ { hmR0VmxExitErrUnexpected },
820 /* 64 VMX_EXIT_XRSTORS */ { hmR0VmxExitErrUnexpected },
821 /* 65 UNDEFINED */ { hmR0VmxExitErrUnexpected },
822 /* 66 VMX_EXIT_SPP_EVENT */ { hmR0VmxExitErrUnexpected },
823 /* 67 VMX_EXIT_UMWAIT */ { hmR0VmxExitErrUnexpected },
824 /* 68 VMX_EXIT_TPAUSE */ { hmR0VmxExitErrUnexpected },
825};
826#endif /* HMVMX_USE_FUNCTION_TABLE */
827
828#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
829static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
830{
831 /* 0 */ "(Not Used)",
832 /* 1 */ "VMCALL executed in VMX root operation.",
833 /* 2 */ "VMCLEAR with invalid physical address.",
834 /* 3 */ "VMCLEAR with VMXON pointer.",
835 /* 4 */ "VMLAUNCH with non-clear VMCS.",
836 /* 5 */ "VMRESUME with non-launched VMCS.",
837 /* 6 */ "VMRESUME after VMXOFF",
838 /* 7 */ "VM-entry with invalid control fields.",
839 /* 8 */ "VM-entry with invalid host state fields.",
840 /* 9 */ "VMPTRLD with invalid physical address.",
841 /* 10 */ "VMPTRLD with VMXON pointer.",
842 /* 11 */ "VMPTRLD with incorrect revision identifier.",
843 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
844 /* 13 */ "VMWRITE to read-only VMCS component.",
845 /* 14 */ "(Not Used)",
846 /* 15 */ "VMXON executed in VMX root operation.",
847 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
848 /* 17 */ "VM-entry with non-launched executing VMCS.",
849 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
850 /* 19 */ "VMCALL with non-clear VMCS.",
851 /* 20 */ "VMCALL with invalid VM-exit control fields.",
852 /* 21 */ "(Not Used)",
853 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
854 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
855 /* 24 */ "VMCALL with invalid SMM-monitor features.",
856 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
857 /* 26 */ "VM-entry with events blocked by MOV SS.",
858 /* 27 */ "(Not Used)",
859 /* 28 */ "Invalid operand to INVEPT/INVVPID."
860};
861#endif /* VBOX_STRICT && LOG_ENABLED */
862
863
864/**
865 * Checks if the given MSR is part of the lastbranch-from-IP MSR stack.
866 * @returns @c true if it's part of LBR stack, @c false otherwise.
867 *
868 * @param pVM The cross context VM structure.
869 * @param idMsr The MSR.
870 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
871 * Optional, can be NULL.
872 *
873 * @remarks Must only be called when LBR is enabled.
874 */
875DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchFromMsr(PCVM pVM, uint32_t idMsr, uint32_t *pidxMsr)
876{
877 Assert(pVM->hm.s.vmx.fLbr);
878 Assert(pVM->hm.s.vmx.idLbrFromIpMsrFirst);
879 uint32_t const cLbrStack = pVM->hm.s.vmx.idLbrFromIpMsrLast - pVM->hm.s.vmx.idLbrFromIpMsrFirst + 1;
880 uint32_t const idxMsr = idMsr - pVM->hm.s.vmx.idLbrFromIpMsrFirst;
881 if (idxMsr < cLbrStack)
882 {
883 if (pidxMsr)
884 *pidxMsr = idxMsr;
885 return true;
886 }
887 return false;
888}
889
890
891/**
892 * Checks if the given MSR is part of the lastbranch-to-IP MSR stack.
893 * @returns @c true if it's part of LBR stack, @c false otherwise.
894 *
895 * @param pVM The cross context VM structure.
896 * @param idMsr The MSR.
897 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
898 * Optional, can be NULL.
899 *
900 * @remarks Must only be called when LBR is enabled and when lastbranch-to-IP MSRs
901 * are supported by the CPU (see hmR0VmxSetupLbrMsrRange).
902 */
903DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchToMsr(PCVM pVM, uint32_t idMsr, uint32_t *pidxMsr)
904{
905 Assert(pVM->hm.s.vmx.fLbr);
906 if (pVM->hm.s.vmx.idLbrToIpMsrFirst)
907 {
908 uint32_t const cLbrStack = pVM->hm.s.vmx.idLbrToIpMsrLast - pVM->hm.s.vmx.idLbrToIpMsrFirst + 1;
909 uint32_t const idxMsr = idMsr - pVM->hm.s.vmx.idLbrToIpMsrFirst;
910 if (idxMsr < cLbrStack)
911 {
912 if (pidxMsr)
913 *pidxMsr = idxMsr;
914 return true;
915 }
916 }
917 return false;
918}
919
920
921/**
922 * Gets the CR0 guest/host mask.
923 *
924 * These bits typically does not change through the lifetime of a VM. Any bit set in
925 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
926 * by the guest.
927 *
928 * @returns The CR0 guest/host mask.
929 * @param pVCpu The cross context virtual CPU structure.
930 */
931static uint64_t hmR0VmxGetFixedCr0Mask(PCVMCPUCC pVCpu)
932{
933 /*
934 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
935 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
936 *
937 * Furthermore, modifications to any bits that are reserved/unspecified currently
938 * by the Intel spec. must also cause a VM-exit. This prevents unpredictable behavior
939 * when future CPUs specify and use currently reserved/unspecified bits.
940 */
941 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
942 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
943 * and @bugref{6944}. */
944 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
945 return ( X86_CR0_PE
946 | X86_CR0_NE
947 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
948 | X86_CR0_PG
949 | VMX_EXIT_HOST_CR0_IGNORE_MASK);
950}
951
952
953/**
954 * Gets the CR4 guest/host mask.
955 *
956 * These bits typically does not change through the lifetime of a VM. Any bit set in
957 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
958 * by the guest.
959 *
960 * @returns The CR4 guest/host mask.
961 * @param pVCpu The cross context virtual CPU structure.
962 */
963static uint64_t hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
964{
965 /*
966 * We construct a mask of all CR4 bits that the guest can modify without causing
967 * a VM-exit. Then invert this mask to obtain all CR4 bits that should cause
968 * a VM-exit when the guest attempts to modify them when executing using
969 * hardware-assisted VMX.
970 *
971 * When a feature is not exposed to the guest (and may be present on the host),
972 * we want to intercept guest modifications to the bit so we can emulate proper
973 * behavior (e.g., #GP).
974 *
975 * Furthermore, only modifications to those bits that don't require immediate
976 * emulation is allowed. For e.g., PCIDE is excluded because the behavior
977 * depends on CR3 which might not always be the guest value while executing
978 * using hardware-assisted VMX.
979 */
980 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
981 bool const fFsGsBase = pVM->cpum.ro.GuestFeatures.fFsGsBase;
982 bool const fXSaveRstor = pVM->cpum.ro.GuestFeatures.fXSaveRstor;
983 bool const fFxSaveRstor = pVM->cpum.ro.GuestFeatures.fFxSaveRstor;
984
985 /*
986 * Paranoia.
987 * Ensure features exposed to the guest are present on the host.
988 */
989 Assert(!fFsGsBase || pVM->cpum.ro.HostFeatures.fFsGsBase);
990 Assert(!fXSaveRstor || pVM->cpum.ro.HostFeatures.fXSaveRstor);
991 Assert(!fFxSaveRstor || pVM->cpum.ro.HostFeatures.fFxSaveRstor);
992
993 uint64_t const fGstMask = ( X86_CR4_PVI
994 | X86_CR4_TSD
995 | X86_CR4_DE
996 | X86_CR4_MCE
997 | X86_CR4_PCE
998 | X86_CR4_OSXMMEEXCPT
999 | (fFsGsBase ? X86_CR4_FSGSBASE : 0)
1000 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
1001 | (fFxSaveRstor ? X86_CR4_OSFXSR : 0));
1002 return ~fGstMask;
1003}
1004
1005
1006/**
1007 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
1008 * area.
1009 *
1010 * @returns @c true if it's different, @c false otherwise.
1011 * @param pVmcsInfo The VMCS info. object.
1012 */
1013DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
1014{
1015 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
1016 && pVmcsInfo->pvGuestMsrStore);
1017}
1018
1019
1020/**
1021 * Sets the given Processor-based VM-execution controls.
1022 *
1023 * @param pVmxTransient The VMX-transient structure.
1024 * @param uProcCtls The Processor-based VM-execution controls to set.
1025 */
1026static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1027{
1028 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1029 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
1030 {
1031 pVmcsInfo->u32ProcCtls |= uProcCtls;
1032 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1033 AssertRC(rc);
1034 }
1035}
1036
1037
1038/**
1039 * Removes the given Processor-based VM-execution controls.
1040 *
1041 * @param pVCpu The cross context virtual CPU structure.
1042 * @param pVmxTransient The VMX-transient structure.
1043 * @param uProcCtls The Processor-based VM-execution controls to remove.
1044 *
1045 * @remarks When executing a nested-guest, this will not remove any of the specified
1046 * controls if the nested hypervisor has set any one of them.
1047 */
1048static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1049{
1050 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1051 if (pVmcsInfo->u32ProcCtls & uProcCtls)
1052 {
1053#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1054 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
1055 ? true
1056 : !CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uProcCtls);
1057#else
1058 NOREF(pVCpu);
1059 bool const fRemoveCtls = true;
1060#endif
1061 if (fRemoveCtls)
1062 {
1063 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
1064 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1065 AssertRC(rc);
1066 }
1067 }
1068}
1069
1070
1071/**
1072 * Sets the TSC offset for the current VMCS.
1073 *
1074 * @param uTscOffset The TSC offset to set.
1075 * @param pVmcsInfo The VMCS info. object.
1076 */
1077static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
1078{
1079 if (pVmcsInfo->u64TscOffset != uTscOffset)
1080 {
1081 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
1082 AssertRC(rc);
1083 pVmcsInfo->u64TscOffset = uTscOffset;
1084 }
1085}
1086
1087
1088/**
1089 * Adds one or more exceptions to the exception bitmap and commits it to the current
1090 * VMCS.
1091 *
1092 * @param pVmxTransient The VMX-transient structure.
1093 * @param uXcptMask The exception(s) to add.
1094 */
1095static void hmR0VmxAddXcptInterceptMask(PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1096{
1097 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1098 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1099 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1100 {
1101 uXcptBitmap |= uXcptMask;
1102 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1103 AssertRC(rc);
1104 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1105 }
1106}
1107
1108
1109/**
1110 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1111 *
1112 * @param pVmxTransient The VMX-transient structure.
1113 * @param uXcpt The exception to add.
1114 */
1115static void hmR0VmxAddXcptIntercept(PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1116{
1117 Assert(uXcpt <= X86_XCPT_LAST);
1118 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1119}
1120
1121
1122/**
1123 * Remove one or more exceptions from the exception bitmap and commits it to the
1124 * current VMCS.
1125 *
1126 * This takes care of not removing the exception intercept if a nested-guest
1127 * requires the exception to be intercepted.
1128 *
1129 * @returns VBox status code.
1130 * @param pVCpu The cross context virtual CPU structure.
1131 * @param pVmxTransient The VMX-transient structure.
1132 * @param uXcptMask The exception(s) to remove.
1133 */
1134static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1135{
1136 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1137 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1138 if (u32XcptBitmap & uXcptMask)
1139 {
1140#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1141 if (!pVmxTransient->fIsNestedGuest)
1142 { /* likely */ }
1143 else
1144 {
1145 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1146 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1147 }
1148#endif
1149#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1150 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1151 | RT_BIT(X86_XCPT_DE)
1152 | RT_BIT(X86_XCPT_NM)
1153 | RT_BIT(X86_XCPT_TS)
1154 | RT_BIT(X86_XCPT_UD)
1155 | RT_BIT(X86_XCPT_NP)
1156 | RT_BIT(X86_XCPT_SS)
1157 | RT_BIT(X86_XCPT_GP)
1158 | RT_BIT(X86_XCPT_PF)
1159 | RT_BIT(X86_XCPT_MF));
1160#elif defined(HMVMX_ALWAYS_TRAP_PF)
1161 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1162#endif
1163 if (uXcptMask)
1164 {
1165 /* Validate we are not removing any essential exception intercepts. */
1166 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1167 NOREF(pVCpu);
1168 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1169 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1170
1171 /* Remove it from the exception bitmap. */
1172 u32XcptBitmap &= ~uXcptMask;
1173
1174 /* Commit and update the cache if necessary. */
1175 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1176 {
1177 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1178 AssertRC(rc);
1179 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1180 }
1181 }
1182 }
1183 return VINF_SUCCESS;
1184}
1185
1186
1187/**
1188 * Remove an exceptions from the exception bitmap and commits it to the current
1189 * VMCS.
1190 *
1191 * @returns VBox status code.
1192 * @param pVCpu The cross context virtual CPU structure.
1193 * @param pVmxTransient The VMX-transient structure.
1194 * @param uXcpt The exception to remove.
1195 */
1196static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1197{
1198 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1199}
1200
1201
1202/**
1203 * Loads the VMCS specified by the VMCS info. object.
1204 *
1205 * @returns VBox status code.
1206 * @param pVmcsInfo The VMCS info. object.
1207 *
1208 * @remarks Can be called with interrupts disabled.
1209 */
1210static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1211{
1212 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1213 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1214
1215 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1216 if (RT_SUCCESS(rc))
1217 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1218 return rc;
1219}
1220
1221
1222/**
1223 * Clears the VMCS specified by the VMCS info. object.
1224 *
1225 * @returns VBox status code.
1226 * @param pVmcsInfo The VMCS info. object.
1227 *
1228 * @remarks Can be called with interrupts disabled.
1229 */
1230static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1231{
1232 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1233 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1234
1235 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1236 if (RT_SUCCESS(rc))
1237 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1238 return rc;
1239}
1240
1241
1242#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1243/**
1244 * Loads the shadow VMCS specified by the VMCS info. object.
1245 *
1246 * @returns VBox status code.
1247 * @param pVmcsInfo The VMCS info. object.
1248 *
1249 * @remarks Can be called with interrupts disabled.
1250 */
1251static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1252{
1253 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1254 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1255
1256 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1257 if (RT_SUCCESS(rc))
1258 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1259 return rc;
1260}
1261
1262
1263/**
1264 * Clears the shadow VMCS specified by the VMCS info. object.
1265 *
1266 * @returns VBox status code.
1267 * @param pVmcsInfo The VMCS info. object.
1268 *
1269 * @remarks Can be called with interrupts disabled.
1270 */
1271static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1272{
1273 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1274 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1275
1276 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1277 if (RT_SUCCESS(rc))
1278 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1279 return rc;
1280}
1281
1282
1283/**
1284 * Switches from and to the specified VMCSes.
1285 *
1286 * @returns VBox status code.
1287 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1288 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1289 *
1290 * @remarks Called with interrupts disabled.
1291 */
1292static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1293{
1294 /*
1295 * Clear the VMCS we are switching out if it has not already been cleared.
1296 * This will sync any CPU internal data back to the VMCS.
1297 */
1298 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1299 {
1300 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1301 if (RT_SUCCESS(rc))
1302 {
1303 /*
1304 * The shadow VMCS, if any, would not be active at this point since we
1305 * would have cleared it while importing the virtual hardware-virtualization
1306 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1307 * clear the shadow VMCS here, just assert for safety.
1308 */
1309 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1310 }
1311 else
1312 return rc;
1313 }
1314
1315 /*
1316 * Clear the VMCS we are switching to if it has not already been cleared.
1317 * This will initialize the VMCS launch state to "clear" required for loading it.
1318 *
1319 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1320 */
1321 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1322 {
1323 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1324 if (RT_SUCCESS(rc))
1325 { /* likely */ }
1326 else
1327 return rc;
1328 }
1329
1330 /*
1331 * Finally, load the VMCS we are switching to.
1332 */
1333 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1334}
1335
1336
1337/**
1338 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1339 * caller.
1340 *
1341 * @returns VBox status code.
1342 * @param pVCpu The cross context virtual CPU structure.
1343 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1344 * true) or guest VMCS (pass false).
1345 */
1346static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1347{
1348 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1349 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1350
1351 PVMXVMCSINFO pVmcsInfoFrom;
1352 PVMXVMCSINFO pVmcsInfoTo;
1353 if (fSwitchToNstGstVmcs)
1354 {
1355 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1356 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1357 }
1358 else
1359 {
1360 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1361 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1362 }
1363
1364 /*
1365 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1366 * preemption hook code path acquires the current VMCS.
1367 */
1368 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1369
1370 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1371 if (RT_SUCCESS(rc))
1372 {
1373 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1374
1375 /*
1376 * If we are switching to a VMCS that was executed on a different host CPU or was
1377 * never executed before, flag that we need to export the host state before executing
1378 * guest/nested-guest code using hardware-assisted VMX.
1379 *
1380 * This could probably be done in a preemptible context since the preemption hook
1381 * will flag the necessary change in host context. However, since preemption is
1382 * already disabled and to avoid making assumptions about host specific code in
1383 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1384 * disabled.
1385 */
1386 if (pVmcsInfoTo->idHostCpuState == RTMpCpuId())
1387 { /* likely */ }
1388 else
1389 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1390
1391 ASMSetFlags(fEFlags);
1392
1393 /*
1394 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1395 * flag that we need to update the host MSR values there. Even if we decide in the
1396 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1397 * if its content differs, we would have to update the host MSRs anyway.
1398 */
1399 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1400 }
1401 else
1402 ASMSetFlags(fEFlags);
1403 return rc;
1404}
1405#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1406
1407
1408/**
1409 * Updates the VM's last error record.
1410 *
1411 * If there was a VMX instruction error, reads the error data from the VMCS and
1412 * updates VCPU's last error record as well.
1413 *
1414 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1415 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1416 * VERR_VMX_INVALID_VMCS_FIELD.
1417 * @param rc The error code.
1418 */
1419static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1420{
1421 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1422 || rc == VERR_VMX_UNABLE_TO_START_VM)
1423 {
1424 AssertPtrReturnVoid(pVCpu);
1425 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1426 }
1427 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1428}
1429
1430
1431#ifdef VBOX_STRICT
1432/**
1433 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1434 * transient structure.
1435 *
1436 * @param pVmxTransient The VMX-transient structure.
1437 */
1438DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1439{
1440 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1441 AssertRC(rc);
1442}
1443
1444
1445/**
1446 * Reads the VM-entry exception error code field from the VMCS into
1447 * the VMX transient structure.
1448 *
1449 * @param pVmxTransient The VMX-transient structure.
1450 */
1451DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1452{
1453 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1454 AssertRC(rc);
1455}
1456
1457
1458/**
1459 * Reads the VM-entry exception error code field from the VMCS into
1460 * the VMX transient structure.
1461 *
1462 * @param pVmxTransient The VMX-transient structure.
1463 */
1464DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1465{
1466 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1467 AssertRC(rc);
1468}
1469#endif /* VBOX_STRICT */
1470
1471
1472/**
1473 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1474 * transient structure.
1475 *
1476 * @param pVmxTransient The VMX-transient structure.
1477 */
1478DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1479{
1480 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1481 {
1482 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1483 AssertRC(rc);
1484 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1485 }
1486}
1487
1488
1489/**
1490 * Reads the VM-exit interruption error code from the VMCS into the VMX
1491 * transient structure.
1492 *
1493 * @param pVmxTransient The VMX-transient structure.
1494 */
1495DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1496{
1497 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1498 {
1499 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1500 AssertRC(rc);
1501 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1502 }
1503}
1504
1505
1506/**
1507 * Reads the VM-exit instruction length field from the VMCS into the VMX
1508 * transient structure.
1509 *
1510 * @param pVmxTransient The VMX-transient structure.
1511 */
1512DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1513{
1514 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1515 {
1516 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1517 AssertRC(rc);
1518 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1519 }
1520}
1521
1522
1523/**
1524 * Reads the VM-exit instruction-information field from the VMCS into
1525 * the VMX transient structure.
1526 *
1527 * @param pVmxTransient The VMX-transient structure.
1528 */
1529DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1530{
1531 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1532 {
1533 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1534 AssertRC(rc);
1535 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1536 }
1537}
1538
1539
1540/**
1541 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1542 *
1543 * @param pVmxTransient The VMX-transient structure.
1544 */
1545DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1546{
1547 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1548 {
1549 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1550 AssertRC(rc);
1551 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1552 }
1553}
1554
1555
1556/**
1557 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1558 *
1559 * @param pVmxTransient The VMX-transient structure.
1560 */
1561DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1562{
1563 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1564 {
1565 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1566 AssertRC(rc);
1567 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1568 }
1569}
1570
1571
1572/**
1573 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1574 *
1575 * @param pVmxTransient The VMX-transient structure.
1576 */
1577DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1578{
1579 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1580 {
1581 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1582 AssertRC(rc);
1583 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1584 }
1585}
1586
1587#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1588/**
1589 * Reads the Guest pending-debug exceptions from the VMCS into the VMX transient
1590 * structure.
1591 *
1592 * @param pVmxTransient The VMX-transient structure.
1593 */
1594DECLINLINE(void) hmR0VmxReadGuestPendingDbgXctps(PVMXTRANSIENT pVmxTransient)
1595{
1596 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PENDING_DBG_XCPTS))
1597 {
1598 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &pVmxTransient->uGuestPendingDbgXcpts);
1599 AssertRC(rc);
1600 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PENDING_DBG_XCPTS;
1601 }
1602}
1603#endif
1604
1605/**
1606 * Reads the IDT-vectoring information field from the VMCS into the VMX
1607 * transient structure.
1608 *
1609 * @param pVmxTransient The VMX-transient structure.
1610 *
1611 * @remarks No-long-jump zone!!!
1612 */
1613DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1614{
1615 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1616 {
1617 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1618 AssertRC(rc);
1619 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1620 }
1621}
1622
1623
1624/**
1625 * Reads the IDT-vectoring error code from the VMCS into the VMX
1626 * transient structure.
1627 *
1628 * @param pVmxTransient The VMX-transient structure.
1629 */
1630DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1631{
1632 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1633 {
1634 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1635 AssertRC(rc);
1636 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1637 }
1638}
1639
1640#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1641/**
1642 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1643 *
1644 * @param pVmxTransient The VMX-transient structure.
1645 */
1646static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1647{
1648 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1649 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1650 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1651 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1652 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1653 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1654 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1655 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1656 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1657 AssertRC(rc);
1658 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1659 | HMVMX_READ_EXIT_INSTR_LEN
1660 | HMVMX_READ_EXIT_INSTR_INFO
1661 | HMVMX_READ_IDT_VECTORING_INFO
1662 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1663 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1664 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1665 | HMVMX_READ_GUEST_LINEAR_ADDR
1666 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1667}
1668#endif
1669
1670/**
1671 * Enters VMX root mode operation on the current CPU.
1672 *
1673 * @returns VBox status code.
1674 * @param pHostCpu The HM physical-CPU structure.
1675 * @param pVM The cross context VM structure. Can be
1676 * NULL, after a resume.
1677 * @param HCPhysCpuPage Physical address of the VMXON region.
1678 * @param pvCpuPage Pointer to the VMXON region.
1679 */
1680static int hmR0VmxEnterRootMode(PHMPHYSCPU pHostCpu, PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1681{
1682 Assert(pHostCpu);
1683 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1684 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1685 Assert(pvCpuPage);
1686 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1687
1688 if (pVM)
1689 {
1690 /* Write the VMCS revision identifier to the VMXON region. */
1691 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1692 }
1693
1694 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1695 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1696
1697 /* Enable the VMX bit in CR4 if necessary. */
1698 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1699
1700 /* Record whether VMXE was already prior to us enabling it above. */
1701 pHostCpu->fVmxeAlreadyEnabled = RT_BOOL(uOldCr4 & X86_CR4_VMXE);
1702
1703 /* Enter VMX root mode. */
1704 int rc = VMXEnable(HCPhysCpuPage);
1705 if (RT_FAILURE(rc))
1706 {
1707 /* Restore CR4.VMXE if it was not set prior to our attempt to set it above. */
1708 if (!pHostCpu->fVmxeAlreadyEnabled)
1709 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1710
1711 if (pVM)
1712 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1713 }
1714
1715 /* Restore interrupts. */
1716 ASMSetFlags(fEFlags);
1717 return rc;
1718}
1719
1720
1721/**
1722 * Exits VMX root mode operation on the current CPU.
1723 *
1724 * @returns VBox status code.
1725 * @param pHostCpu The HM physical-CPU structure.
1726 */
1727static int hmR0VmxLeaveRootMode(PHMPHYSCPU pHostCpu)
1728{
1729 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1730
1731 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1732 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1733
1734 /* If we're for some reason not in VMX root mode, then don't leave it. */
1735 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1736
1737 int rc;
1738 if (uHostCr4 & X86_CR4_VMXE)
1739 {
1740 /* Exit VMX root mode and clear the VMX bit in CR4. */
1741 VMXDisable();
1742
1743 /* Clear CR4.VMXE only if it was clear prior to use setting it. */
1744 if (!pHostCpu->fVmxeAlreadyEnabled)
1745 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1746
1747 rc = VINF_SUCCESS;
1748 }
1749 else
1750 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1751
1752 /* Restore interrupts. */
1753 ASMSetFlags(fEFlags);
1754 return rc;
1755}
1756
1757
1758/**
1759 * Allocates pages specified as specified by an array of VMX page allocation info
1760 * objects.
1761 *
1762 * The pages contents are zero'd after allocation.
1763 *
1764 * @returns VBox status code.
1765 * @param hMemObj The ring-0 memory object associated with the allocation.
1766 * @param paAllocInfo The pointer to the first element of the VMX
1767 * page-allocation info object array.
1768 * @param cEntries The number of elements in the @a paAllocInfo array.
1769 */
1770static int hmR0VmxPagesAllocZ(RTR0MEMOBJ hMemObj, PVMXPAGEALLOCINFO paAllocInfo, uint32_t cEntries)
1771{
1772 /* Figure out how many pages to allocate. */
1773 uint32_t cPages = 0;
1774 for (uint32_t iPage = 0; iPage < cEntries; iPage++)
1775 cPages += !!paAllocInfo[iPage].fValid;
1776
1777 /* Allocate the pages. */
1778 if (cPages)
1779 {
1780 size_t const cbPages = cPages << X86_PAGE_4K_SHIFT;
1781 int rc = RTR0MemObjAllocPage(&hMemObj, cbPages, false /* fExecutable */);
1782 if (RT_FAILURE(rc))
1783 return rc;
1784
1785 /* Zero the contents and assign each page to the corresponding VMX page-allocation entry. */
1786 void *pvFirstPage = RTR0MemObjAddress(hMemObj);
1787 ASMMemZero32(pvFirstPage, cbPages);
1788
1789 uint32_t iPage = 0;
1790 for (uint32_t i = 0; i < cEntries; i++)
1791 if (paAllocInfo[i].fValid)
1792 {
1793 RTHCPHYS const HCPhysPage = RTR0MemObjGetPagePhysAddr(hMemObj, iPage);
1794 void *pvPage = (void *)((uintptr_t)pvFirstPage + (iPage << X86_PAGE_4K_SHIFT));
1795 Assert(HCPhysPage && HCPhysPage != NIL_RTHCPHYS);
1796 AssertPtr(pvPage);
1797
1798 Assert(paAllocInfo[iPage].pHCPhys);
1799 Assert(paAllocInfo[iPage].ppVirt);
1800 *paAllocInfo[iPage].pHCPhys = HCPhysPage;
1801 *paAllocInfo[iPage].ppVirt = pvPage;
1802
1803 /* Move to next page. */
1804 ++iPage;
1805 }
1806
1807 /* Make sure all valid (requested) pages have been assigned. */
1808 Assert(iPage == cPages);
1809 }
1810 return VINF_SUCCESS;
1811}
1812
1813
1814/**
1815 * Frees pages allocated using hmR0VmxPagesAllocZ.
1816 *
1817 * @param hMemObj The ring-0 memory object associated with the allocation.
1818 */
1819DECL_FORCE_INLINE(void) hmR0VmxPagesFree(RTR0MEMOBJ hMemObj)
1820{
1821 /* We can cleanup wholesale since it's all one allocation. */
1822 RTR0MemObjFree(hMemObj, true /* fFreeMappings */);
1823}
1824
1825
1826/**
1827 * Initializes a VMCS info. object.
1828 *
1829 * @param pVmcsInfo The VMCS info. object.
1830 */
1831static void hmR0VmxVmcsInfoInit(PVMXVMCSINFO pVmcsInfo)
1832{
1833 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1834
1835 Assert(pVmcsInfo->hMemObj == NIL_RTR0MEMOBJ);
1836 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1837 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1838 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1839 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1840 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1841 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1842 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1843 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1844 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1845 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
1846 pVmcsInfo->idHostCpuExec = NIL_RTCPUID;
1847}
1848
1849
1850/**
1851 * Frees the VT-x structures for a VMCS info. object.
1852 *
1853 * @param pVmcsInfo The VMCS info. object.
1854 */
1855static void hmR0VmxVmcsInfoFree(PVMXVMCSINFO pVmcsInfo)
1856{
1857 if (pVmcsInfo->hMemObj != NIL_RTR0MEMOBJ)
1858 {
1859 hmR0VmxPagesFree(pVmcsInfo->hMemObj);
1860 hmR0VmxVmcsInfoInit(pVmcsInfo);
1861 }
1862}
1863
1864
1865/**
1866 * Allocates the VT-x structures for a VMCS info. object.
1867 *
1868 * @returns VBox status code.
1869 * @param pVCpu The cross context virtual CPU structure.
1870 * @param pVmcsInfo The VMCS info. object.
1871 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1872 *
1873 * @remarks The caller is expected to take care of any and all allocation failures.
1874 * This function will not perform any cleanup for failures half-way
1875 * through.
1876 */
1877static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1878{
1879 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1880
1881 bool const fMsrBitmaps = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS);
1882 bool const fShadowVmcs = !fIsNstGstVmcs ? pVM->hm.s.vmx.fUseVmcsShadowing : pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing;
1883 Assert(!pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing); /* VMCS shadowing is not yet exposed to the guest. */
1884 VMXPAGEALLOCINFO aAllocInfo[] = {
1885 { true, 0 /* Unused */, &pVmcsInfo->HCPhysVmcs, &pVmcsInfo->pvVmcs },
1886 { true, 0 /* Unused */, &pVmcsInfo->HCPhysGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad },
1887 { true, 0 /* Unused */, &pVmcsInfo->HCPhysHostMsrLoad, &pVmcsInfo->pvHostMsrLoad },
1888 { fMsrBitmaps, 0 /* Unused */, &pVmcsInfo->HCPhysMsrBitmap, &pVmcsInfo->pvMsrBitmap },
1889 { fShadowVmcs, 0 /* Unused */, &pVmcsInfo->HCPhysShadowVmcs, &pVmcsInfo->pvShadowVmcs },
1890 };
1891
1892 int rc = hmR0VmxPagesAllocZ(pVmcsInfo->hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1893 if (RT_FAILURE(rc))
1894 return rc;
1895
1896 /*
1897 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1898 * Because they contain a symmetric list of guest MSRs to load on VM-entry and store on VM-exit.
1899 */
1900 AssertCompile(RT_ELEMENTS(aAllocInfo) > 0);
1901 Assert(pVmcsInfo->HCPhysGuestMsrLoad != NIL_RTHCPHYS);
1902 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1903 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1904
1905 /*
1906 * Get the virtual-APIC page rather than allocating them again.
1907 */
1908 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1909 {
1910 if (!fIsNstGstVmcs)
1911 {
1912 if (PDMHasApic(pVM))
1913 {
1914 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1915 if (RT_FAILURE(rc))
1916 return rc;
1917 Assert(pVmcsInfo->pbVirtApic);
1918 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1919 }
1920 }
1921 else
1922 {
1923 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(&pVCpu->cpum.GstCtx, &pVmcsInfo->HCPhysVirtApic);
1924 Assert(pVmcsInfo->pbVirtApic);
1925 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1926 }
1927 }
1928
1929 return VINF_SUCCESS;
1930}
1931
1932
1933/**
1934 * Free all VT-x structures for the VM.
1935 *
1936 * @returns IPRT status code.
1937 * @param pVM The cross context VM structure.
1938 */
1939static void hmR0VmxStructsFree(PVMCC pVM)
1940{
1941 hmR0VmxPagesFree(pVM->hm.s.vmx.hMemObj);
1942#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1943 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1944 {
1945 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1946 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1947 }
1948#endif
1949
1950 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1951 {
1952 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1953 hmR0VmxVmcsInfoFree(&pVCpu->hm.s.vmx.VmcsInfo);
1954#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1955 if (pVM->cpum.ro.GuestFeatures.fVmx)
1956 hmR0VmxVmcsInfoFree(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1957#endif
1958 }
1959}
1960
1961
1962/**
1963 * Allocate all VT-x structures for the VM.
1964 *
1965 * @returns IPRT status code.
1966 * @param pVM The cross context VM structure.
1967 *
1968 * @remarks This functions will cleanup on memory allocation failures.
1969 */
1970static int hmR0VmxStructsAlloc(PVMCC pVM)
1971{
1972 /*
1973 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1974 * The VMCS size cannot be more than 4096 bytes.
1975 *
1976 * See Intel spec. Appendix A.1 "Basic VMX Information".
1977 */
1978 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1979 if (cbVmcs <= X86_PAGE_4K_SIZE)
1980 { /* likely */ }
1981 else
1982 {
1983 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1984 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1985 }
1986
1987 /*
1988 * Allocate per-VM VT-x structures.
1989 */
1990 bool const fVirtApicAccess = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
1991 bool const fUseVmcsShadowing = pVM->hm.s.vmx.fUseVmcsShadowing;
1992 VMXPAGEALLOCINFO aAllocInfo[] = {
1993 { fVirtApicAccess, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess },
1994 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap },
1995 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap },
1996#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1997 { true, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysScratch, &(PRTR0PTR)pVM->hm.s.vmx.pbScratch },
1998#endif
1999 };
2000
2001 int rc = hmR0VmxPagesAllocZ(pVM->hm.s.vmx.hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
2002 if (RT_FAILURE(rc))
2003 goto cleanup;
2004
2005#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2006 /* Allocate the shadow VMCS-fields array. */
2007 if (fUseVmcsShadowing)
2008 {
2009 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
2010 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
2011 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2012 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2013 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
2014 && pVM->hm.s.vmx.paShadowVmcsRoFields))
2015 { /* likely */ }
2016 else
2017 {
2018 rc = VERR_NO_MEMORY;
2019 goto cleanup;
2020 }
2021 }
2022#endif
2023
2024 /*
2025 * Allocate per-VCPU VT-x structures.
2026 */
2027 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2028 {
2029 /* Allocate the guest VMCS structures. */
2030 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2031 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
2032 if (RT_FAILURE(rc))
2033 goto cleanup;
2034
2035#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2036 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
2037 if (pVM->cpum.ro.GuestFeatures.fVmx)
2038 {
2039 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
2040 if (RT_FAILURE(rc))
2041 goto cleanup;
2042 }
2043#endif
2044 }
2045
2046 return VINF_SUCCESS;
2047
2048cleanup:
2049 hmR0VmxStructsFree(pVM);
2050 Assert(rc != VINF_SUCCESS);
2051 return rc;
2052}
2053
2054
2055/**
2056 * Pre-initializes non-zero fields in VMX structures that will be allocated.
2057 *
2058 * @param pVM The cross context VM structure.
2059 */
2060static void hmR0VmxStructsInit(PVMCC pVM)
2061{
2062 /* Paranoia. */
2063 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
2064#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2065 Assert(pVM->hm.s.vmx.pbScratch == NULL);
2066#endif
2067
2068 /*
2069 * Initialize members up-front so we can cleanup en masse on allocation failures.
2070 */
2071#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2072 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
2073#endif
2074 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
2075 pVM->hm.s.vmx.HCPhysVmreadBitmap = NIL_RTHCPHYS;
2076 pVM->hm.s.vmx.HCPhysVmwriteBitmap = NIL_RTHCPHYS;
2077 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2078 {
2079 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2080 hmR0VmxVmcsInfoInit(&pVCpu->hm.s.vmx.VmcsInfo);
2081 hmR0VmxVmcsInfoInit(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
2082 }
2083}
2084
2085#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2086/**
2087 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2088 *
2089 * @returns @c true if the MSR is intercepted, @c false otherwise.
2090 * @param pvMsrBitmap The MSR bitmap.
2091 * @param offMsr The MSR byte offset.
2092 * @param iBit The bit offset from the byte offset.
2093 */
2094DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2095{
2096 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2097 Assert(pbMsrBitmap);
2098 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2099 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2100}
2101#endif
2102
2103/**
2104 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2105 *
2106 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2107 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2108 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2109 * the read/write access of this MSR.
2110 *
2111 * @param pVCpu The cross context virtual CPU structure.
2112 * @param pVmcsInfo The VMCS info. object.
2113 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2114 * @param idMsr The MSR value.
2115 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2116 * include both a read -and- a write permission!
2117 *
2118 * @sa CPUMGetVmxMsrPermission.
2119 * @remarks Can be called with interrupts disabled.
2120 */
2121static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2122{
2123 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2124 Assert(pbMsrBitmap);
2125 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2126
2127 /*
2128 * MSR-bitmap Layout:
2129 * Byte index MSR range Interpreted as
2130 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2131 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2132 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2133 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2134 *
2135 * A bit corresponding to an MSR within the above range causes a VM-exit
2136 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2137 * the MSR range, it always cause a VM-exit.
2138 *
2139 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2140 */
2141 uint16_t const offBitmapRead = 0;
2142 uint16_t const offBitmapWrite = 0x800;
2143 uint16_t offMsr;
2144 int32_t iBit;
2145 if (idMsr <= UINT32_C(0x00001fff))
2146 {
2147 offMsr = 0;
2148 iBit = idMsr;
2149 }
2150 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2151 {
2152 offMsr = 0x400;
2153 iBit = idMsr - UINT32_C(0xc0000000);
2154 }
2155 else
2156 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2157
2158 /*
2159 * Set the MSR read permission.
2160 */
2161 uint16_t const offMsrRead = offBitmapRead + offMsr;
2162 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2163 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2164 {
2165#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2166 bool const fClear = !fIsNstGstVmcs ? true
2167 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2168#else
2169 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2170 bool const fClear = true;
2171#endif
2172 if (fClear)
2173 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2174 }
2175 else
2176 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2177
2178 /*
2179 * Set the MSR write permission.
2180 */
2181 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2182 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2183 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2184 {
2185#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2186 bool const fClear = !fIsNstGstVmcs ? true
2187 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2188#else
2189 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2190 bool const fClear = true;
2191#endif
2192 if (fClear)
2193 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2194 }
2195 else
2196 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2197}
2198
2199
2200/**
2201 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2202 * area.
2203 *
2204 * @returns VBox status code.
2205 * @param pVCpu The cross context virtual CPU structure.
2206 * @param pVmcsInfo The VMCS info. object.
2207 * @param cMsrs The number of MSRs.
2208 */
2209static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2210{
2211 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2212 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2213 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2214 {
2215 /* Commit the MSR counts to the VMCS and update the cache. */
2216 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2217 {
2218 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2219 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2220 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2221 pVmcsInfo->cEntryMsrLoad = cMsrs;
2222 pVmcsInfo->cExitMsrStore = cMsrs;
2223 pVmcsInfo->cExitMsrLoad = cMsrs;
2224 }
2225 return VINF_SUCCESS;
2226 }
2227
2228 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2229 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2230 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2231}
2232
2233
2234/**
2235 * Adds a new (or updates the value of an existing) guest/host MSR
2236 * pair to be swapped during the world-switch as part of the
2237 * auto-load/store MSR area in the VMCS.
2238 *
2239 * @returns VBox status code.
2240 * @param pVCpu The cross context virtual CPU structure.
2241 * @param pVmxTransient The VMX-transient structure.
2242 * @param idMsr The MSR.
2243 * @param uGuestMsrValue Value of the guest MSR.
2244 * @param fSetReadWrite Whether to set the guest read/write access of this
2245 * MSR (thus not causing a VM-exit).
2246 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2247 * necessary.
2248 */
2249static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2250 bool fSetReadWrite, bool fUpdateHostMsr)
2251{
2252 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2253 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2254 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2255 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2256 uint32_t i;
2257
2258 /* Paranoia. */
2259 Assert(pGuestMsrLoad);
2260
2261 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2262
2263 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2264 for (i = 0; i < cMsrs; i++)
2265 {
2266 if (pGuestMsrLoad[i].u32Msr == idMsr)
2267 break;
2268 }
2269
2270 bool fAdded = false;
2271 if (i == cMsrs)
2272 {
2273 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2274 ++cMsrs;
2275 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2276 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2277
2278 /* Set the guest to read/write this MSR without causing VM-exits. */
2279 if ( fSetReadWrite
2280 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2281 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2282
2283 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2284 fAdded = true;
2285 }
2286
2287 /* Update the MSR value for the newly added or already existing MSR. */
2288 pGuestMsrLoad[i].u32Msr = idMsr;
2289 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2290
2291 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2292 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2293 {
2294 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2295 pGuestMsrStore[i].u32Msr = idMsr;
2296 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2297 }
2298
2299 /* Update the corresponding slot in the host MSR area. */
2300 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2301 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2302 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2303 pHostMsr[i].u32Msr = idMsr;
2304
2305 /*
2306 * Only if the caller requests to update the host MSR value AND we've newly added the
2307 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2308 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2309 *
2310 * We do this for performance reasons since reading MSRs may be quite expensive.
2311 */
2312 if (fAdded)
2313 {
2314 if (fUpdateHostMsr)
2315 {
2316 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2317 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2318 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2319 }
2320 else
2321 {
2322 /* Someone else can do the work. */
2323 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2324 }
2325 }
2326 return VINF_SUCCESS;
2327}
2328
2329
2330/**
2331 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2332 * auto-load/store MSR area in the VMCS.
2333 *
2334 * @returns VBox status code.
2335 * @param pVCpu The cross context virtual CPU structure.
2336 * @param pVmxTransient The VMX-transient structure.
2337 * @param idMsr The MSR.
2338 */
2339static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2340{
2341 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2342 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2343 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2344 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2345
2346 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2347
2348 for (uint32_t i = 0; i < cMsrs; i++)
2349 {
2350 /* Find the MSR. */
2351 if (pGuestMsrLoad[i].u32Msr == idMsr)
2352 {
2353 /*
2354 * If it's the last MSR, we only need to reduce the MSR count.
2355 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2356 */
2357 if (i < cMsrs - 1)
2358 {
2359 /* Remove it from the VM-entry MSR-load area. */
2360 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2361 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2362
2363 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2364 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2365 {
2366 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2367 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2368 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2369 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2370 }
2371
2372 /* Remove it from the VM-exit MSR-load area. */
2373 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2374 Assert(pHostMsr[i].u32Msr == idMsr);
2375 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2376 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2377 }
2378
2379 /* Reduce the count to reflect the removed MSR and bail. */
2380 --cMsrs;
2381 break;
2382 }
2383 }
2384
2385 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2386 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2387 {
2388 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2389 AssertRCReturn(rc, rc);
2390
2391 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2392 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2393 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2394
2395 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2396 return VINF_SUCCESS;
2397 }
2398
2399 return VERR_NOT_FOUND;
2400}
2401
2402
2403/**
2404 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2405 *
2406 * @returns @c true if found, @c false otherwise.
2407 * @param pVmcsInfo The VMCS info. object.
2408 * @param idMsr The MSR to find.
2409 */
2410static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2411{
2412 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2413 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2414 Assert(pMsrs);
2415 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2416 for (uint32_t i = 0; i < cMsrs; i++)
2417 {
2418 if (pMsrs[i].u32Msr == idMsr)
2419 return true;
2420 }
2421 return false;
2422}
2423
2424
2425/**
2426 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2427 *
2428 * @param pVCpu The cross context virtual CPU structure.
2429 * @param pVmcsInfo The VMCS info. object.
2430 *
2431 * @remarks No-long-jump zone!!!
2432 */
2433static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2434{
2435 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2436
2437 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2438 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2439 Assert(pHostMsrLoad);
2440 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2441 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2442 for (uint32_t i = 0; i < cMsrs; i++)
2443 {
2444 /*
2445 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2446 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2447 */
2448 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2449 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2450 else
2451 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2452 }
2453}
2454
2455
2456/**
2457 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2458 * perform lazy restoration of the host MSRs while leaving VT-x.
2459 *
2460 * @param pVCpu The cross context virtual CPU structure.
2461 *
2462 * @remarks No-long-jump zone!!!
2463 */
2464static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2465{
2466 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2467
2468 /*
2469 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2470 */
2471 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2472 {
2473 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2474 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2475 {
2476 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2477 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2478 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2479 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2480 }
2481 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2482 }
2483}
2484
2485
2486/**
2487 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2488 * lazily while leaving VT-x.
2489 *
2490 * @returns true if it does, false otherwise.
2491 * @param pVCpu The cross context virtual CPU structure.
2492 * @param idMsr The MSR to check.
2493 */
2494static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2495{
2496 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2497 {
2498 switch (idMsr)
2499 {
2500 case MSR_K8_LSTAR:
2501 case MSR_K6_STAR:
2502 case MSR_K8_SF_MASK:
2503 case MSR_K8_KERNEL_GS_BASE:
2504 return true;
2505 }
2506 }
2507 return false;
2508}
2509
2510
2511/**
2512 * Loads a set of guests MSRs to allow read/passthru to the guest.
2513 *
2514 * The name of this function is slightly confusing. This function does NOT
2515 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2516 * common prefix for functions dealing with "lazy restoration" of the shared
2517 * MSRs.
2518 *
2519 * @param pVCpu The cross context virtual CPU structure.
2520 *
2521 * @remarks No-long-jump zone!!!
2522 */
2523static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2524{
2525 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2526 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2527
2528 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2529 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2530 {
2531 /*
2532 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2533 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2534 * we can skip a few MSR writes.
2535 *
2536 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2537 * guest MSR values in the guest-CPU context might be different to what's currently
2538 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2539 * CPU, see @bugref{8728}.
2540 */
2541 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2542 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2543 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2544 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2545 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2546 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2547 {
2548#ifdef VBOX_STRICT
2549 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2550 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2551 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2552 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2553#endif
2554 }
2555 else
2556 {
2557 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2558 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2559 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2560 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2561 }
2562 }
2563 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2564}
2565
2566
2567/**
2568 * Performs lazy restoration of the set of host MSRs if they were previously
2569 * loaded with guest MSR values.
2570 *
2571 * @param pVCpu The cross context virtual CPU structure.
2572 *
2573 * @remarks No-long-jump zone!!!
2574 * @remarks The guest MSRs should have been saved back into the guest-CPU
2575 * context by hmR0VmxImportGuestState()!!!
2576 */
2577static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2578{
2579 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2580 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2581
2582 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2583 {
2584 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2585 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2586 {
2587 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2588 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2589 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2590 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2591 }
2592 }
2593 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2594}
2595
2596
2597/**
2598 * Verifies that our cached values of the VMCS fields are all consistent with
2599 * what's actually present in the VMCS.
2600 *
2601 * @returns VBox status code.
2602 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2603 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2604 * VMCS content. HMCPU error-field is
2605 * updated, see VMX_VCI_XXX.
2606 * @param pVCpu The cross context virtual CPU structure.
2607 * @param pVmcsInfo The VMCS info. object.
2608 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2609 */
2610static int hmR0VmxCheckCachedVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2611{
2612 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2613
2614 uint32_t u32Val;
2615 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2616 AssertRC(rc);
2617 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2618 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2619 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2620 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2621
2622 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2623 AssertRC(rc);
2624 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2625 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2626 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2627 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2628
2629 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2630 AssertRC(rc);
2631 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2632 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2633 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2634 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2635
2636 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2637 AssertRC(rc);
2638 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2639 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2640 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2641 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2642
2643 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2644 {
2645 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2646 AssertRC(rc);
2647 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2648 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2649 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2650 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2651 }
2652
2653 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2654 AssertRC(rc);
2655 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2656 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2657 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2658 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2659
2660 uint64_t u64Val;
2661 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2662 AssertRC(rc);
2663 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2664 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2665 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2666 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2667
2668 NOREF(pcszVmcs);
2669 return VINF_SUCCESS;
2670}
2671
2672
2673#ifdef VBOX_STRICT
2674/**
2675 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2676 *
2677 * @param pVCpu The cross context virtual CPU structure.
2678 * @param pVmcsInfo The VMCS info. object.
2679 */
2680static void hmR0VmxCheckHostEferMsr(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2681{
2682 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2683
2684 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2685 {
2686 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2687 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2688 uint64_t uVmcsEferMsrVmcs;
2689 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2690 AssertRC(rc);
2691
2692 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2693 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2694 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2695 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2696 }
2697}
2698
2699
2700/**
2701 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2702 * VMCS are correct.
2703 *
2704 * @param pVCpu The cross context virtual CPU structure.
2705 * @param pVmcsInfo The VMCS info. object.
2706 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2707 */
2708static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2709{
2710 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2711
2712 /* Read the various MSR-area counts from the VMCS. */
2713 uint32_t cEntryLoadMsrs;
2714 uint32_t cExitStoreMsrs;
2715 uint32_t cExitLoadMsrs;
2716 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2717 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2718 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2719
2720 /* Verify all the MSR counts are the same. */
2721 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2722 Assert(cExitStoreMsrs == cExitLoadMsrs);
2723 uint32_t const cMsrs = cExitLoadMsrs;
2724
2725 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2726 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2727
2728 /* Verify the MSR counts are within the allocated page size. */
2729 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2730
2731 /* Verify the relevant contents of the MSR areas match. */
2732 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2733 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2734 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2735 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2736 for (uint32_t i = 0; i < cMsrs; i++)
2737 {
2738 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2739 if (fSeparateExitMsrStorePage)
2740 {
2741 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2742 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2743 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2744 }
2745
2746 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2747 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2748 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2749
2750 uint64_t const u64HostMsr = ASMRdMsr(pHostMsrLoad->u32Msr);
2751 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64HostMsr,
2752 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2753 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64HostMsr, cMsrs));
2754
2755 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2756 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2757 if (fIsEferMsr)
2758 {
2759 AssertMsgReturnVoid(u64HostMsr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2760 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2761 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64HostMsr, cMsrs));
2762 }
2763
2764 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2765 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2766 {
2767 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2768 if (fIsEferMsr)
2769 {
2770 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2771 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2772 }
2773 else
2774 {
2775 /* Verify LBR MSRs (used only for debugging) are intercepted. We don't passthru these MSRs to the guest yet. */
2776 PCVM pVM = pVCpu->CTX_SUFF(pVM);
2777 if ( pVM->hm.s.vmx.fLbr
2778 && ( hmR0VmxIsLbrBranchFromMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2779 || hmR0VmxIsLbrBranchToMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2780 || pGuestMsrLoad->u32Msr == pVM->hm.s.vmx.idLbrTosMsr))
2781 {
2782 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_EXIT_RD_WR,
2783 ("u32Msr=%#RX32 cMsrs=%u Passthru read/write for LBR MSRs!\n",
2784 pGuestMsrLoad->u32Msr, cMsrs));
2785 }
2786 else if (!fIsNstGstVmcs)
2787 {
2788 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_ALLOW_RD_WR,
2789 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2790 }
2791 else
2792 {
2793 /*
2794 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2795 * execute a nested-guest with MSR passthrough.
2796 *
2797 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2798 * allow passthrough too.
2799 */
2800 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2801 Assert(pvMsrBitmapNstGst);
2802 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2803 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2804 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2805 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2806 }
2807 }
2808 }
2809
2810 /* Move to the next MSR. */
2811 pHostMsrLoad++;
2812 pGuestMsrLoad++;
2813 pGuestMsrStore++;
2814 }
2815}
2816#endif /* VBOX_STRICT */
2817
2818
2819/**
2820 * Flushes the TLB using EPT.
2821 *
2822 * @returns VBox status code.
2823 * @param pVCpu The cross context virtual CPU structure of the calling
2824 * EMT. Can be NULL depending on @a enmTlbFlush.
2825 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2826 * enmTlbFlush.
2827 * @param enmTlbFlush Type of flush.
2828 *
2829 * @remarks Caller is responsible for making sure this function is called only
2830 * when NestedPaging is supported and providing @a enmTlbFlush that is
2831 * supported by the CPU.
2832 * @remarks Can be called with interrupts disabled.
2833 */
2834static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2835{
2836 uint64_t au64Descriptor[2];
2837 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2838 au64Descriptor[0] = 0;
2839 else
2840 {
2841 Assert(pVCpu);
2842 Assert(pVmcsInfo);
2843 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2844 }
2845 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2846
2847 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2848 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2849
2850 if ( RT_SUCCESS(rc)
2851 && pVCpu)
2852 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2853}
2854
2855
2856/**
2857 * Flushes the TLB using VPID.
2858 *
2859 * @returns VBox status code.
2860 * @param pVCpu The cross context virtual CPU structure of the calling
2861 * EMT. Can be NULL depending on @a enmTlbFlush.
2862 * @param enmTlbFlush Type of flush.
2863 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2864 * on @a enmTlbFlush).
2865 *
2866 * @remarks Can be called with interrupts disabled.
2867 */
2868static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2869{
2870 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2871
2872 uint64_t au64Descriptor[2];
2873 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2874 {
2875 au64Descriptor[0] = 0;
2876 au64Descriptor[1] = 0;
2877 }
2878 else
2879 {
2880 AssertPtr(pVCpu);
2881 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2882 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2883 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2884 au64Descriptor[1] = GCPtr;
2885 }
2886
2887 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2888 AssertMsg(rc == VINF_SUCCESS,
2889 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2890
2891 if ( RT_SUCCESS(rc)
2892 && pVCpu)
2893 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2894 NOREF(rc);
2895}
2896
2897
2898/**
2899 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2900 * otherwise there is nothing really to invalidate.
2901 *
2902 * @returns VBox status code.
2903 * @param pVCpu The cross context virtual CPU structure.
2904 * @param GCVirt Guest virtual address of the page to invalidate.
2905 */
2906VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2907{
2908 AssertPtr(pVCpu);
2909 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2910
2911 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2912 {
2913 /*
2914 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2915 * the EPT case. See @bugref{6043} and @bugref{6177}.
2916 *
2917 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2918 * as this function maybe called in a loop with individual addresses.
2919 */
2920 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2921 if (pVM->hm.s.vmx.fVpid)
2922 {
2923 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2924 if (fVpidFlush)
2925 {
2926 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2927 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2928 }
2929 else
2930 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2931 }
2932 else if (pVM->hm.s.fNestedPaging)
2933 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2934 }
2935
2936 return VINF_SUCCESS;
2937}
2938
2939
2940/**
2941 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2942 * case where neither EPT nor VPID is supported by the CPU.
2943 *
2944 * @param pHostCpu The HM physical-CPU structure.
2945 * @param pVCpu The cross context virtual CPU structure.
2946 *
2947 * @remarks Called with interrupts disabled.
2948 */
2949static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2950{
2951 AssertPtr(pVCpu);
2952 AssertPtr(pHostCpu);
2953
2954 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2955
2956 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2957 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2958 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2959 pVCpu->hm.s.fForceTLBFlush = false;
2960 return;
2961}
2962
2963
2964/**
2965 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2966 *
2967 * @param pHostCpu The HM physical-CPU structure.
2968 * @param pVCpu The cross context virtual CPU structure.
2969 * @param pVmcsInfo The VMCS info. object.
2970 *
2971 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2972 * nomenclature. The reason is, to avoid confusion in compare statements
2973 * since the host-CPU copies are named "ASID".
2974 *
2975 * @remarks Called with interrupts disabled.
2976 */
2977static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2978{
2979#ifdef VBOX_WITH_STATISTICS
2980 bool fTlbFlushed = false;
2981# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2982# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2983 if (!fTlbFlushed) \
2984 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2985 } while (0)
2986#else
2987# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2988# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2989#endif
2990
2991 AssertPtr(pVCpu);
2992 AssertPtr(pHostCpu);
2993 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2994
2995 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2996 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2997 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2998 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2999
3000 /*
3001 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
3002 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3003 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3004 * cannot reuse the current ASID anymore.
3005 */
3006 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3007 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3008 {
3009 ++pHostCpu->uCurrentAsid;
3010 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3011 {
3012 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
3013 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3014 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3015 }
3016
3017 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3018 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3019 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3020
3021 /*
3022 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
3023 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
3024 */
3025 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3026 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3027 HMVMX_SET_TAGGED_TLB_FLUSHED();
3028 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
3029 }
3030 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
3031 {
3032 /*
3033 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
3034 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
3035 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
3036 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
3037 * mappings, see @bugref{6568}.
3038 *
3039 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
3040 */
3041 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3042 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3043 HMVMX_SET_TAGGED_TLB_FLUSHED();
3044 }
3045 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3046 {
3047 /*
3048 * The nested-guest specifies its own guest-physical address to use as the APIC-access
3049 * address which requires flushing the TLB of EPT cached structures.
3050 *
3051 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
3052 */
3053 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3054 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3055 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3056 HMVMX_SET_TAGGED_TLB_FLUSHED();
3057 }
3058
3059
3060 pVCpu->hm.s.fForceTLBFlush = false;
3061 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
3062
3063 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
3064 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
3065 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3066 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3067 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3068 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3069 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3070 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3071 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3072
3073 /* Update VMCS with the VPID. */
3074 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3075 AssertRC(rc);
3076
3077#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3078}
3079
3080
3081/**
3082 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3083 *
3084 * @param pHostCpu The HM physical-CPU structure.
3085 * @param pVCpu The cross context virtual CPU structure.
3086 * @param pVmcsInfo The VMCS info. object.
3087 *
3088 * @remarks Called with interrupts disabled.
3089 */
3090static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3091{
3092 AssertPtr(pVCpu);
3093 AssertPtr(pHostCpu);
3094 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3095 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3096 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3097
3098 /*
3099 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3100 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3101 */
3102 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3103 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3104 {
3105 pVCpu->hm.s.fForceTLBFlush = true;
3106 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3107 }
3108
3109 /* Check for explicit TLB flushes. */
3110 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3111 {
3112 pVCpu->hm.s.fForceTLBFlush = true;
3113 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3114 }
3115
3116 /* Check for TLB flushes while switching to/from a nested-guest. */
3117 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3118 {
3119 pVCpu->hm.s.fForceTLBFlush = true;
3120 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3121 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3122 }
3123
3124 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3125 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3126
3127 if (pVCpu->hm.s.fForceTLBFlush)
3128 {
3129 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3130 pVCpu->hm.s.fForceTLBFlush = false;
3131 }
3132}
3133
3134
3135/**
3136 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3137 *
3138 * @param pHostCpu The HM physical-CPU structure.
3139 * @param pVCpu The cross context virtual CPU structure.
3140 *
3141 * @remarks Called with interrupts disabled.
3142 */
3143static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3144{
3145 AssertPtr(pVCpu);
3146 AssertPtr(pHostCpu);
3147 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3148 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3149 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3150
3151 /*
3152 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3153 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3154 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3155 * cannot reuse the current ASID anymore.
3156 */
3157 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3158 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3159 {
3160 pVCpu->hm.s.fForceTLBFlush = true;
3161 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3162 }
3163
3164 /* Check for explicit TLB flushes. */
3165 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3166 {
3167 /*
3168 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3169 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3170 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3171 * include fExplicitFlush's too) - an obscure corner case.
3172 */
3173 pVCpu->hm.s.fForceTLBFlush = true;
3174 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3175 }
3176
3177 /* Check for TLB flushes while switching to/from a nested-guest. */
3178 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3179 {
3180 pVCpu->hm.s.fForceTLBFlush = true;
3181 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3182 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3183 }
3184
3185 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3186 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3187 if (pVCpu->hm.s.fForceTLBFlush)
3188 {
3189 ++pHostCpu->uCurrentAsid;
3190 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3191 {
3192 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3193 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3194 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3195 }
3196
3197 pVCpu->hm.s.fForceTLBFlush = false;
3198 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3199 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3200 if (pHostCpu->fFlushAsidBeforeUse)
3201 {
3202 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3203 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3204 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3205 {
3206 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3207 pHostCpu->fFlushAsidBeforeUse = false;
3208 }
3209 else
3210 {
3211 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3212 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3213 }
3214 }
3215 }
3216
3217 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3218 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3219 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3220 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3221 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3222 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3223 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3224
3225 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3226 AssertRC(rc);
3227}
3228
3229
3230/**
3231 * Flushes the guest TLB entry based on CPU capabilities.
3232 *
3233 * @param pHostCpu The HM physical-CPU structure.
3234 * @param pVCpu The cross context virtual CPU structure.
3235 * @param pVmcsInfo The VMCS info. object.
3236 *
3237 * @remarks Called with interrupts disabled.
3238 */
3239static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3240{
3241#ifdef HMVMX_ALWAYS_FLUSH_TLB
3242 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3243#endif
3244 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3245 switch (pVM->hm.s.vmx.enmTlbFlushType)
3246 {
3247 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3248 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3249 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3250 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3251 default:
3252 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3253 break;
3254 }
3255 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3256}
3257
3258
3259/**
3260 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3261 * TLB entries from the host TLB before VM-entry.
3262 *
3263 * @returns VBox status code.
3264 * @param pVM The cross context VM structure.
3265 */
3266static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3267{
3268 /*
3269 * Determine optimal flush type for nested paging.
3270 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3271 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3272 */
3273 if (pVM->hm.s.fNestedPaging)
3274 {
3275 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3276 {
3277 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3278 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3279 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3280 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3281 else
3282 {
3283 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3284 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3285 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3286 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3287 }
3288
3289 /* Make sure the write-back cacheable memory type for EPT is supported. */
3290 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3291 {
3292 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3293 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3294 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3295 }
3296
3297 /* EPT requires a page-walk length of 4. */
3298 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3299 {
3300 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3301 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3302 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3303 }
3304 }
3305 else
3306 {
3307 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3308 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3309 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3310 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3311 }
3312 }
3313
3314 /*
3315 * Determine optimal flush type for VPID.
3316 */
3317 if (pVM->hm.s.vmx.fVpid)
3318 {
3319 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3320 {
3321 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3322 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3323 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3324 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3325 else
3326 {
3327 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3328 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3329 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3330 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3331 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3332 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3333 pVM->hm.s.vmx.fVpid = false;
3334 }
3335 }
3336 else
3337 {
3338 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3339 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3340 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3341 pVM->hm.s.vmx.fVpid = false;
3342 }
3343 }
3344
3345 /*
3346 * Setup the handler for flushing tagged-TLBs.
3347 */
3348 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3349 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3350 else if (pVM->hm.s.fNestedPaging)
3351 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3352 else if (pVM->hm.s.vmx.fVpid)
3353 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3354 else
3355 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3356 return VINF_SUCCESS;
3357}
3358
3359
3360/**
3361 * Sets up the LBR MSR ranges based on the host CPU.
3362 *
3363 * @returns VBox status code.
3364 * @param pVM The cross context VM structure.
3365 */
3366static int hmR0VmxSetupLbrMsrRange(PVMCC pVM)
3367{
3368 Assert(pVM->hm.s.vmx.fLbr);
3369 uint32_t idLbrFromIpMsrFirst;
3370 uint32_t idLbrFromIpMsrLast;
3371 uint32_t idLbrToIpMsrFirst;
3372 uint32_t idLbrToIpMsrLast;
3373 uint32_t idLbrTosMsr;
3374
3375 /*
3376 * Determine the LBR MSRs supported for this host CPU family and model.
3377 *
3378 * See Intel spec. 17.4.8 "LBR Stack".
3379 * See Intel "Model-Specific Registers" spec.
3380 */
3381 uint32_t const uFamilyModel = (pVM->cpum.ro.HostFeatures.uFamily << 8)
3382 | pVM->cpum.ro.HostFeatures.uModel;
3383 switch (uFamilyModel)
3384 {
3385 case 0x0f01: case 0x0f02:
3386 idLbrFromIpMsrFirst = MSR_P4_LASTBRANCH_0;
3387 idLbrFromIpMsrLast = MSR_P4_LASTBRANCH_3;
3388 idLbrToIpMsrFirst = 0x0;
3389 idLbrToIpMsrLast = 0x0;
3390 idLbrTosMsr = MSR_P4_LASTBRANCH_TOS;
3391 break;
3392
3393 case 0x065c: case 0x065f: case 0x064e: case 0x065e: case 0x068e:
3394 case 0x069e: case 0x0655: case 0x0666: case 0x067a: case 0x0667:
3395 case 0x066a: case 0x066c: case 0x067d: case 0x067e:
3396 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3397 idLbrFromIpMsrLast = MSR_LASTBRANCH_31_FROM_IP;
3398 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3399 idLbrToIpMsrLast = MSR_LASTBRANCH_31_TO_IP;
3400 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3401 break;
3402
3403 case 0x063d: case 0x0647: case 0x064f: case 0x0656: case 0x063c:
3404 case 0x0645: case 0x0646: case 0x063f: case 0x062a: case 0x062d:
3405 case 0x063a: case 0x063e: case 0x061a: case 0x061e: case 0x061f:
3406 case 0x062e: case 0x0625: case 0x062c: case 0x062f:
3407 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3408 idLbrFromIpMsrLast = MSR_LASTBRANCH_15_FROM_IP;
3409 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3410 idLbrToIpMsrLast = MSR_LASTBRANCH_15_TO_IP;
3411 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3412 break;
3413
3414 case 0x0617: case 0x061d: case 0x060f:
3415 idLbrFromIpMsrFirst = MSR_CORE2_LASTBRANCH_0_FROM_IP;
3416 idLbrFromIpMsrLast = MSR_CORE2_LASTBRANCH_3_FROM_IP;
3417 idLbrToIpMsrFirst = MSR_CORE2_LASTBRANCH_0_TO_IP;
3418 idLbrToIpMsrLast = MSR_CORE2_LASTBRANCH_3_TO_IP;
3419 idLbrTosMsr = MSR_CORE2_LASTBRANCH_TOS;
3420 break;
3421
3422 /* Atom and related microarchitectures we don't care about:
3423 case 0x0637: case 0x064a: case 0x064c: case 0x064d: case 0x065a:
3424 case 0x065d: case 0x061c: case 0x0626: case 0x0627: case 0x0635:
3425 case 0x0636: */
3426 /* All other CPUs: */
3427 default:
3428 {
3429 LogRelFunc(("Could not determine LBR stack size for the CPU model %#x\n", uFamilyModel));
3430 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_UNKNOWN;
3431 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3432 }
3433 }
3434
3435 /*
3436 * Validate.
3437 */
3438 uint32_t const cLbrStack = idLbrFromIpMsrLast - idLbrFromIpMsrFirst + 1;
3439 PCVMCPU pVCpu0 = VMCC_GET_CPU_0(pVM);
3440 AssertCompile( RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr)
3441 == RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrToIpMsr));
3442 if (cLbrStack > RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr))
3443 {
3444 LogRelFunc(("LBR stack size of the CPU (%u) exceeds our buffer size\n", cLbrStack));
3445 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_OVERFLOW;
3446 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3447 }
3448 NOREF(pVCpu0);
3449
3450 /*
3451 * Update the LBR info. to the VM struct. for use later.
3452 */
3453 pVM->hm.s.vmx.idLbrTosMsr = idLbrTosMsr;
3454 pVM->hm.s.vmx.idLbrFromIpMsrFirst = idLbrFromIpMsrFirst;
3455 pVM->hm.s.vmx.idLbrFromIpMsrLast = idLbrFromIpMsrLast;
3456
3457 pVM->hm.s.vmx.idLbrToIpMsrFirst = idLbrToIpMsrFirst;
3458 pVM->hm.s.vmx.idLbrToIpMsrLast = idLbrToIpMsrLast;
3459 return VINF_SUCCESS;
3460}
3461
3462
3463#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3464/**
3465 * Sets up the shadow VMCS fields arrays.
3466 *
3467 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3468 * executing the guest.
3469 *
3470 * @returns VBox status code.
3471 * @param pVM The cross context VM structure.
3472 */
3473static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3474{
3475 /*
3476 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3477 * when the host does not support it.
3478 */
3479 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3480 if ( !fGstVmwriteAll
3481 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3482 { /* likely. */ }
3483 else
3484 {
3485 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3486 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3487 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3488 }
3489
3490 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3491 uint32_t cRwFields = 0;
3492 uint32_t cRoFields = 0;
3493 for (uint32_t i = 0; i < cVmcsFields; i++)
3494 {
3495 VMXVMCSFIELD VmcsField;
3496 VmcsField.u = g_aVmcsFields[i];
3497
3498 /*
3499 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3500 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3501 * in the shadow VMCS fields array as they would be redundant.
3502 *
3503 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3504 * we must not include it in the shadow VMCS fields array. Guests attempting to
3505 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3506 * the required behavior.
3507 */
3508 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3509 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3510 {
3511 /*
3512 * Read-only fields are placed in a separate array so that while syncing shadow
3513 * VMCS fields later (which is more performance critical) we can avoid branches.
3514 *
3515 * However, if the guest can write to all fields (including read-only fields),
3516 * we treat it a as read/write field. Otherwise, writing to these fields would
3517 * cause a VMWRITE instruction error while syncing the shadow VMCS.
3518 */
3519 if ( fGstVmwriteAll
3520 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3521 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3522 else
3523 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3524 }
3525 }
3526
3527 /* Update the counts. */
3528 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3529 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3530 return VINF_SUCCESS;
3531}
3532
3533
3534/**
3535 * Sets up the VMREAD and VMWRITE bitmaps.
3536 *
3537 * @param pVM The cross context VM structure.
3538 */
3539static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3540{
3541 /*
3542 * By default, ensure guest attempts to access any VMCS fields cause VM-exits.
3543 */
3544 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3545 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3546 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3547 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3548 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3549
3550 /*
3551 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3552 * VMREAD and VMWRITE bitmaps.
3553 */
3554 {
3555 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3556 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3557 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3558 {
3559 uint32_t const uVmcsField = paShadowVmcsFields[i];
3560 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3561 Assert(uVmcsField >> 3 < cbBitmap);
3562 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3563 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3564 }
3565 }
3566
3567 /*
3568 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3569 * if the host supports VMWRITE to all supported VMCS fields.
3570 */
3571 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3572 {
3573 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3574 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3575 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3576 {
3577 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3578 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3579 Assert(uVmcsField >> 3 < cbBitmap);
3580 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3581 }
3582 }
3583}
3584#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3585
3586
3587/**
3588 * Sets up the virtual-APIC page address for the VMCS.
3589 *
3590 * @param pVmcsInfo The VMCS info. object.
3591 */
3592DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3593{
3594 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3595 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3596 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3597 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3598 AssertRC(rc);
3599}
3600
3601
3602/**
3603 * Sets up the MSR-bitmap address for the VMCS.
3604 *
3605 * @param pVmcsInfo The VMCS info. object.
3606 */
3607DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3608{
3609 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3610 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3611 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3612 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3613 AssertRC(rc);
3614}
3615
3616
3617/**
3618 * Sets up the APIC-access page address for the VMCS.
3619 *
3620 * @param pVCpu The cross context virtual CPU structure.
3621 */
3622DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3623{
3624 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3625 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3626 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3627 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3628 AssertRC(rc);
3629}
3630
3631
3632#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3633/**
3634 * Sets up the VMREAD bitmap address for the VMCS.
3635 *
3636 * @param pVCpu The cross context virtual CPU structure.
3637 */
3638DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3639{
3640 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3641 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3642 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3643 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3644 AssertRC(rc);
3645}
3646
3647
3648/**
3649 * Sets up the VMWRITE bitmap address for the VMCS.
3650 *
3651 * @param pVCpu The cross context virtual CPU structure.
3652 */
3653DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3654{
3655 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3656 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3657 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3658 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3659 AssertRC(rc);
3660}
3661#endif
3662
3663
3664/**
3665 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3666 * in the VMCS.
3667 *
3668 * @returns VBox status code.
3669 * @param pVmcsInfo The VMCS info. object.
3670 */
3671DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3672{
3673 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3674 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3675 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3676
3677 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3678 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3679 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3680
3681 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3682 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3683 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3684
3685 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3686 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3687 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3688 return VINF_SUCCESS;
3689}
3690
3691
3692/**
3693 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3694 *
3695 * @param pVCpu The cross context virtual CPU structure.
3696 * @param pVmcsInfo The VMCS info. object.
3697 */
3698static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3699{
3700 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3701
3702 /*
3703 * By default, ensure guest attempts to access any MSR cause VM-exits.
3704 * This shall later be relaxed for specific MSRs as necessary.
3705 *
3706 * Note: For nested-guests, the entire bitmap will be merged prior to
3707 * executing the nested-guest using hardware-assisted VMX and hence there
3708 * is no need to perform this operation. See hmR0VmxMergeMsrBitmapNested.
3709 */
3710 Assert(pVmcsInfo->pvMsrBitmap);
3711 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
3712
3713 /*
3714 * The guest can access the following MSRs (read, write) without causing
3715 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3716 */
3717 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3718 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3719 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3720 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3721 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3722 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3723
3724 /*
3725 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3726 * associated with then. We never need to intercept access (writes need to be
3727 * executed without causing a VM-exit, reads will #GP fault anyway).
3728 *
3729 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3730 * read/write them. We swap the the guest/host MSR value using the
3731 * auto-load/store MSR area.
3732 */
3733 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3734 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3735 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3736 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3737 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3738 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3739
3740 /*
3741 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3742 * required for 64-bit guests.
3743 */
3744 if (pVM->hm.s.fAllow64BitGuests)
3745 {
3746 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3747 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3748 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3749 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3750 }
3751
3752 /*
3753 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3754 */
3755#ifdef VBOX_STRICT
3756 Assert(pVmcsInfo->pvMsrBitmap);
3757 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3758 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3759#endif
3760}
3761
3762
3763/**
3764 * Sets up pin-based VM-execution controls in the VMCS.
3765 *
3766 * @returns VBox status code.
3767 * @param pVCpu The cross context virtual CPU structure.
3768 * @param pVmcsInfo The VMCS info. object.
3769 */
3770static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3771{
3772 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3773 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3774 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3775
3776 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3777 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3778
3779 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3780 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3781
3782 /* Enable the VMX-preemption timer. */
3783 if (pVM->hm.s.vmx.fUsePreemptTimer)
3784 {
3785 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3786 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3787 }
3788
3789#if 0
3790 /* Enable posted-interrupt processing. */
3791 if (pVM->hm.s.fPostedIntrs)
3792 {
3793 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3794 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3795 fVal |= VMX_PIN_CTLS_POSTED_INT;
3796 }
3797#endif
3798
3799 if ((fVal & fZap) != fVal)
3800 {
3801 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3802 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3803 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3804 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3805 }
3806
3807 /* Commit it to the VMCS and update our cache. */
3808 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3809 AssertRC(rc);
3810 pVmcsInfo->u32PinCtls = fVal;
3811
3812 return VINF_SUCCESS;
3813}
3814
3815
3816/**
3817 * Sets up secondary processor-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 hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3824{
3825 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3826 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3827 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3828
3829 /* WBINVD causes a VM-exit. */
3830 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3831 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3832
3833 /* Enable EPT (aka nested-paging). */
3834 if (pVM->hm.s.fNestedPaging)
3835 fVal |= VMX_PROC_CTLS2_EPT;
3836
3837 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3838 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3839 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3840 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3841 fVal |= VMX_PROC_CTLS2_INVPCID;
3842
3843 /* Enable VPID. */
3844 if (pVM->hm.s.vmx.fVpid)
3845 fVal |= VMX_PROC_CTLS2_VPID;
3846
3847 /* Enable unrestricted guest execution. */
3848 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3849 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3850
3851#if 0
3852 if (pVM->hm.s.fVirtApicRegs)
3853 {
3854 /* Enable APIC-register virtualization. */
3855 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3856 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3857
3858 /* Enable virtual-interrupt delivery. */
3859 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3860 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3861 }
3862#endif
3863
3864 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3865 where the TPR shadow resides. */
3866 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3867 * done dynamically. */
3868 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3869 {
3870 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3871 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3872 }
3873
3874 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3875 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3876 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3877 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3878 fVal |= VMX_PROC_CTLS2_RDTSCP;
3879
3880 /* Enable Pause-Loop exiting. */
3881 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3882 && pVM->hm.s.vmx.cPleGapTicks
3883 && pVM->hm.s.vmx.cPleWindowTicks)
3884 {
3885 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3886
3887 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3888 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3889 }
3890
3891 if ((fVal & fZap) != fVal)
3892 {
3893 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3894 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3895 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3896 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3897 }
3898
3899 /* Commit it to the VMCS and update our cache. */
3900 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3901 AssertRC(rc);
3902 pVmcsInfo->u32ProcCtls2 = fVal;
3903
3904 return VINF_SUCCESS;
3905}
3906
3907
3908/**
3909 * Sets up processor-based VM-execution controls in the VMCS.
3910 *
3911 * @returns VBox status code.
3912 * @param pVCpu The cross context virtual CPU structure.
3913 * @param pVmcsInfo The VMCS info. object.
3914 */
3915static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3916{
3917 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3918 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3919 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3920
3921 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3922 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3923 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3924 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3925 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3926 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3927 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3928
3929 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3930 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3931 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3932 {
3933 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3934 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3935 }
3936
3937 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3938 if (!pVM->hm.s.fNestedPaging)
3939 {
3940 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3941 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3942 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3943 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3944 }
3945
3946 /* Use TPR shadowing if supported by the CPU. */
3947 if ( PDMHasApic(pVM)
3948 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
3949 {
3950 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3951 /* CR8 writes cause a VM-exit based on TPR threshold. */
3952 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3953 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3954 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3955 }
3956 else
3957 {
3958 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3959 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3960 if (pVM->hm.s.fAllow64BitGuests)
3961 {
3962 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3963 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3964 }
3965 }
3966
3967 /* Use MSR-bitmaps if supported by the CPU. */
3968 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3969 {
3970 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3971 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3972 }
3973
3974 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3975 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3976 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3977
3978 if ((fVal & fZap) != fVal)
3979 {
3980 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3981 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3982 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3983 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3984 }
3985
3986 /* Commit it to the VMCS and update our cache. */
3987 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3988 AssertRC(rc);
3989 pVmcsInfo->u32ProcCtls = fVal;
3990
3991 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3992 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3993 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3994
3995 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3996 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3997 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3998
3999 /* Sanity check, should not really happen. */
4000 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
4001 { /* likely */ }
4002 else
4003 {
4004 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
4005 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4006 }
4007
4008 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
4009 return VINF_SUCCESS;
4010}
4011
4012
4013/**
4014 * Sets up miscellaneous (everything other than Pin, Processor and secondary
4015 * Processor-based VM-execution) control fields in the VMCS.
4016 *
4017 * @returns VBox status code.
4018 * @param pVCpu The cross context virtual CPU structure.
4019 * @param pVmcsInfo The VMCS info. object.
4020 */
4021static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4022{
4023#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4024 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
4025 {
4026 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
4027 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
4028 }
4029#endif
4030
4031 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4032 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4033 AssertRC(rc);
4034
4035 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4036 if (RT_SUCCESS(rc))
4037 {
4038 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
4039 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
4040
4041 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
4042 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
4043
4044 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
4045 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
4046
4047 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fLbr)
4048 {
4049 rc = VMXWriteVmcsNw(VMX_VMCS64_GUEST_DEBUGCTL_FULL, MSR_IA32_DEBUGCTL_LBR);
4050 AssertRC(rc);
4051 }
4052 return VINF_SUCCESS;
4053 }
4054 else
4055 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
4056 return rc;
4057}
4058
4059
4060/**
4061 * Sets up the initial exception bitmap in the VMCS based on static conditions.
4062 *
4063 * We shall setup those exception intercepts that don't change during the
4064 * lifetime of the VM here. The rest are done dynamically while loading the
4065 * guest state.
4066 *
4067 * @param pVCpu The cross context virtual CPU structure.
4068 * @param pVmcsInfo The VMCS info. object.
4069 */
4070static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4071{
4072 /*
4073 * The following exceptions are always intercepted:
4074 *
4075 * #AC - To prevent the guest from hanging the CPU.
4076 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
4077 * recursive #DBs can cause a CPU hang.
4078 * #PF - To sync our shadow page tables when nested-paging is not used.
4079 */
4080 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
4081 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
4082 | RT_BIT(X86_XCPT_DB)
4083 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
4084
4085 /* Commit it to the VMCS. */
4086 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
4087 AssertRC(rc);
4088
4089 /* Update our cache of the exception bitmap. */
4090 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
4091}
4092
4093
4094#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4095/**
4096 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
4097 *
4098 * @returns VBox status code.
4099 * @param pVCpu The cross context virtual CPU structure.
4100 * @param pVmcsInfo The VMCS info. object.
4101 */
4102static int hmR0VmxSetupVmcsCtlsNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4103{
4104 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4105 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4106 AssertRC(rc);
4107
4108 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4109 if (RT_SUCCESS(rc))
4110 {
4111 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4112 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4113
4114 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
4115 Assert(!pVmcsInfo->u64Cr0Mask);
4116 Assert(!pVmcsInfo->u64Cr4Mask);
4117 return VINF_SUCCESS;
4118 }
4119 else
4120 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
4121 return rc;
4122}
4123#endif
4124
4125
4126/**
4127 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
4128 * VMX.
4129 *
4130 * @returns VBox status code.
4131 * @param pVCpu The cross context virtual CPU structure.
4132 * @param pVmcsInfo The VMCS info. object.
4133 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
4134 */
4135static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
4136{
4137 Assert(pVmcsInfo->pvVmcs);
4138 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4139
4140 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
4141 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4142 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4143 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
4144
4145 LogFlowFunc(("\n"));
4146
4147 /*
4148 * Initialize the VMCS using VMCLEAR before loading the VMCS.
4149 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
4150 */
4151 int rc = hmR0VmxClearVmcs(pVmcsInfo);
4152 if (RT_SUCCESS(rc))
4153 {
4154 rc = hmR0VmxLoadVmcs(pVmcsInfo);
4155 if (RT_SUCCESS(rc))
4156 {
4157 /*
4158 * Initialize the hardware-assisted VMX execution handler for guest and nested-guest VMCS.
4159 * The host is always 64-bit since we no longer support 32-bit hosts.
4160 * Currently we have just a single handler for all guest modes as well, see @bugref{6208#c73}.
4161 */
4162 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
4163 if (!fIsNstGstVmcs)
4164 {
4165 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
4166 if (RT_SUCCESS(rc))
4167 {
4168 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
4169 if (RT_SUCCESS(rc))
4170 {
4171 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
4172 if (RT_SUCCESS(rc))
4173 {
4174 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4175#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4176 /*
4177 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4178 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4179 * making it fit for use when VMCS shadowing is later enabled.
4180 */
4181 if (pVmcsInfo->pvShadowVmcs)
4182 {
4183 VMXVMCSREVID VmcsRevId;
4184 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4185 VmcsRevId.n.fIsShadowVmcs = 1;
4186 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4187 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4188 if (RT_SUCCESS(rc))
4189 { /* likely */ }
4190 else
4191 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4192 }
4193#endif
4194 }
4195 else
4196 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4197 }
4198 else
4199 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4200 }
4201 else
4202 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4203 }
4204 else
4205 {
4206#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4207 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4208 if (RT_SUCCESS(rc))
4209 { /* likely */ }
4210 else
4211 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4212#else
4213 AssertFailed();
4214#endif
4215 }
4216 }
4217 else
4218 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4219 }
4220 else
4221 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4222
4223 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4224 if (RT_SUCCESS(rc))
4225 {
4226 rc = hmR0VmxClearVmcs(pVmcsInfo);
4227 if (RT_SUCCESS(rc))
4228 { /* likely */ }
4229 else
4230 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4231 }
4232
4233 /*
4234 * Update the last-error record both for failures and success, so we
4235 * can propagate the status code back to ring-3 for diagnostics.
4236 */
4237 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4238 NOREF(pszVmcs);
4239 return rc;
4240}
4241
4242
4243/**
4244 * Does global VT-x initialization (called during module initialization).
4245 *
4246 * @returns VBox status code.
4247 */
4248VMMR0DECL(int) VMXR0GlobalInit(void)
4249{
4250#ifdef HMVMX_USE_FUNCTION_TABLE
4251 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_aVMExitHandlers));
4252# ifdef VBOX_STRICT
4253 for (unsigned i = 0; i < RT_ELEMENTS(g_aVMExitHandlers); i++)
4254 Assert(g_aVMExitHandlers[i].pfn);
4255# endif
4256#endif
4257 return VINF_SUCCESS;
4258}
4259
4260
4261/**
4262 * Does global VT-x termination (called during module termination).
4263 */
4264VMMR0DECL(void) VMXR0GlobalTerm()
4265{
4266 /* Nothing to do currently. */
4267}
4268
4269
4270/**
4271 * Sets up and activates VT-x on the current CPU.
4272 *
4273 * @returns VBox status code.
4274 * @param pHostCpu The HM physical-CPU structure.
4275 * @param pVM The cross context VM structure. Can be
4276 * NULL after a host resume operation.
4277 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4278 * fEnabledByHost is @c true).
4279 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4280 * @a fEnabledByHost is @c true).
4281 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4282 * enable VT-x on the host.
4283 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4284 */
4285VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4286 PCSUPHWVIRTMSRS pHwvirtMsrs)
4287{
4288 AssertPtr(pHostCpu);
4289 AssertPtr(pHwvirtMsrs);
4290 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4291
4292 /* Enable VT-x if it's not already enabled by the host. */
4293 if (!fEnabledByHost)
4294 {
4295 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4296 if (RT_FAILURE(rc))
4297 return rc;
4298 }
4299
4300 /*
4301 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4302 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4303 * invalidated when flushing by VPID.
4304 */
4305 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4306 {
4307 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4308 pHostCpu->fFlushAsidBeforeUse = false;
4309 }
4310 else
4311 pHostCpu->fFlushAsidBeforeUse = true;
4312
4313 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4314 ++pHostCpu->cTlbFlushes;
4315
4316 return VINF_SUCCESS;
4317}
4318
4319
4320/**
4321 * Deactivates VT-x on the current CPU.
4322 *
4323 * @returns VBox status code.
4324 * @param pHostCpu The HM physical-CPU structure.
4325 * @param pvCpuPage Pointer to the VMXON region.
4326 * @param HCPhysCpuPage Physical address of the VMXON region.
4327 *
4328 * @remarks This function should never be called when SUPR0EnableVTx() or
4329 * similar was used to enable VT-x on the host.
4330 */
4331VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4332{
4333 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4334
4335 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4336 return hmR0VmxLeaveRootMode(pHostCpu);
4337}
4338
4339
4340/**
4341 * Does per-VM VT-x initialization.
4342 *
4343 * @returns VBox status code.
4344 * @param pVM The cross context VM structure.
4345 */
4346VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4347{
4348 AssertPtr(pVM);
4349 LogFlowFunc(("pVM=%p\n", pVM));
4350
4351 hmR0VmxStructsInit(pVM);
4352 int rc = hmR0VmxStructsAlloc(pVM);
4353 if (RT_FAILURE(rc))
4354 {
4355 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4356 return rc;
4357 }
4358
4359 /* Setup the crash dump page. */
4360#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4361 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
4362 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
4363#endif
4364 return VINF_SUCCESS;
4365}
4366
4367
4368/**
4369 * Does per-VM VT-x termination.
4370 *
4371 * @returns VBox status code.
4372 * @param pVM The cross context VM structure.
4373 */
4374VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4375{
4376 AssertPtr(pVM);
4377 LogFlowFunc(("pVM=%p\n", pVM));
4378
4379#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4380 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4381 {
4382 Assert(pVM->hm.s.vmx.pvScratch);
4383 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4384 }
4385#endif
4386 hmR0VmxStructsFree(pVM);
4387 return VINF_SUCCESS;
4388}
4389
4390
4391/**
4392 * Sets up the VM for execution using hardware-assisted VMX.
4393 * This function is only called once per-VM during initialization.
4394 *
4395 * @returns VBox status code.
4396 * @param pVM The cross context VM structure.
4397 */
4398VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4399{
4400 AssertPtr(pVM);
4401 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4402
4403 LogFlowFunc(("pVM=%p\n", pVM));
4404
4405 /*
4406 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4407 * without causing a #GP.
4408 */
4409 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4410 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4411 { /* likely */ }
4412 else
4413 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4414
4415 /*
4416 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4417 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4418 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4419 */
4420 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4421 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4422 || !pVM->hm.s.vmx.pRealModeTSS))
4423 {
4424 LogRelFunc(("Invalid real-on-v86 state.\n"));
4425 return VERR_INTERNAL_ERROR;
4426 }
4427
4428 /* Initialize these always, see hmR3InitFinalizeR0().*/
4429 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4430 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4431
4432 /* Setup the tagged-TLB flush handlers. */
4433 int rc = hmR0VmxSetupTaggedTlb(pVM);
4434 if (RT_FAILURE(rc))
4435 {
4436 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4437 return rc;
4438 }
4439
4440 /* Determine LBR capabilities. */
4441 if (pVM->hm.s.vmx.fLbr)
4442 {
4443 rc = hmR0VmxSetupLbrMsrRange(pVM);
4444 if (RT_FAILURE(rc))
4445 {
4446 LogRelFunc(("Failed to setup LBR MSR range. rc=%Rrc\n", rc));
4447 return rc;
4448 }
4449 }
4450
4451#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4452 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4453 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4454 {
4455 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4456 if (RT_SUCCESS(rc))
4457 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4458 else
4459 {
4460 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4461 return rc;
4462 }
4463 }
4464#endif
4465
4466 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4467 {
4468 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4469 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4470
4471 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4472 if (RT_SUCCESS(rc))
4473 {
4474#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4475 if (pVM->cpum.ro.GuestFeatures.fVmx)
4476 {
4477 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4478 if (RT_SUCCESS(rc))
4479 { /* likely */ }
4480 else
4481 {
4482 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4483 return rc;
4484 }
4485 }
4486#endif
4487 }
4488 else
4489 {
4490 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4491 return rc;
4492 }
4493 }
4494
4495 return VINF_SUCCESS;
4496}
4497
4498
4499/**
4500 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4501 * the VMCS.
4502 */
4503static void hmR0VmxExportHostControlRegs(void)
4504{
4505 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4506 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4507 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, ASMGetCR4()); AssertRC(rc);
4508}
4509
4510
4511/**
4512 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4513 * the host-state area in the VMCS.
4514 *
4515 * @returns VBox status code.
4516 * @param pVCpu The cross context virtual CPU structure.
4517 */
4518static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu)
4519{
4520/**
4521 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4522 * requirements. See hmR0VmxExportHostSegmentRegs().
4523 */
4524#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_selValue) \
4525 if ((a_selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4526 { \
4527 bool fValidSelector = true; \
4528 if ((a_selValue) & X86_SEL_LDT) \
4529 { \
4530 uint32_t const uAttr = ASMGetSegAttr(a_selValue); \
4531 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4532 } \
4533 if (fValidSelector) \
4534 { \
4535 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4536 pVCpu->hm.s.vmx.RestoreHost.uHostSel##a_Seg = (a_selValue); \
4537 } \
4538 (a_selValue) = 0; \
4539 }
4540
4541 /*
4542 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4543 * will be messed up. We should -not- save the messed up state without restoring
4544 * the original host-state, see @bugref{7240}.
4545 *
4546 * This apparently can happen (most likely the FPU changes), deal with it rather than
4547 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4548 */
4549 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4550 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4551 {
4552 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4553 pVCpu->idCpu));
4554 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4555 }
4556 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4557
4558 /*
4559 * Host segment registers.
4560 */
4561 RTSEL uSelES = ASMGetES();
4562 RTSEL uSelCS = ASMGetCS();
4563 RTSEL uSelSS = ASMGetSS();
4564 RTSEL uSelDS = ASMGetDS();
4565 RTSEL uSelFS = ASMGetFS();
4566 RTSEL uSelGS = ASMGetGS();
4567 RTSEL uSelTR = ASMGetTR();
4568
4569 /*
4570 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4571 * gain VM-entry and restore them before we get preempted.
4572 *
4573 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4574 */
4575 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4576 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4577 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4578 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4579
4580 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4581 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4582 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4583 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4584 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4585 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4586 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4587 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4588 Assert(uSelCS);
4589 Assert(uSelTR);
4590
4591 /* Write these host selector fields into the host-state area in the VMCS. */
4592 int rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, uSelCS); AssertRC(rc);
4593 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, uSelSS); AssertRC(rc);
4594 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4595 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4596 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4597 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4598 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, uSelTR); AssertRC(rc);
4599
4600 /*
4601 * Host GDTR and IDTR.
4602 */
4603 RTGDTR Gdtr;
4604 RTIDTR Idtr;
4605 RT_ZERO(Gdtr);
4606 RT_ZERO(Idtr);
4607 ASMGetGDTR(&Gdtr);
4608 ASMGetIDTR(&Idtr);
4609 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt); AssertRC(rc);
4610 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt); AssertRC(rc);
4611
4612 /*
4613 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4614 * them to the maximum limit (0xffff) on every VM-exit.
4615 */
4616 if (Gdtr.cbGdt != 0xffff)
4617 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4618
4619 /*
4620 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4621 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4622 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4623 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4624 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4625 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4626 * at 0xffff on hosts where we are sure it won't cause trouble.
4627 */
4628#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4629 if (Idtr.cbIdt < 0x0fff)
4630#else
4631 if (Idtr.cbIdt != 0xffff)
4632#endif
4633 {
4634 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4635 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4636 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4637 }
4638
4639 /*
4640 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4641 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4642 * RPL should be too in most cases.
4643 */
4644 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4645 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4646
4647 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4648 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4649
4650 /*
4651 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4652 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4653 * restoration if the host has something else. Task switching is not supported in 64-bit
4654 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4655 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4656 *
4657 * [1] See Intel spec. 3.5 "System Descriptor Types".
4658 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4659 */
4660 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4661 Assert(pDesc->System.u4Type == 11);
4662 if ( pDesc->System.u16LimitLow != 0x67
4663 || pDesc->System.u4LimitHigh)
4664 {
4665 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4666 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4667 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4668 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4669 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4670 }
4671
4672 /*
4673 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4674 */
4675 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4676 {
4677 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4678 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4679 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4680 {
4681 /* The GDT is read-only but the writable GDT is available. */
4682 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4683 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4684 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4685 AssertRCReturn(rc, rc);
4686 }
4687 }
4688
4689 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase);
4690 AssertRC(rc);
4691
4692 /*
4693 * Host FS base and GS base.
4694 */
4695 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4696 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4697 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, u64FSBase); AssertRC(rc);
4698 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, u64GSBase); AssertRC(rc);
4699
4700 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4701 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4702 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4703 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4704 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4705
4706 return VINF_SUCCESS;
4707#undef VMXLOCAL_ADJUST_HOST_SEG
4708}
4709
4710
4711/**
4712 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4713 * host-state area of the VMCS.
4714 *
4715 * These MSRs will be automatically restored on the host after every successful
4716 * VM-exit.
4717 *
4718 * @param pVCpu The cross context virtual CPU structure.
4719 *
4720 * @remarks No-long-jump zone!!!
4721 */
4722static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4723{
4724 AssertPtr(pVCpu);
4725
4726 /*
4727 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4728 * rather than swapping them on every VM-entry.
4729 */
4730 hmR0VmxLazySaveHostMsrs(pVCpu);
4731
4732 /*
4733 * Host Sysenter MSRs.
4734 */
4735 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4736 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4737 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4738
4739 /*
4740 * Host EFER MSR.
4741 *
4742 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4743 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4744 */
4745 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4746 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4747 {
4748 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4749 AssertRC(rc);
4750 }
4751
4752 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4753 * hmR0VmxExportGuestEntryExitCtls(). */
4754}
4755
4756
4757/**
4758 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4759 *
4760 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4761 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4762 *
4763 * @returns true if we need to load guest EFER, false otherwise.
4764 * @param pVCpu The cross context virtual CPU structure.
4765 * @param pVmxTransient The VMX-transient structure.
4766 *
4767 * @remarks Requires EFER, CR4.
4768 * @remarks No-long-jump zone!!!
4769 */
4770static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4771{
4772#ifdef HMVMX_ALWAYS_SWAP_EFER
4773 RT_NOREF2(pVCpu, pVmxTransient);
4774 return true;
4775#else
4776 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4777 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4778 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4779 uint64_t const u64GuestEfer = pCtx->msrEFER;
4780
4781# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4782 /*
4783 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4784 * the nested-guest.
4785 */
4786 if ( pVmxTransient->fIsNestedGuest
4787 && ( CPUMIsGuestVmxEntryCtlsSet(pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4788 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4789 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4790 return true;
4791# else
4792 RT_NOREF(pVmxTransient);
4793#endif
4794
4795 /*
4796 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4797 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4798 */
4799 if ( CPUMIsGuestInLongModeEx(pCtx)
4800 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4801 return true;
4802
4803 /*
4804 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4805 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4806 *
4807 * See Intel spec. 4.5 "IA-32e Paging".
4808 * See Intel spec. 4.1.1 "Three Paging Modes".
4809 *
4810 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4811 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4812 */
4813 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4814 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4815 if ( (pCtx->cr4 & X86_CR4_PAE)
4816 && (pCtx->cr0 & X86_CR0_PG))
4817 {
4818 /*
4819 * If nested paging is not used, verify that the guest paging mode matches the
4820 * shadow paging mode which is/will be placed in the VMCS (which is what will
4821 * actually be used while executing the guest and not the CR4 shadow value).
4822 */
4823 AssertMsg(pVM->hm.s.fNestedPaging || ( pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4824 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4825 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4826 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX),
4827 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4828 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4829 {
4830 /* Verify that the host is NX capable. */
4831 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4832 return true;
4833 }
4834 }
4835
4836 return false;
4837#endif
4838}
4839
4840
4841/**
4842 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4843 * VMCS.
4844 *
4845 * This is typically required when the guest changes paging mode.
4846 *
4847 * @returns VBox status code.
4848 * @param pVCpu The cross context virtual CPU structure.
4849 * @param pVmxTransient The VMX-transient structure.
4850 *
4851 * @remarks Requires EFER.
4852 * @remarks No-long-jump zone!!!
4853 */
4854static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4855{
4856 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4857 {
4858 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4859 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4860
4861 /*
4862 * VM-entry controls.
4863 */
4864 {
4865 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4866 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4867
4868 /*
4869 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4870 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4871 *
4872 * For nested-guests, this is a mandatory VM-entry control. It's also
4873 * required because we do not want to leak host bits to the nested-guest.
4874 */
4875 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4876
4877 /*
4878 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4879 *
4880 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4881 * required to get the nested-guest working with hardware-assisted VMX execution.
4882 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
4883 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4884 * here rather than while merging the guest VMCS controls.
4885 */
4886 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
4887 {
4888 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
4889 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4890 }
4891 else
4892 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4893
4894 /*
4895 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4896 *
4897 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4898 * regardless of whether the nested-guest VMCS specifies it because we are free to
4899 * load whatever MSRs we require and we do not need to modify the guest visible copy
4900 * of the VM-entry MSR load area.
4901 */
4902 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4903 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4904 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4905 else
4906 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4907
4908 /*
4909 * The following should -not- be set (since we're not in SMM mode):
4910 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4911 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4912 */
4913
4914 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4915 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4916
4917 if ((fVal & fZap) == fVal)
4918 { /* likely */ }
4919 else
4920 {
4921 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4922 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4923 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4924 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4925 }
4926
4927 /* Commit it to the VMCS. */
4928 if (pVmcsInfo->u32EntryCtls != fVal)
4929 {
4930 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4931 AssertRC(rc);
4932 pVmcsInfo->u32EntryCtls = fVal;
4933 }
4934 }
4935
4936 /*
4937 * VM-exit controls.
4938 */
4939 {
4940 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4941 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4942
4943 /*
4944 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4945 * supported the 1-setting of this bit.
4946 *
4947 * For nested-guests, we set the "save debug controls" as the converse
4948 * "load debug controls" is mandatory for nested-guests anyway.
4949 */
4950 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4951
4952 /*
4953 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4954 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4955 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4956 * hmR0VmxExportHostMsrs().
4957 *
4958 * For nested-guests, we always set this bit as we do not support 32-bit
4959 * hosts.
4960 */
4961 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4962
4963 /*
4964 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4965 *
4966 * For nested-guests, we should use the "save IA32_EFER" control if we also
4967 * used the "load IA32_EFER" control while exporting VM-entry controls.
4968 */
4969 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4970 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4971 {
4972 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4973 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4974 }
4975
4976 /*
4977 * Enable saving of the VMX-preemption timer value on VM-exit.
4978 * For nested-guests, currently not exposed/used.
4979 */
4980 if ( pVM->hm.s.vmx.fUsePreemptTimer
4981 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4982 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4983
4984 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4985 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4986
4987 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
4988 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
4989 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
4990
4991 if ((fVal & fZap) == fVal)
4992 { /* likely */ }
4993 else
4994 {
4995 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
4996 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
4997 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
4998 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4999 }
5000
5001 /* Commit it to the VMCS. */
5002 if (pVmcsInfo->u32ExitCtls != fVal)
5003 {
5004 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5005 AssertRC(rc);
5006 pVmcsInfo->u32ExitCtls = fVal;
5007 }
5008 }
5009
5010 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5011 }
5012 return VINF_SUCCESS;
5013}
5014
5015
5016/**
5017 * Sets the TPR threshold in the VMCS.
5018 *
5019 * @param pVmcsInfo The VMCS info. object.
5020 * @param u32TprThreshold The TPR threshold (task-priority class only).
5021 */
5022DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5023{
5024 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5025 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5026 RT_NOREF(pVmcsInfo);
5027 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5028 AssertRC(rc);
5029}
5030
5031
5032/**
5033 * Exports the guest APIC TPR state into the VMCS.
5034 *
5035 * @param pVCpu The cross context virtual CPU structure.
5036 * @param pVmxTransient The VMX-transient structure.
5037 *
5038 * @remarks No-long-jump zone!!!
5039 */
5040static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5041{
5042 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5043 {
5044 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5045
5046 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5047 if (!pVmxTransient->fIsNestedGuest)
5048 {
5049 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5050 && APICIsEnabled(pVCpu))
5051 {
5052 /*
5053 * Setup TPR shadowing.
5054 */
5055 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5056 {
5057 bool fPendingIntr = false;
5058 uint8_t u8Tpr = 0;
5059 uint8_t u8PendingIntr = 0;
5060 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5061 AssertRC(rc);
5062
5063 /*
5064 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5065 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5066 * priority of the pending interrupt so we can deliver the interrupt. If there
5067 * are no interrupts pending, set threshold to 0 to not cause any
5068 * TPR-below-threshold VM-exits.
5069 */
5070 uint32_t u32TprThreshold = 0;
5071 if (fPendingIntr)
5072 {
5073 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5074 (which is the Task-Priority Class). */
5075 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5076 const uint8_t u8TprPriority = u8Tpr >> 4;
5077 if (u8PendingPriority <= u8TprPriority)
5078 u32TprThreshold = u8PendingPriority;
5079 }
5080
5081 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
5082 }
5083 }
5084 }
5085 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5086 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5087 }
5088}
5089
5090
5091/**
5092 * Gets the guest interruptibility-state and updates related force-flags.
5093 *
5094 * @returns Guest's interruptibility-state.
5095 * @param pVCpu The cross context virtual CPU structure.
5096 *
5097 * @remarks No-long-jump zone!!!
5098 */
5099static uint32_t hmR0VmxGetGuestIntrStateAndUpdateFFs(PVMCPUCC pVCpu)
5100{
5101 /*
5102 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5103 */
5104 uint32_t fIntrState = 0;
5105 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5106 {
5107 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
5108 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
5109
5110 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5111 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5112 {
5113 if (pCtx->eflags.Bits.u1IF)
5114 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5115 else
5116 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5117 }
5118 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5119 {
5120 /*
5121 * We can clear the inhibit force flag as even if we go back to the recompiler
5122 * without executing guest code in VT-x, the flag's condition to be cleared is
5123 * met and thus the cleared state is correct.
5124 */
5125 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5126 }
5127 }
5128
5129 /*
5130 * Check if we should inhibit NMI delivery.
5131 */
5132 if (CPUMIsGuestNmiBlocking(pVCpu))
5133 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5134
5135 /*
5136 * Validate.
5137 */
5138#ifdef VBOX_STRICT
5139 /* We don't support block-by-SMI yet.*/
5140 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
5141
5142 /* Block-by-STI must not be set when interrupts are disabled. */
5143 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
5144 {
5145 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5146 Assert(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_IF);
5147 }
5148#endif
5149
5150 return fIntrState;
5151}
5152
5153
5154/**
5155 * Exports the exception intercepts required for guest execution in the VMCS.
5156 *
5157 * @param pVCpu The cross context virtual CPU structure.
5158 * @param pVmxTransient The VMX-transient structure.
5159 *
5160 * @remarks No-long-jump zone!!!
5161 */
5162static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5163{
5164 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5165 {
5166 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5167 if ( !pVmxTransient->fIsNestedGuest
5168 && pVCpu->hm.s.fGIMTrapXcptUD)
5169 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5170 else
5171 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5172
5173 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5174 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5175 }
5176}
5177
5178
5179/**
5180 * Exports the guest's RIP into the guest-state area in the VMCS.
5181 *
5182 * @param pVCpu The cross context virtual CPU structure.
5183 *
5184 * @remarks No-long-jump zone!!!
5185 */
5186static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5187{
5188 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5189 {
5190 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5191
5192 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5193 AssertRC(rc);
5194
5195 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5196 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5197 }
5198}
5199
5200
5201/**
5202 * Exports the guest's RSP into the guest-state area in the VMCS.
5203 *
5204 * @param pVCpu The cross context virtual CPU structure.
5205 *
5206 * @remarks No-long-jump zone!!!
5207 */
5208static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5209{
5210 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5211 {
5212 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5213
5214 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5215 AssertRC(rc);
5216
5217 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5218 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5219 }
5220}
5221
5222
5223/**
5224 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5225 *
5226 * @param pVCpu The cross context virtual CPU structure.
5227 * @param pVmxTransient The VMX-transient structure.
5228 *
5229 * @remarks No-long-jump zone!!!
5230 */
5231static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5232{
5233 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5234 {
5235 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5236
5237 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5238 Let us assert it as such and use 32-bit VMWRITE. */
5239 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5240 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5241 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5242 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5243
5244 /*
5245 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5246 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5247 * can run the real-mode guest code under Virtual 8086 mode.
5248 */
5249 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5250 if (pVmcsInfo->RealMode.fRealOnV86Active)
5251 {
5252 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5253 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5254 Assert(!pVmxTransient->fIsNestedGuest);
5255 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5256 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5257 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5258 }
5259
5260 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5261 AssertRC(rc);
5262
5263 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5264 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5265 }
5266}
5267
5268
5269#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5270/**
5271 * Copies the nested-guest VMCS to the shadow VMCS.
5272 *
5273 * @returns VBox status code.
5274 * @param pVCpu The cross context virtual CPU structure.
5275 * @param pVmcsInfo The VMCS info. object.
5276 *
5277 * @remarks No-long-jump zone!!!
5278 */
5279static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5280{
5281 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5282 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5283
5284 /*
5285 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5286 * current VMCS, as we may try saving guest lazy MSRs.
5287 *
5288 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5289 * calling the import VMCS code which is currently performing the guest MSR reads
5290 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5291 * and the rest of the VMX leave session machinery.
5292 */
5293 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5294
5295 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5296 if (RT_SUCCESS(rc))
5297 {
5298 /*
5299 * Copy all guest read/write VMCS fields.
5300 *
5301 * We don't check for VMWRITE failures here for performance reasons and
5302 * because they are not expected to fail, barring irrecoverable conditions
5303 * like hardware errors.
5304 */
5305 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5306 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5307 {
5308 uint64_t u64Val;
5309 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5310 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5311 VMXWriteVmcs64(uVmcsField, u64Val);
5312 }
5313
5314 /*
5315 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5316 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5317 */
5318 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5319 {
5320 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5321 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5322 {
5323 uint64_t u64Val;
5324 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5325 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5326 VMXWriteVmcs64(uVmcsField, u64Val);
5327 }
5328 }
5329
5330 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5331 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5332 }
5333
5334 ASMSetFlags(fEFlags);
5335 return rc;
5336}
5337
5338
5339/**
5340 * Copies the shadow VMCS to the nested-guest VMCS.
5341 *
5342 * @returns VBox status code.
5343 * @param pVCpu The cross context virtual CPU structure.
5344 * @param pVmcsInfo The VMCS info. object.
5345 *
5346 * @remarks Called with interrupts disabled.
5347 */
5348static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5349{
5350 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5351 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5352 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5353
5354 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5355 if (RT_SUCCESS(rc))
5356 {
5357 /*
5358 * Copy guest read/write fields from the shadow VMCS.
5359 * Guest read-only fields cannot be modified, so no need to copy them.
5360 *
5361 * We don't check for VMREAD failures here for performance reasons and
5362 * because they are not expected to fail, barring irrecoverable conditions
5363 * like hardware errors.
5364 */
5365 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5366 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5367 {
5368 uint64_t u64Val;
5369 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5370 VMXReadVmcs64(uVmcsField, &u64Val);
5371 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5372 }
5373
5374 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5375 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5376 }
5377 return rc;
5378}
5379
5380
5381/**
5382 * Enables VMCS shadowing for the given VMCS info. object.
5383 *
5384 * @param pVmcsInfo The VMCS info. object.
5385 *
5386 * @remarks No-long-jump zone!!!
5387 */
5388static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5389{
5390 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5391 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5392 {
5393 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5394 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5395 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5396 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5397 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5398 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5399 Log4Func(("Enabled\n"));
5400 }
5401}
5402
5403
5404/**
5405 * Disables VMCS shadowing for the given VMCS info. object.
5406 *
5407 * @param pVmcsInfo The VMCS info. object.
5408 *
5409 * @remarks No-long-jump zone!!!
5410 */
5411static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5412{
5413 /*
5414 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5415 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5416 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5417 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5418 *
5419 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5420 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5421 */
5422 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5423 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5424 {
5425 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5426 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5427 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5428 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5429 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5430 Log4Func(("Disabled\n"));
5431 }
5432}
5433#endif
5434
5435
5436/**
5437 * Exports the guest hardware-virtualization state.
5438 *
5439 * @returns VBox status code.
5440 * @param pVCpu The cross context virtual CPU structure.
5441 * @param pVmxTransient The VMX-transient structure.
5442 *
5443 * @remarks No-long-jump zone!!!
5444 */
5445static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5446{
5447 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5448 {
5449#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5450 /*
5451 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5452 * VMCS shadowing.
5453 */
5454 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5455 {
5456 /*
5457 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5458 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5459 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5460 *
5461 * We check for VMX root mode here in case the guest executes VMXOFF without
5462 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5463 * not clear the current VMCS pointer.
5464 */
5465 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5466 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5467 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5468 && CPUMIsGuestVmxCurrentVmcsValid(&pVCpu->cpum.GstCtx))
5469 {
5470 /* Paranoia. */
5471 Assert(!pVmxTransient->fIsNestedGuest);
5472
5473 /*
5474 * For performance reasons, also check if the nested hypervisor's current VMCS
5475 * was newly loaded or modified before copying it to the shadow VMCS.
5476 */
5477 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5478 {
5479 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5480 AssertRCReturn(rc, rc);
5481 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5482 }
5483 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5484 }
5485 else
5486 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5487 }
5488#else
5489 NOREF(pVmxTransient);
5490#endif
5491 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5492 }
5493 return VINF_SUCCESS;
5494}
5495
5496
5497/**
5498 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5499 *
5500 * The guest FPU state is always pre-loaded hence we don't need to bother about
5501 * sharing FPU related CR0 bits between the guest and host.
5502 *
5503 * @returns VBox status code.
5504 * @param pVCpu The cross context virtual CPU structure.
5505 * @param pVmxTransient The VMX-transient structure.
5506 *
5507 * @remarks No-long-jump zone!!!
5508 */
5509static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5510{
5511 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5512 {
5513 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5514 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5515
5516 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
5517 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5518 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5519 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5520 else
5521 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5522
5523 if (!pVmxTransient->fIsNestedGuest)
5524 {
5525 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5526 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5527 uint64_t const u64ShadowCr0 = u64GuestCr0;
5528 Assert(!RT_HI_U32(u64GuestCr0));
5529
5530 /*
5531 * Setup VT-x's view of the guest CR0.
5532 */
5533 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5534 if (pVM->hm.s.fNestedPaging)
5535 {
5536 if (CPUMIsGuestPagingEnabled(pVCpu))
5537 {
5538 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5539 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5540 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5541 }
5542 else
5543 {
5544 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5545 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5546 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5547 }
5548
5549 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5550 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5551 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5552 }
5553 else
5554 {
5555 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5556 u64GuestCr0 |= X86_CR0_WP;
5557 }
5558
5559 /*
5560 * Guest FPU bits.
5561 *
5562 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5563 * using CR0.TS.
5564 *
5565 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5566 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5567 */
5568 u64GuestCr0 |= X86_CR0_NE;
5569
5570 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5571 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5572
5573 /*
5574 * Update exception intercepts.
5575 */
5576 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5577 if (pVmcsInfo->RealMode.fRealOnV86Active)
5578 {
5579 Assert(PDMVmmDevHeapIsEnabled(pVM));
5580 Assert(pVM->hm.s.vmx.pRealModeTSS);
5581 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5582 }
5583 else
5584 {
5585 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5586 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5587 if (fInterceptMF)
5588 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5589 }
5590
5591 /* Additional intercepts for debugging, define these yourself explicitly. */
5592#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5593 uXcptBitmap |= 0
5594 | RT_BIT(X86_XCPT_BP)
5595 | RT_BIT(X86_XCPT_DE)
5596 | RT_BIT(X86_XCPT_NM)
5597 | RT_BIT(X86_XCPT_TS)
5598 | RT_BIT(X86_XCPT_UD)
5599 | RT_BIT(X86_XCPT_NP)
5600 | RT_BIT(X86_XCPT_SS)
5601 | RT_BIT(X86_XCPT_GP)
5602 | RT_BIT(X86_XCPT_PF)
5603 | RT_BIT(X86_XCPT_MF)
5604 ;
5605#elif defined(HMVMX_ALWAYS_TRAP_PF)
5606 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5607#endif
5608 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5609 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5610 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5611
5612 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5613 u64GuestCr0 |= fSetCr0;
5614 u64GuestCr0 &= fZapCr0;
5615 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5616
5617 /* Commit the CR0 and related fields to the guest VMCS. */
5618 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5619 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5620 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5621 {
5622 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5623 AssertRC(rc);
5624 }
5625 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5626 {
5627 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5628 AssertRC(rc);
5629 }
5630
5631 /* Update our caches. */
5632 pVmcsInfo->u32ProcCtls = uProcCtls;
5633 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5634
5635 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5636 }
5637 else
5638 {
5639 /*
5640 * With nested-guests, we may have extended the guest/host mask here since we
5641 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5642 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5643 * originally supplied. We must copy those bits from the nested-guest CR0 into
5644 * the nested-guest CR0 read-shadow.
5645 */
5646 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5647 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5648 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(&pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5649 Assert(!RT_HI_U32(u64GuestCr0));
5650 Assert(u64GuestCr0 & X86_CR0_NE);
5651
5652 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5653 u64GuestCr0 |= fSetCr0;
5654 u64GuestCr0 &= fZapCr0;
5655 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5656
5657 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5658 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5659 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5660
5661 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5662 }
5663
5664 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5665 }
5666
5667 return VINF_SUCCESS;
5668}
5669
5670
5671/**
5672 * Exports the guest control registers (CR3, CR4) into the guest-state area
5673 * in the VMCS.
5674 *
5675 * @returns VBox strict status code.
5676 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5677 * without unrestricted guest access and the VMMDev is not presently
5678 * mapped (e.g. EFI32).
5679 *
5680 * @param pVCpu The cross context virtual CPU structure.
5681 * @param pVmxTransient The VMX-transient structure.
5682 *
5683 * @remarks No-long-jump zone!!!
5684 */
5685static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5686{
5687 int rc = VINF_SUCCESS;
5688 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5689
5690 /*
5691 * Guest CR2.
5692 * It's always loaded in the assembler code. Nothing to do here.
5693 */
5694
5695 /*
5696 * Guest CR3.
5697 */
5698 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5699 {
5700 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5701
5702 if (pVM->hm.s.fNestedPaging)
5703 {
5704 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5705 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5706
5707 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5708 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5709 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5710 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5711
5712 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5713 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5714 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5715
5716 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5717 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5718 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5719 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5720 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5721 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5722 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5723
5724 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5725 AssertRC(rc);
5726
5727 uint64_t u64GuestCr3;
5728 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5729 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5730 || CPUMIsGuestPagingEnabledEx(pCtx))
5731 {
5732 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5733 if (CPUMIsGuestInPAEModeEx(pCtx))
5734 {
5735 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5736 AssertRC(rc);
5737 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5738 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5739 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5740 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5741 }
5742
5743 /*
5744 * The guest's view of its CR3 is unblemished with nested paging when the
5745 * guest is using paging or we have unrestricted guest execution to handle
5746 * the guest when it's not using paging.
5747 */
5748 u64GuestCr3 = pCtx->cr3;
5749 }
5750 else
5751 {
5752 /*
5753 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5754 * thinks it accesses physical memory directly, we use our identity-mapped
5755 * page table to map guest-linear to guest-physical addresses. EPT takes care
5756 * of translating it to host-physical addresses.
5757 */
5758 RTGCPHYS GCPhys;
5759 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5760
5761 /* We obtain it here every time as the guest could have relocated this PCI region. */
5762 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5763 if (RT_SUCCESS(rc))
5764 { /* likely */ }
5765 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5766 {
5767 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5768 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5769 }
5770 else
5771 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5772
5773 u64GuestCr3 = GCPhys;
5774 }
5775
5776 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5777 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5778 AssertRC(rc);
5779 }
5780 else
5781 {
5782 Assert(!pVmxTransient->fIsNestedGuest);
5783 /* Non-nested paging case, just use the hypervisor's CR3. */
5784 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5785
5786 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5787 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5788 AssertRC(rc);
5789 }
5790
5791 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5792 }
5793
5794 /*
5795 * Guest CR4.
5796 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5797 */
5798 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5799 {
5800 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5801 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5802
5803 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
5804 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5805
5806 /*
5807 * With nested-guests, we may have extended the guest/host mask here (since we
5808 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5809 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5810 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5811 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5812 */
5813 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5814 uint64_t u64GuestCr4 = pCtx->cr4;
5815 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5816 ? pCtx->cr4
5817 : CPUMGetGuestVmxMaskedCr4(pCtx, pVmcsInfo->u64Cr4Mask);
5818 Assert(!RT_HI_U32(u64GuestCr4));
5819
5820 /*
5821 * Setup VT-x's view of the guest CR4.
5822 *
5823 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5824 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5825 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5826 *
5827 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5828 */
5829 if (pVmcsInfo->RealMode.fRealOnV86Active)
5830 {
5831 Assert(pVM->hm.s.vmx.pRealModeTSS);
5832 Assert(PDMVmmDevHeapIsEnabled(pVM));
5833 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5834 }
5835
5836 if (pVM->hm.s.fNestedPaging)
5837 {
5838 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5839 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5840 {
5841 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5842 u64GuestCr4 |= X86_CR4_PSE;
5843 /* Our identity mapping is a 32-bit page directory. */
5844 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5845 }
5846 /* else use guest CR4.*/
5847 }
5848 else
5849 {
5850 Assert(!pVmxTransient->fIsNestedGuest);
5851
5852 /*
5853 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5854 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5855 */
5856 switch (pVCpu->hm.s.enmShadowMode)
5857 {
5858 case PGMMODE_REAL: /* Real-mode. */
5859 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5860 case PGMMODE_32_BIT: /* 32-bit paging. */
5861 {
5862 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5863 break;
5864 }
5865
5866 case PGMMODE_PAE: /* PAE paging. */
5867 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5868 {
5869 u64GuestCr4 |= X86_CR4_PAE;
5870 break;
5871 }
5872
5873 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5874 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5875 {
5876#ifdef VBOX_WITH_64_BITS_GUESTS
5877 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
5878 Assert(u64GuestCr4 & X86_CR4_PAE);
5879 break;
5880#endif
5881 }
5882 default:
5883 AssertFailed();
5884 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5885 }
5886 }
5887
5888 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
5889 u64GuestCr4 |= fSetCr4;
5890 u64GuestCr4 &= fZapCr4;
5891
5892 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
5893 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
5894 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
5895
5896 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5897 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5898
5899 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5900
5901 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5902 }
5903 return rc;
5904}
5905
5906
5907/**
5908 * Exports the guest debug registers into the guest-state area in the VMCS.
5909 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5910 *
5911 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5912 *
5913 * @returns VBox status code.
5914 * @param pVCpu The cross context virtual CPU structure.
5915 * @param pVmxTransient The VMX-transient structure.
5916 *
5917 * @remarks No-long-jump zone!!!
5918 */
5919static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5920{
5921 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5922
5923 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5924 * stepping. */
5925 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5926 if (pVmxTransient->fIsNestedGuest)
5927 {
5928 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5929 AssertRC(rc);
5930
5931 /* Always intercept Mov DRx accesses for the nested-guest for now. */
5932 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5933 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
5934 AssertRC(rc);
5935 return VINF_SUCCESS;
5936 }
5937
5938#ifdef VBOX_STRICT
5939 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5940 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5941 {
5942 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5943 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5944 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5945 }
5946#endif
5947
5948 bool fSteppingDB = false;
5949 bool fInterceptMovDRx = false;
5950 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5951 if (pVCpu->hm.s.fSingleInstruction)
5952 {
5953 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5954 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5955 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5956 {
5957 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5958 Assert(fSteppingDB == false);
5959 }
5960 else
5961 {
5962 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5963 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5964 pVCpu->hm.s.fClearTrapFlag = true;
5965 fSteppingDB = true;
5966 }
5967 }
5968
5969 uint64_t u64GuestDr7;
5970 if ( fSteppingDB
5971 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5972 {
5973 /*
5974 * Use the combined guest and host DRx values found in the hypervisor register set
5975 * because the hypervisor debugger has breakpoints active or someone is single stepping
5976 * on the host side without a monitor trap flag.
5977 *
5978 * Note! DBGF expects a clean DR6 state before executing guest code.
5979 */
5980 if (!CPUMIsHyperDebugStateActive(pVCpu))
5981 {
5982 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5983 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5984 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5985 }
5986
5987 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
5988 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
5989 pVCpu->hm.s.fUsingHyperDR7 = true;
5990 fInterceptMovDRx = true;
5991 }
5992 else
5993 {
5994 /*
5995 * If the guest has enabled debug registers, we need to load them prior to
5996 * executing guest code so they'll trigger at the right time.
5997 */
5998 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
5999 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6000 {
6001 if (!CPUMIsGuestDebugStateActive(pVCpu))
6002 {
6003 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6004 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6005 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6006 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6007 }
6008 Assert(!fInterceptMovDRx);
6009 }
6010 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6011 {
6012 /*
6013 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6014 * must intercept #DB in order to maintain a correct DR6 guest value, and
6015 * because we need to intercept it to prevent nested #DBs from hanging the
6016 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6017 */
6018 fInterceptMovDRx = true;
6019 }
6020
6021 /* Update DR7 with the actual guest value. */
6022 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6023 pVCpu->hm.s.fUsingHyperDR7 = false;
6024 }
6025
6026 if (fInterceptMovDRx)
6027 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6028 else
6029 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6030
6031 /*
6032 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6033 * monitor-trap flag and update our cache.
6034 */
6035 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6036 {
6037 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6038 AssertRC(rc);
6039 pVmcsInfo->u32ProcCtls = uProcCtls;
6040 }
6041
6042 /*
6043 * Update guest DR7.
6044 */
6045 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
6046 AssertRC(rc);
6047
6048 /*
6049 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6050 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6051 *
6052 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6053 */
6054 if (fSteppingDB)
6055 {
6056 Assert(pVCpu->hm.s.fSingleInstruction);
6057 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6058
6059 uint32_t fIntrState = 0;
6060 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6061 AssertRC(rc);
6062
6063 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6064 {
6065 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6066 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6067 AssertRC(rc);
6068 }
6069 }
6070
6071 return VINF_SUCCESS;
6072}
6073
6074
6075#ifdef VBOX_STRICT
6076/**
6077 * Strict function to validate segment registers.
6078 *
6079 * @param pVCpu The cross context virtual CPU structure.
6080 * @param pVmcsInfo The VMCS info. object.
6081 *
6082 * @remarks Will import guest CR0 on strict builds during validation of
6083 * segments.
6084 */
6085static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
6086{
6087 /*
6088 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6089 *
6090 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6091 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6092 * unusable bit and doesn't change the guest-context value.
6093 */
6094 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6095 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6096 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6097 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
6098 && ( !CPUMIsGuestInRealModeEx(pCtx)
6099 && !CPUMIsGuestInV86ModeEx(pCtx)))
6100 {
6101 /* Protected mode checks */
6102 /* CS */
6103 Assert(pCtx->cs.Attr.n.u1Present);
6104 Assert(!(pCtx->cs.Attr.u & 0xf00));
6105 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6106 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6107 || !(pCtx->cs.Attr.n.u1Granularity));
6108 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6109 || (pCtx->cs.Attr.n.u1Granularity));
6110 /* CS cannot be loaded with NULL in protected mode. */
6111 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6112 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6113 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6114 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6115 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6116 else
6117 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6118 /* SS */
6119 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6120 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6121 if ( !(pCtx->cr0 & X86_CR0_PE)
6122 || pCtx->cs.Attr.n.u4Type == 3)
6123 {
6124 Assert(!pCtx->ss.Attr.n.u2Dpl);
6125 }
6126 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6127 {
6128 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6129 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6130 Assert(pCtx->ss.Attr.n.u1Present);
6131 Assert(!(pCtx->ss.Attr.u & 0xf00));
6132 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6133 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6134 || !(pCtx->ss.Attr.n.u1Granularity));
6135 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6136 || (pCtx->ss.Attr.n.u1Granularity));
6137 }
6138 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6139 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6140 {
6141 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6142 Assert(pCtx->ds.Attr.n.u1Present);
6143 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6144 Assert(!(pCtx->ds.Attr.u & 0xf00));
6145 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6146 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6147 || !(pCtx->ds.Attr.n.u1Granularity));
6148 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6149 || (pCtx->ds.Attr.n.u1Granularity));
6150 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6151 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6152 }
6153 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6154 {
6155 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6156 Assert(pCtx->es.Attr.n.u1Present);
6157 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6158 Assert(!(pCtx->es.Attr.u & 0xf00));
6159 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6160 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6161 || !(pCtx->es.Attr.n.u1Granularity));
6162 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6163 || (pCtx->es.Attr.n.u1Granularity));
6164 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6165 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6166 }
6167 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6168 {
6169 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6170 Assert(pCtx->fs.Attr.n.u1Present);
6171 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6172 Assert(!(pCtx->fs.Attr.u & 0xf00));
6173 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6174 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6175 || !(pCtx->fs.Attr.n.u1Granularity));
6176 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6177 || (pCtx->fs.Attr.n.u1Granularity));
6178 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6179 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6180 }
6181 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6182 {
6183 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6184 Assert(pCtx->gs.Attr.n.u1Present);
6185 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6186 Assert(!(pCtx->gs.Attr.u & 0xf00));
6187 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6188 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6189 || !(pCtx->gs.Attr.n.u1Granularity));
6190 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6191 || (pCtx->gs.Attr.n.u1Granularity));
6192 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6193 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6194 }
6195 /* 64-bit capable CPUs. */
6196 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6197 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6198 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6199 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6200 }
6201 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6202 || ( CPUMIsGuestInRealModeEx(pCtx)
6203 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6204 {
6205 /* Real and v86 mode checks. */
6206 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6207 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6208 if (pVmcsInfo->RealMode.fRealOnV86Active)
6209 {
6210 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6211 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6212 }
6213 else
6214 {
6215 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6216 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6217 }
6218
6219 /* CS */
6220 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6221 Assert(pCtx->cs.u32Limit == 0xffff);
6222 Assert(u32CSAttr == 0xf3);
6223 /* SS */
6224 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6225 Assert(pCtx->ss.u32Limit == 0xffff);
6226 Assert(u32SSAttr == 0xf3);
6227 /* DS */
6228 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6229 Assert(pCtx->ds.u32Limit == 0xffff);
6230 Assert(u32DSAttr == 0xf3);
6231 /* ES */
6232 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6233 Assert(pCtx->es.u32Limit == 0xffff);
6234 Assert(u32ESAttr == 0xf3);
6235 /* FS */
6236 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6237 Assert(pCtx->fs.u32Limit == 0xffff);
6238 Assert(u32FSAttr == 0xf3);
6239 /* GS */
6240 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6241 Assert(pCtx->gs.u32Limit == 0xffff);
6242 Assert(u32GSAttr == 0xf3);
6243 /* 64-bit capable CPUs. */
6244 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6245 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6246 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6247 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6248 }
6249}
6250#endif /* VBOX_STRICT */
6251
6252
6253/**
6254 * Exports a guest segment register into the guest-state area in the VMCS.
6255 *
6256 * @returns VBox status code.
6257 * @param pVCpu The cross context virtual CPU structure.
6258 * @param pVmcsInfo The VMCS info. object.
6259 * @param iSegReg The segment register number (X86_SREG_XXX).
6260 * @param pSelReg Pointer to the segment selector.
6261 *
6262 * @remarks No-long-jump zone!!!
6263 */
6264static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6265{
6266 Assert(iSegReg < X86_SREG_COUNT);
6267 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6268 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6269 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6270 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6271
6272 uint32_t u32Access = pSelReg->Attr.u;
6273 if (pVmcsInfo->RealMode.fRealOnV86Active)
6274 {
6275 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6276 u32Access = 0xf3;
6277 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6278 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6279 RT_NOREF_PV(pVCpu);
6280 }
6281 else
6282 {
6283 /*
6284 * The way to differentiate between whether this is really a null selector or was just
6285 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6286 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6287 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6288 * NULL selectors loaded in protected-mode have their attribute as 0.
6289 */
6290 if (!u32Access)
6291 u32Access = X86DESCATTR_UNUSABLE;
6292 }
6293
6294 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6295 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6296 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6297
6298 /*
6299 * Commit it to the VMCS.
6300 */
6301 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc);
6302 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc);
6303 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc);
6304 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc);
6305 return VINF_SUCCESS;
6306}
6307
6308
6309/**
6310 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6311 * area in the VMCS.
6312 *
6313 * @returns VBox status code.
6314 * @param pVCpu The cross context virtual CPU structure.
6315 * @param pVmxTransient The VMX-transient structure.
6316 *
6317 * @remarks Will import guest CR0 on strict builds during validation of
6318 * segments.
6319 * @remarks No-long-jump zone!!!
6320 */
6321static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6322{
6323 int rc = VERR_INTERNAL_ERROR_5;
6324 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6325 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6326 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6327
6328 /*
6329 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6330 */
6331 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6332 {
6333 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6334 {
6335 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6336 if (pVmcsInfo->RealMode.fRealOnV86Active)
6337 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6338 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6339 AssertRC(rc);
6340 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6341 }
6342
6343 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6344 {
6345 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6346 if (pVmcsInfo->RealMode.fRealOnV86Active)
6347 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6348 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6349 AssertRC(rc);
6350 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6351 }
6352
6353 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6354 {
6355 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6356 if (pVmcsInfo->RealMode.fRealOnV86Active)
6357 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6358 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6359 AssertRC(rc);
6360 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6361 }
6362
6363 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6364 {
6365 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6366 if (pVmcsInfo->RealMode.fRealOnV86Active)
6367 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6368 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6369 AssertRC(rc);
6370 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6371 }
6372
6373 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6374 {
6375 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6376 if (pVmcsInfo->RealMode.fRealOnV86Active)
6377 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6378 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6379 AssertRC(rc);
6380 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6381 }
6382
6383 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6384 {
6385 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6386 if (pVmcsInfo->RealMode.fRealOnV86Active)
6387 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6388 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6389 AssertRC(rc);
6390 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6391 }
6392
6393#ifdef VBOX_STRICT
6394 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6395#endif
6396 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6397 pCtx->cs.Attr.u));
6398 }
6399
6400 /*
6401 * Guest TR.
6402 */
6403 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6404 {
6405 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6406
6407 /*
6408 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6409 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6410 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6411 */
6412 uint16_t u16Sel;
6413 uint32_t u32Limit;
6414 uint64_t u64Base;
6415 uint32_t u32AccessRights;
6416 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6417 {
6418 u16Sel = pCtx->tr.Sel;
6419 u32Limit = pCtx->tr.u32Limit;
6420 u64Base = pCtx->tr.u64Base;
6421 u32AccessRights = pCtx->tr.Attr.u;
6422 }
6423 else
6424 {
6425 Assert(!pVmxTransient->fIsNestedGuest);
6426 Assert(pVM->hm.s.vmx.pRealModeTSS);
6427 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6428
6429 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6430 RTGCPHYS GCPhys;
6431 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6432 AssertRCReturn(rc, rc);
6433
6434 X86DESCATTR DescAttr;
6435 DescAttr.u = 0;
6436 DescAttr.n.u1Present = 1;
6437 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6438
6439 u16Sel = 0;
6440 u32Limit = HM_VTX_TSS_SIZE;
6441 u64Base = GCPhys;
6442 u32AccessRights = DescAttr.u;
6443 }
6444
6445 /* Validate. */
6446 Assert(!(u16Sel & RT_BIT(2)));
6447 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6448 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6449 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6450 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6451 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6452 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6453 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6454 Assert( (u32Limit & 0xfff) == 0xfff
6455 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6456 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6457 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6458
6459 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6460 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6461 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6462 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6463
6464 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6465 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6466 }
6467
6468 /*
6469 * Guest GDTR.
6470 */
6471 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6472 {
6473 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6474
6475 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6476 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6477
6478 /* Validate. */
6479 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6480
6481 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6482 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6483 }
6484
6485 /*
6486 * Guest LDTR.
6487 */
6488 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6489 {
6490 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6491
6492 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6493 uint32_t u32Access;
6494 if ( !pVmxTransient->fIsNestedGuest
6495 && !pCtx->ldtr.Attr.u)
6496 u32Access = X86DESCATTR_UNUSABLE;
6497 else
6498 u32Access = pCtx->ldtr.Attr.u;
6499
6500 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6501 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6502 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6503 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6504
6505 /* Validate. */
6506 if (!(u32Access & X86DESCATTR_UNUSABLE))
6507 {
6508 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6509 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6510 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6511 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6512 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6513 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6514 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6515 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6516 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6517 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6518 }
6519
6520 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6521 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6522 }
6523
6524 /*
6525 * Guest IDTR.
6526 */
6527 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6528 {
6529 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6530
6531 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6532 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6533
6534 /* Validate. */
6535 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6536
6537 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6538 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6539 }
6540
6541 return VINF_SUCCESS;
6542}
6543
6544
6545/**
6546 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6547 * areas.
6548 *
6549 * These MSRs will automatically be loaded to the host CPU on every successful
6550 * VM-entry and stored from the host CPU on every successful VM-exit.
6551 *
6552 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6553 * actual host MSR values are not- updated here for performance reasons. See
6554 * hmR0VmxExportHostMsrs().
6555 *
6556 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6557 *
6558 * @returns VBox status code.
6559 * @param pVCpu The cross context virtual CPU structure.
6560 * @param pVmxTransient The VMX-transient structure.
6561 *
6562 * @remarks No-long-jump zone!!!
6563 */
6564static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6565{
6566 AssertPtr(pVCpu);
6567 AssertPtr(pVmxTransient);
6568
6569 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6570 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6571
6572 /*
6573 * MSRs that we use the auto-load/store MSR area in the VMCS.
6574 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6575 * nothing to do here. The host MSR values are updated when it's safe in
6576 * hmR0VmxLazySaveHostMsrs().
6577 *
6578 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6579 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6580 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6581 * for any MSR that are not part of the lazy MSRs so we do not need to place
6582 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6583 */
6584 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6585 {
6586 /* No auto-load/store MSRs currently. */
6587 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6588 }
6589
6590 /*
6591 * Guest Sysenter MSRs.
6592 */
6593 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6594 {
6595 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6596
6597 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6598 {
6599 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6600 AssertRC(rc);
6601 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6602 }
6603
6604 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6605 {
6606 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6607 AssertRC(rc);
6608 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6609 }
6610
6611 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6612 {
6613 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6614 AssertRC(rc);
6615 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6616 }
6617 }
6618
6619 /*
6620 * Guest/host EFER MSR.
6621 */
6622 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6623 {
6624 /* Whether we are using the VMCS to swap the EFER MSR must have been
6625 determined earlier while exporting VM-entry/VM-exit controls. */
6626 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6627 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6628
6629 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6630 {
6631 /*
6632 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6633 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6634 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6635 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6636 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6637 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6638 * during VM-entry.
6639 */
6640 uint64_t uGuestEferMsr = pCtx->msrEFER;
6641 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6642 {
6643 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6644 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6645 else
6646 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6647 }
6648
6649 /*
6650 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6651 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6652 */
6653 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6654 {
6655 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6656 AssertRC(rc);
6657 }
6658 else
6659 {
6660 /*
6661 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6662 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6663 */
6664 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6665 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6666 AssertRCReturn(rc, rc);
6667 }
6668
6669 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6670 }
6671 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6672 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6673
6674 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6675 }
6676
6677 /*
6678 * Other MSRs.
6679 */
6680 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6681 {
6682 /* Speculation Control (R/W). */
6683 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6684 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6685 {
6686 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6687 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6688 AssertRCReturn(rc, rc);
6689 }
6690
6691 /* Last Branch Record. */
6692 if (pVM->hm.s.vmx.fLbr)
6693 {
6694 uint32_t const idFromIpMsrStart = pVM->hm.s.vmx.idLbrFromIpMsrFirst;
6695 uint32_t const idToIpMsrStart = pVM->hm.s.vmx.idLbrToIpMsrFirst;
6696 uint32_t const cLbrStack = pVM->hm.s.vmx.idLbrFromIpMsrLast - pVM->hm.s.vmx.idLbrFromIpMsrFirst + 1;
6697 Assert(cLbrStack <= 32);
6698 for (uint32_t i = 0; i < cLbrStack; i++)
6699 {
6700 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idFromIpMsrStart + i,
6701 pVmxTransient->pVmcsInfo->au64LbrFromIpMsr[i],
6702 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6703 AssertRCReturn(rc, rc);
6704
6705 /* Some CPUs don't have a Branch-To-IP MSR (P4 and related Xeons). */
6706 if (idToIpMsrStart != 0)
6707 {
6708 rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idToIpMsrStart + i,
6709 pVmxTransient->pVmcsInfo->au64LbrToIpMsr[i],
6710 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6711 AssertRCReturn(rc, rc);
6712 }
6713 }
6714
6715 /* Add LBR top-of-stack MSR (which contains the index to the most recent record). */
6716 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, pVM->hm.s.vmx.idLbrTosMsr,
6717 pVmxTransient->pVmcsInfo->u64LbrTosMsr, false /* fSetReadWrite */,
6718 false /* fUpdateHostMsr */);
6719 AssertRCReturn(rc, rc);
6720 }
6721
6722 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6723 }
6724
6725 return VINF_SUCCESS;
6726}
6727
6728
6729/**
6730 * Wrapper for running the guest code in VT-x.
6731 *
6732 * @returns VBox status code, no informational status codes.
6733 * @param pVCpu The cross context virtual CPU structure.
6734 * @param pVmxTransient The VMX-transient structure.
6735 *
6736 * @remarks No-long-jump zone!!!
6737 */
6738DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6739{
6740 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6741 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6742 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6743
6744 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6745
6746 /*
6747 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6748 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6749 * callee-saved and thus the need for this XMM wrapper.
6750 *
6751 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6752 */
6753 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6754 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6755 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6756#ifdef VBOX_WITH_KERNEL_USING_XMM
6757 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6758#else
6759 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu);
6760#endif
6761 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6762 return rc;
6763}
6764
6765
6766/**
6767 * Reports world-switch error and dumps some useful debug info.
6768 *
6769 * @param pVCpu The cross context virtual CPU structure.
6770 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6771 * @param pVmxTransient The VMX-transient structure (only
6772 * exitReason updated).
6773 */
6774static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6775{
6776 Assert(pVCpu);
6777 Assert(pVmxTransient);
6778 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6779
6780 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6781 switch (rcVMRun)
6782 {
6783 case VERR_VMX_INVALID_VMXON_PTR:
6784 AssertFailed();
6785 break;
6786 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6787 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6788 {
6789 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6790 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6791 AssertRC(rc);
6792 hmR0VmxReadExitQualVmcs(pVmxTransient);
6793
6794 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6795 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6796 Cannot do it here as we may have been long preempted. */
6797
6798#ifdef VBOX_STRICT
6799 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6800 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6801 pVmxTransient->uExitReason));
6802 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6803 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6804 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6805 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6806 else
6807 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6808 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6809 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6810
6811 static struct
6812 {
6813 /** Name of the field to log. */
6814 const char *pszName;
6815 /** The VMCS field. */
6816 uint32_t uVmcsField;
6817 /** Whether host support of this field needs to be checked. */
6818 bool fCheckSupport;
6819 } const s_aVmcsFields[] =
6820 {
6821 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6822 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6823 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6824 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6825 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6826 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6827 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6828 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6829 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6830 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6831 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6832 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6833 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6834 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6835 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6836 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6837 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6838 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6839 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6840 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6841 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6842 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6843 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6844 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6845 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6846 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6847 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6848 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6849 /* The order of selector fields below are fixed! */
6850 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6851 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6852 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6853 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6854 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6855 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6856 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6857 /* End of ordered selector fields. */
6858 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6859 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6860 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6861 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6862 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6863 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6864 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6865 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6866 };
6867
6868 RTGDTR HostGdtr;
6869 ASMGetGDTR(&HostGdtr);
6870
6871 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6872 for (uint32_t i = 0; i < cVmcsFields; i++)
6873 {
6874 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
6875
6876 bool fSupported;
6877 if (!s_aVmcsFields[i].fCheckSupport)
6878 fSupported = true;
6879 else
6880 {
6881 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6882 switch (uVmcsField)
6883 {
6884 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
6885 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
6886 case VMX_VMCS32_CTRL_PROC_EXEC2:
6887 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
6888 break;
6889 default:
6890 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
6891 }
6892 }
6893
6894 if (fSupported)
6895 {
6896 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
6897 switch (uWidth)
6898 {
6899 case VMX_VMCSFIELD_WIDTH_16BIT:
6900 {
6901 uint16_t u16Val;
6902 rc = VMXReadVmcs16(uVmcsField, &u16Val);
6903 AssertRC(rc);
6904 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
6905
6906 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
6907 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
6908 {
6909 if (u16Val < HostGdtr.cbGdt)
6910 {
6911 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
6912 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
6913 "Host FS", "Host GS", "Host TR" };
6914 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
6915 Assert(idxSel < RT_ELEMENTS(s_apszSel));
6916 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
6917 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
6918 }
6919 else
6920 Log4((" Selector value exceeds GDT limit!\n"));
6921 }
6922 break;
6923 }
6924
6925 case VMX_VMCSFIELD_WIDTH_32BIT:
6926 {
6927 uint32_t u32Val;
6928 rc = VMXReadVmcs32(uVmcsField, &u32Val);
6929 AssertRC(rc);
6930 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
6931 break;
6932 }
6933
6934 case VMX_VMCSFIELD_WIDTH_64BIT:
6935 case VMX_VMCSFIELD_WIDTH_NATURAL:
6936 {
6937 uint64_t u64Val;
6938 rc = VMXReadVmcs64(uVmcsField, &u64Val);
6939 AssertRC(rc);
6940 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
6941 break;
6942 }
6943 }
6944 }
6945 }
6946
6947 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6948 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6949 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6950 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6951 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6952 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6953#endif /* VBOX_STRICT */
6954 break;
6955 }
6956
6957 default:
6958 /* Impossible */
6959 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6960 break;
6961 }
6962}
6963
6964
6965/**
6966 * Sets up the usage of TSC-offsetting and updates the VMCS.
6967 *
6968 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6969 * VMX-preemption timer.
6970 *
6971 * @returns VBox status code.
6972 * @param pVCpu The cross context virtual CPU structure.
6973 * @param pVmxTransient The VMX-transient structure.
6974 *
6975 * @remarks No-long-jump zone!!!
6976 */
6977static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6978{
6979 bool fOffsettedTsc;
6980 bool fParavirtTsc;
6981 uint64_t uTscOffset;
6982 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6983 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6984
6985 if (pVM->hm.s.vmx.fUsePreemptTimer)
6986 {
6987 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
6988
6989 /* Make sure the returned values have sane upper and lower boundaries. */
6990 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
6991 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
6992 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
6993 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
6994
6995 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
6996 * preemption timers here. We probably need to clamp the preemption timer,
6997 * after converting the timer value to the host. */
6998 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
6999 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7000 AssertRC(rc);
7001 }
7002 else
7003 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7004
7005 if (fParavirtTsc)
7006 {
7007 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7008 information before every VM-entry, hence disable it for performance sake. */
7009#if 0
7010 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7011 AssertRC(rc);
7012#endif
7013 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7014 }
7015
7016 if ( fOffsettedTsc
7017 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
7018 {
7019 if (pVmxTransient->fIsNestedGuest)
7020 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7021 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
7022 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7023 }
7024 else
7025 {
7026 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7027 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7028 }
7029}
7030
7031
7032/**
7033 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7034 * VM-exit interruption info type.
7035 *
7036 * @returns The IEM exception flags.
7037 * @param uVector The event vector.
7038 * @param uVmxEventType The VMX event type.
7039 *
7040 * @remarks This function currently only constructs flags required for
7041 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7042 * and CR2 aspects of an exception are not included).
7043 */
7044static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7045{
7046 uint32_t fIemXcptFlags;
7047 switch (uVmxEventType)
7048 {
7049 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7050 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7051 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7052 break;
7053
7054 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7055 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7056 break;
7057
7058 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7059 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7060 break;
7061
7062 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7063 {
7064 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7065 if (uVector == X86_XCPT_BP)
7066 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7067 else if (uVector == X86_XCPT_OF)
7068 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7069 else
7070 {
7071 fIemXcptFlags = 0;
7072 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7073 }
7074 break;
7075 }
7076
7077 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7078 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7079 break;
7080
7081 default:
7082 fIemXcptFlags = 0;
7083 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7084 break;
7085 }
7086 return fIemXcptFlags;
7087}
7088
7089
7090/**
7091 * Sets an event as a pending event to be injected into the guest.
7092 *
7093 * @param pVCpu The cross context virtual CPU structure.
7094 * @param u32IntInfo The VM-entry interruption-information field.
7095 * @param cbInstr The VM-entry instruction length in bytes (for
7096 * software interrupts, exceptions and privileged
7097 * software exceptions).
7098 * @param u32ErrCode The VM-entry exception error code.
7099 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7100 * page-fault.
7101 */
7102DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7103 RTGCUINTPTR GCPtrFaultAddress)
7104{
7105 Assert(!pVCpu->hm.s.Event.fPending);
7106 pVCpu->hm.s.Event.fPending = true;
7107 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7108 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7109 pVCpu->hm.s.Event.cbInstr = cbInstr;
7110 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7111}
7112
7113
7114/**
7115 * Sets an external interrupt as pending-for-injection into the VM.
7116 *
7117 * @param pVCpu The cross context virtual CPU structure.
7118 * @param u8Interrupt The external interrupt vector.
7119 */
7120DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
7121{
7122 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7123 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7124 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7125 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7126 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7127}
7128
7129
7130/**
7131 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7132 *
7133 * @param pVCpu The cross context virtual CPU structure.
7134 */
7135DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
7136{
7137 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7138 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7139 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7140 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7141 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7142}
7143
7144
7145/**
7146 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7147 *
7148 * @param pVCpu The cross context virtual CPU structure.
7149 */
7150DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
7151{
7152 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7153 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7154 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7155 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7156 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7157}
7158
7159
7160/**
7161 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7162 *
7163 * @param pVCpu The cross context virtual CPU structure.
7164 */
7165DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
7166{
7167 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7168 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7169 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7170 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7171 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7172}
7173
7174
7175/**
7176 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7177 *
7178 * @param pVCpu The cross context virtual CPU structure.
7179 */
7180DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
7181{
7182 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7183 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7184 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7185 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7186 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7187}
7188
7189
7190#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7191/**
7192 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7193 *
7194 * @param pVCpu The cross context virtual CPU structure.
7195 * @param u32ErrCode The error code for the general-protection exception.
7196 */
7197DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7198{
7199 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7200 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7201 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7202 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7203 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7204}
7205
7206
7207/**
7208 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7209 *
7210 * @param pVCpu The cross context virtual CPU structure.
7211 * @param u32ErrCode The error code for the stack exception.
7212 */
7213DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7214{
7215 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7216 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7217 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7218 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7219 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7220}
7221#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7222
7223
7224/**
7225 * Fixes up attributes for the specified segment register.
7226 *
7227 * @param pVCpu The cross context virtual CPU structure.
7228 * @param pSelReg The segment register that needs fixing.
7229 * @param idxSel The VMCS field for the corresponding segment register.
7230 */
7231static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7232{
7233 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7234
7235 /*
7236 * If VT-x marks the segment as unusable, most other bits remain undefined:
7237 * - For CS the L, D and G bits have meaning.
7238 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7239 * - For the remaining data segments no bits are defined.
7240 *
7241 * The present bit and the unusable bit has been observed to be set at the
7242 * same time (the selector was supposed to be invalid as we started executing
7243 * a V8086 interrupt in ring-0).
7244 *
7245 * What should be important for the rest of the VBox code, is that the P bit is
7246 * cleared. Some of the other VBox code recognizes the unusable bit, but
7247 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7248 * safe side here, we'll strip off P and other bits we don't care about. If
7249 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7250 *
7251 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7252 */
7253#ifdef VBOX_STRICT
7254 uint32_t const uAttr = pSelReg->Attr.u;
7255#endif
7256
7257 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7258 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7259 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7260
7261#ifdef VBOX_STRICT
7262 VMMRZCallRing3Disable(pVCpu);
7263 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7264# ifdef DEBUG_bird
7265 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7266 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7267 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7268# endif
7269 VMMRZCallRing3Enable(pVCpu);
7270 NOREF(uAttr);
7271#endif
7272 RT_NOREF2(pVCpu, idxSel);
7273}
7274
7275
7276/**
7277 * Imports a guest segment register from the current VMCS into the guest-CPU
7278 * context.
7279 *
7280 * @param pVCpu The cross context virtual CPU structure.
7281 * @param iSegReg The segment register number (X86_SREG_XXX).
7282 *
7283 * @remarks Called with interrupts and/or preemption disabled.
7284 */
7285static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint8_t iSegReg)
7286{
7287 Assert(iSegReg < X86_SREG_COUNT);
7288
7289 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7290 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7291 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7292 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7293
7294 uint16_t u16Sel;
7295 uint64_t u64Base;
7296 uint32_t u32Limit, u32Attr;
7297 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc);
7298 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc);
7299 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc);
7300 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc);
7301
7302 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7303 pSelReg->Sel = u16Sel;
7304 pSelReg->ValidSel = u16Sel;
7305 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7306 pSelReg->u32Limit = u32Limit;
7307 pSelReg->u64Base = u64Base;
7308 pSelReg->Attr.u = u32Attr;
7309 if (u32Attr & X86DESCATTR_UNUSABLE)
7310 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7311}
7312
7313
7314/**
7315 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7316 *
7317 * @param pVCpu The cross context virtual CPU structure.
7318 *
7319 * @remarks Called with interrupts and/or preemption disabled.
7320 */
7321static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7322{
7323 uint16_t u16Sel;
7324 uint64_t u64Base;
7325 uint32_t u32Limit, u32Attr;
7326 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7327 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7328 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7329 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7330
7331 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7332 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7333 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7334 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7335 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7336 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7337 if (u32Attr & X86DESCATTR_UNUSABLE)
7338 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7339}
7340
7341
7342/**
7343 * Imports the guest TR from the current VMCS into the guest-CPU context.
7344 *
7345 * @param pVCpu The cross context virtual CPU structure.
7346 *
7347 * @remarks Called with interrupts and/or preemption disabled.
7348 */
7349static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7350{
7351 uint16_t u16Sel;
7352 uint64_t u64Base;
7353 uint32_t u32Limit, u32Attr;
7354 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7355 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7356 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7357 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7358
7359 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7360 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7361 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7362 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7363 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7364 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7365 /* TR is the only selector that can never be unusable. */
7366 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7367}
7368
7369
7370/**
7371 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7372 *
7373 * @param pVCpu The cross context virtual CPU structure.
7374 *
7375 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7376 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7377 * instead!!!
7378 */
7379static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7380{
7381 uint64_t u64Val;
7382 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7383 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7384 {
7385 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7386 AssertRC(rc);
7387
7388 pCtx->rip = u64Val;
7389 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7390 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7391 }
7392}
7393
7394
7395/**
7396 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7397 *
7398 * @param pVCpu The cross context virtual CPU structure.
7399 * @param pVmcsInfo The VMCS info. object.
7400 *
7401 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7402 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7403 * instead!!!
7404 */
7405static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7406{
7407 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7408 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7409 {
7410 uint64_t u64Val;
7411 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7412 AssertRC(rc);
7413
7414 pCtx->rflags.u64 = u64Val;
7415 if (pVmcsInfo->RealMode.fRealOnV86Active)
7416 {
7417 pCtx->eflags.Bits.u1VM = 0;
7418 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7419 }
7420 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7421 }
7422}
7423
7424
7425/**
7426 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7427 * context.
7428 *
7429 * @param pVCpu The cross context virtual CPU structure.
7430 * @param pVmcsInfo The VMCS info. object.
7431 *
7432 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7433 * do not log!
7434 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7435 * instead!!!
7436 */
7437static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7438{
7439 uint32_t u32Val;
7440 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7441 if (!u32Val)
7442 {
7443 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7444 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7445 CPUMSetGuestNmiBlocking(pVCpu, false);
7446 }
7447 else
7448 {
7449 /*
7450 * We must import RIP here to set our EM interrupt-inhibited state.
7451 * We also import RFLAGS as our code that evaluates pending interrupts
7452 * before VM-entry requires it.
7453 */
7454 hmR0VmxImportGuestRip(pVCpu);
7455 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7456
7457 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7458 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7459 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7460 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7461
7462 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7463 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7464 }
7465}
7466
7467
7468/**
7469 * Worker for VMXR0ImportStateOnDemand.
7470 *
7471 * @returns VBox status code.
7472 * @param pVCpu The cross context virtual CPU structure.
7473 * @param pVmcsInfo The VMCS info. object.
7474 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7475 */
7476static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7477{
7478 int rc = VINF_SUCCESS;
7479 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7480 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7481 uint32_t u32Val;
7482
7483 /*
7484 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7485 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7486 * neither are other host platforms.
7487 *
7488 * Committing this temporarily as it prevents BSOD.
7489 *
7490 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7491 */
7492#ifdef RT_OS_WINDOWS
7493 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7494 return VERR_HM_IPE_1;
7495#endif
7496
7497 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7498
7499 /*
7500 * We disable interrupts to make the updating of the state and in particular
7501 * the fExtrn modification atomic wrt to preemption hooks.
7502 */
7503 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7504
7505 fWhat &= pCtx->fExtrn;
7506 if (fWhat)
7507 {
7508 do
7509 {
7510 if (fWhat & CPUMCTX_EXTRN_RIP)
7511 hmR0VmxImportGuestRip(pVCpu);
7512
7513 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7514 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7515
7516 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7517 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7518
7519 if (fWhat & CPUMCTX_EXTRN_RSP)
7520 {
7521 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7522 AssertRC(rc);
7523 }
7524
7525 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7526 {
7527 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7528 if (fWhat & CPUMCTX_EXTRN_CS)
7529 {
7530 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7531 hmR0VmxImportGuestRip(pVCpu);
7532 if (fRealOnV86Active)
7533 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7534 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7535 }
7536 if (fWhat & CPUMCTX_EXTRN_SS)
7537 {
7538 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7539 if (fRealOnV86Active)
7540 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7541 }
7542 if (fWhat & CPUMCTX_EXTRN_DS)
7543 {
7544 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7545 if (fRealOnV86Active)
7546 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7547 }
7548 if (fWhat & CPUMCTX_EXTRN_ES)
7549 {
7550 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7551 if (fRealOnV86Active)
7552 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7553 }
7554 if (fWhat & CPUMCTX_EXTRN_FS)
7555 {
7556 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7557 if (fRealOnV86Active)
7558 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7559 }
7560 if (fWhat & CPUMCTX_EXTRN_GS)
7561 {
7562 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7563 if (fRealOnV86Active)
7564 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7565 }
7566 }
7567
7568 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7569 {
7570 if (fWhat & CPUMCTX_EXTRN_LDTR)
7571 hmR0VmxImportGuestLdtr(pVCpu);
7572
7573 if (fWhat & CPUMCTX_EXTRN_GDTR)
7574 {
7575 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7576 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7577 pCtx->gdtr.cbGdt = u32Val;
7578 }
7579
7580 /* Guest IDTR. */
7581 if (fWhat & CPUMCTX_EXTRN_IDTR)
7582 {
7583 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7584 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7585 pCtx->idtr.cbIdt = u32Val;
7586 }
7587
7588 /* Guest TR. */
7589 if (fWhat & CPUMCTX_EXTRN_TR)
7590 {
7591 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7592 don't need to import that one. */
7593 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7594 hmR0VmxImportGuestTr(pVCpu);
7595 }
7596 }
7597
7598 if (fWhat & CPUMCTX_EXTRN_DR7)
7599 {
7600 if (!pVCpu->hm.s.fUsingHyperDR7)
7601 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7602 }
7603
7604 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7605 {
7606 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7607 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7608 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7609 pCtx->SysEnter.cs = u32Val;
7610 }
7611
7612 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7613 {
7614 if ( pVM->hm.s.fAllow64BitGuests
7615 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7616 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7617 }
7618
7619 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7620 {
7621 if ( pVM->hm.s.fAllow64BitGuests
7622 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7623 {
7624 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7625 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7626 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7627 }
7628 }
7629
7630 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7631 {
7632 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7633 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7634 Assert(pMsrs);
7635 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7636 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7637 for (uint32_t i = 0; i < cMsrs; i++)
7638 {
7639 uint32_t const idMsr = pMsrs[i].u32Msr;
7640 switch (idMsr)
7641 {
7642 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7643 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7644 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7645 default:
7646 {
7647 uint32_t idxLbrMsr;
7648 if (pVM->hm.s.vmx.fLbr)
7649 {
7650 if (hmR0VmxIsLbrBranchFromMsr(pVM, idMsr, &idxLbrMsr))
7651 {
7652 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfo->au64LbrFromIpMsr));
7653 pVmcsInfo->au64LbrFromIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7654 break;
7655 }
7656 else if (hmR0VmxIsLbrBranchToMsr(pVM, idMsr, &idxLbrMsr))
7657 {
7658 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfo->au64LbrFromIpMsr));
7659 pVmcsInfo->au64LbrToIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7660 break;
7661 }
7662 else if (idMsr == pVM->hm.s.vmx.idLbrTosMsr)
7663 {
7664 pVmcsInfo->u64LbrTosMsr = pMsrs[i].u64Value;
7665 break;
7666 }
7667 /* Fallthru (no break) */
7668 }
7669 pCtx->fExtrn = 0;
7670 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7671 ASMSetFlags(fEFlags);
7672 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7673 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7674 }
7675 }
7676 }
7677 }
7678
7679 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7680 {
7681 if (fWhat & CPUMCTX_EXTRN_CR0)
7682 {
7683 uint64_t u64Cr0;
7684 uint64_t u64Shadow;
7685 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7686 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7687#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7688 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7689 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7690#else
7691 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7692 {
7693 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7694 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7695 }
7696 else
7697 {
7698 /*
7699 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7700 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7701 * re-construct CR0. See @bugref{9180#c95} for details.
7702 */
7703 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7704 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7705 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7706 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7707 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7708 }
7709#endif
7710 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7711 CPUMSetGuestCR0(pVCpu, u64Cr0);
7712 VMMRZCallRing3Enable(pVCpu);
7713 }
7714
7715 if (fWhat & CPUMCTX_EXTRN_CR4)
7716 {
7717 uint64_t u64Cr4;
7718 uint64_t u64Shadow;
7719 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7720 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7721#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7722 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7723 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7724#else
7725 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7726 {
7727 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7728 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7729 }
7730 else
7731 {
7732 /*
7733 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7734 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7735 * re-construct CR4. See @bugref{9180#c95} for details.
7736 */
7737 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7738 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7739 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7740 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7741 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7742 }
7743#endif
7744 pCtx->cr4 = u64Cr4;
7745 }
7746
7747 if (fWhat & CPUMCTX_EXTRN_CR3)
7748 {
7749 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7750 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7751 || ( pVM->hm.s.fNestedPaging
7752 && CPUMIsGuestPagingEnabledEx(pCtx)))
7753 {
7754 uint64_t u64Cr3;
7755 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7756 if (pCtx->cr3 != u64Cr3)
7757 {
7758 pCtx->cr3 = u64Cr3;
7759 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7760 }
7761
7762 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7763 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7764 if (CPUMIsGuestInPAEModeEx(pCtx))
7765 {
7766 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7767 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7768 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7769 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7770 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7771 }
7772 }
7773 }
7774 }
7775
7776#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7777 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7778 {
7779 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7780 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7781 {
7782 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7783 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7784 if (RT_SUCCESS(rc))
7785 { /* likely */ }
7786 else
7787 break;
7788 }
7789 }
7790#endif
7791 } while (0);
7792
7793 if (RT_SUCCESS(rc))
7794 {
7795 /* Update fExtrn. */
7796 pCtx->fExtrn &= ~fWhat;
7797
7798 /* If everything has been imported, clear the HM keeper bit. */
7799 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7800 {
7801 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7802 Assert(!pCtx->fExtrn);
7803 }
7804 }
7805 }
7806 else
7807 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7808
7809 /*
7810 * Restore interrupts.
7811 */
7812 ASMSetFlags(fEFlags);
7813
7814 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7815
7816 if (RT_SUCCESS(rc))
7817 { /* likely */ }
7818 else
7819 return rc;
7820
7821 /*
7822 * Honor any pending CR3 updates.
7823 *
7824 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7825 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7826 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7827 *
7828 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7829 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7830 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7831 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7832 *
7833 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7834 */
7835 if (VMMRZCallRing3IsEnabled(pVCpu))
7836 {
7837 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7838 {
7839 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7840 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7841 }
7842
7843 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7844 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7845
7846 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7847 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7848 }
7849
7850 return VINF_SUCCESS;
7851}
7852
7853
7854/**
7855 * Saves the guest state from the VMCS into the guest-CPU context.
7856 *
7857 * @returns VBox status code.
7858 * @param pVCpu The cross context virtual CPU structure.
7859 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7860 */
7861VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
7862{
7863 AssertPtr(pVCpu);
7864 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7865 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7866}
7867
7868
7869/**
7870 * Check per-VM and per-VCPU force flag actions that require us to go back to
7871 * ring-3 for one reason or another.
7872 *
7873 * @returns Strict VBox status code (i.e. informational status codes too)
7874 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7875 * ring-3.
7876 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7877 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7878 * interrupts)
7879 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7880 * all EMTs to be in ring-3.
7881 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7882 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7883 * to the EM loop.
7884 *
7885 * @param pVCpu The cross context virtual CPU structure.
7886 * @param pVmxTransient The VMX-transient structure.
7887 * @param fStepping Whether we are single-stepping the guest using the
7888 * hypervisor debugger.
7889 *
7890 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
7891 * is no longer in VMX non-root mode.
7892 */
7893static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, bool fStepping)
7894{
7895 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7896
7897 /*
7898 * Update pending interrupts into the APIC's IRR.
7899 */
7900 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7901 APICUpdatePendingInterrupts(pVCpu);
7902
7903 /*
7904 * Anything pending? Should be more likely than not if we're doing a good job.
7905 */
7906 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7907 if ( !fStepping
7908 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7909 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7910 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7911 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7912 return VINF_SUCCESS;
7913
7914 /* Pending PGM C3 sync. */
7915 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7916 {
7917 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7918 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7919 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7920 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7921 if (rcStrict != VINF_SUCCESS)
7922 {
7923 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
7924 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
7925 return rcStrict;
7926 }
7927 }
7928
7929 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7930 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7931 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7932 {
7933 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7934 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7935 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
7936 return rc;
7937 }
7938
7939 /* Pending VM request packets, such as hardware interrupts. */
7940 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7941 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7942 {
7943 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
7944 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7945 return VINF_EM_PENDING_REQUEST;
7946 }
7947
7948 /* Pending PGM pool flushes. */
7949 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7950 {
7951 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
7952 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7953 return VINF_PGM_POOL_FLUSH_PENDING;
7954 }
7955
7956 /* Pending DMA requests. */
7957 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7958 {
7959 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
7960 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7961 return VINF_EM_RAW_TO_R3;
7962 }
7963
7964#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7965 /*
7966 * Pending nested-guest events.
7967 *
7968 * Please note the priority of these events are specified and important.
7969 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
7970 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
7971 */
7972 if (pVmxTransient->fIsNestedGuest)
7973 {
7974 /* Pending nested-guest APIC-write. */
7975 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
7976 {
7977 Log4Func(("Pending nested-guest APIC-write\n"));
7978 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
7979 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7980 return rcStrict;
7981 }
7982
7983 /* Pending nested-guest monitor-trap flag (MTF). */
7984 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
7985 {
7986 Log4Func(("Pending nested-guest MTF\n"));
7987 VBOXSTRICTRC rcStrict = IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */);
7988 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7989 return rcStrict;
7990 }
7991
7992 /* Pending nested-guest VMX-preemption timer expired. */
7993 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
7994 {
7995 Log4Func(("Pending nested-guest MTF\n"));
7996 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitPreemptTimer(pVCpu);
7997 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7998 return rcStrict;
7999 }
8000 }
8001#else
8002 NOREF(pVmxTransient);
8003#endif
8004
8005 return VINF_SUCCESS;
8006}
8007
8008
8009/**
8010 * Converts any TRPM trap into a pending HM event. This is typically used when
8011 * entering from ring-3 (not longjmp returns).
8012 *
8013 * @param pVCpu The cross context virtual CPU structure.
8014 */
8015static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
8016{
8017 Assert(TRPMHasTrap(pVCpu));
8018 Assert(!pVCpu->hm.s.Event.fPending);
8019
8020 uint8_t uVector;
8021 TRPMEVENT enmTrpmEvent;
8022 uint32_t uErrCode;
8023 RTGCUINTPTR GCPtrFaultAddress;
8024 uint8_t cbInstr;
8025 bool fIcebp;
8026
8027 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
8028 AssertRC(rc);
8029
8030 uint32_t u32IntInfo;
8031 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8032 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
8033
8034 rc = TRPMResetTrap(pVCpu);
8035 AssertRC(rc);
8036 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8037 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8038
8039 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8040}
8041
8042
8043/**
8044 * Converts the pending HM event into a TRPM trap.
8045 *
8046 * @param pVCpu The cross context virtual CPU structure.
8047 */
8048static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
8049{
8050 Assert(pVCpu->hm.s.Event.fPending);
8051
8052 /* If a trap was already pending, we did something wrong! */
8053 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8054
8055 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8056 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8057 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8058
8059 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8060
8061 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8062 AssertRC(rc);
8063
8064 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8065 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8066
8067 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8068 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8069 else
8070 {
8071 uint8_t const uVectorType = VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo);
8072 switch (uVectorType)
8073 {
8074 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
8075 TRPMSetTrapDueToIcebp(pVCpu);
8076 RT_FALL_THRU();
8077 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
8078 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
8079 {
8080 AssertMsg( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
8081 || ( uVector == X86_XCPT_BP /* INT3 */
8082 || uVector == X86_XCPT_OF /* INTO */
8083 || uVector == X86_XCPT_DB /* INT1 (ICEBP) */),
8084 ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uVectorType));
8085 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8086 break;
8087 }
8088 }
8089 }
8090
8091 /* We're now done converting the pending event. */
8092 pVCpu->hm.s.Event.fPending = false;
8093}
8094
8095
8096/**
8097 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8098 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8099 *
8100 * @param pVCpu The cross context virtual CPU structure.
8101 * @param pVmcsInfo The VMCS info. object.
8102 */
8103static void hmR0VmxSetIntWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
8104{
8105 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8106 {
8107 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8108 {
8109 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8110 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8111 AssertRC(rc);
8112 }
8113 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8114}
8115
8116
8117/**
8118 * Clears the interrupt-window exiting control in the VMCS.
8119 *
8120 * @param pVmcsInfo The VMCS info. object.
8121 */
8122DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8123{
8124 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8125 {
8126 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8127 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8128 AssertRC(rc);
8129 }
8130}
8131
8132
8133/**
8134 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8135 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8136 *
8137 * @param pVCpu The cross context virtual CPU structure.
8138 * @param pVmcsInfo The VMCS info. object.
8139 */
8140static void hmR0VmxSetNmiWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
8141{
8142 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8143 {
8144 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8145 {
8146 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8147 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8148 AssertRC(rc);
8149 Log4Func(("Setup NMI-window exiting\n"));
8150 }
8151 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8152}
8153
8154
8155/**
8156 * Clears the NMI-window exiting control in the VMCS.
8157 *
8158 * @param pVmcsInfo The VMCS info. object.
8159 */
8160DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8161{
8162 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8163 {
8164 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8165 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8166 AssertRC(rc);
8167 }
8168}
8169
8170
8171/**
8172 * Does the necessary state syncing before returning to ring-3 for any reason
8173 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8174 *
8175 * @returns VBox status code.
8176 * @param pVCpu The cross context virtual CPU structure.
8177 * @param fImportState Whether to import the guest state from the VMCS back
8178 * to the guest-CPU context.
8179 *
8180 * @remarks No-long-jmp zone!!!
8181 */
8182static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
8183{
8184 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8185 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8186
8187 RTCPUID const idCpu = RTMpCpuId();
8188 Log4Func(("HostCpuId=%u\n", idCpu));
8189
8190 /*
8191 * !!! IMPORTANT !!!
8192 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
8193 */
8194
8195 /* Save the guest state if necessary. */
8196 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8197 if (fImportState)
8198 {
8199 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8200 AssertRCReturn(rc, rc);
8201 }
8202
8203 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8204 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8205 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8206
8207 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8208#ifdef VBOX_STRICT
8209 if (CPUMIsHyperDebugStateActive(pVCpu))
8210 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8211#endif
8212 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8213 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
8214 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
8215
8216 /* Restore host-state bits that VT-x only restores partially. */
8217 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8218 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8219 {
8220 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
8221 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8222 }
8223 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8224
8225 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8226 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8227 {
8228 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8229 if (!fImportState)
8230 {
8231 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8232 AssertRCReturn(rc, rc);
8233 }
8234 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8235 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
8236 }
8237 else
8238 pVCpu->hm.s.vmx.fLazyMsrs = 0;
8239
8240 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8241 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8242
8243 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8244 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8245 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8246 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8247 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8248 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8249 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8250 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8251 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8252 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8253
8254 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8255
8256 /** @todo This partially defeats the purpose of having preemption hooks.
8257 * The problem is, deregistering the hooks should be moved to a place that
8258 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8259 * context.
8260 */
8261 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8262 AssertRCReturn(rc, rc);
8263
8264#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8265 /*
8266 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8267 * clear a shadow VMCS before allowing that VMCS to become active on another
8268 * logical processor. We may or may not be importing guest state which clears
8269 * it, so cover for it here.
8270 *
8271 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8272 */
8273 if ( pVmcsInfo->pvShadowVmcs
8274 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8275 {
8276 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8277 AssertRCReturn(rc, rc);
8278 }
8279
8280 /*
8281 * Flag that we need to re-export the host state if we switch to this VMCS before
8282 * executing guest or nested-guest code.
8283 */
8284 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8285#endif
8286
8287 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8288 NOREF(idCpu);
8289 return VINF_SUCCESS;
8290}
8291
8292
8293/**
8294 * Leaves the VT-x session.
8295 *
8296 * @returns VBox status code.
8297 * @param pVCpu The cross context virtual CPU structure.
8298 *
8299 * @remarks No-long-jmp zone!!!
8300 */
8301static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8302{
8303 HM_DISABLE_PREEMPT(pVCpu);
8304 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8305 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8306 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8307
8308 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8309 and done this from the VMXR0ThreadCtxCallback(). */
8310 if (!pVCpu->hm.s.fLeaveDone)
8311 {
8312 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8313 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8314 pVCpu->hm.s.fLeaveDone = true;
8315 }
8316 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8317
8318 /*
8319 * !!! IMPORTANT !!!
8320 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8321 */
8322
8323 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8324 /** @todo Deregistering here means we need to VMCLEAR always
8325 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8326 * for calling VMMR0ThreadCtxHookDisable here! */
8327 VMMR0ThreadCtxHookDisable(pVCpu);
8328
8329 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8330 int rc = HMR0LeaveCpu(pVCpu);
8331 HM_RESTORE_PREEMPT();
8332 return rc;
8333}
8334
8335
8336/**
8337 * Does the necessary state syncing before doing a longjmp to ring-3.
8338 *
8339 * @returns VBox status code.
8340 * @param pVCpu The cross context virtual CPU structure.
8341 *
8342 * @remarks No-long-jmp zone!!!
8343 */
8344DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8345{
8346 return hmR0VmxLeaveSession(pVCpu);
8347}
8348
8349
8350/**
8351 * Take necessary actions before going back to ring-3.
8352 *
8353 * An action requires us to go back to ring-3. This function does the necessary
8354 * steps before we can safely return to ring-3. This is not the same as longjmps
8355 * to ring-3, this is voluntary and prepares the guest so it may continue
8356 * executing outside HM (recompiler/IEM).
8357 *
8358 * @returns VBox status code.
8359 * @param pVCpu The cross context virtual CPU structure.
8360 * @param rcExit The reason for exiting to ring-3. Can be
8361 * VINF_VMM_UNKNOWN_RING3_CALL.
8362 */
8363static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8364{
8365 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8366
8367 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8368 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8369 {
8370 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8371 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8372 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8373 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8374 }
8375
8376 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8377 VMMRZCallRing3Disable(pVCpu);
8378 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8379
8380 /*
8381 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8382 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8383 *
8384 * This is because execution may continue from ring-3 and we would need to inject
8385 * the event from there (hence place it back in TRPM).
8386 */
8387 if (pVCpu->hm.s.Event.fPending)
8388 {
8389 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8390 Assert(!pVCpu->hm.s.Event.fPending);
8391
8392 /* Clear the events from the VMCS. */
8393 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc);
8394 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0); AssertRC(rc);
8395 }
8396#ifdef VBOX_STRICT
8397 /*
8398 * We check for rcExit here since for errors like VERR_VMX_UNABLE_TO_START_VM (which are
8399 * fatal), we don't care about verifying duplicate injection of events. Errors like
8400 * VERR_EM_INTERPRET are converted to their VINF_* counterparts -prior- to calling this
8401 * function so those should and will be checked below.
8402 */
8403 else if (RT_SUCCESS(rcExit))
8404 {
8405 /*
8406 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8407 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8408 * occasionally, see @bugref{9180#c42}.
8409 *
8410 * However, if the VM-entry failed, any VM entry-interruption info. field would
8411 * be left unmodified as the event would not have been injected to the guest. In
8412 * such cases, don't assert, we're not going to continue guest execution anyway.
8413 */
8414 uint32_t uExitReason;
8415 uint32_t uEntryIntInfo;
8416 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8417 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8418 AssertRC(rc);
8419 AssertMsg(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo),
8420 ("uExitReason=%#RX32 uEntryIntInfo=%#RX32 rcExit=%d\n", uExitReason, uEntryIntInfo, VBOXSTRICTRC_VAL(rcExit)));
8421 }
8422#endif
8423
8424 /*
8425 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8426 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8427 * (e.g. TPR below threshold).
8428 */
8429 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8430 {
8431 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8432 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8433 }
8434
8435 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8436 and if we're injecting an event we should have a TRPM trap pending. */
8437 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8438#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8439 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8440#endif
8441
8442 /* Save guest state and restore host state bits. */
8443 int rc = hmR0VmxLeaveSession(pVCpu);
8444 AssertRCReturn(rc, rc);
8445 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8446
8447 /* Thread-context hooks are unregistered at this point!!! */
8448 /* Ring-3 callback notifications are unregistered at this point!!! */
8449
8450 /* Sync recompiler state. */
8451 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8452 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8453 | CPUM_CHANGED_LDTR
8454 | CPUM_CHANGED_GDTR
8455 | CPUM_CHANGED_IDTR
8456 | CPUM_CHANGED_TR
8457 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8458 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8459 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8460 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8461
8462 Assert(!pVCpu->hm.s.fClearTrapFlag);
8463
8464 /* Update the exit-to-ring 3 reason. */
8465 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8466
8467 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8468 if ( rcExit != VINF_EM_RAW_INTERRUPT
8469 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8470 {
8471 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8472 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8473 }
8474
8475 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8476 VMMRZCallRing3Enable(pVCpu);
8477 return rc;
8478}
8479
8480
8481/**
8482 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8483 * longjump to ring-3 and possibly get preempted.
8484 *
8485 * @returns VBox status code.
8486 * @param pVCpu The cross context virtual CPU structure.
8487 * @param enmOperation The operation causing the ring-3 longjump.
8488 */
8489VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8490{
8491 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8492 {
8493 /*
8494 * !!! IMPORTANT !!!
8495 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8496 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8497 */
8498 VMMRZCallRing3RemoveNotification(pVCpu);
8499 VMMRZCallRing3Disable(pVCpu);
8500 HM_DISABLE_PREEMPT(pVCpu);
8501
8502 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8503 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8504 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8505 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8506
8507 /* Restore host-state bits that VT-x only restores partially. */
8508 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8509 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8510 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8511 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8512
8513 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8514 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8515 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8516
8517 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8518 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8519 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8520
8521 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8522 cleared as part of importing the guest state above. */
8523 hmR0VmxClearVmcs(pVmcsInfo);
8524
8525 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8526 VMMR0ThreadCtxHookDisable(pVCpu);
8527
8528 /* Leave HM context. This takes care of local init (term). */
8529 HMR0LeaveCpu(pVCpu);
8530 HM_RESTORE_PREEMPT();
8531 return VINF_SUCCESS;
8532 }
8533
8534 Assert(pVCpu);
8535 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8536 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8537
8538 VMMRZCallRing3Disable(pVCpu);
8539 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8540
8541 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8542
8543 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8544 AssertRCReturn(rc, rc);
8545
8546 VMMRZCallRing3Enable(pVCpu);
8547 return VINF_SUCCESS;
8548}
8549
8550
8551/**
8552 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8553 * stack.
8554 *
8555 * @returns Strict VBox status code (i.e. informational status codes too).
8556 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8557 * @param pVCpu The cross context virtual CPU structure.
8558 * @param uValue The value to push to the guest stack.
8559 */
8560static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8561{
8562 /*
8563 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8564 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8565 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8566 */
8567 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8568 if (pCtx->sp == 1)
8569 return VINF_EM_RESET;
8570 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8571 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8572 AssertRC(rc);
8573 return rc;
8574}
8575
8576
8577/**
8578 * Injects an event into the guest upon VM-entry by updating the relevant fields
8579 * in the VM-entry area in the VMCS.
8580 *
8581 * @returns Strict VBox status code (i.e. informational status codes too).
8582 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8583 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8584 *
8585 * @param pVCpu The cross context virtual CPU structure.
8586 * @param pVmxTransient The VMX-transient structure.
8587 * @param pEvent The event being injected.
8588 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8589 * will be updated if necessary. This cannot not be NULL.
8590 * @param fStepping Whether we're single-stepping guest execution and should
8591 * return VINF_EM_DBG_STEPPED if the event is injected
8592 * directly (registers modified by us, not by hardware on
8593 * VM-entry).
8594 */
8595static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8596 uint32_t *pfIntrState)
8597{
8598 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8599 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8600 Assert(pfIntrState);
8601
8602 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8603 uint32_t u32IntInfo = pEvent->u64IntInfo;
8604 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8605 uint32_t const cbInstr = pEvent->cbInstr;
8606 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8607 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8608 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8609
8610#ifdef VBOX_STRICT
8611 /*
8612 * Validate the error-code-valid bit for hardware exceptions.
8613 * No error codes for exceptions in real-mode.
8614 *
8615 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8616 */
8617 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8618 && !CPUMIsGuestInRealModeEx(pCtx))
8619 {
8620 switch (uVector)
8621 {
8622 case X86_XCPT_PF:
8623 case X86_XCPT_DF:
8624 case X86_XCPT_TS:
8625 case X86_XCPT_NP:
8626 case X86_XCPT_SS:
8627 case X86_XCPT_GP:
8628 case X86_XCPT_AC:
8629 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8630 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8631 RT_FALL_THRU();
8632 default:
8633 break;
8634 }
8635 }
8636
8637 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8638 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8639 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8640#endif
8641
8642 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8643 || uIntType == VMX_EXIT_INT_INFO_TYPE_NMI
8644 || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT
8645 || uIntType == VMX_EXIT_INT_INFO_TYPE_SW_XCPT)
8646 {
8647 Assert(uVector <= X86_XCPT_LAST);
8648 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_NMI || uVector == X86_XCPT_NMI);
8649 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT || uVector == X86_XCPT_DB);
8650 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedXcptsR0[uVector]);
8651 }
8652 else
8653 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8654
8655 /*
8656 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8657 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8658 * interrupt handler in the (real-mode) guest.
8659 *
8660 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8661 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8662 */
8663 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8664 {
8665 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8666 {
8667 /*
8668 * For CPUs with unrestricted guest execution enabled and with the guest
8669 * in real-mode, we must not set the deliver-error-code bit.
8670 *
8671 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8672 */
8673 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8674 }
8675 else
8676 {
8677 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8678 Assert(PDMVmmDevHeapIsEnabled(pVM));
8679 Assert(pVM->hm.s.vmx.pRealModeTSS);
8680 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8681
8682 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8683 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8684 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8685 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8686 AssertRCReturn(rc2, rc2);
8687
8688 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8689 size_t const cbIdtEntry = sizeof(X86IDTR16);
8690 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8691 {
8692 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8693 if (uVector == X86_XCPT_DF)
8694 return VINF_EM_RESET;
8695
8696 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8697 No error codes for exceptions in real-mode. */
8698 if (uVector == X86_XCPT_GP)
8699 {
8700 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8701 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8702 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8703 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8704 HMEVENT EventXcptDf;
8705 RT_ZERO(EventXcptDf);
8706 EventXcptDf.u64IntInfo = uXcptDfInfo;
8707 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8708 }
8709
8710 /*
8711 * If we're injecting an event with no valid IDT entry, inject a #GP.
8712 * No error codes for exceptions in real-mode.
8713 *
8714 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8715 */
8716 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8717 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8718 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8719 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8720 HMEVENT EventXcptGp;
8721 RT_ZERO(EventXcptGp);
8722 EventXcptGp.u64IntInfo = uXcptGpInfo;
8723 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8724 }
8725
8726 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8727 uint16_t uGuestIp = pCtx->ip;
8728 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8729 {
8730 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8731 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8732 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8733 }
8734 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8735 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8736
8737 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8738 X86IDTR16 IdtEntry;
8739 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8740 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8741 AssertRCReturn(rc2, rc2);
8742
8743 /* Construct the stack frame for the interrupt/exception handler. */
8744 VBOXSTRICTRC rcStrict;
8745 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8746 if (rcStrict == VINF_SUCCESS)
8747 {
8748 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8749 if (rcStrict == VINF_SUCCESS)
8750 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8751 }
8752
8753 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8754 if (rcStrict == VINF_SUCCESS)
8755 {
8756 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8757 pCtx->rip = IdtEntry.offSel;
8758 pCtx->cs.Sel = IdtEntry.uSel;
8759 pCtx->cs.ValidSel = IdtEntry.uSel;
8760 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8761 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8762 && uVector == X86_XCPT_PF)
8763 pCtx->cr2 = GCPtrFault;
8764
8765 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8766 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8767 | HM_CHANGED_GUEST_RSP);
8768
8769 /*
8770 * If we delivered a hardware exception (other than an NMI) and if there was
8771 * block-by-STI in effect, we should clear it.
8772 */
8773 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8774 {
8775 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8776 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8777 Log4Func(("Clearing inhibition due to STI\n"));
8778 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8779 }
8780
8781 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8782 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8783
8784 /*
8785 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8786 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8787 */
8788 pVCpu->hm.s.Event.fPending = false;
8789
8790 /*
8791 * If we eventually support nested-guest execution without unrestricted guest execution,
8792 * we should set fInterceptEvents here.
8793 */
8794 Assert(!pVmxTransient->fIsNestedGuest);
8795
8796 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8797 if (fStepping)
8798 rcStrict = VINF_EM_DBG_STEPPED;
8799 }
8800 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8801 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8802 return rcStrict;
8803 }
8804 }
8805
8806 /*
8807 * Validate.
8808 */
8809 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8810 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8811
8812 /*
8813 * Inject the event into the VMCS.
8814 */
8815 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8816 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8817 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8818 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8819 AssertRC(rc);
8820
8821 /*
8822 * Update guest CR2 if this is a page-fault.
8823 */
8824 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8825 pCtx->cr2 = GCPtrFault;
8826
8827 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8828 return VINF_SUCCESS;
8829}
8830
8831
8832/**
8833 * Evaluates the event to be delivered to the guest and sets it as the pending
8834 * event.
8835 *
8836 * Toggling of interrupt force-flags here is safe since we update TRPM on premature
8837 * exits to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must
8838 * NOT restore these force-flags.
8839 *
8840 * @returns Strict VBox status code (i.e. informational status codes too).
8841 * @param pVCpu The cross context virtual CPU structure.
8842 * @param pVmxTransient The VMX-transient structure.
8843 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8844 */
8845static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8846{
8847 Assert(pfIntrState);
8848 Assert(!TRPMHasTrap(pVCpu));
8849
8850 /*
8851 * Compute/update guest-interruptibility state related FFs.
8852 * The FFs will be used below while evaluating events to be injected.
8853 */
8854 *pfIntrState = hmR0VmxGetGuestIntrStateAndUpdateFFs(pVCpu);
8855
8856 /*
8857 * Evaluate if a new event needs to be injected.
8858 * An event that's already pending has already performed all necessary checks.
8859 */
8860 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8861 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8862 if ( !pVCpu->hm.s.Event.fPending
8863 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
8864 {
8865 /** @todo SMI. SMIs take priority over NMIs. */
8866
8867 /*
8868 * NMIs.
8869 * NMIs take priority over external interrupts.
8870 */
8871 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8872 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8873 {
8874 /*
8875 * For a guest, the FF always indicates the guest's ability to receive an NMI.
8876 *
8877 * For a nested-guest, the FF always indicates the outer guest's ability to
8878 * receive an NMI while the guest-interruptibility state bit depends on whether
8879 * the nested-hypervisor is using virtual-NMIs.
8880 */
8881 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
8882 {
8883#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8884 if ( fIsNestedGuest
8885 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_NMI_EXIT))
8886 return IEMExecVmxVmexitXcptNmi(pVCpu);
8887#endif
8888 hmR0VmxSetPendingXcptNmi(pVCpu);
8889 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8890 Log4Func(("NMI pending injection\n"));
8891
8892 /* We've injected the NMI, bail. */
8893 return VINF_SUCCESS;
8894 }
8895 else if (!fIsNestedGuest)
8896 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8897 }
8898
8899 /*
8900 * External interrupts (PIC/APIC).
8901 * Once PDMGetInterrupt() returns a valid interrupt we -must- deliver it.
8902 * We cannot re-request the interrupt from the controller again.
8903 */
8904 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8905 && !pVCpu->hm.s.fSingleInstruction)
8906 {
8907 Assert(!DBGFIsStepping(pVCpu));
8908 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8909 AssertRC(rc);
8910
8911 if (pCtx->eflags.u32 & X86_EFL_IF)
8912 {
8913#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8914 if ( fIsNestedGuest
8915 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8916 && !CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8917 {
8918 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
8919 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8920 return rcStrict;
8921 }
8922#endif
8923 uint8_t u8Interrupt;
8924 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8925 if (RT_SUCCESS(rc))
8926 {
8927#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8928 if ( fIsNestedGuest
8929 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8930 && CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8931 {
8932 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8933 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8934 return rcStrict;
8935 }
8936#endif
8937 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8938 Log4Func(("External interrupt (%#x) pending injection\n", u8Interrupt));
8939 }
8940 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8941 {
8942 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8943
8944 if ( !fIsNestedGuest
8945 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8946 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
8947 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
8948
8949 /*
8950 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8951 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8952 * need to re-set this force-flag here.
8953 */
8954 }
8955 else
8956 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8957
8958 /* We've injected the interrupt or taken necessary action, bail. */
8959 return VINF_SUCCESS;
8960 }
8961 else if (!fIsNestedGuest)
8962 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8963 }
8964 }
8965 else if (!fIsNestedGuest)
8966 {
8967 /*
8968 * An event is being injected or we are in an interrupt shadow. Check if another event is
8969 * pending. If so, instruct VT-x to cause a VM-exit as soon as the guest is ready to accept
8970 * the pending event.
8971 */
8972 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8973 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8974 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8975 && !pVCpu->hm.s.fSingleInstruction)
8976 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8977 }
8978 /* else: for nested-guests, NMI/interrupt-window exiting will be picked up when merging VMCS controls. */
8979
8980 return VINF_SUCCESS;
8981}
8982
8983
8984/**
8985 * Injects any pending events into the guest if the guest is in a state to
8986 * receive them.
8987 *
8988 * @returns Strict VBox status code (i.e. informational status codes too).
8989 * @param pVCpu The cross context virtual CPU structure.
8990 * @param pVmxTransient The VMX-transient structure.
8991 * @param fIntrState The VT-x guest-interruptibility state.
8992 * @param fStepping Whether we are single-stepping the guest using the
8993 * hypervisor debugger and should return
8994 * VINF_EM_DBG_STEPPED if the event was dispatched
8995 * directly.
8996 */
8997static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
8998{
8999 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9000 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9001
9002#ifdef VBOX_STRICT
9003 /*
9004 * Verify guest-interruptibility state.
9005 *
9006 * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
9007 * since injecting an event may modify the interruptibility state and we must thus always
9008 * use fIntrState.
9009 */
9010 {
9011 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9012 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9013 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9014 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9015 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9016 Assert(!TRPMHasTrap(pVCpu));
9017 NOREF(fBlockMovSS); NOREF(fBlockSti);
9018 }
9019#endif
9020
9021 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9022 if (pVCpu->hm.s.Event.fPending)
9023 {
9024 /*
9025 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9026 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9027 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9028 *
9029 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9030 */
9031 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9032#ifdef VBOX_STRICT
9033 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9034 {
9035 Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9036 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9037 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9038 }
9039 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9040 {
9041 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
9042 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9043 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9044 }
9045#endif
9046 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9047 uIntType));
9048
9049 /*
9050 * Inject the event and get any changes to the guest-interruptibility state.
9051 *
9052 * The guest-interruptibility state may need to be updated if we inject the event
9053 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9054 */
9055 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9056 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9057
9058 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9059 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9060 else
9061 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9062 }
9063
9064 /*
9065 * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
9066 * is an interrupt shadow (block-by-STI or block-by-MOV SS).
9067 */
9068 if ( (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9069 && !pVmxTransient->fIsNestedGuest)
9070 {
9071 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
9072
9073 if (!pVCpu->hm.s.fSingleInstruction)
9074 {
9075 /*
9076 * Set or clear the BS bit depending on whether the trap flag is active or not. We need
9077 * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
9078 */
9079 Assert(!DBGFIsStepping(pVCpu));
9080 uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
9081 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
9082 AssertRC(rc);
9083 }
9084 else
9085 {
9086 /*
9087 * We must not deliver a debug exception when single-stepping over STI/Mov-SS in the
9088 * hypervisor debugger using EFLAGS.TF but rather clear interrupt inhibition. However,
9089 * we take care of this case in hmR0VmxExportSharedDebugState and also the case if
9090 * we use MTF, so just make sure it's called before executing guest-code.
9091 */
9092 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR_MASK);
9093 }
9094 }
9095 /* else: for nested-guest currently handling while merging controls. */
9096
9097 /*
9098 * Finally, update the guest-interruptibility state.
9099 *
9100 * This is required for the real-on-v86 software interrupt injection, for
9101 * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
9102 */
9103 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9104 AssertRC(rc);
9105
9106 /*
9107 * There's no need to clear the VM-entry interruption-information field here if we're not
9108 * injecting anything. VT-x clears the valid bit on every VM-exit.
9109 *
9110 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9111 */
9112
9113 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9114 return rcStrict;
9115}
9116
9117
9118/**
9119 * Enters the VT-x session.
9120 *
9121 * @returns VBox status code.
9122 * @param pVCpu The cross context virtual CPU structure.
9123 */
9124VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
9125{
9126 AssertPtr(pVCpu);
9127 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9128 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9129
9130 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9131 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9132 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9133
9134#ifdef VBOX_STRICT
9135 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9136 RTCCUINTREG uHostCr4 = ASMGetCR4();
9137 if (!(uHostCr4 & X86_CR4_VMXE))
9138 {
9139 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9140 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9141 }
9142#endif
9143
9144 /*
9145 * Load the appropriate VMCS as the current and active one.
9146 */
9147 PVMXVMCSINFO pVmcsInfo;
9148 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9149 if (!fInNestedGuestMode)
9150 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
9151 else
9152 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
9153 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9154 if (RT_SUCCESS(rc))
9155 {
9156 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9157 pVCpu->hm.s.fLeaveDone = false;
9158 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9159
9160 /*
9161 * Do the EMT scheduled L1D flush here if needed.
9162 */
9163 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9164 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9165 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9166 hmR0MdsClear();
9167 }
9168 return rc;
9169}
9170
9171
9172/**
9173 * The thread-context callback (only on platforms which support it).
9174 *
9175 * @param enmEvent The thread-context event.
9176 * @param pVCpu The cross context virtual CPU structure.
9177 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9178 * @thread EMT(pVCpu)
9179 */
9180VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
9181{
9182 AssertPtr(pVCpu);
9183 RT_NOREF1(fGlobalInit);
9184
9185 switch (enmEvent)
9186 {
9187 case RTTHREADCTXEVENT_OUT:
9188 {
9189 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9190 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9191 VMCPU_ASSERT_EMT(pVCpu);
9192
9193 /* No longjmps (logger flushes, locks) in this fragile context. */
9194 VMMRZCallRing3Disable(pVCpu);
9195 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9196
9197 /* Restore host-state (FPU, debug etc.) */
9198 if (!pVCpu->hm.s.fLeaveDone)
9199 {
9200 /*
9201 * Do -not- import the guest-state here as we might already be in the middle of importing
9202 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9203 */
9204 hmR0VmxLeave(pVCpu, false /* fImportState */);
9205 pVCpu->hm.s.fLeaveDone = true;
9206 }
9207
9208 /* Leave HM context, takes care of local init (term). */
9209 int rc = HMR0LeaveCpu(pVCpu);
9210 AssertRC(rc);
9211
9212 /* Restore longjmp state. */
9213 VMMRZCallRing3Enable(pVCpu);
9214 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9215 break;
9216 }
9217
9218 case RTTHREADCTXEVENT_IN:
9219 {
9220 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9221 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9222 VMCPU_ASSERT_EMT(pVCpu);
9223
9224 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9225 VMMRZCallRing3Disable(pVCpu);
9226 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9227
9228 /* Initialize the bare minimum state required for HM. This takes care of
9229 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9230 int rc = hmR0EnterCpu(pVCpu);
9231 AssertRC(rc);
9232 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9233 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9234
9235 /* Load the active VMCS as the current one. */
9236 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9237 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9238 AssertRC(rc);
9239 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9240 pVCpu->hm.s.fLeaveDone = false;
9241
9242 /* Do the EMT scheduled L1D flush if needed. */
9243 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9244 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9245
9246 /* Restore longjmp state. */
9247 VMMRZCallRing3Enable(pVCpu);
9248 break;
9249 }
9250
9251 default:
9252 break;
9253 }
9254}
9255
9256
9257/**
9258 * Exports the host state into the VMCS host-state area.
9259 * Sets up the VM-exit MSR-load area.
9260 *
9261 * The CPU state will be loaded from these fields on every successful VM-exit.
9262 *
9263 * @returns VBox status code.
9264 * @param pVCpu The cross context virtual CPU structure.
9265 *
9266 * @remarks No-long-jump zone!!!
9267 */
9268static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
9269{
9270 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9271
9272 int rc = VINF_SUCCESS;
9273 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9274 {
9275 hmR0VmxExportHostControlRegs();
9276
9277 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
9278 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9279
9280 hmR0VmxExportHostMsrs(pVCpu);
9281
9282 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9283 }
9284 return rc;
9285}
9286
9287
9288/**
9289 * Saves the host state in the VMCS host-state.
9290 *
9291 * @returns VBox status code.
9292 * @param pVCpu The cross context virtual CPU structure.
9293 *
9294 * @remarks No-long-jump zone!!!
9295 */
9296VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
9297{
9298 AssertPtr(pVCpu);
9299 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9300
9301 /*
9302 * Export the host state here while entering HM context.
9303 * When thread-context hooks are used, we might get preempted and have to re-save the host
9304 * state but most of the time we won't be, so do it here before we disable interrupts.
9305 */
9306 return hmR0VmxExportHostState(pVCpu);
9307}
9308
9309
9310/**
9311 * Exports the guest state into the VMCS guest-state area.
9312 *
9313 * The will typically be done before VM-entry when the guest-CPU state and the
9314 * VMCS state may potentially be out of sync.
9315 *
9316 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9317 * VM-entry controls.
9318 * Sets up the appropriate VMX non-root function to execute guest code based on
9319 * the guest CPU mode.
9320 *
9321 * @returns VBox strict status code.
9322 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9323 * without unrestricted guest execution and the VMMDev is not presently
9324 * mapped (e.g. EFI32).
9325 *
9326 * @param pVCpu The cross context virtual CPU structure.
9327 * @param pVmxTransient The VMX-transient structure.
9328 *
9329 * @remarks No-long-jump zone!!!
9330 */
9331static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9332{
9333 AssertPtr(pVCpu);
9334 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9335 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9336
9337 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9338
9339 /*
9340 * Determine real-on-v86 mode.
9341 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9342 */
9343 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9344 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9345 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9346 pVmcsInfo->RealMode.fRealOnV86Active = false;
9347 else
9348 {
9349 Assert(!pVmxTransient->fIsNestedGuest);
9350 pVmcsInfo->RealMode.fRealOnV86Active = true;
9351 }
9352
9353 /*
9354 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9355 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9356 */
9357 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9358 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9359
9360 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9361 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9362
9363 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9364 if (rcStrict == VINF_SUCCESS)
9365 { /* likely */ }
9366 else
9367 {
9368 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9369 return rcStrict;
9370 }
9371
9372 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9373 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9374
9375 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9376 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9377
9378 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9379 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9380 hmR0VmxExportGuestRip(pVCpu);
9381 hmR0VmxExportGuestRsp(pVCpu);
9382 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9383
9384 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9385 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9386
9387 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9388 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9389 | HM_CHANGED_GUEST_CR2
9390 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9391 | HM_CHANGED_GUEST_X87
9392 | HM_CHANGED_GUEST_SSE_AVX
9393 | HM_CHANGED_GUEST_OTHER_XSAVE
9394 | HM_CHANGED_GUEST_XCRx
9395 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9396 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9397 | HM_CHANGED_GUEST_TSC_AUX
9398 | HM_CHANGED_GUEST_OTHER_MSRS
9399 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9400
9401 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9402 return rc;
9403}
9404
9405
9406/**
9407 * Exports the state shared between the host and guest into the VMCS.
9408 *
9409 * @param pVCpu The cross context virtual CPU structure.
9410 * @param pVmxTransient The VMX-transient structure.
9411 *
9412 * @remarks No-long-jump zone!!!
9413 */
9414static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9415{
9416 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9417 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9418
9419 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9420 {
9421 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9422 AssertRC(rc);
9423 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9424
9425 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9426 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9427 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9428 }
9429
9430 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9431 {
9432 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9433 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9434 }
9435
9436 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9437 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9438}
9439
9440
9441/**
9442 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9443 *
9444 * @returns Strict VBox status code (i.e. informational status codes too).
9445 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9446 * without unrestricted guest execution and the VMMDev is not presently
9447 * mapped (e.g. EFI32).
9448 *
9449 * @param pVCpu The cross context virtual CPU structure.
9450 * @param pVmxTransient The VMX-transient structure.
9451 *
9452 * @remarks No-long-jump zone!!!
9453 */
9454static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9455{
9456 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9457 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9458 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9459
9460#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9461 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9462#endif
9463
9464 /*
9465 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9466 * changes. First try to export only these without going through all other changed-flag checks.
9467 */
9468 VBOXSTRICTRC rcStrict;
9469 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9470 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9471 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9472
9473 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9474 if ( (fCtxChanged & fMinimalMask)
9475 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9476 {
9477 hmR0VmxExportGuestRip(pVCpu);
9478 hmR0VmxExportGuestRsp(pVCpu);
9479 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9480 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9481 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9482 }
9483 /* If anything else also changed, go through the full export routine and export as required. */
9484 else if (fCtxChanged & fCtxMask)
9485 {
9486 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9487 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9488 { /* likely */}
9489 else
9490 {
9491 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9492 VBOXSTRICTRC_VAL(rcStrict)));
9493 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9494 return rcStrict;
9495 }
9496 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9497 }
9498 /* Nothing changed, nothing to load here. */
9499 else
9500 rcStrict = VINF_SUCCESS;
9501
9502#ifdef VBOX_STRICT
9503 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9504 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9505 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9506#endif
9507 return rcStrict;
9508}
9509
9510
9511/**
9512 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9513 * and update error record fields accordingly.
9514 *
9515 * @returns VMX_IGS_* error codes.
9516 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9517 * wrong with the guest state.
9518 *
9519 * @param pVCpu The cross context virtual CPU structure.
9520 * @param pVmcsInfo The VMCS info. object.
9521 *
9522 * @remarks This function assumes our cache of the VMCS controls
9523 * are valid, i.e. hmR0VmxCheckCachedVmcsCtls() succeeded.
9524 */
9525static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9526{
9527#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9528#define HMVMX_CHECK_BREAK(expr, err) do { \
9529 if (!(expr)) { uError = (err); break; } \
9530 } while (0)
9531
9532 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9533 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9534 uint32_t uError = VMX_IGS_ERROR;
9535 uint32_t u32IntrState = 0;
9536 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9537 do
9538 {
9539 int rc;
9540
9541 /*
9542 * Guest-interruptibility state.
9543 *
9544 * Read this first so that any check that fails prior to those that actually
9545 * require the guest-interruptibility state would still reflect the correct
9546 * VMCS value and avoids causing further confusion.
9547 */
9548 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9549 AssertRC(rc);
9550
9551 uint32_t u32Val;
9552 uint64_t u64Val;
9553
9554 /*
9555 * CR0.
9556 */
9557 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9558 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9559 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9560 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9561 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9562 if (fUnrestrictedGuest)
9563 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9564
9565 uint64_t u64GuestCr0;
9566 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9567 AssertRC(rc);
9568 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9569 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9570 if ( !fUnrestrictedGuest
9571 && (u64GuestCr0 & X86_CR0_PG)
9572 && !(u64GuestCr0 & X86_CR0_PE))
9573 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9574
9575 /*
9576 * CR4.
9577 */
9578 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9579 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9580 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9581
9582 uint64_t u64GuestCr4;
9583 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9584 AssertRC(rc);
9585 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9586 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9587
9588 /*
9589 * IA32_DEBUGCTL MSR.
9590 */
9591 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9592 AssertRC(rc);
9593 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9594 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9595 {
9596 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9597 }
9598 uint64_t u64DebugCtlMsr = u64Val;
9599
9600#ifdef VBOX_STRICT
9601 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9602 AssertRC(rc);
9603 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9604#endif
9605 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9606
9607 /*
9608 * RIP and RFLAGS.
9609 */
9610 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9611 AssertRC(rc);
9612 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9613 if ( !fLongModeGuest
9614 || !pCtx->cs.Attr.n.u1Long)
9615 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9616 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9617 * must be identical if the "IA-32e mode guest" VM-entry
9618 * control is 1 and CS.L is 1. No check applies if the
9619 * CPU supports 64 linear-address bits. */
9620
9621 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9622 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9623 AssertRC(rc);
9624 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9625 VMX_IGS_RFLAGS_RESERVED);
9626 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9627 uint32_t const u32Eflags = u64Val;
9628
9629 if ( fLongModeGuest
9630 || ( fUnrestrictedGuest
9631 && !(u64GuestCr0 & X86_CR0_PE)))
9632 {
9633 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9634 }
9635
9636 uint32_t u32EntryInfo;
9637 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9638 AssertRC(rc);
9639 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9640 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9641
9642 /*
9643 * 64-bit checks.
9644 */
9645 if (fLongModeGuest)
9646 {
9647 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9648 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9649 }
9650
9651 if ( !fLongModeGuest
9652 && (u64GuestCr4 & X86_CR4_PCIDE))
9653 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9654
9655 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9656 * 51:32 beyond the processor's physical-address width are 0. */
9657
9658 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9659 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9660 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9661
9662 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9663 AssertRC(rc);
9664 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9665
9666 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9667 AssertRC(rc);
9668 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9669
9670 /*
9671 * PERF_GLOBAL MSR.
9672 */
9673 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9674 {
9675 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9676 AssertRC(rc);
9677 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9678 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9679 }
9680
9681 /*
9682 * PAT MSR.
9683 */
9684 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9685 {
9686 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9687 AssertRC(rc);
9688 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9689 for (unsigned i = 0; i < 8; i++)
9690 {
9691 uint8_t u8Val = (u64Val & 0xff);
9692 if ( u8Val != 0 /* UC */
9693 && u8Val != 1 /* WC */
9694 && u8Val != 4 /* WT */
9695 && u8Val != 5 /* WP */
9696 && u8Val != 6 /* WB */
9697 && u8Val != 7 /* UC- */)
9698 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9699 u64Val >>= 8;
9700 }
9701 }
9702
9703 /*
9704 * EFER MSR.
9705 */
9706 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9707 {
9708 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9709 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9710 AssertRC(rc);
9711 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9712 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9713 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9714 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9715 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9716 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9717 * iemVmxVmentryCheckGuestState(). */
9718 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9719 || !(u64GuestCr0 & X86_CR0_PG)
9720 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9721 VMX_IGS_EFER_LMA_LME_MISMATCH);
9722 }
9723
9724 /*
9725 * Segment registers.
9726 */
9727 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9728 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9729 if (!(u32Eflags & X86_EFL_VM))
9730 {
9731 /* CS */
9732 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9733 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9734 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9735 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9736 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9737 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9738 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9739 /* CS cannot be loaded with NULL in protected mode. */
9740 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9741 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9742 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9743 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9744 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9745 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9746 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9747 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9748 else
9749 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9750
9751 /* SS */
9752 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9753 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9754 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9755 if ( !(pCtx->cr0 & X86_CR0_PE)
9756 || pCtx->cs.Attr.n.u4Type == 3)
9757 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9758
9759 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9760 {
9761 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9762 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9763 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9764 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9765 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9766 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9767 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9768 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9769 }
9770
9771 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9772 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9773 {
9774 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9775 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9776 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9777 || pCtx->ds.Attr.n.u4Type > 11
9778 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9779 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9780 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9781 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9782 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9783 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9784 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9785 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9786 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9787 }
9788 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9789 {
9790 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9791 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9792 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9793 || pCtx->es.Attr.n.u4Type > 11
9794 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9795 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9796 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9797 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9798 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9799 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9800 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9801 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9802 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9803 }
9804 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9805 {
9806 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9807 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9808 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9809 || pCtx->fs.Attr.n.u4Type > 11
9810 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9811 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9812 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9813 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9814 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9815 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9816 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9817 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9818 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9819 }
9820 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9821 {
9822 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9823 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9824 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9825 || pCtx->gs.Attr.n.u4Type > 11
9826 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9827 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9828 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9829 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9830 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9831 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9832 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9833 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9834 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9835 }
9836 /* 64-bit capable CPUs. */
9837 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9838 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9839 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9840 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9841 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9842 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9843 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9844 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9845 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9846 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9847 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9848 }
9849 else
9850 {
9851 /* V86 mode checks. */
9852 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9853 if (pVmcsInfo->RealMode.fRealOnV86Active)
9854 {
9855 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9856 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9857 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9858 }
9859 else
9860 {
9861 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9862 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9863 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9864 }
9865
9866 /* CS */
9867 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9868 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9869 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9870 /* SS */
9871 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9872 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9873 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9874 /* DS */
9875 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9876 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9877 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9878 /* ES */
9879 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9880 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9881 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9882 /* FS */
9883 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9884 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9885 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9886 /* GS */
9887 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9888 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9889 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9890 /* 64-bit capable CPUs. */
9891 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9892 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9893 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9894 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9895 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9896 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9897 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9898 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9899 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9900 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9901 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9902 }
9903
9904 /*
9905 * TR.
9906 */
9907 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9908 /* 64-bit capable CPUs. */
9909 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9910 if (fLongModeGuest)
9911 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9912 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9913 else
9914 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9915 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9916 VMX_IGS_TR_ATTR_TYPE_INVALID);
9917 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9918 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9919 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9920 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9921 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9922 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9923 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9924 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9925
9926 /*
9927 * GDTR and IDTR (64-bit capable checks).
9928 */
9929 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9930 AssertRC(rc);
9931 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9932
9933 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9934 AssertRC(rc);
9935 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9936
9937 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9938 AssertRC(rc);
9939 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9940
9941 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9942 AssertRC(rc);
9943 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9944
9945 /*
9946 * Guest Non-Register State.
9947 */
9948 /* Activity State. */
9949 uint32_t u32ActivityState;
9950 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9951 AssertRC(rc);
9952 HMVMX_CHECK_BREAK( !u32ActivityState
9953 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9954 VMX_IGS_ACTIVITY_STATE_INVALID);
9955 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9956 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9957
9958 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9959 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9960 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9961
9962 /** @todo Activity state and injecting interrupts. Left as a todo since we
9963 * currently don't use activity states but ACTIVE. */
9964
9965 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9966 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9967
9968 /* Guest interruptibility-state. */
9969 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9970 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9971 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9972 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9973 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9974 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9975 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9976 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9977 {
9978 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9979 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9980 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9981 }
9982 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9983 {
9984 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9985 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9986 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9987 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
9988 }
9989 /** @todo Assumes the processor is not in SMM. */
9990 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9991 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
9992 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9993 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9994 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
9995 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
9996 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9997 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
9998
9999 /* Pending debug exceptions. */
10000 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10001 AssertRC(rc);
10002 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10003 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10004 u32Val = u64Val; /* For pending debug exceptions checks below. */
10005
10006 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10007 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10008 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10009 {
10010 if ( (u32Eflags & X86_EFL_TF)
10011 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10012 {
10013 /* Bit 14 is PendingDebug.BS. */
10014 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10015 }
10016 if ( !(u32Eflags & X86_EFL_TF)
10017 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10018 {
10019 /* Bit 14 is PendingDebug.BS. */
10020 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10021 }
10022 }
10023
10024 /* VMCS link pointer. */
10025 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10026 AssertRC(rc);
10027 if (u64Val != UINT64_C(0xffffffffffffffff))
10028 {
10029 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10030 /** @todo Bits beyond the processor's physical-address width MBZ. */
10031 /** @todo SMM checks. */
10032 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10033 Assert(pVmcsInfo->pvShadowVmcs);
10034 VMXVMCSREVID VmcsRevId;
10035 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10036 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
10037 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10038 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10039 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10040 }
10041
10042 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10043 * not using nested paging? */
10044 if ( pVM->hm.s.fNestedPaging
10045 && !fLongModeGuest
10046 && CPUMIsGuestInPAEModeEx(pCtx))
10047 {
10048 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10049 AssertRC(rc);
10050 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10051
10052 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10053 AssertRC(rc);
10054 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10055
10056 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10057 AssertRC(rc);
10058 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10059
10060 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10061 AssertRC(rc);
10062 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10063 }
10064
10065 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10066 if (uError == VMX_IGS_ERROR)
10067 uError = VMX_IGS_REASON_NOT_FOUND;
10068 } while (0);
10069
10070 pVCpu->hm.s.u32HMError = uError;
10071 pVCpu->hm.s.vmx.LastError.u32GuestIntrState = u32IntrState;
10072 return uError;
10073
10074#undef HMVMX_ERROR_BREAK
10075#undef HMVMX_CHECK_BREAK
10076}
10077
10078
10079/**
10080 * Map the APIC-access page for virtualizing APIC accesses.
10081 *
10082 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10083 * this not done as part of exporting guest state, see @bugref{8721}.
10084 *
10085 * @returns VBox status code.
10086 * @param pVCpu The cross context virtual CPU structure.
10087 */
10088static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
10089{
10090 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10091 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10092
10093 Assert(PDMHasApic(pVM));
10094 Assert(u64MsrApicBase);
10095
10096 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10097 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10098
10099 /* Unalias the existing mapping. */
10100 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10101 AssertRCReturn(rc, rc);
10102
10103 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10104 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10105 rc = IOMR0MmioMapMmioHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10106 AssertRCReturn(rc, rc);
10107
10108 /* Update the per-VCPU cache of the APIC base MSR. */
10109 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10110 return VINF_SUCCESS;
10111}
10112
10113
10114/**
10115 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10116 * CPU.
10117 *
10118 * @param idCpu The ID for the CPU the function is called on.
10119 * @param pvUser1 Null, not used.
10120 * @param pvUser2 Null, not used.
10121 */
10122static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10123{
10124 RT_NOREF3(idCpu, pvUser1, pvUser2);
10125 VMXDispatchHostNmi();
10126}
10127
10128
10129/**
10130 * Dispatching an NMI on the host CPU that received it.
10131 *
10132 * @returns VBox status code.
10133 * @param pVCpu The cross context virtual CPU structure.
10134 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10135 * executing when receiving the host NMI in VMX non-root
10136 * operation.
10137 */
10138static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
10139{
10140 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
10141 Assert(idCpu != NIL_RTCPUID);
10142
10143 /*
10144 * We don't want to delay dispatching the NMI any more than we have to. However,
10145 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10146 * after executing guest or nested-guest code for the following reasons:
10147 *
10148 * - We would need to perform VMREADs with interrupts disabled and is orders of
10149 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
10150 * supported by the host hypervisor.
10151 *
10152 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10153 * longer period of time just for handling an edge case like host NMIs which do
10154 * not occur nearly as frequently as other VM-exits.
10155 *
10156 * Let's cover the most likely scenario first. Check if we are on the target CPU
10157 * and dispatch the NMI right away. This should be much faster than calling into
10158 * RTMpOnSpecific() machinery.
10159 */
10160 bool fDispatched = false;
10161 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10162 if (idCpu == RTMpCpuId())
10163 {
10164 VMXDispatchHostNmi();
10165 fDispatched = true;
10166 }
10167 ASMSetFlags(fEFlags);
10168 if (fDispatched)
10169 {
10170 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10171 return VINF_SUCCESS;
10172 }
10173
10174 /*
10175 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10176 * there should be no race or recursion even if we are unlucky enough to be preempted
10177 * (to the target CPU) without dispatching the host NMI above.
10178 */
10179 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10180 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10181}
10182
10183
10184#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10185/**
10186 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10187 * nested-guest using hardware-assisted VMX.
10188 *
10189 * @param pVCpu The cross context virtual CPU structure.
10190 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10191 * @param pVmcsInfoGst The guest VMCS info. object.
10192 */
10193static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10194{
10195 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10196 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10197 Assert(pu64MsrBitmap);
10198
10199 /*
10200 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10201 * MSR that is intercepted by the guest is also intercepted while executing the
10202 * nested-guest using hardware-assisted VMX.
10203 *
10204 * Note! If the nested-guest is not using an MSR bitmap, every MSR must cause a
10205 * nested-guest VM-exit even if the outer guest is not intercepting some
10206 * MSRs. We cannot assume the caller has initialized the nested-guest
10207 * MSR bitmap in this case.
10208 *
10209 * The nested hypervisor may also switch whether it uses MSR bitmaps for
10210 * each of its VM-entry, hence initializing it once per-VM while setting
10211 * up the nested-guest VMCS is not sufficient.
10212 */
10213 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10214 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10215 {
10216 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10217 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10218 Assert(pu64MsrBitmapNstGst);
10219 Assert(pu64MsrBitmapGst);
10220
10221 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10222 for (uint32_t i = 0; i < cFrags; i++)
10223 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10224 }
10225 else
10226 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10227}
10228
10229
10230/**
10231 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10232 * hardware-assisted VMX execution of the nested-guest.
10233 *
10234 * For a guest, we don't modify these controls once we set up the VMCS and hence
10235 * this function is never called.
10236 *
10237 * For nested-guests since the nested hypervisor provides these controls on every
10238 * nested-guest VM-entry and could potentially change them everytime we need to
10239 * merge them before every nested-guest VM-entry.
10240 *
10241 * @returns VBox status code.
10242 * @param pVCpu The cross context virtual CPU structure.
10243 */
10244static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
10245{
10246 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10247 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
10248 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10249 Assert(pVmcsNstGst);
10250
10251 /*
10252 * Merge the controls with the requirements of the guest VMCS.
10253 *
10254 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10255 * VMCS with the features supported by the physical CPU as it's already done by the
10256 * VMLAUNCH/VMRESUME instruction emulation.
10257 *
10258 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10259 * derived from the VMX features supported by the physical CPU.
10260 */
10261
10262 /* Pin-based VM-execution controls. */
10263 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10264
10265 /* Processor-based VM-execution controls. */
10266 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10267 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10268 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10269 | VMX_PROC_CTLS_USE_TPR_SHADOW
10270 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10271
10272 /* Secondary processor-based VM-execution controls. */
10273 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10274 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10275 | VMX_PROC_CTLS2_INVPCID
10276 | VMX_PROC_CTLS2_VMCS_SHADOWING
10277 | VMX_PROC_CTLS2_RDTSCP
10278 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10279 | VMX_PROC_CTLS2_APIC_REG_VIRT
10280 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10281 | VMX_PROC_CTLS2_VMFUNC));
10282
10283 /*
10284 * VM-entry controls:
10285 * These controls contains state that depends on the nested-guest state (primarily
10286 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10287 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
10288 * properly continue executing the nested-guest if the EFER MSR changes but does not
10289 * cause a nested-guest VM-exits.
10290 *
10291 * VM-exit controls:
10292 * These controls specify the host state on return. We cannot use the controls from
10293 * the nested hypervisor state as is as it would contain the guest state rather than
10294 * the host state. Since the host state is subject to change (e.g. preemption, trips
10295 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10296 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10297 *
10298 * VM-entry MSR-load:
10299 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10300 * context by the VMLAUNCH/VMRESUME instruction emulation.
10301 *
10302 * VM-exit MSR-store:
10303 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10304 * back into the VM-exit MSR-store area.
10305 *
10306 * VM-exit MSR-load areas:
10307 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10308 * can entirely ignore what the nested hypervisor wants to load here.
10309 */
10310
10311 /*
10312 * Exception bitmap.
10313 *
10314 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10315 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10316 * code more flexible if intercepting exceptions become more dynamic in the future we do
10317 * it as part of exporting the nested-guest state.
10318 */
10319 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10320
10321 /*
10322 * CR0/CR4 guest/host mask.
10323 *
10324 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10325 * cause VM-exits, so we need to merge them here.
10326 */
10327 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10328 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10329
10330 /*
10331 * Page-fault error-code mask and match.
10332 *
10333 * Although we require unrestricted guest execution (and thereby nested-paging) for
10334 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10335 * normally intercept #PFs, it might intercept them for debugging purposes.
10336 *
10337 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10338 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10339 */
10340 uint32_t u32XcptPFMask;
10341 uint32_t u32XcptPFMatch;
10342 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10343 {
10344 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10345 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10346 }
10347 else
10348 {
10349 u32XcptPFMask = 0;
10350 u32XcptPFMatch = 0;
10351 }
10352
10353 /*
10354 * Pause-Loop exiting.
10355 */
10356 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10357 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10358
10359 /*
10360 * Pending debug exceptions.
10361 * Currently just copy whatever the nested-guest provides us.
10362 */
10363 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10364
10365 /*
10366 * I/O Bitmap.
10367 *
10368 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10369 * intercept all I/O port accesses.
10370 */
10371 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10372 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10373
10374 /*
10375 * VMCS shadowing.
10376 *
10377 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10378 * enabled while executing the nested-guest.
10379 */
10380 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10381
10382 /*
10383 * APIC-access page.
10384 */
10385 RTHCPHYS HCPhysApicAccess;
10386 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10387 {
10388 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10389 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10390
10391 /** @todo NSTVMX: This is not really correct but currently is required to make
10392 * things work. We need to re-enable the page handler when we fallback to
10393 * IEM execution of the nested-guest! */
10394 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10395
10396 void *pvPage;
10397 PGMPAGEMAPLOCK PgLockApicAccess;
10398 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10399 if (RT_SUCCESS(rc))
10400 {
10401 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10402 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10403
10404 /** @todo Handle proper releasing of page-mapping lock later. */
10405 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10406 }
10407 else
10408 return rc;
10409 }
10410 else
10411 HCPhysApicAccess = 0;
10412
10413 /*
10414 * Virtual-APIC page and TPR threshold.
10415 */
10416 RTHCPHYS HCPhysVirtApic;
10417 uint32_t u32TprThreshold;
10418 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10419 {
10420 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10421 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10422
10423 void *pvPage;
10424 PGMPAGEMAPLOCK PgLockVirtApic;
10425 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10426 if (RT_SUCCESS(rc))
10427 {
10428 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10429 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10430
10431 /** @todo Handle proper releasing of page-mapping lock later. */
10432 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10433 }
10434 else
10435 return rc;
10436
10437 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10438 }
10439 else
10440 {
10441 HCPhysVirtApic = 0;
10442 u32TprThreshold = 0;
10443
10444 /*
10445 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10446 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10447 * be taken care of by EPT/shadow paging.
10448 */
10449 if (pVM->hm.s.fAllow64BitGuests)
10450 {
10451 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10452 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10453 }
10454 }
10455
10456 /*
10457 * Validate basic assumptions.
10458 */
10459 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10460 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10461 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10462 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10463
10464 /*
10465 * Commit it to the nested-guest VMCS.
10466 */
10467 int rc = VINF_SUCCESS;
10468 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10469 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10470 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10471 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10472 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10473 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10474 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10475 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10476 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10477 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10478 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10479 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10480 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10481 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10482 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10483 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10484 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10485 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10486 {
10487 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10488 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10489 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10490 }
10491 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10492 {
10493 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10494 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10495 }
10496 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10497 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10498 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10499 AssertRC(rc);
10500
10501 /*
10502 * Update the nested-guest VMCS cache.
10503 */
10504 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10505 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10506 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10507 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10508 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10509 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10510 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10511 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10512 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10513
10514 /*
10515 * We need to flush the TLB if we are switching the APIC-access page address.
10516 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10517 */
10518 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10519 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10520
10521 /*
10522 * MSR bitmap.
10523 *
10524 * The MSR bitmap address has already been initialized while setting up the nested-guest
10525 * VMCS, here we need to merge the MSR bitmaps.
10526 */
10527 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10528 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10529
10530 return VINF_SUCCESS;
10531}
10532#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10533
10534
10535/**
10536 * Does the preparations before executing guest code in VT-x.
10537 *
10538 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10539 * recompiler/IEM. We must be cautious what we do here regarding committing
10540 * guest-state information into the VMCS assuming we assuredly execute the
10541 * guest in VT-x mode.
10542 *
10543 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10544 * the common-state (TRPM/forceflags), we must undo those changes so that the
10545 * recompiler/IEM can (and should) use them when it resumes guest execution.
10546 * Otherwise such operations must be done when we can no longer exit to ring-3.
10547 *
10548 * @returns Strict VBox status code (i.e. informational status codes too).
10549 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10550 * have been disabled.
10551 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10552 * pending events).
10553 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10554 * double-fault into the guest.
10555 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10556 * dispatched directly.
10557 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10558 *
10559 * @param pVCpu The cross context virtual CPU structure.
10560 * @param pVmxTransient The VMX-transient structure.
10561 * @param fStepping Whether we are single-stepping the guest in the
10562 * hypervisor debugger. Makes us ignore some of the reasons
10563 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10564 * if event dispatching took place.
10565 */
10566static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10567{
10568 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10569
10570 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10571
10572#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10573 if (pVmxTransient->fIsNestedGuest)
10574 {
10575 RT_NOREF2(pVCpu, fStepping);
10576 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10577 return VINF_EM_RESCHEDULE_REM;
10578 }
10579#endif
10580
10581#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10582 PGMRZDynMapFlushAutoSet(pVCpu);
10583#endif
10584
10585 /*
10586 * Check and process force flag actions, some of which might require us to go back to ring-3.
10587 */
10588 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, pVmxTransient, fStepping);
10589 if (rcStrict == VINF_SUCCESS)
10590 {
10591 /* FFs don't get set all the time. */
10592#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10593 if ( pVmxTransient->fIsNestedGuest
10594 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10595 {
10596 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10597 return VINF_VMX_VMEXIT;
10598 }
10599#endif
10600 }
10601 else
10602 return rcStrict;
10603
10604 /*
10605 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10606 */
10607 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10608 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10609 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10610 && PDMHasApic(pVM))
10611 {
10612 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10613 AssertRCReturn(rc, rc);
10614 }
10615
10616#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10617 /*
10618 * Merge guest VMCS controls with the nested-guest VMCS controls.
10619 *
10620 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10621 * saved state), we should be okay with merging controls as we initialize the
10622 * guest VMCS controls as part of VM setup phase.
10623 */
10624 if ( pVmxTransient->fIsNestedGuest
10625 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10626 {
10627 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10628 AssertRCReturn(rc, rc);
10629 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10630 }
10631#endif
10632
10633 /*
10634 * Evaluate events to be injected into the guest.
10635 *
10636 * Events in TRPM can be injected without inspecting the guest state.
10637 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10638 * guest to cause a VM-exit the next time they are ready to receive the event.
10639 *
10640 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10641 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10642 * subject to interecption. Otherwise, we should have checked and injected them
10643 * manually elsewhere (IEM).
10644 */
10645 if (TRPMHasTrap(pVCpu))
10646 {
10647 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10648 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10649 }
10650
10651 uint32_t fIntrState;
10652 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10653
10654#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10655 /*
10656 * While evaluating pending events if something failed (unlikely) or if we were
10657 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10658 */
10659 if (rcStrict != VINF_SUCCESS)
10660 return rcStrict;
10661 if ( pVmxTransient->fIsNestedGuest
10662 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10663 {
10664 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10665 return VINF_VMX_VMEXIT;
10666 }
10667#else
10668 Assert(rcStrict == VINF_SUCCESS);
10669#endif
10670
10671 /*
10672 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10673 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10674 * also result in triple-faulting the VM.
10675 *
10676 * With nested-guests, the above does not apply since unrestricted guest execution is a
10677 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10678 */
10679 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10680 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10681 { /* likely */ }
10682 else
10683 {
10684 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10685 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10686 return rcStrict;
10687 }
10688
10689 /*
10690 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10691 * import CR3 themselves. We will need to update them here, as even as late as the above
10692 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10693 * the below force flags to be set.
10694 */
10695 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10696 {
10697 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10698 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10699 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10700 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10701 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10702 }
10703 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10704 {
10705 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10706 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10707 }
10708
10709#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10710 /* Paranoia. */
10711 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10712#endif
10713
10714 /*
10715 * No longjmps to ring-3 from this point on!!!
10716 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10717 * This also disables flushing of the R0-logger instance (if any).
10718 */
10719 VMMRZCallRing3Disable(pVCpu);
10720
10721 /*
10722 * Export the guest state bits.
10723 *
10724 * We cannot perform longjmps while loading the guest state because we do not preserve the
10725 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10726 * CPU migration.
10727 *
10728 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10729 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10730 */
10731 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10732 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10733 { /* likely */ }
10734 else
10735 {
10736 VMMRZCallRing3Enable(pVCpu);
10737 return rcStrict;
10738 }
10739
10740 /*
10741 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10742 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10743 * preemption disabled for a while. Since this is purely to aid the
10744 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10745 * disable interrupt on NT.
10746 *
10747 * We need to check for force-flags that could've possible been altered since we last
10748 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10749 * see @bugref{6398}).
10750 *
10751 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10752 * to ring-3 before executing guest code.
10753 */
10754 pVmxTransient->fEFlags = ASMIntDisableFlags();
10755
10756 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10757 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10758 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10759 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10760 {
10761 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10762 {
10763#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10764 /*
10765 * If we are executing a nested-guest make sure that we should intercept subsequent
10766 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10767 * the VM-exit instruction emulation happy.
10768 */
10769 if (pVmxTransient->fIsNestedGuest)
10770 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10771#endif
10772
10773 /*
10774 * We've injected any pending events. This is really the point of no return (to ring-3).
10775 *
10776 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10777 * returns from this function, so do -not- enable them here.
10778 */
10779 pVCpu->hm.s.Event.fPending = false;
10780 return VINF_SUCCESS;
10781 }
10782
10783 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10784 rcStrict = VINF_EM_RAW_INTERRUPT;
10785 }
10786 else
10787 {
10788 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10789 rcStrict = VINF_EM_RAW_TO_R3;
10790 }
10791
10792 ASMSetFlags(pVmxTransient->fEFlags);
10793 VMMRZCallRing3Enable(pVCpu);
10794
10795 return rcStrict;
10796}
10797
10798
10799/**
10800 * Final preparations before executing guest code using hardware-assisted VMX.
10801 *
10802 * We can no longer get preempted to a different host CPU and there are no returns
10803 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10804 * failures), this function is not intended to fail sans unrecoverable hardware
10805 * errors.
10806 *
10807 * @param pVCpu The cross context virtual CPU structure.
10808 * @param pVmxTransient The VMX-transient structure.
10809 *
10810 * @remarks Called with preemption disabled.
10811 * @remarks No-long-jump zone!!!
10812 */
10813static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10814{
10815 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10816 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10817 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10818 Assert(!pVCpu->hm.s.Event.fPending);
10819
10820 /*
10821 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10822 */
10823 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10824 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10825
10826 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10827 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10828 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10829 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10830
10831 if (!CPUMIsGuestFPUStateActive(pVCpu))
10832 {
10833 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10834 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10835 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10836 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10837 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10838 }
10839
10840 /*
10841 * Re-export the host state bits as we may've been preempted (only happens when
10842 * thread-context hooks are used or when the VM start function changes) or if
10843 * the host CR0 is modified while loading the guest FPU state above.
10844 *
10845 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10846 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10847 * see @bugref{8432}.
10848 *
10849 * This may also happen when switching to/from a nested-guest VMCS without leaving
10850 * ring-0.
10851 */
10852 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10853 {
10854 hmR0VmxExportHostState(pVCpu);
10855 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10856 }
10857 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10858
10859 /*
10860 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10861 */
10862 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10863 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10864 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10865
10866 /*
10867 * Store status of the shared guest/host debug state at the time of VM-entry.
10868 */
10869 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10870 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10871
10872 /*
10873 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10874 * more than one conditional check. The post-run side of our code shall determine
10875 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10876 */
10877 if (pVmcsInfo->pbVirtApic)
10878 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10879
10880 /*
10881 * Update the host MSRs values in the VM-exit MSR-load area.
10882 */
10883 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10884 {
10885 if (pVmcsInfo->cExitMsrLoad > 0)
10886 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10887 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10888 }
10889
10890 /*
10891 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10892 * VMX-preemption timer based on the next virtual sync clock deadline.
10893 */
10894 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10895 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10896 {
10897 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10898 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10899 }
10900
10901 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
10902 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
10903 if (!fIsRdtscIntercepted)
10904 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
10905 else
10906 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
10907
10908 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10909 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10910 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10911 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
10912 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
10913 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
10914
10915 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10916
10917 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10918 as we're about to start executing the guest. */
10919
10920 /*
10921 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10922 *
10923 * This is done this late as updating the TSC offsetting/preemption timer above
10924 * figures out if we can skip intercepting RDTSCP by calculating the number of
10925 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10926 */
10927 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10928 && !fIsRdtscIntercepted)
10929 {
10930 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10931
10932 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
10933 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
10934 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10935 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10936 AssertRC(rc);
10937 Assert(!pVmxTransient->fRemoveTscAuxMsr);
10938 pVmxTransient->fRemoveTscAuxMsr = true;
10939 }
10940
10941#ifdef VBOX_STRICT
10942 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
10943 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
10944 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10945 AssertRC(hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
10946#endif
10947
10948#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10949 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10950 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
10951 * see @bugref{9180#c54}. */
10952 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10953 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10954 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10955#endif
10956}
10957
10958
10959/**
10960 * First C routine invoked after running guest code using hardware-assisted VMX.
10961 *
10962 * @param pVCpu The cross context virtual CPU structure.
10963 * @param pVmxTransient The VMX-transient structure.
10964 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10965 *
10966 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10967 *
10968 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10969 * unconditionally when it is safe to do so.
10970 */
10971static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10972{
10973 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10974
10975 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10976 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10977 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10978 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10979 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10980 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10981
10982 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10983 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10984 {
10985 uint64_t uGstTsc;
10986 if (!pVmxTransient->fIsNestedGuest)
10987 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10988 else
10989 {
10990 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10991 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
10992 }
10993 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
10994 }
10995
10996 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
10997 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
10998 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10999
11000 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11001 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11002#ifdef VBOX_STRICT
11003 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11004#endif
11005 Assert(!ASMIntAreEnabled());
11006 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11007 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11008
11009#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11010 /*
11011 * Clean all the VMCS fields in the transient structure before reading
11012 * anything from the VMCS.
11013 */
11014 pVmxTransient->uExitReason = 0;
11015 pVmxTransient->uExitIntErrorCode = 0;
11016 pVmxTransient->uExitQual = 0;
11017 pVmxTransient->uGuestLinearAddr = 0;
11018 pVmxTransient->uExitIntInfo = 0;
11019 pVmxTransient->cbExitInstr = 0;
11020 pVmxTransient->ExitInstrInfo.u = 0;
11021 pVmxTransient->uEntryIntInfo = 0;
11022 pVmxTransient->uEntryXcptErrorCode = 0;
11023 pVmxTransient->cbEntryInstr = 0;
11024 pVmxTransient->uIdtVectoringInfo = 0;
11025 pVmxTransient->uIdtVectoringErrorCode = 0;
11026#endif
11027
11028 /*
11029 * Save the basic VM-exit reason and check if the VM-entry failed.
11030 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11031 */
11032 uint32_t uExitReason;
11033 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11034 AssertRC(rc);
11035 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11036 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11037
11038 /*
11039 * Log the VM-exit before logging anything else as otherwise it might be a
11040 * tad confusing what happens before and after the world-switch.
11041 */
11042 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11043
11044 /*
11045 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11046 * bitmap permissions, if it was added before VM-entry.
11047 */
11048 if (pVmxTransient->fRemoveTscAuxMsr)
11049 {
11050 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11051 pVmxTransient->fRemoveTscAuxMsr = false;
11052 }
11053
11054 /*
11055 * Check if VMLAUNCH/VMRESUME succeeded.
11056 * If this failed, we cause a guru meditation and cease further execution.
11057 *
11058 * However, if we are executing a nested-guest we might fail if we use the
11059 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11060 */
11061 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11062 {
11063 /*
11064 * Update the VM-exit history array here even if the VM-entry failed due to:
11065 * - Invalid guest state.
11066 * - MSR loading.
11067 * - Machine-check event.
11068 *
11069 * In any of the above cases we will still have a "valid" VM-exit reason
11070 * despite @a fVMEntryFailed being false.
11071 *
11072 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11073 *
11074 * Note! We don't have CS or RIP at this point. Will probably address that later
11075 * by amending the history entry added here.
11076 */
11077 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11078 UINT64_MAX, uHostTsc);
11079
11080 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11081 {
11082 VMMRZCallRing3Enable(pVCpu);
11083
11084 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11085 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11086
11087#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
11088 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
11089#endif
11090
11091 /*
11092 * Import the guest-interruptibility state always as we need it while evaluating
11093 * injecting events on re-entry.
11094 *
11095 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11096 * checking for real-mode while exporting the state because all bits that cause
11097 * mode changes wrt CR0 are intercepted.
11098 */
11099 uint64_t const fImportMask = CPUMCTX_EXTRN_HM_VMX_INT_STATE
11100#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11101 | HMVMX_CPUMCTX_EXTRN_ALL
11102#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11103 | CPUMCTX_EXTRN_RFLAGS
11104#endif
11105 ;
11106 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImportMask);
11107 AssertRC(rc);
11108
11109 /*
11110 * Sync the TPR shadow with our APIC state.
11111 */
11112 if ( !pVmxTransient->fIsNestedGuest
11113 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
11114 {
11115 Assert(pVmcsInfo->pbVirtApic);
11116 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11117 {
11118 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11119 AssertRC(rc);
11120 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11121 }
11122 }
11123
11124 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11125 return;
11126 }
11127 }
11128#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11129 else if (pVmxTransient->fIsNestedGuest)
11130 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11131#endif
11132 else
11133 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11134
11135 VMMRZCallRing3Enable(pVCpu);
11136}
11137
11138
11139/**
11140 * Runs the guest code using hardware-assisted VMX the normal way.
11141 *
11142 * @returns VBox status code.
11143 * @param pVCpu The cross context virtual CPU structure.
11144 * @param pcLoops Pointer to the number of executed loops.
11145 */
11146static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
11147{
11148 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11149 Assert(pcLoops);
11150 Assert(*pcLoops <= cMaxResumeLoops);
11151 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11152
11153#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11154 /*
11155 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11156 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11157 * guest VMCS while entering the VMX ring-0 session.
11158 */
11159 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11160 {
11161 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11162 if (RT_SUCCESS(rc))
11163 { /* likely */ }
11164 else
11165 {
11166 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11167 return rc;
11168 }
11169 }
11170#endif
11171
11172 VMXTRANSIENT VmxTransient;
11173 RT_ZERO(VmxTransient);
11174 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11175
11176 /* Paranoia. */
11177 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
11178
11179 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11180 for (;;)
11181 {
11182 Assert(!HMR0SuspendPending());
11183 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11184 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11185
11186 /*
11187 * Preparatory work for running nested-guest code, this may force us to
11188 * return to ring-3.
11189 *
11190 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11191 */
11192 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11193 if (rcStrict != VINF_SUCCESS)
11194 break;
11195
11196 /* Interrupts are disabled at this point! */
11197 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11198 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11199 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11200 /* Interrupts are re-enabled at this point! */
11201
11202 /*
11203 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11204 */
11205 if (RT_SUCCESS(rcRun))
11206 { /* very likely */ }
11207 else
11208 {
11209 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11210 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11211 return rcRun;
11212 }
11213
11214 /*
11215 * Profile the VM-exit.
11216 */
11217 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11218 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11219 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11220 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11221 HMVMX_START_EXIT_DISPATCH_PROF();
11222
11223 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11224
11225 /*
11226 * Handle the VM-exit.
11227 */
11228#ifdef HMVMX_USE_FUNCTION_TABLE
11229 rcStrict = g_aVMExitHandlers[VmxTransient.uExitReason].pfn(pVCpu, &VmxTransient);
11230#else
11231 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11232#endif
11233 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11234 if (rcStrict == VINF_SUCCESS)
11235 {
11236 if (++(*pcLoops) <= cMaxResumeLoops)
11237 continue;
11238 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11239 rcStrict = VINF_EM_RAW_INTERRUPT;
11240 }
11241 break;
11242 }
11243
11244 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11245 return rcStrict;
11246}
11247
11248
11249#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11250/**
11251 * Runs the nested-guest code using hardware-assisted VMX.
11252 *
11253 * @returns VBox status code.
11254 * @param pVCpu The cross context virtual CPU structure.
11255 * @param pcLoops Pointer to the number of executed loops.
11256 *
11257 * @sa hmR0VmxRunGuestCodeNormal.
11258 */
11259static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
11260{
11261 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11262 Assert(pcLoops);
11263 Assert(*pcLoops <= cMaxResumeLoops);
11264 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11265
11266 /*
11267 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11268 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11269 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11270 */
11271 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11272 {
11273 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11274 if (RT_SUCCESS(rc))
11275 { /* likely */ }
11276 else
11277 {
11278 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11279 return rc;
11280 }
11281 }
11282
11283 VMXTRANSIENT VmxTransient;
11284 RT_ZERO(VmxTransient);
11285 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11286 VmxTransient.fIsNestedGuest = true;
11287
11288 /* Paranoia. */
11289 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11290
11291 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11292 for (;;)
11293 {
11294 Assert(!HMR0SuspendPending());
11295 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11296 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11297
11298 /*
11299 * Preparatory work for running guest code, this may force us to
11300 * return to ring-3.
11301 *
11302 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11303 */
11304 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11305 if (rcStrict != VINF_SUCCESS)
11306 break;
11307
11308 /* Interrupts are disabled at this point! */
11309 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11310 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11311 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11312 /* Interrupts are re-enabled at this point! */
11313
11314 /*
11315 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11316 */
11317 if (RT_SUCCESS(rcRun))
11318 { /* very likely */ }
11319 else
11320 {
11321 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11322 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11323 return rcRun;
11324 }
11325
11326 /*
11327 * Profile the VM-exit.
11328 */
11329 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11330 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11331 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11332 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11333 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11334 HMVMX_START_EXIT_DISPATCH_PROF();
11335
11336 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11337
11338 /*
11339 * Handle the VM-exit.
11340 */
11341 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11342 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11343 if (rcStrict == VINF_SUCCESS)
11344 {
11345 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11346 {
11347 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11348 rcStrict = VINF_VMX_VMEXIT;
11349 }
11350 else
11351 {
11352 if (++(*pcLoops) <= cMaxResumeLoops)
11353 continue;
11354 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11355 rcStrict = VINF_EM_RAW_INTERRUPT;
11356 }
11357 }
11358 else
11359 Assert(rcStrict != VINF_VMX_VMEXIT);
11360 break;
11361 }
11362
11363 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11364 return rcStrict;
11365}
11366#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11367
11368
11369/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11370 * probes.
11371 *
11372 * The following few functions and associated structure contains the bloat
11373 * necessary for providing detailed debug events and dtrace probes as well as
11374 * reliable host side single stepping. This works on the principle of
11375 * "subclassing" the normal execution loop and workers. We replace the loop
11376 * method completely and override selected helpers to add necessary adjustments
11377 * to their core operation.
11378 *
11379 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11380 * any performance for debug and analysis features.
11381 *
11382 * @{
11383 */
11384
11385/**
11386 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11387 * the debug run loop.
11388 */
11389typedef struct VMXRUNDBGSTATE
11390{
11391 /** The RIP we started executing at. This is for detecting that we stepped. */
11392 uint64_t uRipStart;
11393 /** The CS we started executing with. */
11394 uint16_t uCsStart;
11395
11396 /** Whether we've actually modified the 1st execution control field. */
11397 bool fModifiedProcCtls : 1;
11398 /** Whether we've actually modified the 2nd execution control field. */
11399 bool fModifiedProcCtls2 : 1;
11400 /** Whether we've actually modified the exception bitmap. */
11401 bool fModifiedXcptBitmap : 1;
11402
11403 /** We desire the modified the CR0 mask to be cleared. */
11404 bool fClearCr0Mask : 1;
11405 /** We desire the modified the CR4 mask to be cleared. */
11406 bool fClearCr4Mask : 1;
11407 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11408 uint32_t fCpe1Extra;
11409 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11410 uint32_t fCpe1Unwanted;
11411 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11412 uint32_t fCpe2Extra;
11413 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11414 uint32_t bmXcptExtra;
11415 /** The sequence number of the Dtrace provider settings the state was
11416 * configured against. */
11417 uint32_t uDtraceSettingsSeqNo;
11418 /** VM-exits to check (one bit per VM-exit). */
11419 uint32_t bmExitsToCheck[3];
11420
11421 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11422 uint32_t fProcCtlsInitial;
11423 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11424 uint32_t fProcCtls2Initial;
11425 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11426 uint32_t bmXcptInitial;
11427} VMXRUNDBGSTATE;
11428AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11429typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11430
11431
11432/**
11433 * Initializes the VMXRUNDBGSTATE structure.
11434 *
11435 * @param pVCpu The cross context virtual CPU structure of the
11436 * calling EMT.
11437 * @param pVmxTransient The VMX-transient structure.
11438 * @param pDbgState The debug state to initialize.
11439 */
11440static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11441{
11442 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11443 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11444
11445 pDbgState->fModifiedProcCtls = false;
11446 pDbgState->fModifiedProcCtls2 = false;
11447 pDbgState->fModifiedXcptBitmap = false;
11448 pDbgState->fClearCr0Mask = false;
11449 pDbgState->fClearCr4Mask = false;
11450 pDbgState->fCpe1Extra = 0;
11451 pDbgState->fCpe1Unwanted = 0;
11452 pDbgState->fCpe2Extra = 0;
11453 pDbgState->bmXcptExtra = 0;
11454 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11455 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11456 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11457}
11458
11459
11460/**
11461 * Updates the VMSC fields with changes requested by @a pDbgState.
11462 *
11463 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11464 * immediately before executing guest code, i.e. when interrupts are disabled.
11465 * We don't check status codes here as we cannot easily assert or return in the
11466 * latter case.
11467 *
11468 * @param pVCpu The cross context virtual CPU structure.
11469 * @param pVmxTransient The VMX-transient structure.
11470 * @param pDbgState The debug state.
11471 */
11472static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11473{
11474 /*
11475 * Ensure desired flags in VMCS control fields are set.
11476 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11477 *
11478 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11479 * there should be no stale data in pCtx at this point.
11480 */
11481 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11482 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11483 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11484 {
11485 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11486 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11487 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11488 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11489 pDbgState->fModifiedProcCtls = true;
11490 }
11491
11492 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11493 {
11494 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11495 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11496 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11497 pDbgState->fModifiedProcCtls2 = true;
11498 }
11499
11500 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11501 {
11502 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11503 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11504 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11505 pDbgState->fModifiedXcptBitmap = true;
11506 }
11507
11508 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11509 {
11510 pVmcsInfo->u64Cr0Mask = 0;
11511 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11512 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11513 }
11514
11515 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11516 {
11517 pVmcsInfo->u64Cr4Mask = 0;
11518 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11519 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11520 }
11521
11522 NOREF(pVCpu);
11523}
11524
11525
11526/**
11527 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11528 * re-entry next time around.
11529 *
11530 * @returns Strict VBox status code (i.e. informational status codes too).
11531 * @param pVCpu The cross context virtual CPU structure.
11532 * @param pVmxTransient The VMX-transient structure.
11533 * @param pDbgState The debug state.
11534 * @param rcStrict The return code from executing the guest using single
11535 * stepping.
11536 */
11537static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11538 VBOXSTRICTRC rcStrict)
11539{
11540 /*
11541 * Restore VM-exit control settings as we may not reenter this function the
11542 * next time around.
11543 */
11544 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11545
11546 /* We reload the initial value, trigger what we can of recalculations the
11547 next time around. From the looks of things, that's all that's required atm. */
11548 if (pDbgState->fModifiedProcCtls)
11549 {
11550 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11551 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11552 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11553 AssertRC(rc2);
11554 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11555 }
11556
11557 /* We're currently the only ones messing with this one, so just restore the
11558 cached value and reload the field. */
11559 if ( pDbgState->fModifiedProcCtls2
11560 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11561 {
11562 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11563 AssertRC(rc2);
11564 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11565 }
11566
11567 /* If we've modified the exception bitmap, we restore it and trigger
11568 reloading and partial recalculation the next time around. */
11569 if (pDbgState->fModifiedXcptBitmap)
11570 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11571
11572 return rcStrict;
11573}
11574
11575
11576/**
11577 * Configures VM-exit controls for current DBGF and DTrace settings.
11578 *
11579 * This updates @a pDbgState and the VMCS execution control fields to reflect
11580 * the necessary VM-exits demanded by DBGF and DTrace.
11581 *
11582 * @param pVCpu The cross context virtual CPU structure.
11583 * @param pVmxTransient The VMX-transient structure. May update
11584 * fUpdatedTscOffsettingAndPreemptTimer.
11585 * @param pDbgState The debug state.
11586 */
11587static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11588{
11589 /*
11590 * Take down the dtrace serial number so we can spot changes.
11591 */
11592 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11593 ASMCompilerBarrier();
11594
11595 /*
11596 * We'll rebuild most of the middle block of data members (holding the
11597 * current settings) as we go along here, so start by clearing it all.
11598 */
11599 pDbgState->bmXcptExtra = 0;
11600 pDbgState->fCpe1Extra = 0;
11601 pDbgState->fCpe1Unwanted = 0;
11602 pDbgState->fCpe2Extra = 0;
11603 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11604 pDbgState->bmExitsToCheck[i] = 0;
11605
11606 /*
11607 * Software interrupts (INT XXh) - no idea how to trigger these...
11608 */
11609 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11610 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11611 || VBOXVMM_INT_SOFTWARE_ENABLED())
11612 {
11613 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11614 }
11615
11616 /*
11617 * INT3 breakpoints - triggered by #BP exceptions.
11618 */
11619 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11620 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11621
11622 /*
11623 * Exception bitmap and XCPT events+probes.
11624 */
11625 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11626 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11627 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11628
11629 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11630 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11631 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11632 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11633 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11634 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11635 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11636 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11637 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11638 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11639 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11640 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11641 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11642 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11643 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11644 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11645 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11646 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11647
11648 if (pDbgState->bmXcptExtra)
11649 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11650
11651 /*
11652 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11653 *
11654 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11655 * So, when adding/changing/removing please don't forget to update it.
11656 *
11657 * Some of the macros are picking up local variables to save horizontal space,
11658 * (being able to see it in a table is the lesser evil here).
11659 */
11660#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11661 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11662 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11663#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11664 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11665 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11666 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11667 } else do { } while (0)
11668#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11669 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11670 { \
11671 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11672 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11673 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11674 } else do { } while (0)
11675#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11676 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11677 { \
11678 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11679 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11680 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11681 } else do { } while (0)
11682#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11683 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11684 { \
11685 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11686 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11687 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11688 } else do { } while (0)
11689
11690 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11691 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11692 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11693 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11694 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11695
11696 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11697 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11698 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11699 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11700 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11701 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11702 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11703 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11704 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11705 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11706 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11707 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11708 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11709 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11710 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11711 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11712 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11713 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11714 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11715 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11716 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11717 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11718 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11719 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11720 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11721 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11722 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11723 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11724 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11725 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11726 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11727 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11728 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11729 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11730 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11731 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11732
11733 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11734 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11735 {
11736 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11737 | CPUMCTX_EXTRN_APIC_TPR);
11738 AssertRC(rc);
11739
11740#if 0 /** @todo fix me */
11741 pDbgState->fClearCr0Mask = true;
11742 pDbgState->fClearCr4Mask = true;
11743#endif
11744 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11745 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11746 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11747 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11748 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11749 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11750 require clearing here and in the loop if we start using it. */
11751 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11752 }
11753 else
11754 {
11755 if (pDbgState->fClearCr0Mask)
11756 {
11757 pDbgState->fClearCr0Mask = false;
11758 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11759 }
11760 if (pDbgState->fClearCr4Mask)
11761 {
11762 pDbgState->fClearCr4Mask = false;
11763 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11764 }
11765 }
11766 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11767 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11768
11769 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11770 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11771 {
11772 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11773 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11774 }
11775 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11776 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11777
11778 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11779 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11780 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11781 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11782 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11783 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11784 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11785 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11786#if 0 /** @todo too slow, fix handler. */
11787 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11788#endif
11789 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11790
11791 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11792 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11793 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11794 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11795 {
11796 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11797 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11798 }
11799 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11800 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11801 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11802 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11803
11804 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11805 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11806 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11807 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11808 {
11809 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11810 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11811 }
11812 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11813 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11814 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11815 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11816
11817 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11818 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11819 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11820 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11821 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11822 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11823 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11824 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11825 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11826 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11827 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11828 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11829 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11830 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11831 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11832 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11833 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11834 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11835 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11836 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11837 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11838 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11839
11840#undef IS_EITHER_ENABLED
11841#undef SET_ONLY_XBM_IF_EITHER_EN
11842#undef SET_CPE1_XBM_IF_EITHER_EN
11843#undef SET_CPEU_XBM_IF_EITHER_EN
11844#undef SET_CPE2_XBM_IF_EITHER_EN
11845
11846 /*
11847 * Sanitize the control stuff.
11848 */
11849 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11850 if (pDbgState->fCpe2Extra)
11851 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11852 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11853 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11854 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11855 {
11856 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11857 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11858 }
11859
11860 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11861 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11862 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11863 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11864}
11865
11866
11867/**
11868 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11869 * appropriate.
11870 *
11871 * The caller has checked the VM-exit against the
11872 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11873 * already, so we don't have to do that either.
11874 *
11875 * @returns Strict VBox status code (i.e. informational status codes too).
11876 * @param pVCpu The cross context virtual CPU structure.
11877 * @param pVmxTransient The VMX-transient structure.
11878 * @param uExitReason The VM-exit reason.
11879 *
11880 * @remarks The name of this function is displayed by dtrace, so keep it short
11881 * and to the point. No longer than 33 chars long, please.
11882 */
11883static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11884{
11885 /*
11886 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11887 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11888 *
11889 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11890 * does. Must add/change/remove both places. Same ordering, please.
11891 *
11892 * Added/removed events must also be reflected in the next section
11893 * where we dispatch dtrace events.
11894 */
11895 bool fDtrace1 = false;
11896 bool fDtrace2 = false;
11897 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11898 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11899 uint32_t uEventArg = 0;
11900#define SET_EXIT(a_EventSubName) \
11901 do { \
11902 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11903 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11904 } while (0)
11905#define SET_BOTH(a_EventSubName) \
11906 do { \
11907 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11908 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11909 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11910 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11911 } while (0)
11912 switch (uExitReason)
11913 {
11914 case VMX_EXIT_MTF:
11915 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11916
11917 case VMX_EXIT_XCPT_OR_NMI:
11918 {
11919 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11920 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11921 {
11922 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11923 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11924 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11925 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11926 {
11927 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11928 {
11929 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11930 uEventArg = pVmxTransient->uExitIntErrorCode;
11931 }
11932 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11933 switch (enmEvent1)
11934 {
11935 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11936 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11937 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11938 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11939 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11940 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11941 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11942 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11943 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11944 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11945 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11946 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11947 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11948 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11949 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11950 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11951 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11952 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11953 default: break;
11954 }
11955 }
11956 else
11957 AssertFailed();
11958 break;
11959
11960 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11961 uEventArg = idxVector;
11962 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11963 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11964 break;
11965 }
11966 break;
11967 }
11968
11969 case VMX_EXIT_TRIPLE_FAULT:
11970 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11971 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11972 break;
11973 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11974 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11975 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11976 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11977 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11978
11979 /* Instruction specific VM-exits: */
11980 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11981 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11982 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11983 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11984 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11985 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11986 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11987 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
11988 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
11989 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
11990 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
11991 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
11992 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
11993 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
11994 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
11995 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
11996 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
11997 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
11998 case VMX_EXIT_MOV_CRX:
11999 hmR0VmxReadExitQualVmcs(pVmxTransient);
12000 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12001 SET_BOTH(CRX_READ);
12002 else
12003 SET_BOTH(CRX_WRITE);
12004 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12005 break;
12006 case VMX_EXIT_MOV_DRX:
12007 hmR0VmxReadExitQualVmcs(pVmxTransient);
12008 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12009 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12010 SET_BOTH(DRX_READ);
12011 else
12012 SET_BOTH(DRX_WRITE);
12013 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12014 break;
12015 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12016 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12017 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12018 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12019 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12020 case VMX_EXIT_GDTR_IDTR_ACCESS:
12021 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12022 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12023 {
12024 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12025 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12026 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12027 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12028 }
12029 break;
12030
12031 case VMX_EXIT_LDTR_TR_ACCESS:
12032 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12033 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12034 {
12035 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12036 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12037 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12038 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12039 }
12040 break;
12041
12042 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12043 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12044 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12045 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12046 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12047 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12048 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12049 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12050 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12051 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12052 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12053
12054 /* Events that aren't relevant at this point. */
12055 case VMX_EXIT_EXT_INT:
12056 case VMX_EXIT_INT_WINDOW:
12057 case VMX_EXIT_NMI_WINDOW:
12058 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12059 case VMX_EXIT_PREEMPT_TIMER:
12060 case VMX_EXIT_IO_INSTR:
12061 break;
12062
12063 /* Errors and unexpected events. */
12064 case VMX_EXIT_INIT_SIGNAL:
12065 case VMX_EXIT_SIPI:
12066 case VMX_EXIT_IO_SMI:
12067 case VMX_EXIT_SMI:
12068 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12069 case VMX_EXIT_ERR_MSR_LOAD:
12070 case VMX_EXIT_ERR_MACHINE_CHECK:
12071 case VMX_EXIT_PML_FULL:
12072 case VMX_EXIT_VIRTUALIZED_EOI:
12073 break;
12074
12075 default:
12076 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12077 break;
12078 }
12079#undef SET_BOTH
12080#undef SET_EXIT
12081
12082 /*
12083 * Dtrace tracepoints go first. We do them here at once so we don't
12084 * have to copy the guest state saving and stuff a few dozen times.
12085 * Down side is that we've got to repeat the switch, though this time
12086 * we use enmEvent since the probes are a subset of what DBGF does.
12087 */
12088 if (fDtrace1 || fDtrace2)
12089 {
12090 hmR0VmxReadExitQualVmcs(pVmxTransient);
12091 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12092 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12093 switch (enmEvent1)
12094 {
12095 /** @todo consider which extra parameters would be helpful for each probe. */
12096 case DBGFEVENT_END: break;
12097 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12098 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12099 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12100 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12101 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12102 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12103 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12104 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12105 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12106 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12107 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12108 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12109 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12110 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12111 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12112 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12113 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12114 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12115 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12116 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12117 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12118 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12119 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12120 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12121 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12122 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12123 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12124 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12125 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12126 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12127 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12128 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12129 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12130 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12131 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12132 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12133 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12134 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12135 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12136 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12137 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12138 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12139 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12140 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12141 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12142 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12143 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12144 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12145 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12146 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12147 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12148 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12149 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12150 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12151 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12152 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12153 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12154 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12155 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12156 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12157 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12158 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12159 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12160 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12161 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12162 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12163 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12164 }
12165 switch (enmEvent2)
12166 {
12167 /** @todo consider which extra parameters would be helpful for each probe. */
12168 case DBGFEVENT_END: break;
12169 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12170 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12171 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12172 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12173 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12174 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12175 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12176 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12177 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12178 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12179 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12180 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12181 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12182 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12183 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12184 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12185 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12186 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12187 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12188 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12189 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12190 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12191 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12192 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12193 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12194 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12195 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12196 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12197 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12198 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12199 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12200 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12201 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12202 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12203 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12204 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12205 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12206 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12207 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12208 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12209 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12210 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12211 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12212 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12213 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12214 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12215 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12216 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12217 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12218 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12219 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12220 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12221 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12222 }
12223 }
12224
12225 /*
12226 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12227 * the DBGF call will do a full check).
12228 *
12229 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12230 * Note! If we have to events, we prioritize the first, i.e. the instruction
12231 * one, in order to avoid event nesting.
12232 */
12233 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
12234 if ( enmEvent1 != DBGFEVENT_END
12235 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12236 {
12237 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12238 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12239 if (rcStrict != VINF_SUCCESS)
12240 return rcStrict;
12241 }
12242 else if ( enmEvent2 != DBGFEVENT_END
12243 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12244 {
12245 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12246 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12247 if (rcStrict != VINF_SUCCESS)
12248 return rcStrict;
12249 }
12250
12251 return VINF_SUCCESS;
12252}
12253
12254
12255/**
12256 * Single-stepping VM-exit filtering.
12257 *
12258 * This is preprocessing the VM-exits and deciding whether we've gotten far
12259 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12260 * handling is performed.
12261 *
12262 * @returns Strict VBox status code (i.e. informational status codes too).
12263 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12264 * @param pVmxTransient The VMX-transient structure.
12265 * @param pDbgState The debug state.
12266 */
12267DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12268{
12269 /*
12270 * Expensive (saves context) generic dtrace VM-exit probe.
12271 */
12272 uint32_t const uExitReason = pVmxTransient->uExitReason;
12273 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12274 { /* more likely */ }
12275 else
12276 {
12277 hmR0VmxReadExitQualVmcs(pVmxTransient);
12278 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12279 AssertRC(rc);
12280 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12281 }
12282
12283 /*
12284 * Check for host NMI, just to get that out of the way.
12285 */
12286 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12287 { /* normally likely */ }
12288 else
12289 {
12290 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12291 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12292 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12293 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12294 }
12295
12296 /*
12297 * Check for single stepping event if we're stepping.
12298 */
12299 if (pVCpu->hm.s.fSingleInstruction)
12300 {
12301 switch (uExitReason)
12302 {
12303 case VMX_EXIT_MTF:
12304 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12305
12306 /* Various events: */
12307 case VMX_EXIT_XCPT_OR_NMI:
12308 case VMX_EXIT_EXT_INT:
12309 case VMX_EXIT_TRIPLE_FAULT:
12310 case VMX_EXIT_INT_WINDOW:
12311 case VMX_EXIT_NMI_WINDOW:
12312 case VMX_EXIT_TASK_SWITCH:
12313 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12314 case VMX_EXIT_APIC_ACCESS:
12315 case VMX_EXIT_EPT_VIOLATION:
12316 case VMX_EXIT_EPT_MISCONFIG:
12317 case VMX_EXIT_PREEMPT_TIMER:
12318
12319 /* Instruction specific VM-exits: */
12320 case VMX_EXIT_CPUID:
12321 case VMX_EXIT_GETSEC:
12322 case VMX_EXIT_HLT:
12323 case VMX_EXIT_INVD:
12324 case VMX_EXIT_INVLPG:
12325 case VMX_EXIT_RDPMC:
12326 case VMX_EXIT_RDTSC:
12327 case VMX_EXIT_RSM:
12328 case VMX_EXIT_VMCALL:
12329 case VMX_EXIT_VMCLEAR:
12330 case VMX_EXIT_VMLAUNCH:
12331 case VMX_EXIT_VMPTRLD:
12332 case VMX_EXIT_VMPTRST:
12333 case VMX_EXIT_VMREAD:
12334 case VMX_EXIT_VMRESUME:
12335 case VMX_EXIT_VMWRITE:
12336 case VMX_EXIT_VMXOFF:
12337 case VMX_EXIT_VMXON:
12338 case VMX_EXIT_MOV_CRX:
12339 case VMX_EXIT_MOV_DRX:
12340 case VMX_EXIT_IO_INSTR:
12341 case VMX_EXIT_RDMSR:
12342 case VMX_EXIT_WRMSR:
12343 case VMX_EXIT_MWAIT:
12344 case VMX_EXIT_MONITOR:
12345 case VMX_EXIT_PAUSE:
12346 case VMX_EXIT_GDTR_IDTR_ACCESS:
12347 case VMX_EXIT_LDTR_TR_ACCESS:
12348 case VMX_EXIT_INVEPT:
12349 case VMX_EXIT_RDTSCP:
12350 case VMX_EXIT_INVVPID:
12351 case VMX_EXIT_WBINVD:
12352 case VMX_EXIT_XSETBV:
12353 case VMX_EXIT_RDRAND:
12354 case VMX_EXIT_INVPCID:
12355 case VMX_EXIT_VMFUNC:
12356 case VMX_EXIT_RDSEED:
12357 case VMX_EXIT_XSAVES:
12358 case VMX_EXIT_XRSTORS:
12359 {
12360 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12361 AssertRCReturn(rc, rc);
12362 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12363 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12364 return VINF_EM_DBG_STEPPED;
12365 break;
12366 }
12367
12368 /* Errors and unexpected events: */
12369 case VMX_EXIT_INIT_SIGNAL:
12370 case VMX_EXIT_SIPI:
12371 case VMX_EXIT_IO_SMI:
12372 case VMX_EXIT_SMI:
12373 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12374 case VMX_EXIT_ERR_MSR_LOAD:
12375 case VMX_EXIT_ERR_MACHINE_CHECK:
12376 case VMX_EXIT_PML_FULL:
12377 case VMX_EXIT_VIRTUALIZED_EOI:
12378 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12379 break;
12380
12381 default:
12382 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12383 break;
12384 }
12385 }
12386
12387 /*
12388 * Check for debugger event breakpoints and dtrace probes.
12389 */
12390 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12391 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12392 {
12393 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12394 if (rcStrict != VINF_SUCCESS)
12395 return rcStrict;
12396 }
12397
12398 /*
12399 * Normal processing.
12400 */
12401#ifdef HMVMX_USE_FUNCTION_TABLE
12402 return g_aVMExitHandlers[uExitReason].pfn(pVCpu, pVmxTransient);
12403#else
12404 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12405#endif
12406}
12407
12408
12409/**
12410 * Single steps guest code using hardware-assisted VMX.
12411 *
12412 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12413 * but single-stepping through the hypervisor debugger.
12414 *
12415 * @returns Strict VBox status code (i.e. informational status codes too).
12416 * @param pVCpu The cross context virtual CPU structure.
12417 * @param pcLoops Pointer to the number of executed loops.
12418 *
12419 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12420 */
12421static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12422{
12423 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12424 Assert(pcLoops);
12425 Assert(*pcLoops <= cMaxResumeLoops);
12426
12427 VMXTRANSIENT VmxTransient;
12428 RT_ZERO(VmxTransient);
12429 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12430
12431 /* Set HMCPU indicators. */
12432 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12433 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12434 pVCpu->hm.s.fDebugWantRdTscExit = false;
12435 pVCpu->hm.s.fUsingDebugLoop = true;
12436
12437 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12438 VMXRUNDBGSTATE DbgState;
12439 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12440 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12441
12442 /*
12443 * The loop.
12444 */
12445 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12446 for (;;)
12447 {
12448 Assert(!HMR0SuspendPending());
12449 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12450 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12451 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12452
12453 /* Set up VM-execution controls the next two can respond to. */
12454 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12455
12456 /*
12457 * Preparatory work for running guest code, this may force us to
12458 * return to ring-3.
12459 *
12460 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12461 */
12462 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12463 if (rcStrict != VINF_SUCCESS)
12464 break;
12465
12466 /* Interrupts are disabled at this point! */
12467 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12468
12469 /* Override any obnoxious code in the above two calls. */
12470 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12471
12472 /*
12473 * Finally execute the guest.
12474 */
12475 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12476
12477 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12478 /* Interrupts are re-enabled at this point! */
12479
12480 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12481 if (RT_SUCCESS(rcRun))
12482 { /* very likely */ }
12483 else
12484 {
12485 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12486 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12487 return rcRun;
12488 }
12489
12490 /* Profile the VM-exit. */
12491 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12492 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12493 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12494 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12495 HMVMX_START_EXIT_DISPATCH_PROF();
12496
12497 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12498
12499 /*
12500 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12501 */
12502 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12503 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12504 if (rcStrict != VINF_SUCCESS)
12505 break;
12506 if (++(*pcLoops) > cMaxResumeLoops)
12507 {
12508 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12509 rcStrict = VINF_EM_RAW_INTERRUPT;
12510 break;
12511 }
12512
12513 /*
12514 * Stepping: Did the RIP change, if so, consider it a single step.
12515 * Otherwise, make sure one of the TFs gets set.
12516 */
12517 if (fStepping)
12518 {
12519 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12520 AssertRC(rc);
12521 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12522 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12523 {
12524 rcStrict = VINF_EM_DBG_STEPPED;
12525 break;
12526 }
12527 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12528 }
12529
12530 /*
12531 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12532 */
12533 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12534 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12535
12536 /* Restore all controls applied by hmR0VmxPreRunGuestDebugStateApply above. */
12537 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12538 Assert(rcStrict == VINF_SUCCESS);
12539 }
12540
12541 /*
12542 * Clear the X86_EFL_TF if necessary.
12543 */
12544 if (pVCpu->hm.s.fClearTrapFlag)
12545 {
12546 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12547 AssertRC(rc);
12548 pVCpu->hm.s.fClearTrapFlag = false;
12549 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12550 }
12551 /** @todo there seems to be issues with the resume flag when the monitor trap
12552 * flag is pending without being used. Seen early in bios init when
12553 * accessing APIC page in protected mode. */
12554
12555 /* Restore HMCPU indicators. */
12556 pVCpu->hm.s.fUsingDebugLoop = false;
12557 pVCpu->hm.s.fDebugWantRdTscExit = false;
12558 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12559
12560 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12561 return rcStrict;
12562}
12563
12564
12565/** @} */
12566
12567
12568/**
12569 * Checks if any expensive dtrace probes are enabled and we should go to the
12570 * debug loop.
12571 *
12572 * @returns true if we should use debug loop, false if not.
12573 */
12574static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12575{
12576 /* It's probably faster to OR the raw 32-bit counter variables together.
12577 Since the variables are in an array and the probes are next to one
12578 another (more or less), we have good locality. So, better read
12579 eight-nine cache lines ever time and only have one conditional, than
12580 128+ conditionals, right? */
12581 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12582 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12583 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12584 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12585 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12586 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12587 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12588 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12589 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12590 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12591 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12592 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12593 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12594 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12595 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12596 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12597 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12598 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12599 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12600 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12601 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12602 ) != 0
12603 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12604 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12605 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12606 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12607 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12608 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12609 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12610 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12611 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12612 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12613 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12614 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12615 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12616 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12617 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12618 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12619 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12620 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12621 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12622 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12623 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12624 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12625 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12626 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12627 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12628 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12629 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12630 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12631 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12632 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12633 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12634 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12635 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12636 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12637 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12638 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12639 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12640 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12641 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12642 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12643 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12644 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12645 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12646 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12647 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12648 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12649 ) != 0
12650 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12651 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12652 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12653 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12654 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12655 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12656 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12657 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12658 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12659 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12660 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12661 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12662 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12663 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12664 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12665 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12666 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12667 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12668 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12669 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12670 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12671 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12672 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12673 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12674 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12675 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12676 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12677 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12678 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12679 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12680 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12681 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12682 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12683 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12684 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12685 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12686 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12687 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12688 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12689 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12690 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12691 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12692 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12693 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12694 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12695 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12696 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12697 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12698 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12699 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12700 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12701 ) != 0;
12702}
12703
12704
12705/**
12706 * Runs the guest using hardware-assisted VMX.
12707 *
12708 * @returns Strict VBox status code (i.e. informational status codes too).
12709 * @param pVCpu The cross context virtual CPU structure.
12710 */
12711VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12712{
12713 AssertPtr(pVCpu);
12714 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12715 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12716 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12717 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12718
12719 VBOXSTRICTRC rcStrict;
12720 uint32_t cLoops = 0;
12721 for (;;)
12722 {
12723#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12724 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12725#else
12726 NOREF(pCtx);
12727 bool const fInNestedGuestMode = false;
12728#endif
12729 if (!fInNestedGuestMode)
12730 {
12731 if ( !pVCpu->hm.s.fUseDebugLoop
12732 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12733 && !DBGFIsStepping(pVCpu)
12734 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12735 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12736 else
12737 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12738 }
12739#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12740 else
12741 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12742
12743 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12744 {
12745 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12746 continue;
12747 }
12748 if (rcStrict == VINF_VMX_VMEXIT)
12749 {
12750 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12751 continue;
12752 }
12753#endif
12754 break;
12755 }
12756
12757 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12758 switch (rcLoop)
12759 {
12760 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12761 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12762 }
12763
12764 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12765 if (RT_FAILURE(rc2))
12766 {
12767 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12768 rcStrict = rc2;
12769 }
12770 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12771 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12772 return rcStrict;
12773}
12774
12775
12776#ifndef HMVMX_USE_FUNCTION_TABLE
12777/**
12778 * Handles a guest VM-exit from hardware-assisted VMX execution.
12779 *
12780 * @returns Strict VBox status code (i.e. informational status codes too).
12781 * @param pVCpu The cross context virtual CPU structure.
12782 * @param pVmxTransient The VMX-transient structure.
12783 */
12784DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12785{
12786#ifdef DEBUG_ramshankar
12787# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12788 do { \
12789 if (a_fSave != 0) \
12790 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12791 VBOXSTRICTRC rcStrict = a_CallExpr; \
12792 if (a_fSave != 0) \
12793 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12794 return rcStrict; \
12795 } while (0)
12796#else
12797# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12798#endif
12799 uint32_t const uExitReason = pVmxTransient->uExitReason;
12800 switch (uExitReason)
12801 {
12802 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12803 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12804 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12805 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12806 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12807 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12808 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12809 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12810 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12811 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12812 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12813 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12814 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12815 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12816 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12817 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12818 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12819 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12820 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12821 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12822 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12823 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12824 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12825 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12826 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12827 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12828 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12829 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12830 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12831 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12832#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12833 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12834 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12835 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12836 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12837 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12838 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12839 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12840 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12841 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12842 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12843 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12844#else
12845 case VMX_EXIT_VMCLEAR:
12846 case VMX_EXIT_VMLAUNCH:
12847 case VMX_EXIT_VMPTRLD:
12848 case VMX_EXIT_VMPTRST:
12849 case VMX_EXIT_VMREAD:
12850 case VMX_EXIT_VMRESUME:
12851 case VMX_EXIT_VMWRITE:
12852 case VMX_EXIT_VMXOFF:
12853 case VMX_EXIT_VMXON:
12854 case VMX_EXIT_INVVPID:
12855 case VMX_EXIT_INVEPT:
12856 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12857#endif
12858
12859 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12860 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12861 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12862
12863 case VMX_EXIT_INIT_SIGNAL:
12864 case VMX_EXIT_SIPI:
12865 case VMX_EXIT_IO_SMI:
12866 case VMX_EXIT_SMI:
12867 case VMX_EXIT_ERR_MSR_LOAD:
12868 case VMX_EXIT_ERR_MACHINE_CHECK:
12869 case VMX_EXIT_PML_FULL:
12870 case VMX_EXIT_VIRTUALIZED_EOI:
12871 case VMX_EXIT_GDTR_IDTR_ACCESS:
12872 case VMX_EXIT_LDTR_TR_ACCESS:
12873 case VMX_EXIT_APIC_WRITE:
12874 case VMX_EXIT_RDRAND:
12875 case VMX_EXIT_RSM:
12876 case VMX_EXIT_VMFUNC:
12877 case VMX_EXIT_ENCLS:
12878 case VMX_EXIT_RDSEED:
12879 case VMX_EXIT_XSAVES:
12880 case VMX_EXIT_XRSTORS:
12881 case VMX_EXIT_UMWAIT:
12882 case VMX_EXIT_TPAUSE:
12883 default:
12884 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12885 }
12886#undef VMEXIT_CALL_RET
12887}
12888#endif /* !HMVMX_USE_FUNCTION_TABLE */
12889
12890
12891#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12892/**
12893 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12894 *
12895 * @returns Strict VBox status code (i.e. informational status codes too).
12896 * @param pVCpu The cross context virtual CPU structure.
12897 * @param pVmxTransient The VMX-transient structure.
12898 */
12899DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12900{
12901 uint32_t const uExitReason = pVmxTransient->uExitReason;
12902 switch (uExitReason)
12903 {
12904 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
12905 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
12906 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
12907 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
12908 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
12909
12910 /*
12911 * We shouldn't direct host physical interrupts to the nested-guest.
12912 */
12913 case VMX_EXIT_EXT_INT:
12914 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
12915
12916 /*
12917 * Instructions that cause VM-exits unconditionally or the condition is
12918 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12919 * happens, it's guaranteed to be a nested-guest VM-exit).
12920 *
12921 * - Provides VM-exit instruction length ONLY.
12922 */
12923 case VMX_EXIT_CPUID: /* Unconditional. */
12924 case VMX_EXIT_VMCALL:
12925 case VMX_EXIT_GETSEC:
12926 case VMX_EXIT_INVD:
12927 case VMX_EXIT_XSETBV:
12928 case VMX_EXIT_VMLAUNCH:
12929 case VMX_EXIT_VMRESUME:
12930 case VMX_EXIT_VMXOFF:
12931 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
12932 case VMX_EXIT_VMFUNC:
12933 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
12934
12935 /*
12936 * Instructions that cause VM-exits unconditionally or the condition is
12937 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12938 * happens, it's guaranteed to be a nested-guest VM-exit).
12939 *
12940 * - Provides VM-exit instruction length.
12941 * - Provides VM-exit information.
12942 * - Optionally provides Exit qualification.
12943 *
12944 * Since Exit qualification is 0 for all VM-exits where it is not
12945 * applicable, reading and passing it to the guest should produce
12946 * defined behavior.
12947 *
12948 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
12949 */
12950 case VMX_EXIT_INVEPT: /* Unconditional. */
12951 case VMX_EXIT_INVVPID:
12952 case VMX_EXIT_VMCLEAR:
12953 case VMX_EXIT_VMPTRLD:
12954 case VMX_EXIT_VMPTRST:
12955 case VMX_EXIT_VMXON:
12956 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
12957 case VMX_EXIT_LDTR_TR_ACCESS:
12958 case VMX_EXIT_RDRAND:
12959 case VMX_EXIT_RDSEED:
12960 case VMX_EXIT_XSAVES:
12961 case VMX_EXIT_XRSTORS:
12962 case VMX_EXIT_UMWAIT:
12963 case VMX_EXIT_TPAUSE:
12964 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
12965
12966 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
12967 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
12968 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
12969 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
12970 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
12971 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
12972 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
12973 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
12974 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
12975 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
12976 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
12977 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
12978 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
12979 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
12980 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
12981 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
12982 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
12983 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
12984 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
12985
12986 case VMX_EXIT_PREEMPT_TIMER:
12987 {
12988 /** @todo NSTVMX: Preempt timer. */
12989 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
12990 }
12991
12992 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
12993 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
12994
12995 case VMX_EXIT_VMREAD:
12996 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
12997
12998 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
12999 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13000
13001 case VMX_EXIT_INIT_SIGNAL:
13002 case VMX_EXIT_SIPI:
13003 case VMX_EXIT_IO_SMI:
13004 case VMX_EXIT_SMI:
13005 case VMX_EXIT_ERR_MSR_LOAD:
13006 case VMX_EXIT_ERR_MACHINE_CHECK:
13007 case VMX_EXIT_PML_FULL:
13008 case VMX_EXIT_RSM:
13009 default:
13010 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13011 }
13012}
13013#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13014
13015
13016/** @name VM-exit helpers.
13017 * @{
13018 */
13019/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13020/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13021/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13022
13023/** Macro for VM-exits called unexpectedly. */
13024#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13025 do { \
13026 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13027 return VERR_VMX_UNEXPECTED_EXIT; \
13028 } while (0)
13029
13030#ifdef VBOX_STRICT
13031/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13032# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13033 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13034
13035# define HMVMX_ASSERT_PREEMPT_CPUID() \
13036 do { \
13037 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13038 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13039 } while (0)
13040
13041# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13042 do { \
13043 AssertPtr((a_pVCpu)); \
13044 AssertPtr((a_pVmxTransient)); \
13045 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13046 Assert((a_pVmxTransient)->pVmcsInfo); \
13047 Assert(ASMIntAreEnabled()); \
13048 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13049 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13050 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13051 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13052 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13053 HMVMX_ASSERT_PREEMPT_CPUID(); \
13054 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13055 } while (0)
13056
13057# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13058 do { \
13059 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13060 Assert((a_pVmxTransient)->fIsNestedGuest); \
13061 } while (0)
13062
13063# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13064 do { \
13065 Log4Func(("\n")); \
13066 } while (0)
13067#else
13068# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13069 do { \
13070 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13071 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13072 } while (0)
13073
13074# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13075 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13076
13077# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13078#endif
13079
13080#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13081/** Macro that does the necessary privilege checks and intercepted VM-exits for
13082 * guests that attempted to execute a VMX instruction. */
13083# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13084 do \
13085 { \
13086 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13087 if (rcStrictTmp == VINF_SUCCESS) \
13088 { /* likely */ } \
13089 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13090 { \
13091 Assert((a_pVCpu)->hm.s.Event.fPending); \
13092 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13093 return VINF_SUCCESS; \
13094 } \
13095 else \
13096 { \
13097 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13098 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13099 } \
13100 } while (0)
13101
13102/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13103# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13104 do \
13105 { \
13106 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13107 (a_pGCPtrEffAddr)); \
13108 if (rcStrictTmp == VINF_SUCCESS) \
13109 { /* likely */ } \
13110 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13111 { \
13112 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13113 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13114 NOREF(uXcptTmp); \
13115 return VINF_SUCCESS; \
13116 } \
13117 else \
13118 { \
13119 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13120 return rcStrictTmp; \
13121 } \
13122 } while (0)
13123#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13124
13125
13126/**
13127 * Advances the guest RIP by the specified number of bytes.
13128 *
13129 * @param pVCpu The cross context virtual CPU structure.
13130 * @param cbInstr Number of bytes to advance the RIP by.
13131 *
13132 * @remarks No-long-jump zone!!!
13133 */
13134DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
13135{
13136 /* Advance the RIP. */
13137 pVCpu->cpum.GstCtx.rip += cbInstr;
13138 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13139
13140 /* Update interrupt inhibition. */
13141 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13142 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13143 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13144}
13145
13146
13147/**
13148 * Advances the guest RIP after reading it from the VMCS.
13149 *
13150 * @returns VBox status code, no informational status codes.
13151 * @param pVCpu The cross context virtual CPU structure.
13152 * @param pVmxTransient The VMX-transient structure.
13153 *
13154 * @remarks No-long-jump zone!!!
13155 */
13156static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13157{
13158 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13159 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13160 AssertRCReturn(rc, rc);
13161
13162 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
13163 return VINF_SUCCESS;
13164}
13165
13166
13167/**
13168 * Handle a condition that occurred while delivering an event through the guest or
13169 * nested-guest IDT.
13170 *
13171 * @returns Strict VBox status code (i.e. informational status codes too).
13172 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13173 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13174 * to continue execution of the guest which will delivery the \#DF.
13175 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13176 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13177 *
13178 * @param pVCpu The cross context virtual CPU structure.
13179 * @param pVmxTransient The VMX-transient structure.
13180 *
13181 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13182 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13183 * is due to an EPT violation, PML full or SPP-related event.
13184 *
13185 * @remarks No-long-jump zone!!!
13186 */
13187static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13188{
13189 Assert(!pVCpu->hm.s.Event.fPending);
13190 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13191 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13192 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13193 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13194 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13195
13196 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13197 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13198 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13199 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13200 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13201 {
13202 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13203 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13204
13205 /*
13206 * If the event was a software interrupt (generated with INT n) or a software exception
13207 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13208 * can handle the VM-exit and continue guest execution which will re-execute the
13209 * instruction rather than re-injecting the exception, as that can cause premature
13210 * trips to ring-3 before injection and involve TRPM which currently has no way of
13211 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13212 * the problem).
13213 */
13214 IEMXCPTRAISE enmRaise;
13215 IEMXCPTRAISEINFO fRaiseInfo;
13216 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13217 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13218 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13219 {
13220 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13221 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13222 }
13223 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13224 {
13225 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13226 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13227 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13228
13229 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13230 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13231
13232 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13233
13234 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13235 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13236 {
13237 pVmxTransient->fVectoringPF = true;
13238 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13239 }
13240 }
13241 else
13242 {
13243 /*
13244 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13245 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13246 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13247 */
13248 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13249 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13250 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13251 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13252 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13253 }
13254
13255 /*
13256 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13257 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13258 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13259 * subsequent VM-entry would fail, see @bugref{7445}.
13260 *
13261 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13262 */
13263 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13264 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13265 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13266 && CPUMIsGuestNmiBlocking(pVCpu))
13267 {
13268 CPUMSetGuestNmiBlocking(pVCpu, false);
13269 }
13270
13271 switch (enmRaise)
13272 {
13273 case IEMXCPTRAISE_CURRENT_XCPT:
13274 {
13275 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13276 Assert(rcStrict == VINF_SUCCESS);
13277 break;
13278 }
13279
13280 case IEMXCPTRAISE_PREV_EVENT:
13281 {
13282 uint32_t u32ErrCode;
13283 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13284 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13285 else
13286 u32ErrCode = 0;
13287
13288 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13289 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13290 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13291 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13292
13293 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13294 pVCpu->hm.s.Event.u32ErrCode));
13295 Assert(rcStrict == VINF_SUCCESS);
13296 break;
13297 }
13298
13299 case IEMXCPTRAISE_REEXEC_INSTR:
13300 Assert(rcStrict == VINF_SUCCESS);
13301 break;
13302
13303 case IEMXCPTRAISE_DOUBLE_FAULT:
13304 {
13305 /*
13306 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13307 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13308 */
13309 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13310 {
13311 pVmxTransient->fVectoringDoublePF = true;
13312 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13313 pVCpu->cpum.GstCtx.cr2));
13314 rcStrict = VINF_SUCCESS;
13315 }
13316 else
13317 {
13318 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13319 hmR0VmxSetPendingXcptDF(pVCpu);
13320 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13321 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13322 rcStrict = VINF_HM_DOUBLE_FAULT;
13323 }
13324 break;
13325 }
13326
13327 case IEMXCPTRAISE_TRIPLE_FAULT:
13328 {
13329 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13330 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13331 rcStrict = VINF_EM_RESET;
13332 break;
13333 }
13334
13335 case IEMXCPTRAISE_CPU_HANG:
13336 {
13337 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13338 rcStrict = VERR_EM_GUEST_CPU_HANG;
13339 break;
13340 }
13341
13342 default:
13343 {
13344 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13345 rcStrict = VERR_VMX_IPE_2;
13346 break;
13347 }
13348 }
13349 }
13350 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13351 && !CPUMIsGuestNmiBlocking(pVCpu))
13352 {
13353 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13354 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13355 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13356 {
13357 /*
13358 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13359 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13360 * that virtual NMIs remain blocked until the IRET execution is completed.
13361 *
13362 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13363 */
13364 CPUMSetGuestNmiBlocking(pVCpu, true);
13365 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13366 }
13367 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13368 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13369 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13370 {
13371 /*
13372 * Execution of IRET caused an EPT violation, page-modification log-full event or
13373 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13374 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13375 * that virtual NMIs remain blocked until the IRET execution is completed.
13376 *
13377 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13378 */
13379 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13380 {
13381 CPUMSetGuestNmiBlocking(pVCpu, true);
13382 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13383 }
13384 }
13385 }
13386
13387 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13388 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13389 return rcStrict;
13390}
13391
13392
13393#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13394/**
13395 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13396 * guest attempting to execute a VMX instruction.
13397 *
13398 * @returns Strict VBox status code (i.e. informational status codes too).
13399 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13400 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13401 *
13402 * @param pVCpu The cross context virtual CPU structure.
13403 * @param uExitReason The VM-exit reason.
13404 *
13405 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13406 * @remarks No-long-jump zone!!!
13407 */
13408static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13409{
13410 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13411 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13412
13413 /*
13414 * The physical CPU would have already checked the CPU mode/code segment.
13415 * We shall just assert here for paranoia.
13416 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13417 */
13418 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13419 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13420 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13421
13422 if (uExitReason == VMX_EXIT_VMXON)
13423 {
13424 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13425
13426 /*
13427 * We check CR4.VMXE because it is required to be always set while in VMX operation
13428 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13429 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13430 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13431 */
13432 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13433 {
13434 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13435 hmR0VmxSetPendingXcptUD(pVCpu);
13436 return VINF_HM_PENDING_XCPT;
13437 }
13438 }
13439 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13440 {
13441 /*
13442 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13443 * (other than VMXON), we need to raise a #UD.
13444 */
13445 Log4Func(("Not in VMX root mode -> #UD\n"));
13446 hmR0VmxSetPendingXcptUD(pVCpu);
13447 return VINF_HM_PENDING_XCPT;
13448 }
13449
13450 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13451 return VINF_SUCCESS;
13452}
13453
13454
13455/**
13456 * Decodes the memory operand of an instruction that caused a VM-exit.
13457 *
13458 * The Exit qualification field provides the displacement field for memory
13459 * operand instructions, if any.
13460 *
13461 * @returns Strict VBox status code (i.e. informational status codes too).
13462 * @retval VINF_SUCCESS if the operand was successfully decoded.
13463 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13464 * operand.
13465 * @param pVCpu The cross context virtual CPU structure.
13466 * @param uExitInstrInfo The VM-exit instruction information field.
13467 * @param enmMemAccess The memory operand's access type (read or write).
13468 * @param GCPtrDisp The instruction displacement field, if any. For
13469 * RIP-relative addressing pass RIP + displacement here.
13470 * @param pGCPtrMem Where to store the effective destination memory address.
13471 *
13472 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13473 * virtual-8086 mode hence skips those checks while verifying if the
13474 * segment is valid.
13475 */
13476static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13477 PRTGCPTR pGCPtrMem)
13478{
13479 Assert(pGCPtrMem);
13480 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13481 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13482 | CPUMCTX_EXTRN_CR0);
13483
13484 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13485 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13486 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13487
13488 VMXEXITINSTRINFO ExitInstrInfo;
13489 ExitInstrInfo.u = uExitInstrInfo;
13490 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13491 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13492 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13493 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13494 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13495 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13496 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13497 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13498 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13499
13500 /*
13501 * Validate instruction information.
13502 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13503 */
13504 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13505 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13506 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13507 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13508 AssertLogRelMsgReturn(fIsMemOperand,
13509 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13510
13511 /*
13512 * Compute the complete effective address.
13513 *
13514 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13515 * See AMD spec. 4.5.2 "Segment Registers".
13516 */
13517 RTGCPTR GCPtrMem = GCPtrDisp;
13518 if (fBaseRegValid)
13519 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13520 if (fIdxRegValid)
13521 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13522
13523 RTGCPTR const GCPtrOff = GCPtrMem;
13524 if ( !fIsLongMode
13525 || iSegReg >= X86_SREG_FS)
13526 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13527 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13528
13529 /*
13530 * Validate effective address.
13531 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13532 */
13533 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13534 Assert(cbAccess > 0);
13535 if (fIsLongMode)
13536 {
13537 if (X86_IS_CANONICAL(GCPtrMem))
13538 {
13539 *pGCPtrMem = GCPtrMem;
13540 return VINF_SUCCESS;
13541 }
13542
13543 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13544 * "Data Limit Checks in 64-bit Mode". */
13545 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13546 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13547 return VINF_HM_PENDING_XCPT;
13548 }
13549
13550 /*
13551 * This is a watered down version of iemMemApplySegment().
13552 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13553 * and segment CPL/DPL checks are skipped.
13554 */
13555 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13556 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13557 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13558
13559 /* Check if the segment is present and usable. */
13560 if ( pSel->Attr.n.u1Present
13561 && !pSel->Attr.n.u1Unusable)
13562 {
13563 Assert(pSel->Attr.n.u1DescType);
13564 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13565 {
13566 /* Check permissions for the data segment. */
13567 if ( enmMemAccess == VMXMEMACCESS_WRITE
13568 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13569 {
13570 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13571 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13572 return VINF_HM_PENDING_XCPT;
13573 }
13574
13575 /* Check limits if it's a normal data segment. */
13576 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13577 {
13578 if ( GCPtrFirst32 > pSel->u32Limit
13579 || GCPtrLast32 > pSel->u32Limit)
13580 {
13581 Log4Func(("Data segment limit exceeded. "
13582 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13583 GCPtrLast32, pSel->u32Limit));
13584 if (iSegReg == X86_SREG_SS)
13585 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13586 else
13587 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13588 return VINF_HM_PENDING_XCPT;
13589 }
13590 }
13591 else
13592 {
13593 /* Check limits if it's an expand-down data segment.
13594 Note! The upper boundary is defined by the B bit, not the G bit! */
13595 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13596 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13597 {
13598 Log4Func(("Expand-down data segment limit exceeded. "
13599 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13600 GCPtrLast32, pSel->u32Limit));
13601 if (iSegReg == X86_SREG_SS)
13602 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13603 else
13604 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13605 return VINF_HM_PENDING_XCPT;
13606 }
13607 }
13608 }
13609 else
13610 {
13611 /* Check permissions for the code segment. */
13612 if ( enmMemAccess == VMXMEMACCESS_WRITE
13613 || ( enmMemAccess == VMXMEMACCESS_READ
13614 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13615 {
13616 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13617 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13618 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13619 return VINF_HM_PENDING_XCPT;
13620 }
13621
13622 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13623 if ( GCPtrFirst32 > pSel->u32Limit
13624 || GCPtrLast32 > pSel->u32Limit)
13625 {
13626 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13627 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13628 if (iSegReg == X86_SREG_SS)
13629 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13630 else
13631 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13632 return VINF_HM_PENDING_XCPT;
13633 }
13634 }
13635 }
13636 else
13637 {
13638 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13639 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13640 return VINF_HM_PENDING_XCPT;
13641 }
13642
13643 *pGCPtrMem = GCPtrMem;
13644 return VINF_SUCCESS;
13645}
13646#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13647
13648
13649/**
13650 * VM-exit helper for LMSW.
13651 */
13652static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13653{
13654 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13655 AssertRCReturn(rc, rc);
13656
13657 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13658 AssertMsg( rcStrict == VINF_SUCCESS
13659 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13660
13661 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13662 if (rcStrict == VINF_IEM_RAISED_XCPT)
13663 {
13664 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13665 rcStrict = VINF_SUCCESS;
13666 }
13667
13668 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13669 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13670 return rcStrict;
13671}
13672
13673
13674/**
13675 * VM-exit helper for CLTS.
13676 */
13677static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13678{
13679 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13680 AssertRCReturn(rc, rc);
13681
13682 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13683 AssertMsg( rcStrict == VINF_SUCCESS
13684 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13685
13686 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13687 if (rcStrict == VINF_IEM_RAISED_XCPT)
13688 {
13689 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13690 rcStrict = VINF_SUCCESS;
13691 }
13692
13693 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13694 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13695 return rcStrict;
13696}
13697
13698
13699/**
13700 * VM-exit helper for MOV from CRx (CRx read).
13701 */
13702static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13703{
13704 Assert(iCrReg < 16);
13705 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13706
13707 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13708 AssertRCReturn(rc, rc);
13709
13710 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13711 AssertMsg( rcStrict == VINF_SUCCESS
13712 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13713
13714 if (iGReg == X86_GREG_xSP)
13715 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13716 else
13717 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13718#ifdef VBOX_WITH_STATISTICS
13719 switch (iCrReg)
13720 {
13721 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13722 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13723 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13724 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13725 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13726 }
13727#endif
13728 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13729 return rcStrict;
13730}
13731
13732
13733/**
13734 * VM-exit helper for MOV to CRx (CRx write).
13735 */
13736static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13737{
13738 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13739 AssertRCReturn(rc, rc);
13740
13741 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13742 AssertMsg( rcStrict == VINF_SUCCESS
13743 || rcStrict == VINF_IEM_RAISED_XCPT
13744 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13745
13746 switch (iCrReg)
13747 {
13748 case 0:
13749 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13750 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13751 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13752 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13753 break;
13754
13755 case 2:
13756 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13757 /* Nothing to do here, CR2 it's not part of the VMCS. */
13758 break;
13759
13760 case 3:
13761 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13762 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13763 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13764 break;
13765
13766 case 4:
13767 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13768 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13769 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13770 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13771 break;
13772
13773 case 8:
13774 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13775 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13776 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13777 break;
13778
13779 default:
13780 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13781 break;
13782 }
13783
13784 if (rcStrict == VINF_IEM_RAISED_XCPT)
13785 {
13786 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13787 rcStrict = VINF_SUCCESS;
13788 }
13789 return rcStrict;
13790}
13791
13792
13793/**
13794 * VM-exit exception handler for \#PF (Page-fault exception).
13795 *
13796 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13797 */
13798static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13799{
13800 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13801 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13802 hmR0VmxReadExitQualVmcs(pVmxTransient);
13803
13804 if (!pVM->hm.s.fNestedPaging)
13805 { /* likely */ }
13806 else
13807 {
13808#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13809 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
13810#endif
13811 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13812 if (!pVmxTransient->fVectoringDoublePF)
13813 {
13814 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13815 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13816 }
13817 else
13818 {
13819 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13820 Assert(!pVmxTransient->fIsNestedGuest);
13821 hmR0VmxSetPendingXcptDF(pVCpu);
13822 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13823 }
13824 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13825 return VINF_SUCCESS;
13826 }
13827
13828 Assert(!pVmxTransient->fIsNestedGuest);
13829
13830 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13831 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13832 if (pVmxTransient->fVectoringPF)
13833 {
13834 Assert(pVCpu->hm.s.Event.fPending);
13835 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13836 }
13837
13838 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13839 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13840 AssertRCReturn(rc, rc);
13841
13842 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13843 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13844
13845 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13846 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13847
13848 Log4Func(("#PF: rc=%Rrc\n", rc));
13849 if (rc == VINF_SUCCESS)
13850 {
13851 /*
13852 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13853 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13854 */
13855 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13856 TRPMResetTrap(pVCpu);
13857 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13858 return rc;
13859 }
13860
13861 if (rc == VINF_EM_RAW_GUEST_TRAP)
13862 {
13863 if (!pVmxTransient->fVectoringDoublePF)
13864 {
13865 /* It's a guest page fault and needs to be reflected to the guest. */
13866 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
13867 TRPMResetTrap(pVCpu);
13868 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13869 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13870 uGstErrorCode, pVmxTransient->uExitQual);
13871 }
13872 else
13873 {
13874 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13875 TRPMResetTrap(pVCpu);
13876 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
13877 hmR0VmxSetPendingXcptDF(pVCpu);
13878 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
13879 }
13880
13881 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13882 return VINF_SUCCESS;
13883 }
13884
13885 TRPMResetTrap(pVCpu);
13886 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
13887 return rc;
13888}
13889
13890
13891/**
13892 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
13893 *
13894 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13895 */
13896static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13897{
13898 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13899 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
13900
13901 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
13902 AssertRCReturn(rc, rc);
13903
13904 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
13905 {
13906 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
13907 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
13908
13909 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
13910 * provides VM-exit instruction length. If this causes problem later,
13911 * disassemble the instruction like it's done on AMD-V. */
13912 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13913 AssertRCReturn(rc2, rc2);
13914 return rc;
13915 }
13916
13917 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
13918 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13919 return VINF_SUCCESS;
13920}
13921
13922
13923/**
13924 * VM-exit exception handler for \#BP (Breakpoint exception).
13925 *
13926 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13927 */
13928static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13929{
13930 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13931 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
13932
13933 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13934 AssertRCReturn(rc, rc);
13935
13936 if (!pVmxTransient->fIsNestedGuest)
13937 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
13938 else
13939 rc = VINF_EM_RAW_GUEST_TRAP;
13940
13941 if (rc == VINF_EM_RAW_GUEST_TRAP)
13942 {
13943 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13944 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13945 rc = VINF_SUCCESS;
13946 }
13947
13948 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
13949 return rc;
13950}
13951
13952
13953/**
13954 * VM-exit exception handler for \#AC (Alignment-check exception).
13955 *
13956 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13957 */
13958static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13959{
13960 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13961 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
13962
13963 /* Re-inject it. We'll detect any nesting before getting here. */
13964 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13965 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13966 return VINF_SUCCESS;
13967}
13968
13969
13970/**
13971 * VM-exit exception handler for \#DB (Debug exception).
13972 *
13973 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13974 */
13975static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13976{
13977 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13978 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
13979
13980 /*
13981 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
13982 */
13983 hmR0VmxReadExitQualVmcs(pVmxTransient);
13984
13985 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
13986 uint64_t const uDR6 = X86_DR6_INIT_VAL
13987 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
13988 | X86_DR6_BD | X86_DR6_BS));
13989
13990 int rc;
13991 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13992 if (!pVmxTransient->fIsNestedGuest)
13993 {
13994 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
13995
13996 /*
13997 * Prevents stepping twice over the same instruction when the guest is stepping using
13998 * EFLAGS.TF and the hypervisor debugger is stepping using MTF.
13999 * Testcase: DOSQEMM, break (using "ba x 1") at cs:rip 0x70:0x774 and step (using "t").
14000 */
14001 if ( rc == VINF_EM_DBG_STEPPED
14002 && (pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MONITOR_TRAP_FLAG))
14003 {
14004 Assert(pVCpu->hm.s.fSingleInstruction);
14005 rc = VINF_EM_RAW_GUEST_TRAP;
14006 }
14007 }
14008 else
14009 rc = VINF_EM_RAW_GUEST_TRAP;
14010 Log6Func(("rc=%Rrc\n", rc));
14011 if (rc == VINF_EM_RAW_GUEST_TRAP)
14012 {
14013 /*
14014 * The exception was for the guest. Update DR6, DR7.GD and
14015 * IA32_DEBUGCTL.LBR before forwarding it.
14016 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14017 */
14018 VMMRZCallRing3Disable(pVCpu);
14019 HM_DISABLE_PREEMPT(pVCpu);
14020
14021 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14022 pCtx->dr[6] |= uDR6;
14023 if (CPUMIsGuestDebugStateActive(pVCpu))
14024 ASMSetDR6(pCtx->dr[6]);
14025
14026 HM_RESTORE_PREEMPT();
14027 VMMRZCallRing3Enable(pVCpu);
14028
14029 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14030 AssertRCReturn(rc, rc);
14031
14032 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14033 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
14034
14035 /* Paranoia. */
14036 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
14037 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14038
14039 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
14040 AssertRC(rc);
14041
14042 /*
14043 * Raise #DB in the guest.
14044 *
14045 * It is important to reflect exactly what the VM-exit gave us (preserving the
14046 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14047 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14048 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14049 *
14050 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14051 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14052 */
14053 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14054 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14055 return VINF_SUCCESS;
14056 }
14057
14058 /*
14059 * Not a guest trap, must be a hypervisor related debug event then.
14060 * Update DR6 in case someone is interested in it.
14061 */
14062 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14063 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14064 CPUMSetHyperDR6(pVCpu, uDR6);
14065
14066 return rc;
14067}
14068
14069
14070/**
14071 * Hacks its way around the lovely mesa driver's backdoor accesses.
14072 *
14073 * @sa hmR0SvmHandleMesaDrvGp.
14074 */
14075static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14076{
14077 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14078 RT_NOREF(pCtx);
14079
14080 /* For now we'll just skip the instruction. */
14081 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14082}
14083
14084
14085/**
14086 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14087 * backdoor logging w/o checking what it is running inside.
14088 *
14089 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14090 * backdoor port and magic numbers loaded in registers.
14091 *
14092 * @returns true if it is, false if it isn't.
14093 * @sa hmR0SvmIsMesaDrvGp.
14094 */
14095DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14096{
14097 /* 0xed: IN eAX,dx */
14098 uint8_t abInstr[1];
14099 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
14100 return false;
14101
14102 /* Check that it is #GP(0). */
14103 if (pVmxTransient->uExitIntErrorCode != 0)
14104 return false;
14105
14106 /* Check magic and port. */
14107 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14108 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14109 if (pCtx->rax != UINT32_C(0x564d5868))
14110 return false;
14111 if (pCtx->dx != UINT32_C(0x5658))
14112 return false;
14113
14114 /* Flat ring-3 CS. */
14115 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14116 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14117 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14118 if (pCtx->cs.Attr.n.u2Dpl != 3)
14119 return false;
14120 if (pCtx->cs.u64Base != 0)
14121 return false;
14122
14123 /* Check opcode. */
14124 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14125 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14126 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14127 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14128 if (RT_FAILURE(rc))
14129 return false;
14130 if (abInstr[0] != 0xed)
14131 return false;
14132
14133 return true;
14134}
14135
14136
14137/**
14138 * VM-exit exception handler for \#GP (General-protection exception).
14139 *
14140 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14141 */
14142static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14143{
14144 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14145 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14146
14147 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14148 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14149 if (pVmcsInfo->RealMode.fRealOnV86Active)
14150 { /* likely */ }
14151 else
14152 {
14153#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14154 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14155#endif
14156 /*
14157 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14158 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14159 */
14160 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14161 AssertRCReturn(rc, rc);
14162 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14163 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14164
14165 if ( pVmxTransient->fIsNestedGuest
14166 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14167 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14168 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14169 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14170 else
14171 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14172 return rc;
14173 }
14174
14175 Assert(CPUMIsGuestInRealModeEx(pCtx));
14176 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14177 Assert(!pVmxTransient->fIsNestedGuest);
14178
14179 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14180 AssertRCReturn(rc, rc);
14181
14182 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14183 if (rcStrict == VINF_SUCCESS)
14184 {
14185 if (!CPUMIsGuestInRealModeEx(pCtx))
14186 {
14187 /*
14188 * The guest is no longer in real-mode, check if we can continue executing the
14189 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14190 */
14191 pVmcsInfo->RealMode.fRealOnV86Active = false;
14192 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
14193 {
14194 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14195 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14196 }
14197 else
14198 {
14199 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14200 rcStrict = VINF_EM_RESCHEDULE;
14201 }
14202 }
14203 else
14204 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14205 }
14206 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14207 {
14208 rcStrict = VINF_SUCCESS;
14209 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14210 }
14211 return VBOXSTRICTRC_VAL(rcStrict);
14212}
14213
14214
14215/**
14216 * VM-exit exception handler wrapper for all other exceptions that are not handled
14217 * by a specific handler.
14218 *
14219 * This simply re-injects the exception back into the VM without any special
14220 * processing.
14221 *
14222 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14223 */
14224static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14225{
14226 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14227
14228#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14229 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14230 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14231 ("uVector=%#x u32XcptBitmap=%#X32\n",
14232 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14233 NOREF(pVmcsInfo);
14234#endif
14235
14236 /*
14237 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14238 * would have been handled while checking exits due to event delivery.
14239 */
14240 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14241
14242#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14243 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14244 AssertRCReturn(rc, rc);
14245 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14246#endif
14247
14248#ifdef VBOX_WITH_STATISTICS
14249 switch (uVector)
14250 {
14251 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14252 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14253 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14254 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14255 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14256 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14257 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14258 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14259 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14260 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14261 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14262 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14263 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14264 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14265 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14266 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14267 default:
14268 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14269 break;
14270 }
14271#endif
14272
14273 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14274 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14275 NOREF(uVector);
14276
14277 /* Re-inject the original exception into the guest. */
14278 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14279 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14280 return VINF_SUCCESS;
14281}
14282
14283
14284/**
14285 * VM-exit exception handler for all exceptions (except NMIs!).
14286 *
14287 * @remarks This may be called for both guests and nested-guests. Take care to not
14288 * make assumptions and avoid doing anything that is not relevant when
14289 * executing a nested-guest (e.g., Mesa driver hacks).
14290 */
14291static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14292{
14293 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14294
14295 /*
14296 * If this VM-exit occurred while delivering an event through the guest IDT, take
14297 * action based on the return code and additional hints (e.g. for page-faults)
14298 * that will be updated in the VMX transient structure.
14299 */
14300 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14301 if (rcStrict == VINF_SUCCESS)
14302 {
14303 /*
14304 * If an exception caused a VM-exit due to delivery of an event, the original
14305 * event may have to be re-injected into the guest. We shall reinject it and
14306 * continue guest execution. However, page-fault is a complicated case and
14307 * needs additional processing done in hmR0VmxExitXcptPF().
14308 */
14309 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14310 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14311 if ( !pVCpu->hm.s.Event.fPending
14312 || uVector == X86_XCPT_PF)
14313 {
14314 switch (uVector)
14315 {
14316 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14317 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14318 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14319 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14320 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14321 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14322 default:
14323 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14324 }
14325 }
14326 /* else: inject pending event before resuming guest execution. */
14327 }
14328 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14329 {
14330 Assert(pVCpu->hm.s.Event.fPending);
14331 rcStrict = VINF_SUCCESS;
14332 }
14333
14334 return rcStrict;
14335}
14336/** @} */
14337
14338
14339/** @name VM-exit handlers.
14340 * @{
14341 */
14342/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14343/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14344/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14345
14346/**
14347 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14348 */
14349HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14350{
14351 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14352 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14353 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14354 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14355 return VINF_SUCCESS;
14356 return VINF_EM_RAW_INTERRUPT;
14357}
14358
14359
14360/**
14361 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14362 * VM-exit.
14363 */
14364HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14365{
14366 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14367 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14368
14369 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14370
14371 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14372 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14373 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14374
14375 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14376 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14377 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14378 NOREF(pVmcsInfo);
14379
14380 VBOXSTRICTRC rcStrict;
14381 switch (uExitIntType)
14382 {
14383 /*
14384 * Host physical NMIs:
14385 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14386 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14387 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14388 *
14389 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14390 * See Intel spec. 27.5.5 "Updating Non-Register State".
14391 */
14392 case VMX_EXIT_INT_INFO_TYPE_NMI:
14393 {
14394 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14395 break;
14396 }
14397
14398 /*
14399 * Privileged software exceptions (#DB from ICEBP),
14400 * Software exceptions (#BP and #OF),
14401 * Hardware exceptions:
14402 * Process the required exceptions and resume guest execution if possible.
14403 */
14404 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14405 Assert(uVector == X86_XCPT_DB);
14406 RT_FALL_THRU();
14407 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14408 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14409 RT_FALL_THRU();
14410 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14411 {
14412 NOREF(uVector);
14413 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14414 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14415 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14416 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14417
14418 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14419 break;
14420 }
14421
14422 default:
14423 {
14424 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14425 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14426 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14427 break;
14428 }
14429 }
14430
14431 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14432 return rcStrict;
14433}
14434
14435
14436/**
14437 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14438 */
14439HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14440{
14441 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14442
14443 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14444 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14445 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14446
14447 /* Evaluate and deliver pending events and resume guest execution. */
14448 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14449 return VINF_SUCCESS;
14450}
14451
14452
14453/**
14454 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14455 */
14456HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14457{
14458 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14459
14460 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14461 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14462 {
14463 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14464 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14465 }
14466
14467 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14468
14469 /*
14470 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14471 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14472 */
14473 uint32_t fIntrState;
14474 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14475 AssertRC(rc);
14476 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14477 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14478 {
14479 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14480 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14481
14482 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14483 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14484 AssertRC(rc);
14485 }
14486
14487 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14488 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14489
14490 /* Evaluate and deliver pending events and resume guest execution. */
14491 return VINF_SUCCESS;
14492}
14493
14494
14495/**
14496 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14497 */
14498HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14499{
14500 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14501 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14502}
14503
14504
14505/**
14506 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14507 */
14508HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14509{
14510 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14511 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14512}
14513
14514
14515/**
14516 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14517 */
14518HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14519{
14520 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14521
14522 /*
14523 * Get the state we need and update the exit history entry.
14524 */
14525 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14526 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14527
14528 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14529 AssertRCReturn(rc, rc);
14530
14531 VBOXSTRICTRC rcStrict;
14532 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14533 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14534 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14535 if (!pExitRec)
14536 {
14537 /*
14538 * Regular CPUID instruction execution.
14539 */
14540 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14541 if (rcStrict == VINF_SUCCESS)
14542 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14543 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14544 {
14545 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14546 rcStrict = VINF_SUCCESS;
14547 }
14548 }
14549 else
14550 {
14551 /*
14552 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14553 */
14554 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14555 AssertRCReturn(rc2, rc2);
14556
14557 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14558 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14559
14560 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14561 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14562
14563 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14564 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14565 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14566 }
14567 return rcStrict;
14568}
14569
14570
14571/**
14572 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14573 */
14574HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14575{
14576 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14577
14578 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14579 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14580 AssertRCReturn(rc, rc);
14581
14582 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14583 return VINF_EM_RAW_EMULATE_INSTR;
14584
14585 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14586 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14587}
14588
14589
14590/**
14591 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14592 */
14593HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14594{
14595 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14596
14597 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14598 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14599 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14600 AssertRCReturn(rc, rc);
14601
14602 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14603 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14604 {
14605 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14606 we must reset offsetting on VM-entry. See @bugref{6634}. */
14607 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14608 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14609 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14610 }
14611 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14612 {
14613 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14614 rcStrict = VINF_SUCCESS;
14615 }
14616 return rcStrict;
14617}
14618
14619
14620/**
14621 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14622 */
14623HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14624{
14625 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14626
14627 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14628 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14629 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14630 AssertRCReturn(rc, rc);
14631
14632 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14633 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14634 {
14635 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14636 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14637 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14638 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14639 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14640 }
14641 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14642 {
14643 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14644 rcStrict = VINF_SUCCESS;
14645 }
14646 return rcStrict;
14647}
14648
14649
14650/**
14651 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14652 */
14653HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14654{
14655 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14656
14657 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14658 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14659 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14660 AssertRCReturn(rc, rc);
14661
14662 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14663 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14664 if (RT_LIKELY(rc == VINF_SUCCESS))
14665 {
14666 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14667 Assert(pVmxTransient->cbExitInstr == 2);
14668 }
14669 else
14670 {
14671 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14672 rc = VERR_EM_INTERPRETER;
14673 }
14674 return rc;
14675}
14676
14677
14678/**
14679 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14680 */
14681HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14682{
14683 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14684
14685 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14686 if (EMAreHypercallInstructionsEnabled(pVCpu))
14687 {
14688 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14689 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14690 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14691 AssertRCReturn(rc, rc);
14692
14693 /* Perform the hypercall. */
14694 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14695 if (rcStrict == VINF_SUCCESS)
14696 {
14697 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14698 AssertRCReturn(rc, rc);
14699 }
14700 else
14701 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14702 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14703 || RT_FAILURE(rcStrict));
14704
14705 /* If the hypercall changes anything other than guest's general-purpose registers,
14706 we would need to reload the guest changed bits here before VM-entry. */
14707 }
14708 else
14709 Log4Func(("Hypercalls not enabled\n"));
14710
14711 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14712 if (RT_FAILURE(rcStrict))
14713 {
14714 hmR0VmxSetPendingXcptUD(pVCpu);
14715 rcStrict = VINF_SUCCESS;
14716 }
14717
14718 return rcStrict;
14719}
14720
14721
14722/**
14723 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14724 */
14725HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14726{
14727 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14728 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
14729
14730 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14731 hmR0VmxReadExitQualVmcs(pVmxTransient);
14732 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14733 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14734 AssertRCReturn(rc, rc);
14735
14736 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14737
14738 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14739 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14740 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14741 {
14742 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14743 rcStrict = VINF_SUCCESS;
14744 }
14745 else
14746 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14747 VBOXSTRICTRC_VAL(rcStrict)));
14748 return rcStrict;
14749}
14750
14751
14752/**
14753 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14754 */
14755HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14756{
14757 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14758
14759 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14760 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14761 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14762 AssertRCReturn(rc, rc);
14763
14764 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14765 if (rcStrict == VINF_SUCCESS)
14766 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14767 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14768 {
14769 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14770 rcStrict = VINF_SUCCESS;
14771 }
14772
14773 return rcStrict;
14774}
14775
14776
14777/**
14778 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14779 */
14780HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14781{
14782 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14783
14784 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14785 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14786 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14787 AssertRCReturn(rc, rc);
14788
14789 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14790 if (RT_SUCCESS(rcStrict))
14791 {
14792 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14793 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14794 rcStrict = VINF_SUCCESS;
14795 }
14796
14797 return rcStrict;
14798}
14799
14800
14801/**
14802 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14803 * VM-exit.
14804 */
14805HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14806{
14807 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14808 return VINF_EM_RESET;
14809}
14810
14811
14812/**
14813 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14814 */
14815HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14816{
14817 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14818
14819 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14820 AssertRCReturn(rc, rc);
14821
14822 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14823 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14824 rc = VINF_SUCCESS;
14825 else
14826 rc = VINF_EM_HALT;
14827
14828 if (rc != VINF_SUCCESS)
14829 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14830 return rc;
14831}
14832
14833
14834/**
14835 * VM-exit handler for instructions that result in a \#UD exception delivered to
14836 * the guest.
14837 */
14838HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14839{
14840 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14841 hmR0VmxSetPendingXcptUD(pVCpu);
14842 return VINF_SUCCESS;
14843}
14844
14845
14846/**
14847 * VM-exit handler for expiry of the VMX-preemption timer.
14848 */
14849HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14850{
14851 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14852
14853 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14854 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14855
14856 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14857 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14858 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14859 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14860 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14861}
14862
14863
14864/**
14865 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14866 */
14867HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14868{
14869 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14870
14871 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14872 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14873 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
14874 AssertRCReturn(rc, rc);
14875
14876 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
14877 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14878 : HM_CHANGED_RAISED_XCPT_MASK);
14879
14880 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14881 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
14882
14883 return rcStrict;
14884}
14885
14886
14887/**
14888 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
14889 */
14890HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14891{
14892 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14893
14894 /** @todo Enable the new code after finding a reliably guest test-case. */
14895#if 1
14896 return VERR_EM_INTERPRETER;
14897#else
14898 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14899 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
14900 hmR0VmxReadExitQualVmcs(pVmxTransient);
14901 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
14902 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14903 AssertRCReturn(rc, rc);
14904
14905 /* Paranoia. Ensure this has a memory operand. */
14906 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
14907
14908 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
14909 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14910 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
14911 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
14912
14913 RTGCPTR GCPtrDesc;
14914 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
14915
14916 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
14917 GCPtrDesc, uType);
14918 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14919 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14920 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14921 {
14922 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14923 rcStrict = VINF_SUCCESS;
14924 }
14925 return rcStrict;
14926#endif
14927}
14928
14929
14930/**
14931 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
14932 * VM-exit.
14933 */
14934HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14935{
14936 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14937 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14938 AssertRCReturn(rc, rc);
14939
14940 rc = hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
14941 if (RT_FAILURE(rc))
14942 return rc;
14943
14944 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
14945 NOREF(uInvalidReason);
14946
14947#ifdef VBOX_STRICT
14948 uint32_t fIntrState;
14949 uint64_t u64Val;
14950 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
14951 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
14952 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
14953
14954 Log4(("uInvalidReason %u\n", uInvalidReason));
14955 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
14956 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
14957 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
14958
14959 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
14960 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
14961 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
14962 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
14963 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
14964 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
14965 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
14966 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14967 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
14968 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
14969 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
14970 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14971 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
14972 {
14973 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
14974 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
14975 }
14976 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
14977#endif
14978
14979 return VERR_VMX_INVALID_GUEST_STATE;
14980}
14981
14982/**
14983 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
14984 */
14985HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14986{
14987 /*
14988 * Cumulative notes of all recognized but unexpected VM-exits.
14989 *
14990 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
14991 * nested-paging is used.
14992 *
14993 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
14994 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
14995 * this function (and thereby stop VM execution) for handling such instructions.
14996 *
14997 *
14998 * VMX_EXIT_INIT_SIGNAL:
14999 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15000 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15001 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15002 *
15003 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15004 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15005 * See Intel spec. "23.8 Restrictions on VMX operation".
15006 *
15007 * VMX_EXIT_SIPI:
15008 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15009 * activity state is used. We don't make use of it as our guests don't have direct
15010 * access to the host local APIC.
15011 *
15012 * See Intel spec. 25.3 "Other Causes of VM-exits".
15013 *
15014 * VMX_EXIT_IO_SMI:
15015 * VMX_EXIT_SMI:
15016 * This can only happen if we support dual-monitor treatment of SMI, which can be
15017 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15018 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15019 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15020 *
15021 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15022 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15023 *
15024 * VMX_EXIT_ERR_MSR_LOAD:
15025 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15026 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15027 * execution.
15028 *
15029 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15030 *
15031 * VMX_EXIT_ERR_MACHINE_CHECK:
15032 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15033 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15034 * #MC exception abort class exception is raised. We thus cannot assume a
15035 * reasonable chance of continuing any sort of execution and we bail.
15036 *
15037 * See Intel spec. 15.1 "Machine-check Architecture".
15038 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15039 *
15040 * VMX_EXIT_PML_FULL:
15041 * VMX_EXIT_VIRTUALIZED_EOI:
15042 * VMX_EXIT_APIC_WRITE:
15043 * We do not currently support any of these features and thus they are all unexpected
15044 * VM-exits.
15045 *
15046 * VMX_EXIT_GDTR_IDTR_ACCESS:
15047 * VMX_EXIT_LDTR_TR_ACCESS:
15048 * VMX_EXIT_RDRAND:
15049 * VMX_EXIT_RSM:
15050 * VMX_EXIT_VMFUNC:
15051 * VMX_EXIT_ENCLS:
15052 * VMX_EXIT_RDSEED:
15053 * VMX_EXIT_XSAVES:
15054 * VMX_EXIT_XRSTORS:
15055 * VMX_EXIT_UMWAIT:
15056 * VMX_EXIT_TPAUSE:
15057 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15058 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15059 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15060 *
15061 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15062 */
15063 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15064 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15065 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15066}
15067
15068
15069/**
15070 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15071 */
15072HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15073{
15074 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15075
15076 /** @todo Optimize this: We currently drag in the whole MSR state
15077 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15078 * MSRs required. That would require changes to IEM and possibly CPUM too.
15079 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15080 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15081 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15082 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15083 switch (idMsr)
15084 {
15085 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15086 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15087 }
15088
15089 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15090 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15091 AssertRCReturn(rc, rc);
15092
15093 Log4Func(("ecx=%#RX32\n", idMsr));
15094
15095#ifdef VBOX_STRICT
15096 Assert(!pVmxTransient->fIsNestedGuest);
15097 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15098 {
15099 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15100 && idMsr != MSR_K6_EFER)
15101 {
15102 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15103 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15104 }
15105 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15106 {
15107 Assert(pVmcsInfo->pvMsrBitmap);
15108 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15109 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15110 {
15111 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15112 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15113 }
15114 }
15115 }
15116#endif
15117
15118 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
15119 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15120 if (rcStrict == VINF_SUCCESS)
15121 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15122 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15123 {
15124 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15125 rcStrict = VINF_SUCCESS;
15126 }
15127 else
15128 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15129
15130 return rcStrict;
15131}
15132
15133
15134/**
15135 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15136 */
15137HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15138{
15139 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15140
15141 /** @todo Optimize this: We currently drag in the whole MSR state
15142 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15143 * MSRs required. That would require changes to IEM and possibly CPUM too.
15144 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15145 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15146 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15147
15148 /*
15149 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15150 * Although we don't need to fetch the base as it will be overwritten shortly, while
15151 * loading guest-state we would also load the entire segment register including limit
15152 * and attributes and thus we need to load them here.
15153 */
15154 switch (idMsr)
15155 {
15156 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15157 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15158 }
15159
15160 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15161 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15162 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15163 AssertRCReturn(rc, rc);
15164
15165 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15166
15167 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
15168 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15169
15170 if (rcStrict == VINF_SUCCESS)
15171 {
15172 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15173
15174 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15175 if ( idMsr == MSR_IA32_APICBASE
15176 || ( idMsr >= MSR_IA32_X2APIC_START
15177 && idMsr <= MSR_IA32_X2APIC_END))
15178 {
15179 /*
15180 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15181 * When full APIC register virtualization is implemented we'll have to make
15182 * sure APIC state is saved from the VMCS before IEM changes it.
15183 */
15184 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15185 }
15186 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15187 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15188 else if (idMsr == MSR_K6_EFER)
15189 {
15190 /*
15191 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15192 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15193 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15194 */
15195 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15196 }
15197
15198 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15199 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15200 {
15201 switch (idMsr)
15202 {
15203 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15204 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15205 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15206 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15207 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15208 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15209 default:
15210 {
15211 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15212 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15213 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15214 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15215 break;
15216 }
15217 }
15218 }
15219#ifdef VBOX_STRICT
15220 else
15221 {
15222 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15223 switch (idMsr)
15224 {
15225 case MSR_IA32_SYSENTER_CS:
15226 case MSR_IA32_SYSENTER_EIP:
15227 case MSR_IA32_SYSENTER_ESP:
15228 case MSR_K8_FS_BASE:
15229 case MSR_K8_GS_BASE:
15230 {
15231 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15232 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15233 }
15234
15235 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15236 default:
15237 {
15238 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15239 {
15240 /* EFER MSR writes are always intercepted. */
15241 if (idMsr != MSR_K6_EFER)
15242 {
15243 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15244 idMsr));
15245 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15246 }
15247 }
15248
15249 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15250 {
15251 Assert(pVmcsInfo->pvMsrBitmap);
15252 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15253 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15254 {
15255 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15256 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15257 }
15258 }
15259 break;
15260 }
15261 }
15262 }
15263#endif /* VBOX_STRICT */
15264 }
15265 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15266 {
15267 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15268 rcStrict = VINF_SUCCESS;
15269 }
15270 else
15271 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15272
15273 return rcStrict;
15274}
15275
15276
15277/**
15278 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15279 */
15280HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15281{
15282 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15283
15284 /** @todo The guest has likely hit a contended spinlock. We might want to
15285 * poke a schedule different guest VCPU. */
15286 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15287 if (RT_SUCCESS(rc))
15288 return VINF_EM_RAW_INTERRUPT;
15289
15290 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15291 return rc;
15292}
15293
15294
15295/**
15296 * VM-exit handler for when the TPR value is lowered below the specified
15297 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15298 */
15299HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15300{
15301 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15302 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15303
15304 /*
15305 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15306 * We'll re-evaluate pending interrupts and inject them before the next VM
15307 * entry so we can just continue execution here.
15308 */
15309 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15310 return VINF_SUCCESS;
15311}
15312
15313
15314/**
15315 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15316 * VM-exit.
15317 *
15318 * @retval VINF_SUCCESS when guest execution can continue.
15319 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15320 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15321 * incompatible guest state for VMX execution (real-on-v86 case).
15322 */
15323HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15324{
15325 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15326 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15327
15328 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15329 hmR0VmxReadExitQualVmcs(pVmxTransient);
15330 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15331
15332 VBOXSTRICTRC rcStrict;
15333 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15334 uint64_t const uExitQual = pVmxTransient->uExitQual;
15335 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15336 switch (uAccessType)
15337 {
15338 /*
15339 * MOV to CRx.
15340 */
15341 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15342 {
15343 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15344 AssertRCReturn(rc, rc);
15345
15346 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15347 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15348 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15349 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15350
15351 /*
15352 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15353 * - When nested paging isn't used.
15354 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15355 * - We are executing in the VM debug loop.
15356 */
15357 Assert( iCrReg != 3
15358 || !pVM->hm.s.fNestedPaging
15359 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15360 || pVCpu->hm.s.fUsingDebugLoop);
15361
15362 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15363 Assert( iCrReg != 8
15364 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15365
15366 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15367 AssertMsg( rcStrict == VINF_SUCCESS
15368 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15369
15370 /*
15371 * This is a kludge for handling switches back to real mode when we try to use
15372 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15373 * deal with special selector values, so we have to return to ring-3 and run
15374 * there till the selector values are V86 mode compatible.
15375 *
15376 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15377 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15378 * this function.
15379 */
15380 if ( iCrReg == 0
15381 && rcStrict == VINF_SUCCESS
15382 && !pVM->hm.s.vmx.fUnrestrictedGuest
15383 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15384 && (uOldCr0 & X86_CR0_PE)
15385 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15386 {
15387 /** @todo Check selectors rather than returning all the time. */
15388 Assert(!pVmxTransient->fIsNestedGuest);
15389 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15390 rcStrict = VINF_EM_RESCHEDULE_REM;
15391 }
15392 break;
15393 }
15394
15395 /*
15396 * MOV from CRx.
15397 */
15398 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15399 {
15400 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15401 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15402
15403 /*
15404 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15405 * - When nested paging isn't used.
15406 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15407 * - We are executing in the VM debug loop.
15408 */
15409 Assert( iCrReg != 3
15410 || !pVM->hm.s.fNestedPaging
15411 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15412 || pVCpu->hm.s.fUsingDebugLoop);
15413
15414 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15415 Assert( iCrReg != 8
15416 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15417
15418 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15419 break;
15420 }
15421
15422 /*
15423 * CLTS (Clear Task-Switch Flag in CR0).
15424 */
15425 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15426 {
15427 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15428 break;
15429 }
15430
15431 /*
15432 * LMSW (Load Machine-Status Word into CR0).
15433 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15434 */
15435 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15436 {
15437 RTGCPTR GCPtrEffDst;
15438 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15439 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15440 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15441 if (fMemOperand)
15442 {
15443 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15444 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15445 }
15446 else
15447 GCPtrEffDst = NIL_RTGCPTR;
15448 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15449 break;
15450 }
15451
15452 default:
15453 {
15454 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15455 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15456 }
15457 }
15458
15459 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15460 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15461 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15462
15463 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15464 NOREF(pVM);
15465 return rcStrict;
15466}
15467
15468
15469/**
15470 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15471 * VM-exit.
15472 */
15473HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15474{
15475 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15476 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15477
15478 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15479 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15480 hmR0VmxReadExitQualVmcs(pVmxTransient);
15481 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15482 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15483 | CPUMCTX_EXTRN_EFER);
15484 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15485 AssertRCReturn(rc, rc);
15486
15487 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15488 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15489 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15490 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15491 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15492 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15493 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15494 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15495
15496 /*
15497 * Update exit history to see if this exit can be optimized.
15498 */
15499 VBOXSTRICTRC rcStrict;
15500 PCEMEXITREC pExitRec = NULL;
15501 if ( !fGstStepping
15502 && !fDbgStepping)
15503 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15504 !fIOString
15505 ? !fIOWrite
15506 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15507 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15508 : !fIOWrite
15509 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15510 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15511 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15512 if (!pExitRec)
15513 {
15514 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15515 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15516
15517 uint32_t const cbValue = s_aIOSizes[uIOSize];
15518 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15519 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15520 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15521 if (fIOString)
15522 {
15523 /*
15524 * INS/OUTS - I/O String instruction.
15525 *
15526 * Use instruction-information if available, otherwise fall back on
15527 * interpreting the instruction.
15528 */
15529 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15530 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15531 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15532 if (fInsOutsInfo)
15533 {
15534 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15535 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15536 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15537 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15538 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15539 if (fIOWrite)
15540 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15541 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15542 else
15543 {
15544 /*
15545 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15546 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15547 * See Intel Instruction spec. for "INS".
15548 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15549 */
15550 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15551 }
15552 }
15553 else
15554 rcStrict = IEMExecOne(pVCpu);
15555
15556 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15557 fUpdateRipAlready = true;
15558 }
15559 else
15560 {
15561 /*
15562 * IN/OUT - I/O instruction.
15563 */
15564 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15565 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15566 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15567 if (fIOWrite)
15568 {
15569 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15570 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15571 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15572 && !pCtx->eflags.Bits.u1TF)
15573 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15574 }
15575 else
15576 {
15577 uint32_t u32Result = 0;
15578 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15579 if (IOM_SUCCESS(rcStrict))
15580 {
15581 /* Save result of I/O IN instr. in AL/AX/EAX. */
15582 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15583 }
15584 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15585 && !pCtx->eflags.Bits.u1TF)
15586 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15587 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15588 }
15589 }
15590
15591 if (IOM_SUCCESS(rcStrict))
15592 {
15593 if (!fUpdateRipAlready)
15594 {
15595 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15596 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15597 }
15598
15599 /*
15600 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15601 * while booting Fedora 17 64-bit guest.
15602 *
15603 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15604 */
15605 if (fIOString)
15606 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15607
15608 /*
15609 * If any I/O breakpoints are armed, we need to check if one triggered
15610 * and take appropriate action.
15611 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15612 */
15613 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15614 AssertRCReturn(rc, rc);
15615
15616 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15617 * execution engines about whether hyper BPs and such are pending. */
15618 uint32_t const uDr7 = pCtx->dr[7];
15619 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15620 && X86_DR7_ANY_RW_IO(uDr7)
15621 && (pCtx->cr4 & X86_CR4_DE))
15622 || DBGFBpIsHwIoArmed(pVM)))
15623 {
15624 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15625
15626 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15627 VMMRZCallRing3Disable(pVCpu);
15628 HM_DISABLE_PREEMPT(pVCpu);
15629
15630 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15631
15632 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15633 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15634 {
15635 /* Raise #DB. */
15636 if (fIsGuestDbgActive)
15637 ASMSetDR6(pCtx->dr[6]);
15638 if (pCtx->dr[7] != uDr7)
15639 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15640
15641 hmR0VmxSetPendingXcptDB(pVCpu);
15642 }
15643 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15644 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15645 else if ( rcStrict2 != VINF_SUCCESS
15646 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15647 rcStrict = rcStrict2;
15648 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15649
15650 HM_RESTORE_PREEMPT();
15651 VMMRZCallRing3Enable(pVCpu);
15652 }
15653 }
15654
15655#ifdef VBOX_STRICT
15656 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15657 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15658 Assert(!fIOWrite);
15659 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15660 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15661 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15662 Assert(fIOWrite);
15663 else
15664 {
15665# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15666 * statuses, that the VMM device and some others may return. See
15667 * IOM_SUCCESS() for guidance. */
15668 AssertMsg( RT_FAILURE(rcStrict)
15669 || rcStrict == VINF_SUCCESS
15670 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15671 || rcStrict == VINF_EM_DBG_BREAKPOINT
15672 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15673 || rcStrict == VINF_EM_RAW_TO_R3
15674 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15675# endif
15676 }
15677#endif
15678 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15679 }
15680 else
15681 {
15682 /*
15683 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15684 */
15685 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15686 AssertRCReturn(rc2, rc2);
15687 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15688 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15689 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15690 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15691 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15692 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15693
15694 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15695 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15696
15697 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15698 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15699 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15700 }
15701 return rcStrict;
15702}
15703
15704
15705/**
15706 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15707 * VM-exit.
15708 */
15709HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15710{
15711 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15712
15713 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15714 hmR0VmxReadExitQualVmcs(pVmxTransient);
15715 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15716 {
15717 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15718 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15719 {
15720 uint32_t uErrCode;
15721 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15722 {
15723 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15724 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15725 }
15726 else
15727 uErrCode = 0;
15728
15729 RTGCUINTPTR GCPtrFaultAddress;
15730 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15731 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15732 else
15733 GCPtrFaultAddress = 0;
15734
15735 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15736
15737 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15738 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15739
15740 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15741 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15742 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15743 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15744 }
15745 }
15746
15747 /* Fall back to the interpreter to emulate the task-switch. */
15748 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15749 return VERR_EM_INTERPRETER;
15750}
15751
15752
15753/**
15754 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15755 */
15756HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15757{
15758 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15759
15760 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15761 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15762 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15763 AssertRC(rc);
15764 return VINF_EM_DBG_STEPPED;
15765}
15766
15767
15768/**
15769 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15770 */
15771HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15772{
15773 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15774 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15775
15776 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15777 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15778 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15779 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15780 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15781
15782 /*
15783 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15784 */
15785 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15786 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15787 {
15788 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15789 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15790 {
15791 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15792 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15793 }
15794 }
15795 else
15796 {
15797 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15798 return rcStrict;
15799 }
15800
15801 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15802 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15803 hmR0VmxReadExitQualVmcs(pVmxTransient);
15804 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15805 AssertRCReturn(rc, rc);
15806
15807 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15808 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15809 switch (uAccessType)
15810 {
15811 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15812 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15813 {
15814 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15815 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15816 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15817
15818 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15819 GCPhys &= PAGE_BASE_GC_MASK;
15820 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15821 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15822 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15823
15824 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
15825 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
15826 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15827 if ( rcStrict == VINF_SUCCESS
15828 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15829 || rcStrict == VERR_PAGE_NOT_PRESENT)
15830 {
15831 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15832 | HM_CHANGED_GUEST_APIC_TPR);
15833 rcStrict = VINF_SUCCESS;
15834 }
15835 break;
15836 }
15837
15838 default:
15839 {
15840 Log4Func(("uAccessType=%#x\n", uAccessType));
15841 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15842 break;
15843 }
15844 }
15845
15846 if (rcStrict != VINF_SUCCESS)
15847 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15848 return rcStrict;
15849}
15850
15851
15852/**
15853 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15854 * VM-exit.
15855 */
15856HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15857{
15858 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15859 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15860
15861 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15862 if (!pVmxTransient->fIsNestedGuest)
15863 {
15864 /* We should -not- get this VM-exit if the guest's debug registers were active. */
15865 if (pVmxTransient->fWasGuestDebugStateActive)
15866 {
15867 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
15868 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15869 }
15870
15871 if ( !pVCpu->hm.s.fSingleInstruction
15872 && !pVmxTransient->fWasHyperDebugStateActive)
15873 {
15874 Assert(!DBGFIsStepping(pVCpu));
15875 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
15876
15877 /* Don't intercept MOV DRx any more. */
15878 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
15879 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15880 AssertRC(rc);
15881
15882 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
15883 VMMRZCallRing3Disable(pVCpu);
15884 HM_DISABLE_PREEMPT(pVCpu);
15885
15886 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
15887 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
15888 Assert(CPUMIsGuestDebugStateActive(pVCpu));
15889
15890 HM_RESTORE_PREEMPT();
15891 VMMRZCallRing3Enable(pVCpu);
15892
15893#ifdef VBOX_WITH_STATISTICS
15894 hmR0VmxReadExitQualVmcs(pVmxTransient);
15895 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15896 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15897 else
15898 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15899#endif
15900 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
15901 return VINF_SUCCESS;
15902 }
15903 }
15904
15905 /*
15906 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
15907 * The EFER MSR is always up-to-date.
15908 * Update the segment registers and DR7 from the CPU.
15909 */
15910 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15911 hmR0VmxReadExitQualVmcs(pVmxTransient);
15912 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
15913 AssertRCReturn(rc, rc);
15914 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
15915
15916 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15917 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15918 {
15919 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15920 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
15921 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
15922 if (RT_SUCCESS(rc))
15923 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
15924 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15925 }
15926 else
15927 {
15928 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15929 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
15930 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
15931 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15932 }
15933
15934 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
15935 if (RT_SUCCESS(rc))
15936 {
15937 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15938 AssertRCReturn(rc2, rc2);
15939 return VINF_SUCCESS;
15940 }
15941 return rc;
15942}
15943
15944
15945/**
15946 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
15947 * Conditional VM-exit.
15948 */
15949HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15950{
15951 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15952 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15953
15954 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15955 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15956 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15957 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15958 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15959
15960 /*
15961 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15962 */
15963 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15964 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15965 {
15966 /*
15967 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
15968 * instruction emulation to inject the original event. Otherwise, injecting the original event
15969 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
15970 */
15971 if (!pVCpu->hm.s.Event.fPending)
15972 { /* likely */ }
15973 else
15974 {
15975 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15976#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15977 /** @todo NSTVMX: Think about how this should be handled. */
15978 if (pVmxTransient->fIsNestedGuest)
15979 return VERR_VMX_IPE_3;
15980#endif
15981 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15982 }
15983 }
15984 else
15985 {
15986 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15987 return rcStrict;
15988 }
15989
15990 /*
15991 * Get sufficient state and update the exit history entry.
15992 */
15993 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15994 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15995 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15996 AssertRCReturn(rc, rc);
15997
15998 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15999 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16000 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16001 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16002 if (!pExitRec)
16003 {
16004 /*
16005 * If we succeed, resume guest execution.
16006 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16007 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16008 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16009 * weird case. See @bugref{6043}.
16010 */
16011 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16012 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16013/** @todo bird: We can probably just go straight to IOM here and assume that
16014 * it's MMIO, then fall back on PGM if that hunch didn't work out so
16015 * well. However, we need to address that aliasing workarounds that
16016 * PGMR0Trap0eHandlerNPMisconfig implements. So, some care is needed.
16017 *
16018 * Might also be interesting to see if we can get this done more or
16019 * less locklessly inside IOM. Need to consider the lookup table
16020 * updating and use a bit more carefully first (or do all updates via
16021 * rendezvous) */
16022 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16023 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16024 if ( rcStrict == VINF_SUCCESS
16025 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16026 || rcStrict == VERR_PAGE_NOT_PRESENT)
16027 {
16028 /* Successfully handled MMIO operation. */
16029 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16030 | HM_CHANGED_GUEST_APIC_TPR);
16031 rcStrict = VINF_SUCCESS;
16032 }
16033 }
16034 else
16035 {
16036 /*
16037 * Frequent exit or something needing probing. Call EMHistoryExec.
16038 */
16039 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16040 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16041
16042 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16043 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16044
16045 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16046 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16047 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16048 }
16049 return rcStrict;
16050}
16051
16052
16053/**
16054 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16055 * VM-exit.
16056 */
16057HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16058{
16059 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16060 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16061
16062 hmR0VmxReadExitQualVmcs(pVmxTransient);
16063 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16064 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16065 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16066 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16067 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16068
16069 /*
16070 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16071 */
16072 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16073 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16074 {
16075 /*
16076 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16077 * we shall resolve the nested #PF and re-inject the original event.
16078 */
16079 if (pVCpu->hm.s.Event.fPending)
16080 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16081 }
16082 else
16083 {
16084 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16085 return rcStrict;
16086 }
16087
16088 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16089 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16090 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16091 AssertRCReturn(rc, rc);
16092
16093 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16094 uint64_t const uExitQual = pVmxTransient->uExitQual;
16095 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16096
16097 RTGCUINT uErrorCode = 0;
16098 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16099 uErrorCode |= X86_TRAP_PF_ID;
16100 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16101 uErrorCode |= X86_TRAP_PF_RW;
16102 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16103 uErrorCode |= X86_TRAP_PF_P;
16104
16105 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16106 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16107 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16108
16109 /*
16110 * Handle the pagefault trap for the nested shadow table.
16111 */
16112 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16113 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16114 TRPMResetTrap(pVCpu);
16115
16116 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16117 if ( rcStrict == VINF_SUCCESS
16118 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16119 || rcStrict == VERR_PAGE_NOT_PRESENT)
16120 {
16121 /* Successfully synced our nested page tables. */
16122 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16123 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16124 return VINF_SUCCESS;
16125 }
16126
16127 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16128 return rcStrict;
16129}
16130
16131
16132#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16133/**
16134 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16135 */
16136HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16137{
16138 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16139
16140 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16141 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16142 hmR0VmxReadExitQualVmcs(pVmxTransient);
16143 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16144 | CPUMCTX_EXTRN_HWVIRT
16145 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16146 AssertRCReturn(rc, rc);
16147
16148 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16149
16150 VMXVEXITINFO ExitInfo;
16151 RT_ZERO(ExitInfo);
16152 ExitInfo.uReason = pVmxTransient->uExitReason;
16153 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16154 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16155 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16156 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16157
16158 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16159 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16160 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16161 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16162 {
16163 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16164 rcStrict = VINF_SUCCESS;
16165 }
16166 return rcStrict;
16167}
16168
16169
16170/**
16171 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16172 */
16173HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16174{
16175 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16176
16177 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16178 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16179 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16180 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16181 AssertRCReturn(rc, rc);
16182
16183 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16184
16185 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16186 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
16187 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16188 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16189 {
16190 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16191 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16192 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16193 }
16194 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16195 return rcStrict;
16196}
16197
16198
16199/**
16200 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16201 */
16202HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16203{
16204 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16205
16206 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16207 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16208 hmR0VmxReadExitQualVmcs(pVmxTransient);
16209 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16210 | CPUMCTX_EXTRN_HWVIRT
16211 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16212 AssertRCReturn(rc, rc);
16213
16214 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16215
16216 VMXVEXITINFO ExitInfo;
16217 RT_ZERO(ExitInfo);
16218 ExitInfo.uReason = pVmxTransient->uExitReason;
16219 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16220 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16221 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16222 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16223
16224 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16225 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16226 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16227 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16228 {
16229 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16230 rcStrict = VINF_SUCCESS;
16231 }
16232 return rcStrict;
16233}
16234
16235
16236/**
16237 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16238 */
16239HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16240{
16241 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16242
16243 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16244 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16245 hmR0VmxReadExitQualVmcs(pVmxTransient);
16246 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16247 | CPUMCTX_EXTRN_HWVIRT
16248 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16249 AssertRCReturn(rc, rc);
16250
16251 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16252
16253 VMXVEXITINFO ExitInfo;
16254 RT_ZERO(ExitInfo);
16255 ExitInfo.uReason = pVmxTransient->uExitReason;
16256 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16257 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16258 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16259 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16260
16261 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16262 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16263 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16264 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16265 {
16266 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16267 rcStrict = VINF_SUCCESS;
16268 }
16269 return rcStrict;
16270}
16271
16272
16273/**
16274 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16275 */
16276HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16277{
16278 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16279
16280 /*
16281 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16282 * thus might not need to import the shadow VMCS state, it's safer just in case
16283 * code elsewhere dares look at unsynced VMCS fields.
16284 */
16285 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16286 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16287 hmR0VmxReadExitQualVmcs(pVmxTransient);
16288 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16289 | CPUMCTX_EXTRN_HWVIRT
16290 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16291 AssertRCReturn(rc, rc);
16292
16293 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16294
16295 VMXVEXITINFO ExitInfo;
16296 RT_ZERO(ExitInfo);
16297 ExitInfo.uReason = pVmxTransient->uExitReason;
16298 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16299 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16300 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16301 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16302 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16303
16304 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16305 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16306 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16307 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16308 {
16309 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16310 rcStrict = VINF_SUCCESS;
16311 }
16312 return rcStrict;
16313}
16314
16315
16316/**
16317 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16318 */
16319HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16320{
16321 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16322
16323 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16324 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16325 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16326 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16327 AssertRCReturn(rc, rc);
16328
16329 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16330
16331 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16332 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16333 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16334 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16335 {
16336 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16337 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16338 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16339 }
16340 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16341 return rcStrict;
16342}
16343
16344
16345/**
16346 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16347 */
16348HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16349{
16350 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16351
16352 /*
16353 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16354 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16355 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16356 */
16357 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16358 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16359 hmR0VmxReadExitQualVmcs(pVmxTransient);
16360 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16361 | CPUMCTX_EXTRN_HWVIRT
16362 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16363 AssertRCReturn(rc, rc);
16364
16365 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16366
16367 VMXVEXITINFO ExitInfo;
16368 RT_ZERO(ExitInfo);
16369 ExitInfo.uReason = pVmxTransient->uExitReason;
16370 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16371 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16372 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16373 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16374 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16375
16376 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16377 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16378 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16379 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16380 {
16381 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16382 rcStrict = VINF_SUCCESS;
16383 }
16384 return rcStrict;
16385}
16386
16387
16388/**
16389 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16390 */
16391HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16392{
16393 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16394
16395 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16396 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16397 | CPUMCTX_EXTRN_HWVIRT
16398 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16399 AssertRCReturn(rc, rc);
16400
16401 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16402
16403 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16404 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16405 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16406 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16407 {
16408 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16409 rcStrict = VINF_SUCCESS;
16410 }
16411 return rcStrict;
16412}
16413
16414
16415/**
16416 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16417 */
16418HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16419{
16420 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16421
16422 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16423 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16424 hmR0VmxReadExitQualVmcs(pVmxTransient);
16425 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16426 | CPUMCTX_EXTRN_HWVIRT
16427 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16428 AssertRCReturn(rc, rc);
16429
16430 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16431
16432 VMXVEXITINFO ExitInfo;
16433 RT_ZERO(ExitInfo);
16434 ExitInfo.uReason = pVmxTransient->uExitReason;
16435 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16436 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16437 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16438 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16439
16440 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16441 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16442 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16443 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16444 {
16445 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16446 rcStrict = VINF_SUCCESS;
16447 }
16448 return rcStrict;
16449}
16450
16451
16452/**
16453 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16454 */
16455HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16456{
16457 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16458
16459 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16460 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16461 hmR0VmxReadExitQualVmcs(pVmxTransient);
16462 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16463 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16464 AssertRCReturn(rc, rc);
16465
16466 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16467
16468 VMXVEXITINFO ExitInfo;
16469 RT_ZERO(ExitInfo);
16470 ExitInfo.uReason = pVmxTransient->uExitReason;
16471 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16472 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16473 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16474 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16475
16476 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16477 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16478 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16479 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16480 {
16481 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16482 rcStrict = VINF_SUCCESS;
16483 }
16484 return rcStrict;
16485}
16486#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16487/** @} */
16488
16489
16490#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16491/** @name Nested-guest VM-exit handlers.
16492 * @{
16493 */
16494/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16495/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16496/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16497
16498/**
16499 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16500 * Conditional VM-exit.
16501 */
16502HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16503{
16504 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16505
16506 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16507
16508 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16509 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16510 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16511
16512 switch (uExitIntType)
16513 {
16514 /*
16515 * Physical NMIs:
16516 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16517 */
16518 case VMX_EXIT_INT_INFO_TYPE_NMI:
16519 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16520
16521 /*
16522 * Hardware exceptions,
16523 * Software exceptions,
16524 * Privileged software exceptions:
16525 * Figure out if the exception must be delivered to the guest or the nested-guest.
16526 */
16527 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16528 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16529 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16530 {
16531 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16532 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16533 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16534 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16535
16536 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16537 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16538 pVmxTransient->uExitIntErrorCode);
16539 if (fIntercept)
16540 {
16541 /* Exit qualification is required for debug and page-fault exceptions. */
16542 hmR0VmxReadExitQualVmcs(pVmxTransient);
16543
16544 /*
16545 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16546 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16547 * length. However, if delivery of a software interrupt, software exception or privileged
16548 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16549 */
16550 VMXVEXITINFO ExitInfo;
16551 RT_ZERO(ExitInfo);
16552 ExitInfo.uReason = pVmxTransient->uExitReason;
16553 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16554 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16555
16556 VMXVEXITEVENTINFO ExitEventInfo;
16557 RT_ZERO(ExitEventInfo);
16558 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16559 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16560 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16561 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16562
16563#ifdef DEBUG_ramshankar
16564 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16565 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16566 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16567 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16568 {
16569 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16570 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16571 }
16572#endif
16573 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16574 }
16575
16576 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16577 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16578 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16579 }
16580
16581 /*
16582 * Software interrupts:
16583 * VM-exits cannot be caused by software interrupts.
16584 *
16585 * External interrupts:
16586 * This should only happen when "acknowledge external interrupts on VM-exit"
16587 * control is set. However, we never set this when executing a guest or
16588 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16589 * the guest.
16590 */
16591 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16592 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16593 default:
16594 {
16595 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16596 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16597 }
16598 }
16599}
16600
16601
16602/**
16603 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16604 * Unconditional VM-exit.
16605 */
16606HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16607{
16608 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16609 return IEMExecVmxVmexitTripleFault(pVCpu);
16610}
16611
16612
16613/**
16614 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16615 */
16616HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16617{
16618 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16619
16620 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16621 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16622 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16623}
16624
16625
16626/**
16627 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16628 */
16629HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16630{
16631 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16632
16633 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16634 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16635 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16636}
16637
16638
16639/**
16640 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16641 * Unconditional VM-exit.
16642 */
16643HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16644{
16645 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16646
16647 hmR0VmxReadExitQualVmcs(pVmxTransient);
16648 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16649 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16650 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16651
16652 VMXVEXITINFO ExitInfo;
16653 RT_ZERO(ExitInfo);
16654 ExitInfo.uReason = pVmxTransient->uExitReason;
16655 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16656 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16657
16658 VMXVEXITEVENTINFO ExitEventInfo;
16659 RT_ZERO(ExitEventInfo);
16660 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16661 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16662 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16663}
16664
16665
16666/**
16667 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16668 */
16669HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16670{
16671 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16672
16673 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16674 {
16675 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16676 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16677 }
16678 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16679}
16680
16681
16682/**
16683 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16684 */
16685HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16686{
16687 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16688
16689 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16690 {
16691 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16692 hmR0VmxReadExitQualVmcs(pVmxTransient);
16693
16694 VMXVEXITINFO ExitInfo;
16695 RT_ZERO(ExitInfo);
16696 ExitInfo.uReason = pVmxTransient->uExitReason;
16697 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16698 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16699 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16700 }
16701 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16702}
16703
16704
16705/**
16706 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16707 */
16708HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16709{
16710 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16711
16712 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16713 {
16714 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16715 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16716 }
16717 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16718}
16719
16720
16721/**
16722 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16723 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16724 */
16725HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16726{
16727 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16728
16729 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16730 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16731
16732 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16733
16734 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16735 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16736 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16737
16738 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16739 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16740 u64VmcsField &= UINT64_C(0xffffffff);
16741
16742 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16743 {
16744 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16745 hmR0VmxReadExitQualVmcs(pVmxTransient);
16746
16747 VMXVEXITINFO ExitInfo;
16748 RT_ZERO(ExitInfo);
16749 ExitInfo.uReason = pVmxTransient->uExitReason;
16750 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16751 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16752 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16753 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16754 }
16755
16756 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16757 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16758 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16759}
16760
16761
16762/**
16763 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16764 */
16765HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16766{
16767 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16768
16769 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16770 {
16771 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16772 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16773 }
16774
16775 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16776}
16777
16778
16779/**
16780 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16781 * Conditional VM-exit.
16782 */
16783HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16784{
16785 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16786
16787 hmR0VmxReadExitQualVmcs(pVmxTransient);
16788 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16789
16790 VBOXSTRICTRC rcStrict;
16791 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16792 switch (uAccessType)
16793 {
16794 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16795 {
16796 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16797 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16798 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16799 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16800
16801 bool fIntercept;
16802 switch (iCrReg)
16803 {
16804 case 0:
16805 case 4:
16806 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(&pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16807 break;
16808
16809 case 3:
16810 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16811 break;
16812
16813 case 8:
16814 fIntercept = CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16815 break;
16816
16817 default:
16818 fIntercept = false;
16819 break;
16820 }
16821 if (fIntercept)
16822 {
16823 VMXVEXITINFO ExitInfo;
16824 RT_ZERO(ExitInfo);
16825 ExitInfo.uReason = pVmxTransient->uExitReason;
16826 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16827 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16828 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16829 }
16830 else
16831 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16832 break;
16833 }
16834
16835 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16836 {
16837 /*
16838 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16839 * CR2 reads do not cause a VM-exit.
16840 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16841 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16842 */
16843 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16844 if ( iCrReg == 3
16845 || iCrReg == 8)
16846 {
16847 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16848 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16849 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16850 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uIntercept))
16851 {
16852 VMXVEXITINFO ExitInfo;
16853 RT_ZERO(ExitInfo);
16854 ExitInfo.uReason = pVmxTransient->uExitReason;
16855 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16856 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16857 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16858 }
16859 else
16860 {
16861 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16862 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16863 }
16864 }
16865 else
16866 {
16867 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
16868 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
16869 }
16870 break;
16871 }
16872
16873 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
16874 {
16875 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
16876 Assert(pVmcsNstGst);
16877 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
16878 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
16879 if ( (uGstHostMask & X86_CR0_TS)
16880 && (uReadShadow & X86_CR0_TS))
16881 {
16882 VMXVEXITINFO ExitInfo;
16883 RT_ZERO(ExitInfo);
16884 ExitInfo.uReason = pVmxTransient->uExitReason;
16885 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16886 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16887 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16888 }
16889 else
16890 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
16891 break;
16892 }
16893
16894 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
16895 {
16896 RTGCPTR GCPtrEffDst;
16897 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
16898 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
16899 if (fMemOperand)
16900 {
16901 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16902 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
16903 }
16904 else
16905 GCPtrEffDst = NIL_RTGCPTR;
16906
16907 if (CPUMIsGuestVmxLmswInterceptSet(&pVCpu->cpum.GstCtx, uNewMsw))
16908 {
16909 VMXVEXITINFO ExitInfo;
16910 RT_ZERO(ExitInfo);
16911 ExitInfo.uReason = pVmxTransient->uExitReason;
16912 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16913 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
16914 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16915 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16916 }
16917 else
16918 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
16919 break;
16920 }
16921
16922 default:
16923 {
16924 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
16925 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
16926 }
16927 }
16928
16929 if (rcStrict == VINF_IEM_RAISED_XCPT)
16930 {
16931 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16932 rcStrict = VINF_SUCCESS;
16933 }
16934 return rcStrict;
16935}
16936
16937
16938/**
16939 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
16940 * Conditional VM-exit.
16941 */
16942HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16943{
16944 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16945
16946 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
16947 {
16948 hmR0VmxReadExitQualVmcs(pVmxTransient);
16949 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16950
16951 VMXVEXITINFO ExitInfo;
16952 RT_ZERO(ExitInfo);
16953 ExitInfo.uReason = pVmxTransient->uExitReason;
16954 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16955 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16956 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16957 }
16958 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
16959}
16960
16961
16962/**
16963 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
16964 * Conditional VM-exit.
16965 */
16966HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16967{
16968 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16969
16970 hmR0VmxReadExitQualVmcs(pVmxTransient);
16971
16972 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16973 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16974 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16975
16976 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16977 uint8_t const cbAccess = s_aIOSizes[uIOSize];
16978 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
16979 {
16980 /*
16981 * IN/OUT instruction:
16982 * - Provides VM-exit instruction length.
16983 *
16984 * INS/OUTS instruction:
16985 * - Provides VM-exit instruction length.
16986 * - Provides Guest-linear address.
16987 * - Optionally provides VM-exit instruction info (depends on CPU feature).
16988 */
16989 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16990 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16991
16992 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
16993 pVmxTransient->ExitInstrInfo.u = 0;
16994 pVmxTransient->uGuestLinearAddr = 0;
16995
16996 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
16997 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
16998 if (fIOString)
16999 {
17000 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17001 if (fVmxInsOutsInfo)
17002 {
17003 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17004 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17005 }
17006 }
17007
17008 VMXVEXITINFO ExitInfo;
17009 RT_ZERO(ExitInfo);
17010 ExitInfo.uReason = pVmxTransient->uExitReason;
17011 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17012 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17013 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17014 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17015 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17016 }
17017 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17018}
17019
17020
17021/**
17022 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17023 */
17024HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17025{
17026 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17027
17028 uint32_t fMsrpm;
17029 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17030 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17031 else
17032 fMsrpm = VMXMSRPM_EXIT_RD;
17033
17034 if (fMsrpm & VMXMSRPM_EXIT_RD)
17035 {
17036 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17037 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17038 }
17039 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17040}
17041
17042
17043/**
17044 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17045 */
17046HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17047{
17048 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17049
17050 uint32_t fMsrpm;
17051 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17052 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17053 else
17054 fMsrpm = VMXMSRPM_EXIT_WR;
17055
17056 if (fMsrpm & VMXMSRPM_EXIT_WR)
17057 {
17058 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17059 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17060 }
17061 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17062}
17063
17064
17065/**
17066 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17067 */
17068HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17069{
17070 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17071
17072 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17073 {
17074 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17075 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17076 }
17077 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17078}
17079
17080
17081/**
17082 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17083 * VM-exit.
17084 */
17085HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17086{
17087 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17088
17089 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17090 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17091 VMXVEXITINFO ExitInfo;
17092 RT_ZERO(ExitInfo);
17093 ExitInfo.uReason = pVmxTransient->uExitReason;
17094 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17095 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17096}
17097
17098
17099/**
17100 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17101 */
17102HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17103{
17104 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17105
17106 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17107 {
17108 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17109 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17110 }
17111 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17112}
17113
17114
17115/**
17116 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17117 */
17118HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17119{
17120 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17121
17122 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17123 * PAUSE when executing a nested-guest? If it does not, we would not need
17124 * to check for the intercepts here. Just call VM-exit... */
17125
17126 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17127 if ( CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17128 || CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17129 {
17130 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17131 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17132 }
17133 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17134}
17135
17136
17137/**
17138 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17139 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17140 */
17141HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17142{
17143 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17144
17145 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17146 {
17147 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17148 VMXVEXITINFO ExitInfo;
17149 RT_ZERO(ExitInfo);
17150 ExitInfo.uReason = pVmxTransient->uExitReason;
17151 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17152 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17153 }
17154 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17155}
17156
17157
17158/**
17159 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17160 * VM-exit.
17161 */
17162HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17163{
17164 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17165
17166 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17167 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17168 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17169 hmR0VmxReadExitQualVmcs(pVmxTransient);
17170
17171 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17172
17173 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
17174 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
17175
17176 VMXVEXITINFO ExitInfo;
17177 RT_ZERO(ExitInfo);
17178 ExitInfo.uReason = pVmxTransient->uExitReason;
17179 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17180 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17181
17182 VMXVEXITEVENTINFO ExitEventInfo;
17183 RT_ZERO(ExitEventInfo);
17184 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17185 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17186 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17187}
17188
17189
17190/**
17191 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17192 * Conditional VM-exit.
17193 */
17194HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17195{
17196 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17197
17198 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17199 hmR0VmxReadExitQualVmcs(pVmxTransient);
17200 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17201}
17202
17203
17204/**
17205 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17206 * Conditional VM-exit.
17207 */
17208HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17209{
17210 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17211
17212 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17213 hmR0VmxReadExitQualVmcs(pVmxTransient);
17214 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17215}
17216
17217
17218/**
17219 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17220 */
17221HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17222{
17223 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17224
17225 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17226 {
17227 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17228 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17229 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17230 }
17231 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17232}
17233
17234
17235/**
17236 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17237 */
17238HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17239{
17240 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17241
17242 if (CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17243 {
17244 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17245 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17246 }
17247 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17248}
17249
17250
17251/**
17252 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17253 */
17254HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17255{
17256 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17257
17258 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17259 {
17260 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17261 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17262 hmR0VmxReadExitQualVmcs(pVmxTransient);
17263 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17264
17265 VMXVEXITINFO ExitInfo;
17266 RT_ZERO(ExitInfo);
17267 ExitInfo.uReason = pVmxTransient->uExitReason;
17268 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17269 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17270 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17271 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17272 }
17273 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17274}
17275
17276
17277/**
17278 * Nested-guest VM-exit handler for invalid-guest state
17279 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17280 */
17281HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17282{
17283 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17284
17285 /*
17286 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17287 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17288 * Handle it like it's in an invalid guest state of the outer guest.
17289 *
17290 * When the fast path is implemented, this should be changed to cause the corresponding
17291 * nested-guest VM-exit.
17292 */
17293 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17294}
17295
17296
17297/**
17298 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17299 * and only provide the instruction length.
17300 *
17301 * Unconditional VM-exit.
17302 */
17303HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17304{
17305 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17306
17307#ifdef VBOX_STRICT
17308 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17309 switch (pVmxTransient->uExitReason)
17310 {
17311 case VMX_EXIT_ENCLS:
17312 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17313 break;
17314
17315 case VMX_EXIT_VMFUNC:
17316 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_VMFUNC));
17317 break;
17318 }
17319#endif
17320
17321 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17322 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17323}
17324
17325
17326/**
17327 * Nested-guest VM-exit handler for instructions that provide instruction length as
17328 * well as more information.
17329 *
17330 * Unconditional VM-exit.
17331 */
17332HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17333{
17334 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17335
17336#ifdef VBOX_STRICT
17337 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17338 switch (pVmxTransient->uExitReason)
17339 {
17340 case VMX_EXIT_GDTR_IDTR_ACCESS:
17341 case VMX_EXIT_LDTR_TR_ACCESS:
17342 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17343 break;
17344
17345 case VMX_EXIT_RDRAND:
17346 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17347 break;
17348
17349 case VMX_EXIT_RDSEED:
17350 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17351 break;
17352
17353 case VMX_EXIT_XSAVES:
17354 case VMX_EXIT_XRSTORS:
17355 /** @todo NSTVMX: Verify XSS-bitmap. */
17356 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17357 break;
17358
17359 case VMX_EXIT_UMWAIT:
17360 case VMX_EXIT_TPAUSE:
17361 Assert(CPUMIsGuestVmxProcCtlsSet(pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17362 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17363 break;
17364 }
17365#endif
17366
17367 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17368 hmR0VmxReadExitQualVmcs(pVmxTransient);
17369 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17370
17371 VMXVEXITINFO ExitInfo;
17372 RT_ZERO(ExitInfo);
17373 ExitInfo.uReason = pVmxTransient->uExitReason;
17374 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17375 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17376 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17377 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17378}
17379
17380/** @} */
17381#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17382
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