VirtualBox

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

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

VMM/HMVMXR0: Comment. bugref:10080

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 739.7 KB
Line 
1/* $Id: HMVMXR0.cpp 90613 2021-08-11 05:39:33Z vboxsync $ */
2/** @file
3 * HM VMX (Intel VT-x) - Host Context Ring-0.
4 */
5
6/*
7 * Copyright (C) 2012-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_HM
23#define VMCPU_INCL_CPUM_GST_CTX
24#include <iprt/x86.h>
25#include <iprt/asm-amd64-x86.h>
26#include <iprt/thread.h>
27#include <iprt/mem.h>
28#include <iprt/mp.h>
29
30#include <VBox/vmm/pdmapi.h>
31#include <VBox/vmm/dbgf.h>
32#include <VBox/vmm/iem.h>
33#include <VBox/vmm/iom.h>
34#include <VBox/vmm/tm.h>
35#include <VBox/vmm/em.h>
36#include <VBox/vmm/gim.h>
37#include <VBox/vmm/apic.h>
38#include "HMInternal.h"
39#include <VBox/vmm/vmcc.h>
40#include <VBox/vmm/hmvmxinline.h>
41#include "HMVMXR0.h"
42#include "dtrace/VBoxVMM.h"
43
44#ifdef DEBUG_ramshankar
45# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
46# define HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
47# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
48# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
49# define HMVMX_ALWAYS_CLEAN_TRANSIENT
50# define HMVMX_ALWAYS_CHECK_GUEST_STATE
51# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
52# define HMVMX_ALWAYS_TRAP_PF
53# define HMVMX_ALWAYS_FLUSH_TLB
54# define HMVMX_ALWAYS_SWAP_EFER
55#endif
56
57
58/*********************************************************************************************************************************
59* Defined Constants And Macros *
60*********************************************************************************************************************************/
61/** Use the function table. */
62#define HMVMX_USE_FUNCTION_TABLE
63
64/** Determine which tagged-TLB flush handler to use. */
65#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
66#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
67#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
68#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
69
70/**
71 * Flags to skip redundant reads of some common VMCS fields that are not part of
72 * the guest-CPU or VCPU state but are needed while handling VM-exits.
73 */
74#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
75#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
76#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
77#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
78#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
79#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
80#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
81#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
82#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
83#define HMVMX_READ_GUEST_PENDING_DBG_XCPTS RT_BIT_32(9)
84
85/** All the VMCS fields required for processing of exception/NMI VM-exits. */
86#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
87 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
88 | HMVMX_READ_EXIT_INSTR_LEN \
89 | HMVMX_READ_IDT_VECTORING_INFO \
90 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
91
92/** Assert that all the given fields have been read from the VMCS. */
93#ifdef VBOX_STRICT
94# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
95 do { \
96 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
97 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
98 } while (0)
99#else
100# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
101#endif
102
103/**
104 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
105 * guest using hardware-assisted VMX.
106 *
107 * This excludes state like GPRs (other than RSP) which are always are
108 * swapped and restored across the world-switch and also registers like EFER,
109 * MSR which cannot be modified by the guest without causing a VM-exit.
110 */
111#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
112 | CPUMCTX_EXTRN_RFLAGS \
113 | CPUMCTX_EXTRN_RSP \
114 | CPUMCTX_EXTRN_SREG_MASK \
115 | CPUMCTX_EXTRN_TABLE_MASK \
116 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
117 | CPUMCTX_EXTRN_SYSCALL_MSRS \
118 | CPUMCTX_EXTRN_SYSENTER_MSRS \
119 | CPUMCTX_EXTRN_TSC_AUX \
120 | CPUMCTX_EXTRN_OTHER_MSRS \
121 | CPUMCTX_EXTRN_CR0 \
122 | CPUMCTX_EXTRN_CR3 \
123 | CPUMCTX_EXTRN_CR4 \
124 | CPUMCTX_EXTRN_DR7 \
125 | CPUMCTX_EXTRN_HWVIRT \
126 | CPUMCTX_EXTRN_HM_VMX_MASK)
127
128/**
129 * Exception bitmap mask for real-mode guests (real-on-v86).
130 *
131 * We need to intercept all exceptions manually except:
132 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
133 * due to bugs in Intel CPUs.
134 * - \#PF need not be intercepted even in real-mode if we have nested paging
135 * support.
136 */
137#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
138 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
139 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
140 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
141 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
142 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
143 | RT_BIT(X86_XCPT_XF))
144
145/** Maximum VM-instruction error number. */
146#define HMVMX_INSTR_ERROR_MAX 28
147
148/** Profiling macro. */
149#ifdef HM_PROFILE_EXIT_DISPATCH
150# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
151# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
152#else
153# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
154# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
155#endif
156
157/** Assert that preemption is disabled or covered by thread-context hooks. */
158#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
159 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
160
161/** Assert that we haven't migrated CPUs when thread-context hooks are not
162 * used. */
163#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
164 || (a_pVCpu)->hmr0.s.idEnteredCpu == RTMpCpuId(), \
165 ("Illegal migration! Entered on CPU %u Current %u\n", \
166 (a_pVCpu)->hmr0.s.idEnteredCpu, RTMpCpuId()))
167
168/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
169 * context. */
170#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
171 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
172 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
173
174/** Log the VM-exit reason with an easily visible marker to identify it in a
175 * potential sea of logging data. */
176#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
177 do { \
178 Log4(("VM-exit: vcpu[%RU32] %85s -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-\n", (a_pVCpu)->idCpu, \
179 HMGetVmxExitName(a_uExitReason))); \
180 } while (0) \
181
182
183/*********************************************************************************************************************************
184* Structures and Typedefs *
185*********************************************************************************************************************************/
186/**
187 * VMX per-VCPU transient state.
188 *
189 * A state structure for holding miscellaneous information across
190 * VMX non-root operation and restored after the transition.
191 *
192 * Note: The members are ordered and aligned such that the most
193 * frequently used ones (in the guest execution loop) fall within
194 * the first cache line.
195 */
196typedef struct VMXTRANSIENT
197{
198 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
199 uint32_t fVmcsFieldsRead;
200 /** The guest's TPR value used for TPR shadowing. */
201 uint8_t u8GuestTpr;
202 uint8_t abAlignment0[3];
203
204 /** Whether the VM-exit was caused by a page-fault during delivery of an
205 * external interrupt or NMI. */
206 bool fVectoringPF;
207 /** Whether the VM-exit was caused by a page-fault during delivery of a
208 * contributory exception or a page-fault. */
209 bool fVectoringDoublePF;
210 /** Whether the VM-entry failed or not. */
211 bool fVMEntryFailed;
212 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
213 * area after VM-exit. */
214 bool fRemoveTscAuxMsr;
215 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
216 bool fUpdatedTscOffsettingAndPreemptTimer;
217 /** Whether we are currently executing a nested-guest. */
218 bool fIsNestedGuest;
219 /** Whether the guest debug state was active at the time of VM-exit. */
220 bool fWasGuestDebugStateActive;
221 /** Whether the hyper debug state was active at the time of VM-exit. */
222 bool fWasHyperDebugStateActive;
223
224 /** The basic VM-exit reason. */
225 uint32_t uExitReason;
226 /** The VM-exit interruption error code. */
227 uint32_t uExitIntErrorCode;
228
229 /** The host's rflags/eflags. */
230 RTCCUINTREG fEFlags;
231
232 /** The VM-exit exit code qualification. */
233 uint64_t uExitQual;
234
235 /** The VMCS info. object. */
236 PVMXVMCSINFO pVmcsInfo;
237
238 /** The VM-exit interruption-information field. */
239 uint32_t uExitIntInfo;
240 /** The VM-exit instruction-length field. */
241 uint32_t cbExitInstr;
242
243 /** The VM-exit instruction-information field. */
244 VMXEXITINSTRINFO ExitInstrInfo;
245 /** IDT-vectoring information field. */
246 uint32_t uIdtVectoringInfo;
247
248 /** IDT-vectoring error code. */
249 uint32_t uIdtVectoringErrorCode;
250 uint32_t u32Alignment0;
251
252 /** The Guest-linear address. */
253 uint64_t uGuestLinearAddr;
254
255 /** The Guest-physical address. */
256 uint64_t uGuestPhysicalAddr;
257
258 /** The Guest pending-debug exceptions. */
259 uint64_t uGuestPendingDbgXcpts;
260
261 /** The VM-entry interruption-information field. */
262 uint32_t uEntryIntInfo;
263 /** The VM-entry exception error code field. */
264 uint32_t uEntryXcptErrorCode;
265
266 /** The VM-entry instruction length field. */
267 uint32_t cbEntryInstr;
268} VMXTRANSIENT;
269AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, fVmcsFieldsRead, 8);
271AssertCompileMemberAlignment(VMXTRANSIENT, fVectoringPF, 8);
272AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, 8);
273AssertCompileMemberAlignment(VMXTRANSIENT, fEFlags, 8);
274AssertCompileMemberAlignment(VMXTRANSIENT, uExitQual, 8);
275AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, 8);
276AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, 8);
277AssertCompileMemberAlignment(VMXTRANSIENT, ExitInstrInfo, 8);
278AssertCompileMemberAlignment(VMXTRANSIENT, uIdtVectoringErrorCode, 8);
279AssertCompileMemberAlignment(VMXTRANSIENT, uGuestLinearAddr, 8);
280AssertCompileMemberAlignment(VMXTRANSIENT, uGuestPhysicalAddr, 8);
281AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, 8);
282AssertCompileMemberAlignment(VMXTRANSIENT, cbEntryInstr, 8);
283/** Pointer to VMX transient state. */
284typedef VMXTRANSIENT *PVMXTRANSIENT;
285/** Pointer to a const VMX transient state. */
286typedef const VMXTRANSIENT *PCVMXTRANSIENT;
287
288/**
289 * VMX page allocation information.
290 */
291typedef struct
292{
293 uint32_t fValid; /**< Whether to allocate this page (e.g, based on a CPU feature). */
294 uint32_t uPadding0; /**< Padding to ensure array of these structs are aligned to a multiple of 8. */
295 PRTHCPHYS pHCPhys; /**< Where to store the host-physical address of the allocation. */
296 PRTR0PTR ppVirt; /**< Where to store the host-virtual address of the allocation. */
297} VMXPAGEALLOCINFO;
298/** Pointer to VMX page-allocation info. */
299typedef VMXPAGEALLOCINFO *PVMXPAGEALLOCINFO;
300/** Pointer to a const VMX page-allocation info. */
301typedef const VMXPAGEALLOCINFO *PCVMXPAGEALLOCINFO;
302AssertCompileSizeAlignment(VMXPAGEALLOCINFO, 8);
303
304/**
305 * Memory operand read or write access.
306 */
307typedef enum VMXMEMACCESS
308{
309 VMXMEMACCESS_READ = 0,
310 VMXMEMACCESS_WRITE = 1
311} VMXMEMACCESS;
312
313/**
314 * VMX VM-exit handler.
315 *
316 * @returns Strict VBox status code (i.e. informational status codes too).
317 * @param pVCpu The cross context virtual CPU structure.
318 * @param pVmxTransient The VMX-transient structure.
319 */
320#ifndef HMVMX_USE_FUNCTION_TABLE
321typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
322#else
323typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNVMXEXITHANDLER,(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient));
324/** Pointer to VM-exit handler. */
325typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
326#endif
327
328/**
329 * VMX VM-exit handler, non-strict status code.
330 *
331 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
332 *
333 * @returns VBox status code, no informational status code returned.
334 * @param pVCpu The cross context virtual CPU structure.
335 * @param pVmxTransient The VMX-transient structure.
336 *
337 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
338 * use of that status code will be replaced with VINF_EM_SOMETHING
339 * later when switching over to IEM.
340 */
341#ifndef HMVMX_USE_FUNCTION_TABLE
342typedef int FNVMXEXITHANDLERNSRC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
343#else
344typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
345#endif
346
347
348/*********************************************************************************************************************************
349* Internal Functions *
350*********************************************************************************************************************************/
351#ifndef HMVMX_USE_FUNCTION_TABLE
352DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
353# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
354# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
355#else
356# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
357# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
358#endif
359#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
360DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
361#endif
362
363static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
364
365/** @name VM-exit handler prototypes.
366 * @{
367 */
368static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
369static FNVMXEXITHANDLER hmR0VmxExitExtInt;
370static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
371static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
372static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
373static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
374static FNVMXEXITHANDLER hmR0VmxExitCpuid;
375static FNVMXEXITHANDLER hmR0VmxExitGetsec;
376static FNVMXEXITHANDLER hmR0VmxExitHlt;
377static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
378static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
379static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
380static FNVMXEXITHANDLER hmR0VmxExitVmcall;
381#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
382static FNVMXEXITHANDLER hmR0VmxExitVmclear;
383static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
384static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
385static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
386static FNVMXEXITHANDLER hmR0VmxExitVmread;
387static FNVMXEXITHANDLER hmR0VmxExitVmresume;
388static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
389static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
390static FNVMXEXITHANDLER hmR0VmxExitVmxon;
391static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
392#endif
393static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
394static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
395static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
396static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
397static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
398static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
399static FNVMXEXITHANDLER hmR0VmxExitMwait;
400static FNVMXEXITHANDLER hmR0VmxExitMtf;
401static FNVMXEXITHANDLER hmR0VmxExitMonitor;
402static FNVMXEXITHANDLER hmR0VmxExitPause;
403static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
404static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
405static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
406static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
407static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
408static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
409static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
410static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
411static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
412static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
413static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
414static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
415/** @} */
416
417#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
418/** @name Nested-guest VM-exit handler prototypes.
419 * @{
420 */
421static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
422static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
423static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
424static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
425static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
426static FNVMXEXITHANDLER hmR0VmxExitHltNested;
427static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
428static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
429static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
430static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
431static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
432static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
433static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
434static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
435static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
436static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
437static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
438static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
439static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
440static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
441static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
442static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
443static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
444static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
445static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
446static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
447static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
448static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
449static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
450/** @} */
451#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
452
453
454/*********************************************************************************************************************************
455* Global Variables *
456*********************************************************************************************************************************/
457#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
458/**
459 * Array of all VMCS fields.
460 * Any fields added to the VT-x spec. should be added here.
461 *
462 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
463 * of nested-guests.
464 */
465static const uint32_t g_aVmcsFields[] =
466{
467 /* 16-bit control fields. */
468 VMX_VMCS16_VPID,
469 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
470 VMX_VMCS16_EPTP_INDEX,
471
472 /* 16-bit guest-state fields. */
473 VMX_VMCS16_GUEST_ES_SEL,
474 VMX_VMCS16_GUEST_CS_SEL,
475 VMX_VMCS16_GUEST_SS_SEL,
476 VMX_VMCS16_GUEST_DS_SEL,
477 VMX_VMCS16_GUEST_FS_SEL,
478 VMX_VMCS16_GUEST_GS_SEL,
479 VMX_VMCS16_GUEST_LDTR_SEL,
480 VMX_VMCS16_GUEST_TR_SEL,
481 VMX_VMCS16_GUEST_INTR_STATUS,
482 VMX_VMCS16_GUEST_PML_INDEX,
483
484 /* 16-bits host-state fields. */
485 VMX_VMCS16_HOST_ES_SEL,
486 VMX_VMCS16_HOST_CS_SEL,
487 VMX_VMCS16_HOST_SS_SEL,
488 VMX_VMCS16_HOST_DS_SEL,
489 VMX_VMCS16_HOST_FS_SEL,
490 VMX_VMCS16_HOST_GS_SEL,
491 VMX_VMCS16_HOST_TR_SEL,
492
493 /* 64-bit control fields. */
494 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
495 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
496 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
497 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
498 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
499 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
500 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
501 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
502 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
503 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
504 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
505 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
506 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
507 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
508 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
509 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
510 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
511 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
512 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
513 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
514 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
515 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
516 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
517 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
518 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
519 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
520 VMX_VMCS64_CTRL_EPTP_FULL,
521 VMX_VMCS64_CTRL_EPTP_HIGH,
522 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
523 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
524 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
525 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
526 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
527 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
528 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
529 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
530 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
531 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
532 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
533 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
534 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
535 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
536 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
537 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
538 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
539 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
540 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
541 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
542 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
543 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
544
545 /* 64-bit read-only data fields. */
546 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
547 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
548
549 /* 64-bit guest-state fields. */
550 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
551 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
552 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
553 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
554 VMX_VMCS64_GUEST_PAT_FULL,
555 VMX_VMCS64_GUEST_PAT_HIGH,
556 VMX_VMCS64_GUEST_EFER_FULL,
557 VMX_VMCS64_GUEST_EFER_HIGH,
558 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
559 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
560 VMX_VMCS64_GUEST_PDPTE0_FULL,
561 VMX_VMCS64_GUEST_PDPTE0_HIGH,
562 VMX_VMCS64_GUEST_PDPTE1_FULL,
563 VMX_VMCS64_GUEST_PDPTE1_HIGH,
564 VMX_VMCS64_GUEST_PDPTE2_FULL,
565 VMX_VMCS64_GUEST_PDPTE2_HIGH,
566 VMX_VMCS64_GUEST_PDPTE3_FULL,
567 VMX_VMCS64_GUEST_PDPTE3_HIGH,
568 VMX_VMCS64_GUEST_BNDCFGS_FULL,
569 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
570
571 /* 64-bit host-state fields. */
572 VMX_VMCS64_HOST_PAT_FULL,
573 VMX_VMCS64_HOST_PAT_HIGH,
574 VMX_VMCS64_HOST_EFER_FULL,
575 VMX_VMCS64_HOST_EFER_HIGH,
576 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
577 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
578
579 /* 32-bit control fields. */
580 VMX_VMCS32_CTRL_PIN_EXEC,
581 VMX_VMCS32_CTRL_PROC_EXEC,
582 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
583 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
584 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
585 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
586 VMX_VMCS32_CTRL_EXIT,
587 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
588 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
589 VMX_VMCS32_CTRL_ENTRY,
590 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
591 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
592 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
593 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
594 VMX_VMCS32_CTRL_TPR_THRESHOLD,
595 VMX_VMCS32_CTRL_PROC_EXEC2,
596 VMX_VMCS32_CTRL_PLE_GAP,
597 VMX_VMCS32_CTRL_PLE_WINDOW,
598
599 /* 32-bits read-only fields. */
600 VMX_VMCS32_RO_VM_INSTR_ERROR,
601 VMX_VMCS32_RO_EXIT_REASON,
602 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
603 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
604 VMX_VMCS32_RO_IDT_VECTORING_INFO,
605 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
606 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
607 VMX_VMCS32_RO_EXIT_INSTR_INFO,
608
609 /* 32-bit guest-state fields. */
610 VMX_VMCS32_GUEST_ES_LIMIT,
611 VMX_VMCS32_GUEST_CS_LIMIT,
612 VMX_VMCS32_GUEST_SS_LIMIT,
613 VMX_VMCS32_GUEST_DS_LIMIT,
614 VMX_VMCS32_GUEST_FS_LIMIT,
615 VMX_VMCS32_GUEST_GS_LIMIT,
616 VMX_VMCS32_GUEST_LDTR_LIMIT,
617 VMX_VMCS32_GUEST_TR_LIMIT,
618 VMX_VMCS32_GUEST_GDTR_LIMIT,
619 VMX_VMCS32_GUEST_IDTR_LIMIT,
620 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
621 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
622 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
623 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
624 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
625 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
626 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
627 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
628 VMX_VMCS32_GUEST_INT_STATE,
629 VMX_VMCS32_GUEST_ACTIVITY_STATE,
630 VMX_VMCS32_GUEST_SMBASE,
631 VMX_VMCS32_GUEST_SYSENTER_CS,
632 VMX_VMCS32_PREEMPT_TIMER_VALUE,
633
634 /* 32-bit host-state fields. */
635 VMX_VMCS32_HOST_SYSENTER_CS,
636
637 /* Natural-width control fields. */
638 VMX_VMCS_CTRL_CR0_MASK,
639 VMX_VMCS_CTRL_CR4_MASK,
640 VMX_VMCS_CTRL_CR0_READ_SHADOW,
641 VMX_VMCS_CTRL_CR4_READ_SHADOW,
642 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
643 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
644 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
645 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
646
647 /* Natural-width read-only data fields. */
648 VMX_VMCS_RO_EXIT_QUALIFICATION,
649 VMX_VMCS_RO_IO_RCX,
650 VMX_VMCS_RO_IO_RSI,
651 VMX_VMCS_RO_IO_RDI,
652 VMX_VMCS_RO_IO_RIP,
653 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
654
655 /* Natural-width guest-state field */
656 VMX_VMCS_GUEST_CR0,
657 VMX_VMCS_GUEST_CR3,
658 VMX_VMCS_GUEST_CR4,
659 VMX_VMCS_GUEST_ES_BASE,
660 VMX_VMCS_GUEST_CS_BASE,
661 VMX_VMCS_GUEST_SS_BASE,
662 VMX_VMCS_GUEST_DS_BASE,
663 VMX_VMCS_GUEST_FS_BASE,
664 VMX_VMCS_GUEST_GS_BASE,
665 VMX_VMCS_GUEST_LDTR_BASE,
666 VMX_VMCS_GUEST_TR_BASE,
667 VMX_VMCS_GUEST_GDTR_BASE,
668 VMX_VMCS_GUEST_IDTR_BASE,
669 VMX_VMCS_GUEST_DR7,
670 VMX_VMCS_GUEST_RSP,
671 VMX_VMCS_GUEST_RIP,
672 VMX_VMCS_GUEST_RFLAGS,
673 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
674 VMX_VMCS_GUEST_SYSENTER_ESP,
675 VMX_VMCS_GUEST_SYSENTER_EIP,
676
677 /* Natural-width host-state fields */
678 VMX_VMCS_HOST_CR0,
679 VMX_VMCS_HOST_CR3,
680 VMX_VMCS_HOST_CR4,
681 VMX_VMCS_HOST_FS_BASE,
682 VMX_VMCS_HOST_GS_BASE,
683 VMX_VMCS_HOST_TR_BASE,
684 VMX_VMCS_HOST_GDTR_BASE,
685 VMX_VMCS_HOST_IDTR_BASE,
686 VMX_VMCS_HOST_SYSENTER_ESP,
687 VMX_VMCS_HOST_SYSENTER_EIP,
688 VMX_VMCS_HOST_RSP,
689 VMX_VMCS_HOST_RIP
690};
691#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
692
693#ifdef VBOX_STRICT
694static const uint32_t g_aVmcsSegBase[] =
695{
696 VMX_VMCS_GUEST_ES_BASE,
697 VMX_VMCS_GUEST_CS_BASE,
698 VMX_VMCS_GUEST_SS_BASE,
699 VMX_VMCS_GUEST_DS_BASE,
700 VMX_VMCS_GUEST_FS_BASE,
701 VMX_VMCS_GUEST_GS_BASE
702};
703static const uint32_t g_aVmcsSegSel[] =
704{
705 VMX_VMCS16_GUEST_ES_SEL,
706 VMX_VMCS16_GUEST_CS_SEL,
707 VMX_VMCS16_GUEST_SS_SEL,
708 VMX_VMCS16_GUEST_DS_SEL,
709 VMX_VMCS16_GUEST_FS_SEL,
710 VMX_VMCS16_GUEST_GS_SEL
711};
712static const uint32_t g_aVmcsSegLimit[] =
713{
714 VMX_VMCS32_GUEST_ES_LIMIT,
715 VMX_VMCS32_GUEST_CS_LIMIT,
716 VMX_VMCS32_GUEST_SS_LIMIT,
717 VMX_VMCS32_GUEST_DS_LIMIT,
718 VMX_VMCS32_GUEST_FS_LIMIT,
719 VMX_VMCS32_GUEST_GS_LIMIT
720};
721static const uint32_t g_aVmcsSegAttr[] =
722{
723 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
724 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
725 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
726 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
727 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
728 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
729};
730AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
731AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
732AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
733AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
734#endif /* VBOX_STRICT */
735
736#ifdef HMVMX_USE_FUNCTION_TABLE
737/**
738 * VMX_EXIT dispatch table.
739 */
740static const struct CLANG11NOTHROWWEIRDNESS { PFNVMXEXITHANDLER pfn; } g_aVMExitHandlers[VMX_EXIT_MAX + 1] =
741{
742 /* 0 VMX_EXIT_XCPT_OR_NMI */ { hmR0VmxExitXcptOrNmi },
743 /* 1 VMX_EXIT_EXT_INT */ { hmR0VmxExitExtInt },
744 /* 2 VMX_EXIT_TRIPLE_FAULT */ { hmR0VmxExitTripleFault },
745 /* 3 VMX_EXIT_INIT_SIGNAL */ { hmR0VmxExitErrUnexpected },
746 /* 4 VMX_EXIT_SIPI */ { hmR0VmxExitErrUnexpected },
747 /* 5 VMX_EXIT_IO_SMI */ { hmR0VmxExitErrUnexpected },
748 /* 6 VMX_EXIT_SMI */ { hmR0VmxExitErrUnexpected },
749 /* 7 VMX_EXIT_INT_WINDOW */ { hmR0VmxExitIntWindow },
750 /* 8 VMX_EXIT_NMI_WINDOW */ { hmR0VmxExitNmiWindow },
751 /* 9 VMX_EXIT_TASK_SWITCH */ { hmR0VmxExitTaskSwitch },
752 /* 10 VMX_EXIT_CPUID */ { hmR0VmxExitCpuid },
753 /* 11 VMX_EXIT_GETSEC */ { hmR0VmxExitGetsec },
754 /* 12 VMX_EXIT_HLT */ { hmR0VmxExitHlt },
755 /* 13 VMX_EXIT_INVD */ { hmR0VmxExitInvd },
756 /* 14 VMX_EXIT_INVLPG */ { hmR0VmxExitInvlpg },
757 /* 15 VMX_EXIT_RDPMC */ { hmR0VmxExitRdpmc },
758 /* 16 VMX_EXIT_RDTSC */ { hmR0VmxExitRdtsc },
759 /* 17 VMX_EXIT_RSM */ { hmR0VmxExitErrUnexpected },
760 /* 18 VMX_EXIT_VMCALL */ { hmR0VmxExitVmcall },
761#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
762 /* 19 VMX_EXIT_VMCLEAR */ { hmR0VmxExitVmclear },
763 /* 20 VMX_EXIT_VMLAUNCH */ { hmR0VmxExitVmlaunch },
764 /* 21 VMX_EXIT_VMPTRLD */ { hmR0VmxExitVmptrld },
765 /* 22 VMX_EXIT_VMPTRST */ { hmR0VmxExitVmptrst },
766 /* 23 VMX_EXIT_VMREAD */ { hmR0VmxExitVmread },
767 /* 24 VMX_EXIT_VMRESUME */ { hmR0VmxExitVmresume },
768 /* 25 VMX_EXIT_VMWRITE */ { hmR0VmxExitVmwrite },
769 /* 26 VMX_EXIT_VMXOFF */ { hmR0VmxExitVmxoff },
770 /* 27 VMX_EXIT_VMXON */ { hmR0VmxExitVmxon },
771#else
772 /* 19 VMX_EXIT_VMCLEAR */ { hmR0VmxExitSetPendingXcptUD },
773 /* 20 VMX_EXIT_VMLAUNCH */ { hmR0VmxExitSetPendingXcptUD },
774 /* 21 VMX_EXIT_VMPTRLD */ { hmR0VmxExitSetPendingXcptUD },
775 /* 22 VMX_EXIT_VMPTRST */ { hmR0VmxExitSetPendingXcptUD },
776 /* 23 VMX_EXIT_VMREAD */ { hmR0VmxExitSetPendingXcptUD },
777 /* 24 VMX_EXIT_VMRESUME */ { hmR0VmxExitSetPendingXcptUD },
778 /* 25 VMX_EXIT_VMWRITE */ { hmR0VmxExitSetPendingXcptUD },
779 /* 26 VMX_EXIT_VMXOFF */ { hmR0VmxExitSetPendingXcptUD },
780 /* 27 VMX_EXIT_VMXON */ { hmR0VmxExitSetPendingXcptUD },
781#endif
782 /* 28 VMX_EXIT_MOV_CRX */ { hmR0VmxExitMovCRx },
783 /* 29 VMX_EXIT_MOV_DRX */ { hmR0VmxExitMovDRx },
784 /* 30 VMX_EXIT_IO_INSTR */ { hmR0VmxExitIoInstr },
785 /* 31 VMX_EXIT_RDMSR */ { hmR0VmxExitRdmsr },
786 /* 32 VMX_EXIT_WRMSR */ { hmR0VmxExitWrmsr },
787 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ { hmR0VmxExitErrInvalidGuestState },
788 /* 34 VMX_EXIT_ERR_MSR_LOAD */ { hmR0VmxExitErrUnexpected },
789 /* 35 UNDEFINED */ { hmR0VmxExitErrUnexpected },
790 /* 36 VMX_EXIT_MWAIT */ { hmR0VmxExitMwait },
791 /* 37 VMX_EXIT_MTF */ { hmR0VmxExitMtf },
792 /* 38 UNDEFINED */ { hmR0VmxExitErrUnexpected },
793 /* 39 VMX_EXIT_MONITOR */ { hmR0VmxExitMonitor },
794 /* 40 VMX_EXIT_PAUSE */ { hmR0VmxExitPause },
795 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ { hmR0VmxExitErrUnexpected },
796 /* 42 UNDEFINED */ { hmR0VmxExitErrUnexpected },
797 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ { hmR0VmxExitTprBelowThreshold },
798 /* 44 VMX_EXIT_APIC_ACCESS */ { hmR0VmxExitApicAccess },
799 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ { hmR0VmxExitErrUnexpected },
800 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ { hmR0VmxExitErrUnexpected },
801 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ { hmR0VmxExitErrUnexpected },
802 /* 48 VMX_EXIT_EPT_VIOLATION */ { hmR0VmxExitEptViolation },
803 /* 49 VMX_EXIT_EPT_MISCONFIG */ { hmR0VmxExitEptMisconfig },
804 /* 50 VMX_EXIT_INVEPT */ { hmR0VmxExitSetPendingXcptUD },
805 /* 51 VMX_EXIT_RDTSCP */ { hmR0VmxExitRdtscp },
806 /* 52 VMX_EXIT_PREEMPT_TIMER */ { hmR0VmxExitPreemptTimer },
807#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
808 /* 53 VMX_EXIT_INVVPID */ { hmR0VmxExitInvvpid },
809#else
810 /* 53 VMX_EXIT_INVVPID */ { hmR0VmxExitSetPendingXcptUD },
811#endif
812 /* 54 VMX_EXIT_WBINVD */ { hmR0VmxExitWbinvd },
813 /* 55 VMX_EXIT_XSETBV */ { hmR0VmxExitXsetbv },
814 /* 56 VMX_EXIT_APIC_WRITE */ { hmR0VmxExitErrUnexpected },
815 /* 57 VMX_EXIT_RDRAND */ { hmR0VmxExitErrUnexpected },
816 /* 58 VMX_EXIT_INVPCID */ { hmR0VmxExitInvpcid },
817 /* 59 VMX_EXIT_VMFUNC */ { hmR0VmxExitErrUnexpected },
818 /* 60 VMX_EXIT_ENCLS */ { hmR0VmxExitErrUnexpected },
819 /* 61 VMX_EXIT_RDSEED */ { hmR0VmxExitErrUnexpected },
820 /* 62 VMX_EXIT_PML_FULL */ { hmR0VmxExitErrUnexpected },
821 /* 63 VMX_EXIT_XSAVES */ { hmR0VmxExitErrUnexpected },
822 /* 64 VMX_EXIT_XRSTORS */ { hmR0VmxExitErrUnexpected },
823 /* 65 UNDEFINED */ { hmR0VmxExitErrUnexpected },
824 /* 66 VMX_EXIT_SPP_EVENT */ { hmR0VmxExitErrUnexpected },
825 /* 67 VMX_EXIT_UMWAIT */ { hmR0VmxExitErrUnexpected },
826 /* 68 VMX_EXIT_TPAUSE */ { hmR0VmxExitErrUnexpected },
827};
828#endif /* HMVMX_USE_FUNCTION_TABLE */
829
830#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
831static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
832{
833 /* 0 */ "(Not Used)",
834 /* 1 */ "VMCALL executed in VMX root operation.",
835 /* 2 */ "VMCLEAR with invalid physical address.",
836 /* 3 */ "VMCLEAR with VMXON pointer.",
837 /* 4 */ "VMLAUNCH with non-clear VMCS.",
838 /* 5 */ "VMRESUME with non-launched VMCS.",
839 /* 6 */ "VMRESUME after VMXOFF",
840 /* 7 */ "VM-entry with invalid control fields.",
841 /* 8 */ "VM-entry with invalid host state fields.",
842 /* 9 */ "VMPTRLD with invalid physical address.",
843 /* 10 */ "VMPTRLD with VMXON pointer.",
844 /* 11 */ "VMPTRLD with incorrect revision identifier.",
845 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
846 /* 13 */ "VMWRITE to read-only VMCS component.",
847 /* 14 */ "(Not Used)",
848 /* 15 */ "VMXON executed in VMX root operation.",
849 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
850 /* 17 */ "VM-entry with non-launched executing VMCS.",
851 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
852 /* 19 */ "VMCALL with non-clear VMCS.",
853 /* 20 */ "VMCALL with invalid VM-exit control fields.",
854 /* 21 */ "(Not Used)",
855 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
856 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
857 /* 24 */ "VMCALL with invalid SMM-monitor features.",
858 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
859 /* 26 */ "VM-entry with events blocked by MOV SS.",
860 /* 27 */ "(Not Used)",
861 /* 28 */ "Invalid operand to INVEPT/INVVPID."
862};
863#endif /* VBOX_STRICT && LOG_ENABLED */
864
865
866/**
867 * Checks if the given MSR is part of the lastbranch-from-IP MSR stack.
868 * @returns @c true if it's part of LBR stack, @c false otherwise.
869 *
870 * @param pVM The cross context VM structure.
871 * @param idMsr The MSR.
872 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
873 * Optional, can be NULL.
874 *
875 * @remarks Must only be called when LBR is enabled.
876 */
877DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchFromMsr(PCVMCC pVM, uint32_t idMsr, uint32_t *pidxMsr)
878{
879 Assert(pVM->hmr0.s.vmx.fLbr);
880 Assert(pVM->hmr0.s.vmx.idLbrFromIpMsrFirst);
881 uint32_t const cLbrStack = pVM->hmr0.s.vmx.idLbrFromIpMsrLast - pVM->hmr0.s.vmx.idLbrFromIpMsrFirst + 1;
882 uint32_t const idxMsr = idMsr - pVM->hmr0.s.vmx.idLbrFromIpMsrFirst;
883 if (idxMsr < cLbrStack)
884 {
885 if (pidxMsr)
886 *pidxMsr = idxMsr;
887 return true;
888 }
889 return false;
890}
891
892
893/**
894 * Checks if the given MSR is part of the lastbranch-to-IP MSR stack.
895 * @returns @c true if it's part of LBR stack, @c false otherwise.
896 *
897 * @param pVM The cross context VM structure.
898 * @param idMsr The MSR.
899 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
900 * Optional, can be NULL.
901 *
902 * @remarks Must only be called when LBR is enabled and when lastbranch-to-IP MSRs
903 * are supported by the CPU (see hmR0VmxSetupLbrMsrRange).
904 */
905DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchToMsr(PCVMCC pVM, uint32_t idMsr, uint32_t *pidxMsr)
906{
907 Assert(pVM->hmr0.s.vmx.fLbr);
908 if (pVM->hmr0.s.vmx.idLbrToIpMsrFirst)
909 {
910 uint32_t const cLbrStack = pVM->hmr0.s.vmx.idLbrToIpMsrLast - pVM->hmr0.s.vmx.idLbrToIpMsrFirst + 1;
911 uint32_t const idxMsr = idMsr - pVM->hmr0.s.vmx.idLbrToIpMsrFirst;
912 if (idxMsr < cLbrStack)
913 {
914 if (pidxMsr)
915 *pidxMsr = idxMsr;
916 return true;
917 }
918 }
919 return false;
920}
921
922
923/**
924 * Gets the CR0 guest/host mask.
925 *
926 * These bits typically does not change through the lifetime of a VM. Any bit set in
927 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
928 * by the guest.
929 *
930 * @returns The CR0 guest/host mask.
931 * @param pVCpu The cross context virtual CPU structure.
932 */
933static uint64_t hmR0VmxGetFixedCr0Mask(PCVMCPUCC pVCpu)
934{
935 /*
936 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
937 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
938 *
939 * Furthermore, modifications to any bits that are reserved/unspecified currently
940 * by the Intel spec. must also cause a VM-exit. This prevents unpredictable behavior
941 * when future CPUs specify and use currently reserved/unspecified bits.
942 */
943 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
944 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
945 * and @bugref{6944}. */
946 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
947 return ( X86_CR0_PE
948 | X86_CR0_NE
949 | (pVM->hmr0.s.fNestedPaging ? 0 : X86_CR0_WP)
950 | X86_CR0_PG
951 | VMX_EXIT_HOST_CR0_IGNORE_MASK);
952}
953
954
955/**
956 * Gets the CR4 guest/host mask.
957 *
958 * These bits typically does not change through the lifetime of a VM. Any bit set in
959 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
960 * by the guest.
961 *
962 * @returns The CR4 guest/host mask.
963 * @param pVCpu The cross context virtual CPU structure.
964 */
965static uint64_t hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
966{
967 /*
968 * We construct a mask of all CR4 bits that the guest can modify without causing
969 * a VM-exit. Then invert this mask to obtain all CR4 bits that should cause
970 * a VM-exit when the guest attempts to modify them when executing using
971 * hardware-assisted VMX.
972 *
973 * When a feature is not exposed to the guest (and may be present on the host),
974 * we want to intercept guest modifications to the bit so we can emulate proper
975 * behavior (e.g., #GP).
976 *
977 * Furthermore, only modifications to those bits that don't require immediate
978 * emulation is allowed. For e.g., PCIDE is excluded because the behavior
979 * depends on CR3 which might not always be the guest value while executing
980 * using hardware-assisted VMX.
981 */
982 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
983 bool const fFsGsBase = pVM->cpum.ro.GuestFeatures.fFsGsBase;
984 bool const fXSaveRstor = pVM->cpum.ro.GuestFeatures.fXSaveRstor;
985 bool const fFxSaveRstor = pVM->cpum.ro.GuestFeatures.fFxSaveRstor;
986
987 /*
988 * Paranoia.
989 * Ensure features exposed to the guest are present on the host.
990 */
991 Assert(!fFsGsBase || pVM->cpum.ro.HostFeatures.fFsGsBase);
992 Assert(!fXSaveRstor || pVM->cpum.ro.HostFeatures.fXSaveRstor);
993 Assert(!fFxSaveRstor || pVM->cpum.ro.HostFeatures.fFxSaveRstor);
994
995 uint64_t const fGstMask = ( X86_CR4_PVI
996 | X86_CR4_TSD
997 | X86_CR4_DE
998 | X86_CR4_MCE
999 | X86_CR4_PCE
1000 | X86_CR4_OSXMMEEXCPT
1001 | (fFsGsBase ? X86_CR4_FSGSBASE : 0)
1002 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
1003 | (fFxSaveRstor ? X86_CR4_OSFXSR : 0));
1004 return ~fGstMask;
1005}
1006
1007
1008/**
1009 * Gets the active (in use) VMCS info. object for the specified VCPU.
1010 *
1011 * This is either the guest or nested-guest VMCS info. and need not necessarily
1012 * pertain to the "current" VMCS (in the VMX definition of the term). For instance,
1013 * if the VM-entry failed due to an invalid-guest state, we may have "cleared" the
1014 * current VMCS while returning to ring-3. However, the VMCS info. object for that
1015 * VMCS would still be active and returned here so that we could dump the VMCS
1016 * fields to ring-3 for diagnostics. This function is thus only used to
1017 * distinguish between the nested-guest or guest VMCS.
1018 *
1019 * @returns The active VMCS information.
1020 * @param pVCpu The cross context virtual CPU structure.
1021 *
1022 * @thread EMT.
1023 * @remarks This function may be called with preemption or interrupts disabled!
1024 */
1025DECLINLINE(PVMXVMCSINFO) hmGetVmxActiveVmcsInfo(PVMCPUCC pVCpu)
1026{
1027 if (!pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
1028 return &pVCpu->hmr0.s.vmx.VmcsInfo;
1029 return &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1030}
1031
1032
1033/**
1034 * Returns whether the VM-exit MSR-store area differs from the VM-exit MSR-load
1035 * area.
1036 *
1037 * @returns @c true if it's different, @c false otherwise.
1038 * @param pVmcsInfo The VMCS info. object.
1039 */
1040DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
1041{
1042 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
1043 && pVmcsInfo->pvGuestMsrStore);
1044}
1045
1046
1047/**
1048 * Sets the given Processor-based VM-execution controls.
1049 *
1050 * @param pVmxTransient The VMX-transient structure.
1051 * @param uProcCtls The Processor-based VM-execution controls to set.
1052 */
1053static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1054{
1055 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1056 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
1057 {
1058 pVmcsInfo->u32ProcCtls |= uProcCtls;
1059 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1060 AssertRC(rc);
1061 }
1062}
1063
1064
1065/**
1066 * Removes the given Processor-based VM-execution controls.
1067 *
1068 * @param pVCpu The cross context virtual CPU structure.
1069 * @param pVmxTransient The VMX-transient structure.
1070 * @param uProcCtls The Processor-based VM-execution controls to remove.
1071 *
1072 * @remarks When executing a nested-guest, this will not remove any of the specified
1073 * controls if the nested hypervisor has set any one of them.
1074 */
1075static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1076{
1077 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1078 if (pVmcsInfo->u32ProcCtls & uProcCtls)
1079 {
1080#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1081 if ( !pVmxTransient->fIsNestedGuest
1082 || !CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uProcCtls))
1083#else
1084 NOREF(pVCpu);
1085 if (!pVmxTransient->fIsNestedGuest)
1086#endif
1087 {
1088 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
1089 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1090 AssertRC(rc);
1091 }
1092 }
1093}
1094
1095
1096/**
1097 * Sets the TSC offset for the current VMCS.
1098 *
1099 * @param uTscOffset The TSC offset to set.
1100 * @param pVmcsInfo The VMCS info. object.
1101 */
1102static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
1103{
1104 if (pVmcsInfo->u64TscOffset != uTscOffset)
1105 {
1106 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
1107 AssertRC(rc);
1108 pVmcsInfo->u64TscOffset = uTscOffset;
1109 }
1110}
1111
1112
1113/**
1114 * Adds one or more exceptions to the exception bitmap and commits it to the current
1115 * VMCS.
1116 *
1117 * @param pVmxTransient The VMX-transient structure.
1118 * @param uXcptMask The exception(s) to add.
1119 */
1120static void hmR0VmxAddXcptInterceptMask(PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1121{
1122 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1123 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1124 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1125 {
1126 uXcptBitmap |= uXcptMask;
1127 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1128 AssertRC(rc);
1129 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1130 }
1131}
1132
1133
1134/**
1135 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1136 *
1137 * @param pVmxTransient The VMX-transient structure.
1138 * @param uXcpt The exception to add.
1139 */
1140static void hmR0VmxAddXcptIntercept(PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1141{
1142 Assert(uXcpt <= X86_XCPT_LAST);
1143 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1144}
1145
1146
1147/**
1148 * Remove one or more exceptions from the exception bitmap and commits it to the
1149 * current VMCS.
1150 *
1151 * This takes care of not removing the exception intercept if a nested-guest
1152 * requires the exception to be intercepted.
1153 *
1154 * @returns VBox status code.
1155 * @param pVCpu The cross context virtual CPU structure.
1156 * @param pVmxTransient The VMX-transient structure.
1157 * @param uXcptMask The exception(s) to remove.
1158 */
1159static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1160{
1161 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1162 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1163 if (u32XcptBitmap & uXcptMask)
1164 {
1165#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1166 if (!pVmxTransient->fIsNestedGuest)
1167 { /* likely */ }
1168 else
1169 {
1170 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1171 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1172 }
1173#endif
1174#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1175 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1176 | RT_BIT(X86_XCPT_DE)
1177 | RT_BIT(X86_XCPT_NM)
1178 | RT_BIT(X86_XCPT_TS)
1179 | RT_BIT(X86_XCPT_UD)
1180 | RT_BIT(X86_XCPT_NP)
1181 | RT_BIT(X86_XCPT_SS)
1182 | RT_BIT(X86_XCPT_GP)
1183 | RT_BIT(X86_XCPT_PF)
1184 | RT_BIT(X86_XCPT_MF));
1185#elif defined(HMVMX_ALWAYS_TRAP_PF)
1186 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1187#endif
1188 if (uXcptMask)
1189 {
1190 /* Validate we are not removing any essential exception intercepts. */
1191 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1192 NOREF(pVCpu);
1193 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1194 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1195
1196 /* Remove it from the exception bitmap. */
1197 u32XcptBitmap &= ~uXcptMask;
1198
1199 /* Commit and update the cache if necessary. */
1200 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1201 {
1202 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1203 AssertRC(rc);
1204 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1205 }
1206 }
1207 }
1208 return VINF_SUCCESS;
1209}
1210
1211
1212/**
1213 * Remove an exceptions from the exception bitmap and commits it to the current
1214 * VMCS.
1215 *
1216 * @returns VBox status code.
1217 * @param pVCpu The cross context virtual CPU structure.
1218 * @param pVmxTransient The VMX-transient structure.
1219 * @param uXcpt The exception to remove.
1220 */
1221static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1222{
1223 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1224}
1225
1226
1227/**
1228 * Loads the VMCS specified by the VMCS info. object.
1229 *
1230 * @returns VBox status code.
1231 * @param pVmcsInfo The VMCS info. object.
1232 *
1233 * @remarks Can be called with interrupts disabled.
1234 */
1235static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1236{
1237 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1238 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1239
1240 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1241 if (RT_SUCCESS(rc))
1242 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1243 return rc;
1244}
1245
1246
1247/**
1248 * Clears the VMCS specified by the VMCS info. object.
1249 *
1250 * @returns VBox status code.
1251 * @param pVmcsInfo The VMCS info. object.
1252 *
1253 * @remarks Can be called with interrupts disabled.
1254 */
1255static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1256{
1257 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1258 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1259
1260 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1261 if (RT_SUCCESS(rc))
1262 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1263 return rc;
1264}
1265
1266
1267#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1268/**
1269 * Loads the shadow VMCS specified by the VMCS info. object.
1270 *
1271 * @returns VBox status code.
1272 * @param pVmcsInfo The VMCS info. object.
1273 *
1274 * @remarks Can be called with interrupts disabled.
1275 */
1276static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1277{
1278 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1279 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1280
1281 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1282 if (RT_SUCCESS(rc))
1283 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1284 return rc;
1285}
1286
1287
1288/**
1289 * Clears the shadow VMCS specified by the VMCS info. object.
1290 *
1291 * @returns VBox status code.
1292 * @param pVmcsInfo The VMCS info. object.
1293 *
1294 * @remarks Can be called with interrupts disabled.
1295 */
1296static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1297{
1298 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1299 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1300
1301 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1302 if (RT_SUCCESS(rc))
1303 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1304 return rc;
1305}
1306
1307
1308/**
1309 * Switches from and to the specified VMCSes.
1310 *
1311 * @returns VBox status code.
1312 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1313 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1314 *
1315 * @remarks Called with interrupts disabled.
1316 */
1317static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1318{
1319 /*
1320 * Clear the VMCS we are switching out if it has not already been cleared.
1321 * This will sync any CPU internal data back to the VMCS.
1322 */
1323 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1324 {
1325 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1326 if (RT_SUCCESS(rc))
1327 {
1328 /*
1329 * The shadow VMCS, if any, would not be active at this point since we
1330 * would have cleared it while importing the virtual hardware-virtualization
1331 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1332 * clear the shadow VMCS here, just assert for safety.
1333 */
1334 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1335 }
1336 else
1337 return rc;
1338 }
1339
1340 /*
1341 * Clear the VMCS we are switching to if it has not already been cleared.
1342 * This will initialize the VMCS launch state to "clear" required for loading it.
1343 *
1344 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1345 */
1346 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1347 {
1348 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1349 if (RT_SUCCESS(rc))
1350 { /* likely */ }
1351 else
1352 return rc;
1353 }
1354
1355 /*
1356 * Finally, load the VMCS we are switching to.
1357 */
1358 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1359}
1360
1361
1362/**
1363 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1364 * caller.
1365 *
1366 * @returns VBox status code.
1367 * @param pVCpu The cross context virtual CPU structure.
1368 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1369 * true) or guest VMCS (pass false).
1370 */
1371static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1372{
1373 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1374 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1375
1376 PVMXVMCSINFO pVmcsInfoFrom;
1377 PVMXVMCSINFO pVmcsInfoTo;
1378 if (fSwitchToNstGstVmcs)
1379 {
1380 pVmcsInfoFrom = &pVCpu->hmr0.s.vmx.VmcsInfo;
1381 pVmcsInfoTo = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1382 }
1383 else
1384 {
1385 pVmcsInfoFrom = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1386 pVmcsInfoTo = &pVCpu->hmr0.s.vmx.VmcsInfo;
1387 }
1388
1389 /*
1390 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1391 * preemption hook code path acquires the current VMCS.
1392 */
1393 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1394
1395 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1396 if (RT_SUCCESS(rc))
1397 {
1398 pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1399 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcsCopyForRing3 = fSwitchToNstGstVmcs;
1400
1401 /*
1402 * If we are switching to a VMCS that was executed on a different host CPU or was
1403 * never executed before, flag that we need to export the host state before executing
1404 * guest/nested-guest code using hardware-assisted VMX.
1405 *
1406 * This could probably be done in a preemptible context since the preemption hook
1407 * will flag the necessary change in host context. However, since preemption is
1408 * already disabled and to avoid making assumptions about host specific code in
1409 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1410 * disabled.
1411 */
1412 if (pVmcsInfoTo->idHostCpuState == RTMpCpuId())
1413 { /* likely */ }
1414 else
1415 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1416
1417 ASMSetFlags(fEFlags);
1418
1419 /*
1420 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1421 * flag that we need to update the host MSR values there. Even if we decide in the
1422 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1423 * if its content differs, we would have to update the host MSRs anyway.
1424 */
1425 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
1426 }
1427 else
1428 ASMSetFlags(fEFlags);
1429 return rc;
1430}
1431#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1432
1433
1434/**
1435 * Updates the VM's last error record.
1436 *
1437 * If there was a VMX instruction error, reads the error data from the VMCS and
1438 * updates VCPU's last error record as well.
1439 *
1440 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1441 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1442 * VERR_VMX_INVALID_VMCS_FIELD.
1443 * @param rc The error code.
1444 */
1445static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1446{
1447 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1448 || rc == VERR_VMX_UNABLE_TO_START_VM)
1449 {
1450 AssertPtrReturnVoid(pVCpu);
1451 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1452 }
1453 pVCpu->CTX_SUFF(pVM)->hm.s.ForR3.rcInit = rc;
1454}
1455
1456
1457#ifdef VBOX_STRICT
1458/**
1459 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1460 * transient structure.
1461 *
1462 * @param pVmxTransient The VMX-transient structure.
1463 */
1464DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1465{
1466 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1467 AssertRC(rc);
1468}
1469
1470
1471/**
1472 * Reads the VM-entry exception error code field from the VMCS into
1473 * the VMX transient structure.
1474 *
1475 * @param pVmxTransient The VMX-transient structure.
1476 */
1477DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1478{
1479 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1480 AssertRC(rc);
1481}
1482
1483
1484/**
1485 * Reads the VM-entry exception error code field from the VMCS into
1486 * the VMX transient structure.
1487 *
1488 * @param pVmxTransient The VMX-transient structure.
1489 */
1490DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1491{
1492 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1493 AssertRC(rc);
1494}
1495#endif /* VBOX_STRICT */
1496
1497
1498/**
1499 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1500 * transient structure.
1501 *
1502 * @param pVmxTransient The VMX-transient structure.
1503 */
1504DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1505{
1506 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1507 {
1508 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1509 AssertRC(rc);
1510 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1511 }
1512}
1513
1514
1515/**
1516 * Reads the VM-exit interruption error code from the VMCS into the VMX
1517 * transient structure.
1518 *
1519 * @param pVmxTransient The VMX-transient structure.
1520 */
1521DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1522{
1523 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1524 {
1525 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1526 AssertRC(rc);
1527 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1528 }
1529}
1530
1531
1532/**
1533 * Reads the VM-exit instruction length field from the VMCS into the VMX
1534 * transient structure.
1535 *
1536 * @param pVmxTransient The VMX-transient structure.
1537 */
1538DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1539{
1540 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1541 {
1542 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1543 AssertRC(rc);
1544 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1545 }
1546}
1547
1548
1549/**
1550 * Reads the VM-exit instruction-information field from the VMCS into
1551 * the VMX transient structure.
1552 *
1553 * @param pVmxTransient The VMX-transient structure.
1554 */
1555DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1556{
1557 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1558 {
1559 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1560 AssertRC(rc);
1561 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1562 }
1563}
1564
1565
1566/**
1567 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1568 *
1569 * @param pVmxTransient The VMX-transient structure.
1570 */
1571DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1572{
1573 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1574 {
1575 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1576 AssertRC(rc);
1577 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1578 }
1579}
1580
1581
1582/**
1583 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1584 *
1585 * @param pVmxTransient The VMX-transient structure.
1586 */
1587DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1588{
1589 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1590 {
1591 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1592 AssertRC(rc);
1593 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1594 }
1595}
1596
1597
1598/**
1599 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1600 *
1601 * @param pVmxTransient The VMX-transient structure.
1602 */
1603DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1604{
1605 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1606 {
1607 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1608 AssertRC(rc);
1609 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1610 }
1611}
1612
1613#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1614/**
1615 * Reads the Guest pending-debug exceptions from the VMCS into the VMX transient
1616 * structure.
1617 *
1618 * @param pVmxTransient The VMX-transient structure.
1619 */
1620DECLINLINE(void) hmR0VmxReadGuestPendingDbgXctps(PVMXTRANSIENT pVmxTransient)
1621{
1622 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PENDING_DBG_XCPTS))
1623 {
1624 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &pVmxTransient->uGuestPendingDbgXcpts);
1625 AssertRC(rc);
1626 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PENDING_DBG_XCPTS;
1627 }
1628}
1629#endif
1630
1631/**
1632 * Reads the IDT-vectoring information field from the VMCS into the VMX
1633 * transient structure.
1634 *
1635 * @param pVmxTransient The VMX-transient structure.
1636 *
1637 * @remarks No-long-jump zone!!!
1638 */
1639DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1640{
1641 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1642 {
1643 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1644 AssertRC(rc);
1645 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1646 }
1647}
1648
1649
1650/**
1651 * Reads the IDT-vectoring error code from the VMCS into the VMX
1652 * transient structure.
1653 *
1654 * @param pVmxTransient The VMX-transient structure.
1655 */
1656DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1657{
1658 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1659 {
1660 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1661 AssertRC(rc);
1662 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1663 }
1664}
1665
1666#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1667/**
1668 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1669 *
1670 * @param pVmxTransient The VMX-transient structure.
1671 */
1672static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1673{
1674 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1675 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1676 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1677 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1678 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1679 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1680 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1681 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1682 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1683 AssertRC(rc);
1684 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1685 | HMVMX_READ_EXIT_INSTR_LEN
1686 | HMVMX_READ_EXIT_INSTR_INFO
1687 | HMVMX_READ_IDT_VECTORING_INFO
1688 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1689 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1690 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1691 | HMVMX_READ_GUEST_LINEAR_ADDR
1692 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1693}
1694#endif
1695
1696/**
1697 * Enters VMX root mode operation on the current CPU.
1698 *
1699 * @returns VBox status code.
1700 * @param pHostCpu The HM physical-CPU structure.
1701 * @param pVM The cross context VM structure. Can be
1702 * NULL, after a resume.
1703 * @param HCPhysCpuPage Physical address of the VMXON region.
1704 * @param pvCpuPage Pointer to the VMXON region.
1705 */
1706static int hmR0VmxEnterRootMode(PHMPHYSCPU pHostCpu, PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1707{
1708 Assert(pHostCpu);
1709 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1710 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1711 Assert(pvCpuPage);
1712 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1713
1714 if (pVM)
1715 {
1716 /* Write the VMCS revision identifier to the VMXON region. */
1717 *(uint32_t *)pvCpuPage = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
1718 }
1719
1720 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1721 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1722
1723 /* Enable the VMX bit in CR4 if necessary. */
1724 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1725
1726 /* Record whether VMXE was already prior to us enabling it above. */
1727 pHostCpu->fVmxeAlreadyEnabled = RT_BOOL(uOldCr4 & X86_CR4_VMXE);
1728
1729 /* Enter VMX root mode. */
1730 int rc = VMXEnable(HCPhysCpuPage);
1731 if (RT_FAILURE(rc))
1732 {
1733 /* Restore CR4.VMXE if it was not set prior to our attempt to set it above. */
1734 if (!pHostCpu->fVmxeAlreadyEnabled)
1735 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1736
1737 if (pVM)
1738 pVM->hm.s.ForR3.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1739 }
1740
1741 /* Restore interrupts. */
1742 ASMSetFlags(fEFlags);
1743 return rc;
1744}
1745
1746
1747/**
1748 * Exits VMX root mode operation on the current CPU.
1749 *
1750 * @returns VBox status code.
1751 * @param pHostCpu The HM physical-CPU structure.
1752 */
1753static int hmR0VmxLeaveRootMode(PHMPHYSCPU pHostCpu)
1754{
1755 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1756
1757 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1758 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1759
1760 /* If we're for some reason not in VMX root mode, then don't leave it. */
1761 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1762
1763 int rc;
1764 if (uHostCr4 & X86_CR4_VMXE)
1765 {
1766 /* Exit VMX root mode and clear the VMX bit in CR4. */
1767 VMXDisable();
1768
1769 /* Clear CR4.VMXE only if it was clear prior to use setting it. */
1770 if (!pHostCpu->fVmxeAlreadyEnabled)
1771 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1772
1773 rc = VINF_SUCCESS;
1774 }
1775 else
1776 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1777
1778 /* Restore interrupts. */
1779 ASMSetFlags(fEFlags);
1780 return rc;
1781}
1782
1783
1784/**
1785 * Allocates pages specified as specified by an array of VMX page allocation info
1786 * objects.
1787 *
1788 * The pages contents are zero'd after allocation.
1789 *
1790 * @returns VBox status code.
1791 * @param phMemObj Where to return the handle to the allocation.
1792 * @param paAllocInfo The pointer to the first element of the VMX
1793 * page-allocation info object array.
1794 * @param cEntries The number of elements in the @a paAllocInfo array.
1795 */
1796static int hmR0VmxPagesAllocZ(PRTR0MEMOBJ phMemObj, PVMXPAGEALLOCINFO paAllocInfo, uint32_t cEntries)
1797{
1798 *phMemObj = NIL_RTR0MEMOBJ;
1799
1800 /* Figure out how many pages to allocate. */
1801 uint32_t cPages = 0;
1802 for (uint32_t iPage = 0; iPage < cEntries; iPage++)
1803 cPages += !!paAllocInfo[iPage].fValid;
1804
1805 /* Allocate the pages. */
1806 if (cPages)
1807 {
1808 size_t const cbPages = cPages << PAGE_SHIFT;
1809 int rc = RTR0MemObjAllocPage(phMemObj, cbPages, false /* fExecutable */);
1810 if (RT_FAILURE(rc))
1811 return rc;
1812
1813 /* Zero the contents and assign each page to the corresponding VMX page-allocation entry. */
1814 void *pvFirstPage = RTR0MemObjAddress(*phMemObj);
1815 RT_BZERO(pvFirstPage, cbPages);
1816
1817 uint32_t iPage = 0;
1818 for (uint32_t i = 0; i < cEntries; i++)
1819 if (paAllocInfo[i].fValid)
1820 {
1821 RTHCPHYS const HCPhysPage = RTR0MemObjGetPagePhysAddr(*phMemObj, iPage);
1822 void *pvPage = (void *)((uintptr_t)pvFirstPage + (iPage << X86_PAGE_4K_SHIFT));
1823 Assert(HCPhysPage && HCPhysPage != NIL_RTHCPHYS);
1824 AssertPtr(pvPage);
1825
1826 Assert(paAllocInfo[iPage].pHCPhys);
1827 Assert(paAllocInfo[iPage].ppVirt);
1828 *paAllocInfo[iPage].pHCPhys = HCPhysPage;
1829 *paAllocInfo[iPage].ppVirt = pvPage;
1830
1831 /* Move to next page. */
1832 ++iPage;
1833 }
1834
1835 /* Make sure all valid (requested) pages have been assigned. */
1836 Assert(iPage == cPages);
1837 }
1838 return VINF_SUCCESS;
1839}
1840
1841
1842/**
1843 * Frees pages allocated using hmR0VmxPagesAllocZ.
1844 *
1845 * @param phMemObj Pointer to the memory object handle. Will be set to
1846 * NIL.
1847 */
1848DECL_FORCE_INLINE(void) hmR0VmxPagesFree(PRTR0MEMOBJ phMemObj)
1849{
1850 /* We can cleanup wholesale since it's all one allocation. */
1851 if (*phMemObj != NIL_RTR0MEMOBJ)
1852 {
1853 RTR0MemObjFree(*phMemObj, true /* fFreeMappings */);
1854 *phMemObj = NIL_RTR0MEMOBJ;
1855 }
1856}
1857
1858
1859/**
1860 * Initializes a VMCS info. object.
1861 *
1862 * @param pVmcsInfo The VMCS info. object.
1863 * @param pVmcsInfoShared The VMCS info. object shared with ring-3.
1864 */
1865static void hmR0VmxVmcsInfoInit(PVMXVMCSINFO pVmcsInfo, PVMXVMCSINFOSHARED pVmcsInfoShared)
1866{
1867 RT_ZERO(*pVmcsInfo);
1868 RT_ZERO(*pVmcsInfoShared);
1869
1870 pVmcsInfo->pShared = pVmcsInfoShared;
1871 Assert(pVmcsInfo->hMemObj == NIL_RTR0MEMOBJ);
1872 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1873 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1874 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1875 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1876 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1877 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1878 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1879 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1880 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1881 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
1882 pVmcsInfo->idHostCpuExec = NIL_RTCPUID;
1883}
1884
1885
1886/**
1887 * Frees the VT-x structures for a VMCS info. object.
1888 *
1889 * @param pVmcsInfo The VMCS info. object.
1890 * @param pVmcsInfoShared The VMCS info. object shared with ring-3.
1891 */
1892static void hmR0VmxVmcsInfoFree(PVMXVMCSINFO pVmcsInfo, PVMXVMCSINFOSHARED pVmcsInfoShared)
1893{
1894 hmR0VmxPagesFree(&pVmcsInfo->hMemObj);
1895 hmR0VmxVmcsInfoInit(pVmcsInfo, pVmcsInfoShared);
1896}
1897
1898
1899/**
1900 * Allocates the VT-x structures for a VMCS info. object.
1901 *
1902 * @returns VBox status code.
1903 * @param pVCpu The cross context virtual CPU structure.
1904 * @param pVmcsInfo The VMCS info. object.
1905 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1906 *
1907 * @remarks The caller is expected to take care of any and all allocation failures.
1908 * This function will not perform any cleanup for failures half-way
1909 * through.
1910 */
1911static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1912{
1913 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1914
1915 bool const fMsrBitmaps = RT_BOOL(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS);
1916 bool const fShadowVmcs = !fIsNstGstVmcs ? pVM->hmr0.s.vmx.fUseVmcsShadowing : pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing;
1917 Assert(!pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing); /* VMCS shadowing is not yet exposed to the guest. */
1918 VMXPAGEALLOCINFO aAllocInfo[] =
1919 {
1920 { true, 0 /* Unused */, &pVmcsInfo->HCPhysVmcs, &pVmcsInfo->pvVmcs },
1921 { true, 0 /* Unused */, &pVmcsInfo->HCPhysGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad },
1922 { true, 0 /* Unused */, &pVmcsInfo->HCPhysHostMsrLoad, &pVmcsInfo->pvHostMsrLoad },
1923 { fMsrBitmaps, 0 /* Unused */, &pVmcsInfo->HCPhysMsrBitmap, &pVmcsInfo->pvMsrBitmap },
1924 { fShadowVmcs, 0 /* Unused */, &pVmcsInfo->HCPhysShadowVmcs, &pVmcsInfo->pvShadowVmcs },
1925 };
1926
1927 int rc = hmR0VmxPagesAllocZ(&pVmcsInfo->hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1928 if (RT_FAILURE(rc))
1929 return rc;
1930
1931 /*
1932 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1933 * Because they contain a symmetric list of guest MSRs to load on VM-entry and store on VM-exit.
1934 */
1935 AssertCompile(RT_ELEMENTS(aAllocInfo) > 0);
1936 Assert(pVmcsInfo->HCPhysGuestMsrLoad != NIL_RTHCPHYS);
1937 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1938 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1939
1940 /*
1941 * Get the virtual-APIC page rather than allocating them again.
1942 */
1943 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1944 {
1945 if (!fIsNstGstVmcs)
1946 {
1947 if (PDMHasApic(pVM))
1948 {
1949 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1950 if (RT_FAILURE(rc))
1951 return rc;
1952 Assert(pVmcsInfo->pbVirtApic);
1953 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1954 }
1955 }
1956 else
1957 {
1958 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(&pVCpu->cpum.GstCtx, &pVmcsInfo->HCPhysVirtApic);
1959 Assert(pVmcsInfo->pbVirtApic);
1960 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1961 }
1962 }
1963
1964 return VINF_SUCCESS;
1965}
1966
1967
1968/**
1969 * Free all VT-x structures for the VM.
1970 *
1971 * @returns IPRT status code.
1972 * @param pVM The cross context VM structure.
1973 */
1974static void hmR0VmxStructsFree(PVMCC pVM)
1975{
1976 hmR0VmxPagesFree(&pVM->hmr0.s.vmx.hMemObj);
1977#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1978 if (pVM->hmr0.s.vmx.fUseVmcsShadowing)
1979 {
1980 RTMemFree(pVM->hmr0.s.vmx.paShadowVmcsFields);
1981 pVM->hmr0.s.vmx.paShadowVmcsFields = NULL;
1982 RTMemFree(pVM->hmr0.s.vmx.paShadowVmcsRoFields);
1983 pVM->hmr0.s.vmx.paShadowVmcsRoFields = NULL;
1984 }
1985#endif
1986
1987 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1988 {
1989 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1990 hmR0VmxVmcsInfoFree(&pVCpu->hmr0.s.vmx.VmcsInfo, &pVCpu->hm.s.vmx.VmcsInfo);
1991#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1992 if (pVM->cpum.ro.GuestFeatures.fVmx)
1993 hmR0VmxVmcsInfoFree(&pVCpu->hmr0.s.vmx.VmcsInfoNstGst, &pVCpu->hm.s.vmx.VmcsInfoNstGst);
1994#endif
1995 }
1996}
1997
1998
1999/**
2000 * Allocate all VT-x structures for the VM.
2001 *
2002 * @returns IPRT status code.
2003 * @param pVM The cross context VM structure.
2004 *
2005 * @remarks This functions will cleanup on memory allocation failures.
2006 */
2007static int hmR0VmxStructsAlloc(PVMCC pVM)
2008{
2009 /*
2010 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
2011 * The VMCS size cannot be more than 4096 bytes.
2012 *
2013 * See Intel spec. Appendix A.1 "Basic VMX Information".
2014 */
2015 uint32_t const cbVmcs = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
2016 if (cbVmcs <= X86_PAGE_4K_SIZE)
2017 { /* likely */ }
2018 else
2019 {
2020 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
2021 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2022 }
2023
2024 /*
2025 * Allocate per-VM VT-x structures.
2026 */
2027 bool const fVirtApicAccess = RT_BOOL(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
2028 bool const fUseVmcsShadowing = pVM->hmr0.s.vmx.fUseVmcsShadowing;
2029 VMXPAGEALLOCINFO aAllocInfo[] =
2030 {
2031 { fVirtApicAccess, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysApicAccess, (PRTR0PTR)&pVM->hmr0.s.vmx.pbApicAccess },
2032 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysVmreadBitmap, &pVM->hmr0.s.vmx.pvVmreadBitmap },
2033 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysVmwriteBitmap, &pVM->hmr0.s.vmx.pvVmwriteBitmap },
2034#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2035 { true, 0 /* Unused */, &pVM->hmr0.s.vmx.HCPhysScratch, (PRTR0PTR)&pVM->hmr0.s.vmx.pbScratch },
2036#endif
2037 };
2038
2039 int rc = hmR0VmxPagesAllocZ(&pVM->hmr0.s.vmx.hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
2040 if (RT_SUCCESS(rc))
2041 {
2042#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2043 /* Allocate the shadow VMCS-fields array. */
2044 if (fUseVmcsShadowing)
2045 {
2046 Assert(!pVM->hmr0.s.vmx.cShadowVmcsFields);
2047 Assert(!pVM->hmr0.s.vmx.cShadowVmcsRoFields);
2048 pVM->hmr0.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2049 pVM->hmr0.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2050 if (!pVM->hmr0.s.vmx.paShadowVmcsFields || !pVM->hmr0.s.vmx.paShadowVmcsRoFields)
2051 rc = VERR_NO_MEMORY;
2052 }
2053#endif
2054
2055 /*
2056 * Allocate per-VCPU VT-x structures.
2057 */
2058 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus && RT_SUCCESS(rc); idCpu++)
2059 {
2060 /* Allocate the guest VMCS structures. */
2061 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2062 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
2063
2064#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2065 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
2066 if (pVM->cpum.ro.GuestFeatures.fVmx && RT_SUCCESS(rc))
2067 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
2068#endif
2069 }
2070 if (RT_SUCCESS(rc))
2071 return VINF_SUCCESS;
2072 }
2073 hmR0VmxStructsFree(pVM);
2074 return rc;
2075}
2076
2077
2078/**
2079 * Pre-initializes non-zero fields in VMX structures that will be allocated.
2080 *
2081 * @param pVM The cross context VM structure.
2082 */
2083static void hmR0VmxStructsInit(PVMCC pVM)
2084{
2085 /* Paranoia. */
2086 Assert(pVM->hmr0.s.vmx.pbApicAccess == NULL);
2087#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2088 Assert(pVM->hmr0.s.vmx.pbScratch == NULL);
2089#endif
2090
2091 /*
2092 * Initialize members up-front so we can cleanup en masse on allocation failures.
2093 */
2094#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2095 pVM->hmr0.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
2096#endif
2097 pVM->hmr0.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
2098 pVM->hmr0.s.vmx.HCPhysVmreadBitmap = NIL_RTHCPHYS;
2099 pVM->hmr0.s.vmx.HCPhysVmwriteBitmap = NIL_RTHCPHYS;
2100 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2101 {
2102 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2103 hmR0VmxVmcsInfoInit(&pVCpu->hmr0.s.vmx.VmcsInfo, &pVCpu->hm.s.vmx.VmcsInfo);
2104 hmR0VmxVmcsInfoInit(&pVCpu->hmr0.s.vmx.VmcsInfoNstGst, &pVCpu->hm.s.vmx.VmcsInfoNstGst);
2105 }
2106}
2107
2108#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2109/**
2110 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2111 *
2112 * @returns @c true if the MSR is intercepted, @c false otherwise.
2113 * @param pvMsrBitmap The MSR bitmap.
2114 * @param offMsr The MSR byte offset.
2115 * @param iBit The bit offset from the byte offset.
2116 */
2117DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2118{
2119 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2120 Assert(pbMsrBitmap);
2121 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2122 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2123}
2124#endif
2125
2126/**
2127 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2128 *
2129 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2130 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2131 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2132 * the read/write access of this MSR.
2133 *
2134 * @param pVCpu The cross context virtual CPU structure.
2135 * @param pVmcsInfo The VMCS info. object.
2136 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2137 * @param idMsr The MSR value.
2138 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2139 * include both a read -and- a write permission!
2140 *
2141 * @sa CPUMGetVmxMsrPermission.
2142 * @remarks Can be called with interrupts disabled.
2143 */
2144static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2145{
2146 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2147 Assert(pbMsrBitmap);
2148 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2149
2150 /*
2151 * MSR-bitmap Layout:
2152 * Byte index MSR range Interpreted as
2153 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2154 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2155 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2156 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2157 *
2158 * A bit corresponding to an MSR within the above range causes a VM-exit
2159 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2160 * the MSR range, it always cause a VM-exit.
2161 *
2162 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2163 */
2164 uint16_t const offBitmapRead = 0;
2165 uint16_t const offBitmapWrite = 0x800;
2166 uint16_t offMsr;
2167 int32_t iBit;
2168 if (idMsr <= UINT32_C(0x00001fff))
2169 {
2170 offMsr = 0;
2171 iBit = idMsr;
2172 }
2173 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2174 {
2175 offMsr = 0x400;
2176 iBit = idMsr - UINT32_C(0xc0000000);
2177 }
2178 else
2179 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2180
2181 /*
2182 * Set the MSR read permission.
2183 */
2184 uint16_t const offMsrRead = offBitmapRead + offMsr;
2185 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2186 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2187 {
2188#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2189 bool const fClear = !fIsNstGstVmcs ? true
2190 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2191#else
2192 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2193 bool const fClear = true;
2194#endif
2195 if (fClear)
2196 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2197 }
2198 else
2199 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2200
2201 /*
2202 * Set the MSR write permission.
2203 */
2204 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2205 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2206 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2207 {
2208#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2209 bool const fClear = !fIsNstGstVmcs ? true
2210 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2211#else
2212 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2213 bool const fClear = true;
2214#endif
2215 if (fClear)
2216 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2217 }
2218 else
2219 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2220}
2221
2222
2223/**
2224 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2225 * area.
2226 *
2227 * @returns VBox status code.
2228 * @param pVCpu The cross context virtual CPU structure.
2229 * @param pVmcsInfo The VMCS info. object.
2230 * @param cMsrs The number of MSRs.
2231 */
2232static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2233{
2234 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2235 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc);
2236 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2237 {
2238 /* Commit the MSR counts to the VMCS and update the cache. */
2239 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2240 {
2241 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2242 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2243 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2244 pVmcsInfo->cEntryMsrLoad = cMsrs;
2245 pVmcsInfo->cExitMsrStore = cMsrs;
2246 pVmcsInfo->cExitMsrLoad = cMsrs;
2247 }
2248 return VINF_SUCCESS;
2249 }
2250
2251 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2252 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2253 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2254}
2255
2256
2257/**
2258 * Adds a new (or updates the value of an existing) guest/host MSR
2259 * pair to be swapped during the world-switch as part of the
2260 * auto-load/store MSR area in the VMCS.
2261 *
2262 * @returns VBox status code.
2263 * @param pVCpu The cross context virtual CPU structure.
2264 * @param pVmxTransient The VMX-transient structure.
2265 * @param idMsr The MSR.
2266 * @param uGuestMsrValue Value of the guest MSR.
2267 * @param fSetReadWrite Whether to set the guest read/write access of this
2268 * MSR (thus not causing a VM-exit).
2269 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2270 * necessary.
2271 */
2272static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2273 bool fSetReadWrite, bool fUpdateHostMsr)
2274{
2275 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2276 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2277 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2278 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2279 uint32_t i;
2280
2281 /* Paranoia. */
2282 Assert(pGuestMsrLoad);
2283
2284#ifndef DEBUG_bird
2285 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGuestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2286#endif
2287
2288 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2289 for (i = 0; i < cMsrs; i++)
2290 {
2291 if (pGuestMsrLoad[i].u32Msr == idMsr)
2292 break;
2293 }
2294
2295 bool fAdded = false;
2296 if (i == cMsrs)
2297 {
2298 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2299 ++cMsrs;
2300 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2301 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2302
2303 /* Set the guest to read/write this MSR without causing VM-exits. */
2304 if ( fSetReadWrite
2305 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2306 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2307
2308 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2309 fAdded = true;
2310 }
2311
2312 /* Update the MSR value for the newly added or already existing MSR. */
2313 pGuestMsrLoad[i].u32Msr = idMsr;
2314 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2315
2316 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2317 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2318 {
2319 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2320 pGuestMsrStore[i].u32Msr = idMsr;
2321 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2322 }
2323
2324 /* Update the corresponding slot in the host MSR area. */
2325 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2326 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2327 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2328 pHostMsr[i].u32Msr = idMsr;
2329
2330 /*
2331 * Only if the caller requests to update the host MSR value AND we've newly added the
2332 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2333 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2334 *
2335 * We do this for performance reasons since reading MSRs may be quite expensive.
2336 */
2337 if (fAdded)
2338 {
2339 if (fUpdateHostMsr)
2340 {
2341 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2342 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2343 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2344 }
2345 else
2346 {
2347 /* Someone else can do the work. */
2348 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
2349 }
2350 }
2351 return VINF_SUCCESS;
2352}
2353
2354
2355/**
2356 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2357 * auto-load/store MSR area in the VMCS.
2358 *
2359 * @returns VBox status code.
2360 * @param pVCpu The cross context virtual CPU structure.
2361 * @param pVmxTransient The VMX-transient structure.
2362 * @param idMsr The MSR.
2363 */
2364static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2365{
2366 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2367 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2368 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2369 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2370
2371#ifndef DEBUG_bird
2372 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2373#endif
2374
2375 for (uint32_t i = 0; i < cMsrs; i++)
2376 {
2377 /* Find the MSR. */
2378 if (pGuestMsrLoad[i].u32Msr == idMsr)
2379 {
2380 /*
2381 * If it's the last MSR, we only need to reduce the MSR count.
2382 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2383 */
2384 if (i < cMsrs - 1)
2385 {
2386 /* Remove it from the VM-entry MSR-load area. */
2387 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2388 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2389
2390 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2391 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2392 {
2393 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2394 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2395 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2396 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2397 }
2398
2399 /* Remove it from the VM-exit MSR-load area. */
2400 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2401 Assert(pHostMsr[i].u32Msr == idMsr);
2402 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2403 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2404 }
2405
2406 /* Reduce the count to reflect the removed MSR and bail. */
2407 --cMsrs;
2408 break;
2409 }
2410 }
2411
2412 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2413 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2414 {
2415 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2416 AssertRCReturn(rc, rc);
2417
2418 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2419 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2420 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2421
2422 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2423 return VINF_SUCCESS;
2424 }
2425
2426 return VERR_NOT_FOUND;
2427}
2428
2429
2430/**
2431 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2432 *
2433 * @returns @c true if found, @c false otherwise.
2434 * @param pVmcsInfo The VMCS info. object.
2435 * @param idMsr The MSR to find.
2436 */
2437static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2438{
2439 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2440 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2441 Assert(pMsrs);
2442 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2443 for (uint32_t i = 0; i < cMsrs; i++)
2444 {
2445 if (pMsrs[i].u32Msr == idMsr)
2446 return true;
2447 }
2448 return false;
2449}
2450
2451
2452/**
2453 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2454 *
2455 * @param pVCpu The cross context virtual CPU structure.
2456 * @param pVmcsInfo The VMCS info. object.
2457 *
2458 * @remarks No-long-jump zone!!!
2459 */
2460static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2461{
2462 RT_NOREF(pVCpu);
2463 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2464
2465 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2466 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2467 Assert(pHostMsrLoad);
2468 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2469 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2470 for (uint32_t i = 0; i < cMsrs; i++)
2471 {
2472 /*
2473 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2474 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2475 */
2476 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2477 pHostMsrLoad[i].u64Value = g_uHmVmxHostMsrEfer;
2478 else
2479 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2480 }
2481}
2482
2483
2484/**
2485 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2486 * perform lazy restoration of the host MSRs while leaving VT-x.
2487 *
2488 * @param pVCpu The cross context virtual CPU structure.
2489 *
2490 * @remarks No-long-jump zone!!!
2491 */
2492static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2493{
2494 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2495
2496 /*
2497 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2498 */
2499 if (!(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2500 {
2501 Assert(!(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2502 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2503 {
2504 pVCpu->hmr0.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2505 pVCpu->hmr0.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2506 pVCpu->hmr0.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2507 pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2508 }
2509 pVCpu->hmr0.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2510 }
2511}
2512
2513
2514/**
2515 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2516 * lazily while leaving VT-x.
2517 *
2518 * @returns true if it does, false otherwise.
2519 * @param pVCpu The cross context virtual CPU structure.
2520 * @param idMsr The MSR to check.
2521 */
2522static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2523{
2524 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2525 {
2526 switch (idMsr)
2527 {
2528 case MSR_K8_LSTAR:
2529 case MSR_K6_STAR:
2530 case MSR_K8_SF_MASK:
2531 case MSR_K8_KERNEL_GS_BASE:
2532 return true;
2533 }
2534 }
2535 return false;
2536}
2537
2538
2539/**
2540 * Loads a set of guests MSRs to allow read/passthru to the guest.
2541 *
2542 * The name of this function is slightly confusing. This function does NOT
2543 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2544 * common prefix for functions dealing with "lazy restoration" of the shared
2545 * MSRs.
2546 *
2547 * @param pVCpu The cross context virtual CPU structure.
2548 *
2549 * @remarks No-long-jump zone!!!
2550 */
2551static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2552{
2553 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2554 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2555
2556 Assert(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2557 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2558 {
2559 /*
2560 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2561 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2562 * we can skip a few MSR writes.
2563 *
2564 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2565 * guest MSR values in the guest-CPU context might be different to what's currently
2566 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2567 * CPU, see @bugref{8728}.
2568 */
2569 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2570 if ( !(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2571 && pCtx->msrKERNELGSBASE == pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase
2572 && pCtx->msrLSTAR == pVCpu->hmr0.s.vmx.u64HostMsrLStar
2573 && pCtx->msrSTAR == pVCpu->hmr0.s.vmx.u64HostMsrStar
2574 && pCtx->msrSFMASK == pVCpu->hmr0.s.vmx.u64HostMsrSfMask)
2575 {
2576#ifdef VBOX_STRICT
2577 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2578 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2579 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2580 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2581#endif
2582 }
2583 else
2584 {
2585 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2586 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2587 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2588 /* The system call flag mask register isn't as benign and accepting of all
2589 values as the above, so mask it to avoid #GP'ing on corrupted input. */
2590 Assert(!(pCtx->msrSFMASK & ~(uint64_t)UINT32_MAX));
2591 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK & UINT32_MAX);
2592 }
2593 }
2594 pVCpu->hmr0.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2595}
2596
2597
2598/**
2599 * Performs lazy restoration of the set of host MSRs if they were previously
2600 * loaded with guest MSR values.
2601 *
2602 * @param pVCpu The cross context virtual CPU structure.
2603 *
2604 * @remarks No-long-jump zone!!!
2605 * @remarks The guest MSRs should have been saved back into the guest-CPU
2606 * context by hmR0VmxImportGuestState()!!!
2607 */
2608static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2609{
2610 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2611 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2612
2613 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2614 {
2615 Assert(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2616 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fAllow64BitGuests)
2617 {
2618 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hmr0.s.vmx.u64HostMsrLStar);
2619 ASMWrMsr(MSR_K6_STAR, pVCpu->hmr0.s.vmx.u64HostMsrStar);
2620 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hmr0.s.vmx.u64HostMsrSfMask);
2621 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase);
2622 }
2623 }
2624 pVCpu->hmr0.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2625}
2626
2627
2628/**
2629 * Verifies that our cached values of the VMCS fields are all consistent with
2630 * what's actually present in the VMCS.
2631 *
2632 * @returns VBox status code.
2633 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2634 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2635 * VMCS content. HMCPU error-field is
2636 * updated, see VMX_VCI_XXX.
2637 * @param pVCpu The cross context virtual CPU structure.
2638 * @param pVmcsInfo The VMCS info. object.
2639 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2640 */
2641static int hmR0VmxCheckCachedVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2642{
2643 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2644
2645 uint32_t u32Val;
2646 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2647 AssertRC(rc);
2648 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2649 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2650 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2651 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2652
2653 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2654 AssertRC(rc);
2655 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2656 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2657 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2658 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2659
2660 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2661 AssertRC(rc);
2662 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2663 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2664 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2665 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2666
2667 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2668 AssertRC(rc);
2669 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2670 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2671 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2672 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2673
2674 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2675 {
2676 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2677 AssertRC(rc);
2678 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2679 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2680 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2681 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2682 }
2683
2684 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2685 AssertRC(rc);
2686 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2687 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2688 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2689 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2690
2691 uint64_t u64Val;
2692 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2693 AssertRC(rc);
2694 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2695 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2696 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2697 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2698
2699 NOREF(pcszVmcs);
2700 return VINF_SUCCESS;
2701}
2702
2703#ifdef VBOX_STRICT
2704
2705/**
2706 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2707 *
2708 * @param pVmcsInfo The VMCS info. object.
2709 */
2710static void hmR0VmxCheckHostEferMsr(PCVMXVMCSINFO pVmcsInfo)
2711{
2712 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2713
2714 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2715 {
2716 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2717 uint64_t const uHostEferMsrCache = g_uHmVmxHostMsrEfer;
2718 uint64_t uVmcsEferMsrVmcs;
2719 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2720 AssertRC(rc);
2721
2722 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2723 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2724 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2725 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2726 }
2727}
2728
2729
2730/**
2731 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2732 * VMCS are correct.
2733 *
2734 * @param pVCpu The cross context virtual CPU structure.
2735 * @param pVmcsInfo The VMCS info. object.
2736 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2737 */
2738static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2739{
2740 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2741
2742 /* Read the various MSR-area counts from the VMCS. */
2743 uint32_t cEntryLoadMsrs;
2744 uint32_t cExitStoreMsrs;
2745 uint32_t cExitLoadMsrs;
2746 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2747 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2748 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2749
2750 /* Verify all the MSR counts are the same. */
2751 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2752 Assert(cExitStoreMsrs == cExitLoadMsrs);
2753 uint32_t const cMsrs = cExitLoadMsrs;
2754
2755 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2756 Assert(cMsrs < VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc));
2757
2758 /* Verify the MSR counts are within the allocated page size. */
2759 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2760
2761 /* Verify the relevant contents of the MSR areas match. */
2762 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2763 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2764 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2765 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2766 for (uint32_t i = 0; i < cMsrs; i++)
2767 {
2768 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2769 if (fSeparateExitMsrStorePage)
2770 {
2771 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2772 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2773 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2774 }
2775
2776 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2777 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2778 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2779
2780 uint64_t const u64HostMsr = ASMRdMsr(pHostMsrLoad->u32Msr);
2781 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64HostMsr,
2782 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2783 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64HostMsr, cMsrs));
2784
2785 /* Verify that cached host EFER MSR matches what's loaded on the CPU. */
2786 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2787 AssertMsgReturnVoid(!fIsEferMsr || u64HostMsr == g_uHmVmxHostMsrEfer,
2788 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n", g_uHmVmxHostMsrEfer, u64HostMsr, cMsrs));
2789
2790 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2791 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2792 {
2793 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2794 if (fIsEferMsr)
2795 {
2796 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2797 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2798 }
2799 else
2800 {
2801 /* Verify LBR MSRs (used only for debugging) are intercepted. We don't passthru these MSRs to the guest yet. */
2802 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
2803 if ( pVM->hmr0.s.vmx.fLbr
2804 && ( hmR0VmxIsLbrBranchFromMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2805 || hmR0VmxIsLbrBranchToMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2806 || pGuestMsrLoad->u32Msr == pVM->hmr0.s.vmx.idLbrTosMsr))
2807 {
2808 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_EXIT_RD_WR,
2809 ("u32Msr=%#RX32 cMsrs=%u Passthru read/write for LBR MSRs!\n",
2810 pGuestMsrLoad->u32Msr, cMsrs));
2811 }
2812 else if (!fIsNstGstVmcs)
2813 {
2814 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_ALLOW_RD_WR,
2815 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2816 }
2817 else
2818 {
2819 /*
2820 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2821 * execute a nested-guest with MSR passthrough.
2822 *
2823 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2824 * allow passthrough too.
2825 */
2826 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2827 Assert(pvMsrBitmapNstGst);
2828 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2829 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2830 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2831 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2832 }
2833 }
2834 }
2835
2836 /* Move to the next MSR. */
2837 pHostMsrLoad++;
2838 pGuestMsrLoad++;
2839 pGuestMsrStore++;
2840 }
2841}
2842
2843#endif /* VBOX_STRICT */
2844
2845/**
2846 * Flushes the TLB using EPT.
2847 *
2848 * @returns VBox status code.
2849 * @param pVCpu The cross context virtual CPU structure of the calling
2850 * EMT. Can be NULL depending on @a enmTlbFlush.
2851 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2852 * enmTlbFlush.
2853 * @param enmTlbFlush Type of flush.
2854 *
2855 * @remarks Caller is responsible for making sure this function is called only
2856 * when NestedPaging is supported and providing @a enmTlbFlush that is
2857 * supported by the CPU.
2858 * @remarks Can be called with interrupts disabled.
2859 */
2860static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2861{
2862 uint64_t au64Descriptor[2];
2863 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2864 au64Descriptor[0] = 0;
2865 else
2866 {
2867 Assert(pVCpu);
2868 Assert(pVmcsInfo);
2869 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2870 }
2871 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2872
2873 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2874 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2875
2876 if ( RT_SUCCESS(rc)
2877 && pVCpu)
2878 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2879}
2880
2881
2882/**
2883 * Flushes the TLB using VPID.
2884 *
2885 * @returns VBox status code.
2886 * @param pVCpu The cross context virtual CPU structure of the calling
2887 * EMT. Can be NULL depending on @a enmTlbFlush.
2888 * @param enmTlbFlush Type of flush.
2889 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2890 * on @a enmTlbFlush).
2891 *
2892 * @remarks Can be called with interrupts disabled.
2893 */
2894static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2895{
2896 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid);
2897
2898 uint64_t au64Descriptor[2];
2899 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2900 {
2901 au64Descriptor[0] = 0;
2902 au64Descriptor[1] = 0;
2903 }
2904 else
2905 {
2906 AssertPtr(pVCpu);
2907 AssertMsg(pVCpu->hmr0.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hmr0.s.uCurrentAsid));
2908 AssertMsg(pVCpu->hmr0.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hmr0.s.uCurrentAsid));
2909 au64Descriptor[0] = pVCpu->hmr0.s.uCurrentAsid;
2910 au64Descriptor[1] = GCPtr;
2911 }
2912
2913 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2914 AssertMsg(rc == VINF_SUCCESS,
2915 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hmr0.s.uCurrentAsid : 0, GCPtr, rc));
2916
2917 if ( RT_SUCCESS(rc)
2918 && pVCpu)
2919 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2920 NOREF(rc);
2921}
2922
2923
2924/**
2925 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2926 * otherwise there is nothing really to invalidate.
2927 *
2928 * @returns VBox status code.
2929 * @param pVCpu The cross context virtual CPU structure.
2930 * @param GCVirt Guest virtual address of the page to invalidate.
2931 */
2932VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2933{
2934 AssertPtr(pVCpu);
2935 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2936
2937 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2938 {
2939 /*
2940 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2941 * the EPT case. See @bugref{6043} and @bugref{6177}.
2942 *
2943 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2944 * as this function maybe called in a loop with individual addresses.
2945 */
2946 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2947 if (pVM->hmr0.s.vmx.fVpid)
2948 {
2949 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
2950 {
2951 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2952 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2953 }
2954 else
2955 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2956 }
2957 else if (pVM->hmr0.s.fNestedPaging)
2958 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2959 }
2960
2961 return VINF_SUCCESS;
2962}
2963
2964
2965/**
2966 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2967 * case where neither EPT nor VPID is supported by the CPU.
2968 *
2969 * @param pHostCpu The HM physical-CPU structure.
2970 * @param pVCpu The cross context virtual CPU structure.
2971 *
2972 * @remarks Called with interrupts disabled.
2973 */
2974static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2975{
2976 AssertPtr(pVCpu);
2977 AssertPtr(pHostCpu);
2978
2979 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2980
2981 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2982 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
2983 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2984 pVCpu->hmr0.s.fForceTLBFlush = false;
2985 return;
2986}
2987
2988
2989/**
2990 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2991 *
2992 * @param pHostCpu The HM physical-CPU structure.
2993 * @param pVCpu The cross context virtual CPU structure.
2994 * @param pVmcsInfo The VMCS info. object.
2995 *
2996 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2997 * nomenclature. The reason is, to avoid confusion in compare statements
2998 * since the host-CPU copies are named "ASID".
2999 *
3000 * @remarks Called with interrupts disabled.
3001 */
3002static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3003{
3004#ifdef VBOX_WITH_STATISTICS
3005 bool fTlbFlushed = false;
3006# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
3007# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
3008 if (!fTlbFlushed) \
3009 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
3010 } while (0)
3011#else
3012# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
3013# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
3014#endif
3015
3016 AssertPtr(pVCpu);
3017 AssertPtr(pHostCpu);
3018 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3019
3020 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3021 AssertMsg(pVM->hmr0.s.fNestedPaging && pVM->hmr0.s.vmx.fVpid,
3022 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
3023 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hmr0.s.fNestedPaging, pVM->hmr0.s.vmx.fVpid));
3024
3025 /*
3026 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
3027 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3028 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3029 * cannot reuse the current ASID anymore.
3030 */
3031 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3032 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3033 {
3034 ++pHostCpu->uCurrentAsid;
3035 if (pHostCpu->uCurrentAsid >= g_uHmMaxAsid)
3036 {
3037 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
3038 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3039 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3040 }
3041
3042 pVCpu->hmr0.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3043 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3044 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3045
3046 /*
3047 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
3048 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
3049 */
3050 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3051 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3052 HMVMX_SET_TAGGED_TLB_FLUSHED();
3053 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
3054 }
3055 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
3056 {
3057 /*
3058 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
3059 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
3060 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
3061 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
3062 * mappings, see @bugref{6568}.
3063 *
3064 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
3065 */
3066 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3067 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3068 HMVMX_SET_TAGGED_TLB_FLUSHED();
3069 }
3070 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3071 {
3072 /*
3073 * The nested-guest specifies its own guest-physical address to use as the APIC-access
3074 * address which requires flushing the TLB of EPT cached structures.
3075 *
3076 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
3077 */
3078 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hmr0.s.vmx.enmTlbFlushEpt);
3079 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3080 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3081 HMVMX_SET_TAGGED_TLB_FLUSHED();
3082 }
3083
3084
3085 pVCpu->hmr0.s.fForceTLBFlush = false;
3086 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
3087
3088 Assert(pVCpu->hmr0.s.idLastCpu == pHostCpu->idCpu);
3089 Assert(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes);
3090 AssertMsg(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3091 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hmr0.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3092 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < g_uHmMaxAsid,
3093 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3094 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hmr0.s.idLastCpu, pVCpu->hmr0.s.cTlbFlushes));
3095 AssertMsg(pVCpu->hmr0.s.uCurrentAsid >= 1 && pVCpu->hmr0.s.uCurrentAsid < g_uHmMaxAsid,
3096 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hmr0.s.uCurrentAsid));
3097
3098 /* Update VMCS with the VPID. */
3099 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hmr0.s.uCurrentAsid);
3100 AssertRC(rc);
3101
3102#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3103}
3104
3105
3106/**
3107 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3108 *
3109 * @param pHostCpu The HM physical-CPU structure.
3110 * @param pVCpu The cross context virtual CPU structure.
3111 * @param pVmcsInfo The VMCS info. object.
3112 *
3113 * @remarks Called with interrupts disabled.
3114 */
3115static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3116{
3117 AssertPtr(pVCpu);
3118 AssertPtr(pHostCpu);
3119 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3120 AssertMsg(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3121 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3122
3123 /*
3124 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3125 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3126 */
3127 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3128 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3129 {
3130 pVCpu->hmr0.s.fForceTLBFlush = true;
3131 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3132 }
3133
3134 /* Check for explicit TLB flushes. */
3135 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3136 {
3137 pVCpu->hmr0.s.fForceTLBFlush = true;
3138 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3139 }
3140
3141 /* Check for TLB flushes while switching to/from a nested-guest. */
3142 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3143 {
3144 pVCpu->hmr0.s.fForceTLBFlush = true;
3145 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3146 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3147 }
3148
3149 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3150 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3151
3152 if (pVCpu->hmr0.s.fForceTLBFlush)
3153 {
3154 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.enmTlbFlushEpt);
3155 pVCpu->hmr0.s.fForceTLBFlush = false;
3156 }
3157}
3158
3159
3160/**
3161 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3162 *
3163 * @param pHostCpu The HM physical-CPU structure.
3164 * @param pVCpu The cross context virtual CPU structure.
3165 *
3166 * @remarks Called with interrupts disabled.
3167 */
3168static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3169{
3170 AssertPtr(pVCpu);
3171 AssertPtr(pHostCpu);
3172 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3173 AssertMsg(pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3174 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3175
3176 /*
3177 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3178 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3179 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3180 * cannot reuse the current ASID anymore.
3181 */
3182 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3183 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3184 {
3185 pVCpu->hmr0.s.fForceTLBFlush = true;
3186 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3187 }
3188
3189 /* Check for explicit TLB flushes. */
3190 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3191 {
3192 /*
3193 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3194 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3195 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3196 * include fExplicitFlush's too) - an obscure corner case.
3197 */
3198 pVCpu->hmr0.s.fForceTLBFlush = true;
3199 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3200 }
3201
3202 /* Check for TLB flushes while switching to/from a nested-guest. */
3203 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3204 {
3205 pVCpu->hmr0.s.fForceTLBFlush = true;
3206 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3207 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3208 }
3209
3210 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3211 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3212 if (pVCpu->hmr0.s.fForceTLBFlush)
3213 {
3214 ++pHostCpu->uCurrentAsid;
3215 if (pHostCpu->uCurrentAsid >= g_uHmMaxAsid)
3216 {
3217 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3218 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3219 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3220 }
3221
3222 pVCpu->hmr0.s.fForceTLBFlush = false;
3223 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3224 pVCpu->hmr0.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3225 if (pHostCpu->fFlushAsidBeforeUse)
3226 {
3227 if (pVM->hmr0.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3228 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3229 else if (pVM->hmr0.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3230 {
3231 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3232 pHostCpu->fFlushAsidBeforeUse = false;
3233 }
3234 else
3235 {
3236 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3237 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3238 }
3239 }
3240 }
3241
3242 AssertMsg(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3243 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hmr0.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3244 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < g_uHmMaxAsid,
3245 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3246 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hmr0.s.idLastCpu, pVCpu->hmr0.s.cTlbFlushes));
3247 AssertMsg(pVCpu->hmr0.s.uCurrentAsid >= 1 && pVCpu->hmr0.s.uCurrentAsid < g_uHmMaxAsid,
3248 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hmr0.s.uCurrentAsid));
3249
3250 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hmr0.s.uCurrentAsid);
3251 AssertRC(rc);
3252}
3253
3254
3255/**
3256 * Flushes the guest TLB entry based on CPU capabilities.
3257 *
3258 * @param pHostCpu The HM physical-CPU structure.
3259 * @param pVCpu The cross context virtual CPU structure.
3260 * @param pVmcsInfo The VMCS info. object.
3261 *
3262 * @remarks Called with interrupts disabled.
3263 */
3264static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3265{
3266#ifdef HMVMX_ALWAYS_FLUSH_TLB
3267 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3268#endif
3269 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3270 switch (pVM->hmr0.s.vmx.enmTlbFlushType)
3271 {
3272 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3273 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3274 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3275 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3276 default:
3277 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3278 break;
3279 }
3280 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3281}
3282
3283
3284/**
3285 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3286 * TLB entries from the host TLB before VM-entry.
3287 *
3288 * @returns VBox status code.
3289 * @param pVM The cross context VM structure.
3290 */
3291static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3292{
3293 /*
3294 * Determine optimal flush type for nested paging.
3295 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3296 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3297 */
3298 if (pVM->hmr0.s.fNestedPaging)
3299 {
3300 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3301 {
3302 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3303 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3304 else if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3305 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3306 else
3307 {
3308 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3309 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3310 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3311 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3312 }
3313
3314 /* Make sure the write-back cacheable memory type for EPT is supported. */
3315 if (RT_UNLIKELY(!(g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3316 {
3317 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3318 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3319 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3320 }
3321
3322 /* EPT requires a page-walk length of 4. */
3323 if (RT_UNLIKELY(!(g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3324 {
3325 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3326 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3327 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3328 }
3329 }
3330 else
3331 {
3332 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3333 pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3334 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3335 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3336 }
3337 }
3338
3339 /*
3340 * Determine optimal flush type for VPID.
3341 */
3342 if (pVM->hmr0.s.vmx.fVpid)
3343 {
3344 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3345 {
3346 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3347 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3348 else if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3349 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3350 else
3351 {
3352 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3353 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3354 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3355 if (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3356 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3357 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3358 pVM->hmr0.s.vmx.fVpid = false;
3359 }
3360 }
3361 else
3362 {
3363 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3364 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3365 pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3366 pVM->hmr0.s.vmx.fVpid = false;
3367 }
3368 }
3369
3370 /*
3371 * Setup the handler for flushing tagged-TLBs.
3372 */
3373 if (pVM->hmr0.s.fNestedPaging && pVM->hmr0.s.vmx.fVpid)
3374 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3375 else if (pVM->hmr0.s.fNestedPaging)
3376 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3377 else if (pVM->hmr0.s.vmx.fVpid)
3378 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3379 else
3380 pVM->hmr0.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3381
3382
3383 /*
3384 * Copy out the result to ring-3.
3385 */
3386 pVM->hm.s.ForR3.vmx.fVpid = pVM->hmr0.s.vmx.fVpid;
3387 pVM->hm.s.ForR3.vmx.enmTlbFlushType = pVM->hmr0.s.vmx.enmTlbFlushType;
3388 pVM->hm.s.ForR3.vmx.enmTlbFlushEpt = pVM->hmr0.s.vmx.enmTlbFlushEpt;
3389 pVM->hm.s.ForR3.vmx.enmTlbFlushVpid = pVM->hmr0.s.vmx.enmTlbFlushVpid;
3390 return VINF_SUCCESS;
3391}
3392
3393
3394/**
3395 * Sets up the LBR MSR ranges based on the host CPU.
3396 *
3397 * @returns VBox status code.
3398 * @param pVM The cross context VM structure.
3399 */
3400static int hmR0VmxSetupLbrMsrRange(PVMCC pVM)
3401{
3402 Assert(pVM->hmr0.s.vmx.fLbr);
3403 uint32_t idLbrFromIpMsrFirst;
3404 uint32_t idLbrFromIpMsrLast;
3405 uint32_t idLbrToIpMsrFirst;
3406 uint32_t idLbrToIpMsrLast;
3407 uint32_t idLbrTosMsr;
3408
3409 /*
3410 * Determine the LBR MSRs supported for this host CPU family and model.
3411 *
3412 * See Intel spec. 17.4.8 "LBR Stack".
3413 * See Intel "Model-Specific Registers" spec.
3414 */
3415 uint32_t const uFamilyModel = (pVM->cpum.ro.HostFeatures.uFamily << 8)
3416 | pVM->cpum.ro.HostFeatures.uModel;
3417 switch (uFamilyModel)
3418 {
3419 case 0x0f01: case 0x0f02:
3420 idLbrFromIpMsrFirst = MSR_P4_LASTBRANCH_0;
3421 idLbrFromIpMsrLast = MSR_P4_LASTBRANCH_3;
3422 idLbrToIpMsrFirst = 0x0;
3423 idLbrToIpMsrLast = 0x0;
3424 idLbrTosMsr = MSR_P4_LASTBRANCH_TOS;
3425 break;
3426
3427 case 0x065c: case 0x065f: case 0x064e: case 0x065e: case 0x068e:
3428 case 0x069e: case 0x0655: case 0x0666: case 0x067a: case 0x0667:
3429 case 0x066a: case 0x066c: case 0x067d: case 0x067e:
3430 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3431 idLbrFromIpMsrLast = MSR_LASTBRANCH_31_FROM_IP;
3432 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3433 idLbrToIpMsrLast = MSR_LASTBRANCH_31_TO_IP;
3434 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3435 break;
3436
3437 case 0x063d: case 0x0647: case 0x064f: case 0x0656: case 0x063c:
3438 case 0x0645: case 0x0646: case 0x063f: case 0x062a: case 0x062d:
3439 case 0x063a: case 0x063e: case 0x061a: case 0x061e: case 0x061f:
3440 case 0x062e: case 0x0625: case 0x062c: case 0x062f:
3441 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3442 idLbrFromIpMsrLast = MSR_LASTBRANCH_15_FROM_IP;
3443 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3444 idLbrToIpMsrLast = MSR_LASTBRANCH_15_TO_IP;
3445 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3446 break;
3447
3448 case 0x0617: case 0x061d: case 0x060f:
3449 idLbrFromIpMsrFirst = MSR_CORE2_LASTBRANCH_0_FROM_IP;
3450 idLbrFromIpMsrLast = MSR_CORE2_LASTBRANCH_3_FROM_IP;
3451 idLbrToIpMsrFirst = MSR_CORE2_LASTBRANCH_0_TO_IP;
3452 idLbrToIpMsrLast = MSR_CORE2_LASTBRANCH_3_TO_IP;
3453 idLbrTosMsr = MSR_CORE2_LASTBRANCH_TOS;
3454 break;
3455
3456 /* Atom and related microarchitectures we don't care about:
3457 case 0x0637: case 0x064a: case 0x064c: case 0x064d: case 0x065a:
3458 case 0x065d: case 0x061c: case 0x0626: case 0x0627: case 0x0635:
3459 case 0x0636: */
3460 /* All other CPUs: */
3461 default:
3462 {
3463 LogRelFunc(("Could not determine LBR stack size for the CPU model %#x\n", uFamilyModel));
3464 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_UNKNOWN;
3465 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3466 }
3467 }
3468
3469 /*
3470 * Validate.
3471 */
3472 uint32_t const cLbrStack = idLbrFromIpMsrLast - idLbrFromIpMsrFirst + 1;
3473 PCVMCPU pVCpu0 = VMCC_GET_CPU_0(pVM);
3474 AssertCompile( RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr)
3475 == RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrToIpMsr));
3476 if (cLbrStack > RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr))
3477 {
3478 LogRelFunc(("LBR stack size of the CPU (%u) exceeds our buffer size\n", cLbrStack));
3479 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_OVERFLOW;
3480 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3481 }
3482 NOREF(pVCpu0);
3483
3484 /*
3485 * Update the LBR info. to the VM struct. for use later.
3486 */
3487 pVM->hmr0.s.vmx.idLbrTosMsr = idLbrTosMsr;
3488
3489 pVM->hm.s.ForR3.vmx.idLbrFromIpMsrFirst = pVM->hmr0.s.vmx.idLbrFromIpMsrFirst = idLbrFromIpMsrFirst;
3490 pVM->hm.s.ForR3.vmx.idLbrFromIpMsrLast = pVM->hmr0.s.vmx.idLbrFromIpMsrLast = idLbrFromIpMsrLast;
3491
3492 pVM->hm.s.ForR3.vmx.idLbrToIpMsrFirst = pVM->hmr0.s.vmx.idLbrToIpMsrFirst = idLbrToIpMsrFirst;
3493 pVM->hm.s.ForR3.vmx.idLbrToIpMsrLast = pVM->hmr0.s.vmx.idLbrToIpMsrLast = idLbrToIpMsrLast;
3494 return VINF_SUCCESS;
3495}
3496
3497
3498#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3499/**
3500 * Sets up the shadow VMCS fields arrays.
3501 *
3502 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3503 * executing the guest.
3504 *
3505 * @returns VBox status code.
3506 * @param pVM The cross context VM structure.
3507 */
3508static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3509{
3510 /*
3511 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3512 * when the host does not support it.
3513 */
3514 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3515 if ( !fGstVmwriteAll
3516 || (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL))
3517 { /* likely. */ }
3518 else
3519 {
3520 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3521 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3522 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3523 }
3524
3525 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3526 uint32_t cRwFields = 0;
3527 uint32_t cRoFields = 0;
3528 for (uint32_t i = 0; i < cVmcsFields; i++)
3529 {
3530 VMXVMCSFIELD VmcsField;
3531 VmcsField.u = g_aVmcsFields[i];
3532
3533 /*
3534 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3535 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3536 * in the shadow VMCS fields array as they would be redundant.
3537 *
3538 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3539 * we must not include it in the shadow VMCS fields array. Guests attempting to
3540 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3541 * the required behavior.
3542 */
3543 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3544 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3545 {
3546 /*
3547 * Read-only fields are placed in a separate array so that while syncing shadow
3548 * VMCS fields later (which is more performance critical) we can avoid branches.
3549 *
3550 * However, if the guest can write to all fields (including read-only fields),
3551 * we treat it a as read/write field. Otherwise, writing to these fields would
3552 * cause a VMWRITE instruction error while syncing the shadow VMCS.
3553 */
3554 if ( fGstVmwriteAll
3555 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3556 pVM->hmr0.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3557 else
3558 pVM->hmr0.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3559 }
3560 }
3561
3562 /* Update the counts. */
3563 pVM->hmr0.s.vmx.cShadowVmcsFields = cRwFields;
3564 pVM->hmr0.s.vmx.cShadowVmcsRoFields = cRoFields;
3565 return VINF_SUCCESS;
3566}
3567
3568
3569/**
3570 * Sets up the VMREAD and VMWRITE bitmaps.
3571 *
3572 * @param pVM The cross context VM structure.
3573 */
3574static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3575{
3576 /*
3577 * By default, ensure guest attempts to access any VMCS fields cause VM-exits.
3578 */
3579 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3580 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hmr0.s.vmx.pvVmreadBitmap;
3581 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hmr0.s.vmx.pvVmwriteBitmap;
3582 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3583 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3584
3585 /*
3586 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3587 * VMREAD and VMWRITE bitmaps.
3588 */
3589 {
3590 uint32_t const *paShadowVmcsFields = pVM->hmr0.s.vmx.paShadowVmcsFields;
3591 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
3592 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3593 {
3594 uint32_t const uVmcsField = paShadowVmcsFields[i];
3595 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3596 Assert(uVmcsField >> 3 < cbBitmap);
3597 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3598 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3599 }
3600 }
3601
3602 /*
3603 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3604 * if the host supports VMWRITE to all supported VMCS fields.
3605 */
3606 if (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL)
3607 {
3608 uint32_t const *paShadowVmcsRoFields = pVM->hmr0.s.vmx.paShadowVmcsRoFields;
3609 uint32_t const cShadowVmcsRoFields = pVM->hmr0.s.vmx.cShadowVmcsRoFields;
3610 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3611 {
3612 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3613 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3614 Assert(uVmcsField >> 3 < cbBitmap);
3615 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3616 }
3617 }
3618}
3619#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3620
3621
3622/**
3623 * Sets up the virtual-APIC page address for the VMCS.
3624 *
3625 * @param pVmcsInfo The VMCS info. object.
3626 */
3627DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3628{
3629 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3630 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3631 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3632 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3633 AssertRC(rc);
3634}
3635
3636
3637/**
3638 * Sets up the MSR-bitmap address for the VMCS.
3639 *
3640 * @param pVmcsInfo The VMCS info. object.
3641 */
3642DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3643{
3644 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3645 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3646 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3647 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3648 AssertRC(rc);
3649}
3650
3651
3652/**
3653 * Sets up the APIC-access page address for the VMCS.
3654 *
3655 * @param pVCpu The cross context virtual CPU structure.
3656 */
3657DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3658{
3659 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysApicAccess;
3660 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3661 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3662 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3663 AssertRC(rc);
3664}
3665
3666#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3667
3668/**
3669 * Sets up the VMREAD bitmap address for the VMCS.
3670 *
3671 * @param pVCpu The cross context virtual CPU structure.
3672 */
3673DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3674{
3675 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysVmreadBitmap;
3676 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3677 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3678 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3679 AssertRC(rc);
3680}
3681
3682
3683/**
3684 * Sets up the VMWRITE bitmap address for the VMCS.
3685 *
3686 * @param pVCpu The cross context virtual CPU structure.
3687 */
3688DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3689{
3690 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.HCPhysVmwriteBitmap;
3691 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3692 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3693 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3694 AssertRC(rc);
3695}
3696
3697#endif
3698
3699/**
3700 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3701 * in the VMCS.
3702 *
3703 * @returns VBox status code.
3704 * @param pVmcsInfo The VMCS info. object.
3705 */
3706DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3707{
3708 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3709 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3710 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3711
3712 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3713 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3714 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3715
3716 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3717 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3718 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3719
3720 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3721 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3722 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3723 return VINF_SUCCESS;
3724}
3725
3726
3727/**
3728 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3729 *
3730 * @param pVCpu The cross context virtual CPU structure.
3731 * @param pVmcsInfo The VMCS info. object.
3732 */
3733static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3734{
3735 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3736
3737 /*
3738 * By default, ensure guest attempts to access any MSR cause VM-exits.
3739 * This shall later be relaxed for specific MSRs as necessary.
3740 *
3741 * Note: For nested-guests, the entire bitmap will be merged prior to
3742 * executing the nested-guest using hardware-assisted VMX and hence there
3743 * is no need to perform this operation. See hmR0VmxMergeMsrBitmapNested.
3744 */
3745 Assert(pVmcsInfo->pvMsrBitmap);
3746 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
3747
3748 /*
3749 * The guest can access the following MSRs (read, write) without causing
3750 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3751 */
3752 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3753 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3754 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3755 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3756 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3757 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3758
3759 /*
3760 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3761 * associated with then. We never need to intercept access (writes need to be
3762 * executed without causing a VM-exit, reads will #GP fault anyway).
3763 *
3764 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3765 * read/write them. We swap the guest/host MSR value using the
3766 * auto-load/store MSR area.
3767 */
3768 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3769 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3770 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3771 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3772 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3773 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3774
3775 /*
3776 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3777 * required for 64-bit guests.
3778 */
3779 if (pVM->hmr0.s.fAllow64BitGuests)
3780 {
3781 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3782 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3783 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3784 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3785 }
3786
3787 /*
3788 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3789 */
3790#ifdef VBOX_STRICT
3791 Assert(pVmcsInfo->pvMsrBitmap);
3792 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3793 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3794#endif
3795}
3796
3797
3798/**
3799 * Sets up pin-based VM-execution controls in the VMCS.
3800 *
3801 * @returns VBox status code.
3802 * @param pVCpu The cross context virtual CPU structure.
3803 * @param pVmcsInfo The VMCS info. object.
3804 */
3805static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3806{
3807 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3808 uint32_t fVal = g_HmMsrs.u.vmx.PinCtls.n.allowed0; /* Bits set here must always be set. */
3809 uint32_t const fZap = g_HmMsrs.u.vmx.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3810
3811 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3812 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3813
3814 if (g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3815 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3816
3817 /* Enable the VMX-preemption timer. */
3818 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
3819 {
3820 Assert(g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3821 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3822 }
3823
3824#if 0
3825 /* Enable posted-interrupt processing. */
3826 if (pVM->hm.s.fPostedIntrs)
3827 {
3828 Assert(g_HmMsrs.u.vmx.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3829 Assert(g_HmMsrs.u.vmx.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3830 fVal |= VMX_PIN_CTLS_POSTED_INT;
3831 }
3832#endif
3833
3834 if ((fVal & fZap) != fVal)
3835 {
3836 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3837 g_HmMsrs.u.vmx.PinCtls.n.allowed0, fVal, fZap));
3838 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3839 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3840 }
3841
3842 /* Commit it to the VMCS and update our cache. */
3843 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3844 AssertRC(rc);
3845 pVmcsInfo->u32PinCtls = fVal;
3846
3847 return VINF_SUCCESS;
3848}
3849
3850
3851/**
3852 * Sets up secondary processor-based VM-execution controls in the VMCS.
3853 *
3854 * @returns VBox status code.
3855 * @param pVCpu The cross context virtual CPU structure.
3856 * @param pVmcsInfo The VMCS info. object.
3857 */
3858static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3859{
3860 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3861 uint32_t fVal = g_HmMsrs.u.vmx.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3862 uint32_t const fZap = g_HmMsrs.u.vmx.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3863
3864 /* WBINVD causes a VM-exit. */
3865 if (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3866 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3867
3868 /* Enable EPT (aka nested-paging). */
3869 if (pVM->hmr0.s.fNestedPaging)
3870 fVal |= VMX_PROC_CTLS2_EPT;
3871
3872 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3873 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3874 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3875 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3876 fVal |= VMX_PROC_CTLS2_INVPCID;
3877
3878 /* Enable VPID. */
3879 if (pVM->hmr0.s.vmx.fVpid)
3880 fVal |= VMX_PROC_CTLS2_VPID;
3881
3882 /* Enable unrestricted guest execution. */
3883 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
3884 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3885
3886#if 0
3887 if (pVM->hm.s.fVirtApicRegs)
3888 {
3889 /* Enable APIC-register virtualization. */
3890 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3891 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3892
3893 /* Enable virtual-interrupt delivery. */
3894 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3895 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3896 }
3897#endif
3898
3899 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3900 where the TPR shadow resides. */
3901 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3902 * done dynamically. */
3903 if (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3904 {
3905 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3906 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3907 }
3908
3909 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3910 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3911 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3912 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3913 fVal |= VMX_PROC_CTLS2_RDTSCP;
3914
3915 /* Enable Pause-Loop exiting. */
3916 if ( (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3917 && pVM->hm.s.vmx.cPleGapTicks
3918 && pVM->hm.s.vmx.cPleWindowTicks)
3919 {
3920 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3921
3922 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3923 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3924 }
3925
3926 if ((fVal & fZap) != fVal)
3927 {
3928 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3929 g_HmMsrs.u.vmx.ProcCtls2.n.allowed0, fVal, fZap));
3930 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3931 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3932 }
3933
3934 /* Commit it to the VMCS and update our cache. */
3935 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3936 AssertRC(rc);
3937 pVmcsInfo->u32ProcCtls2 = fVal;
3938
3939 return VINF_SUCCESS;
3940}
3941
3942
3943/**
3944 * Sets up processor-based VM-execution controls in the VMCS.
3945 *
3946 * @returns VBox status code.
3947 * @param pVCpu The cross context virtual CPU structure.
3948 * @param pVmcsInfo The VMCS info. object.
3949 */
3950static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3951{
3952 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3953 uint32_t fVal = g_HmMsrs.u.vmx.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3954 uint32_t const fZap = g_HmMsrs.u.vmx.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3955
3956 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3957 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3958 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3959 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3960 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3961 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3962 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3963
3964 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3965 if ( !(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3966 || (g_HmMsrs.u.vmx.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3967 {
3968 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3969 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3970 }
3971
3972 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3973 if (!pVM->hmr0.s.fNestedPaging)
3974 {
3975 Assert(!pVM->hmr0.s.vmx.fUnrestrictedGuest);
3976 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3977 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3978 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3979 }
3980
3981 /* Use TPR shadowing if supported by the CPU. */
3982 if ( PDMHasApic(pVM)
3983 && (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
3984 {
3985 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3986 /* CR8 writes cause a VM-exit based on TPR threshold. */
3987 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3988 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3989 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3990 }
3991 else
3992 {
3993 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3994 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3995 if (pVM->hmr0.s.fAllow64BitGuests)
3996 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3997 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3998 }
3999
4000 /* Use MSR-bitmaps if supported by the CPU. */
4001 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4002 {
4003 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
4004 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4005 }
4006
4007 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
4008 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
4009 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
4010
4011 if ((fVal & fZap) != fVal)
4012 {
4013 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4014 g_HmMsrs.u.vmx.ProcCtls.n.allowed0, fVal, fZap));
4015 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
4016 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4017 }
4018
4019 /* Commit it to the VMCS and update our cache. */
4020 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
4021 AssertRC(rc);
4022 pVmcsInfo->u32ProcCtls = fVal;
4023
4024 /* Set up MSR permissions that don't change through the lifetime of the VM. */
4025 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4026 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
4027
4028 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
4029 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
4030 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
4031
4032 /* Sanity check, should not really happen. */
4033 if (RT_LIKELY(!pVM->hmr0.s.vmx.fUnrestrictedGuest))
4034 { /* likely */ }
4035 else
4036 {
4037 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
4038 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4039 }
4040
4041 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
4042 return VINF_SUCCESS;
4043}
4044
4045
4046/**
4047 * Sets up miscellaneous (everything other than Pin, Processor and secondary
4048 * Processor-based VM-execution) control fields in the VMCS.
4049 *
4050 * @returns VBox status code.
4051 * @param pVCpu The cross context virtual CPU structure.
4052 * @param pVmcsInfo The VMCS info. object.
4053 */
4054static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4055{
4056#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4057 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUseVmcsShadowing)
4058 {
4059 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
4060 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
4061 }
4062#endif
4063
4064 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4065 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4066 AssertRC(rc);
4067
4068 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4069 if (RT_SUCCESS(rc))
4070 {
4071 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
4072 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
4073
4074 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
4075 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
4076
4077 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
4078 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
4079
4080 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fLbr)
4081 {
4082 rc = VMXWriteVmcsNw(VMX_VMCS64_GUEST_DEBUGCTL_FULL, MSR_IA32_DEBUGCTL_LBR);
4083 AssertRC(rc);
4084 }
4085 return VINF_SUCCESS;
4086 }
4087 else
4088 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
4089 return rc;
4090}
4091
4092
4093/**
4094 * Sets up the initial exception bitmap in the VMCS based on static conditions.
4095 *
4096 * We shall setup those exception intercepts that don't change during the
4097 * lifetime of the VM here. The rest are done dynamically while loading the
4098 * guest state.
4099 *
4100 * @param pVCpu The cross context virtual CPU structure.
4101 * @param pVmcsInfo The VMCS info. object.
4102 */
4103static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4104{
4105 /*
4106 * The following exceptions are always intercepted:
4107 *
4108 * #AC - To prevent the guest from hanging the CPU and for dealing with
4109 * split-lock detecting host configs.
4110 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
4111 * recursive #DBs can cause a CPU hang.
4112 * #PF - To sync our shadow page tables when nested-paging is not used.
4113 */
4114 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging;
4115 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
4116 | RT_BIT(X86_XCPT_DB)
4117 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
4118
4119 /* Commit it to the VMCS. */
4120 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
4121 AssertRC(rc);
4122
4123 /* Update our cache of the exception bitmap. */
4124 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
4125}
4126
4127
4128#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4129/**
4130 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
4131 *
4132 * @returns VBox status code.
4133 * @param pVmcsInfo The VMCS info. object.
4134 */
4135static int hmR0VmxSetupVmcsCtlsNested(PVMXVMCSINFO pVmcsInfo)
4136{
4137 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4138 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4139 AssertRC(rc);
4140
4141 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4142 if (RT_SUCCESS(rc))
4143 {
4144 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4145 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4146
4147 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
4148 Assert(!pVmcsInfo->u64Cr0Mask);
4149 Assert(!pVmcsInfo->u64Cr4Mask);
4150 return VINF_SUCCESS;
4151 }
4152 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
4153 return rc;
4154}
4155#endif
4156
4157
4158/**
4159 * Sets pfnStartVm to the best suited variant.
4160 *
4161 * This must be called whenever anything changes relative to the hmR0VmXStartVm
4162 * variant selection:
4163 * - pVCpu->hm.s.fLoadSaveGuestXcr0
4164 * - HM_WSF_IBPB_ENTRY in pVCpu->hmr0.s.fWorldSwitcher
4165 * - HM_WSF_IBPB_EXIT in pVCpu->hmr0.s.fWorldSwitcher
4166 * - Perhaps: CPUMIsGuestFPUStateActive() (windows only)
4167 * - Perhaps: CPUMCTX.fXStateMask (windows only)
4168 *
4169 * We currently ASSUME that neither HM_WSF_IBPB_ENTRY nor HM_WSF_IBPB_EXIT
4170 * cannot be changed at runtime.
4171 */
4172static void hmR0VmxUpdateStartVmFunction(PVMCPUCC pVCpu)
4173{
4174 static const struct CLANGWORKAROUND { PFNHMVMXSTARTVM pfn; } s_aHmR0VmxStartVmFunctions[] =
4175 {
4176 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4177 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4178 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4179 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4180 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4181 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4182 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4183 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4184 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4185 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4186 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4187 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4188 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4189 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4190 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4191 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4192 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4193 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4194 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4195 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4196 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4197 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4198 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4199 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4200 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4201 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4202 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4203 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4204 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4205 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4206 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4207 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4208 };
4209 uintptr_t const idx = (pVCpu->hmr0.s.fLoadSaveGuestXcr0 ? 1 : 0)
4210 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_IBPB_ENTRY ? 2 : 0)
4211 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_L1D_ENTRY ? 4 : 0)
4212 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_MDS_ENTRY ? 8 : 0)
4213 | (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_IBPB_EXIT ? 16 : 0);
4214 PFNHMVMXSTARTVM const pfnStartVm = s_aHmR0VmxStartVmFunctions[idx].pfn;
4215 if (pVCpu->hmr0.s.vmx.pfnStartVm != pfnStartVm)
4216 pVCpu->hmr0.s.vmx.pfnStartVm = pfnStartVm;
4217}
4218
4219
4220/**
4221 * Selector FNHMSVMVMRUN implementation.
4222 */
4223static DECLCALLBACK(int) hmR0VmxStartVmSelector(PVMXVMCSINFO pVmcsInfo, PVMCPUCC pVCpu, bool fResume)
4224{
4225 hmR0VmxUpdateStartVmFunction(pVCpu);
4226 return pVCpu->hmr0.s.vmx.pfnStartVm(pVmcsInfo, pVCpu, fResume);
4227}
4228
4229
4230/**
4231 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
4232 * VMX.
4233 *
4234 * @returns VBox status code.
4235 * @param pVCpu The cross context virtual CPU structure.
4236 * @param pVmcsInfo The VMCS info. object.
4237 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
4238 */
4239static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
4240{
4241 Assert(pVmcsInfo->pvVmcs);
4242 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4243
4244 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
4245 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
4246 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
4247
4248 LogFlowFunc(("\n"));
4249
4250 /*
4251 * Initialize the VMCS using VMCLEAR before loading the VMCS.
4252 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
4253 */
4254 int rc = hmR0VmxClearVmcs(pVmcsInfo);
4255 if (RT_SUCCESS(rc))
4256 {
4257 rc = hmR0VmxLoadVmcs(pVmcsInfo);
4258 if (RT_SUCCESS(rc))
4259 {
4260 /*
4261 * Initialize the hardware-assisted VMX execution handler for guest and nested-guest VMCS.
4262 * The host is always 64-bit since we no longer support 32-bit hosts.
4263 * Currently we have just a single handler for all guest modes as well, see @bugref{6208#c73}.
4264 */
4265 if (!fIsNstGstVmcs)
4266 {
4267 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
4268 if (RT_SUCCESS(rc))
4269 {
4270 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
4271 if (RT_SUCCESS(rc))
4272 {
4273 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
4274 if (RT_SUCCESS(rc))
4275 {
4276 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4277#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4278 /*
4279 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4280 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4281 * making it fit for use when VMCS shadowing is later enabled.
4282 */
4283 if (pVmcsInfo->pvShadowVmcs)
4284 {
4285 VMXVMCSREVID VmcsRevId;
4286 VmcsRevId.u = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID);
4287 VmcsRevId.n.fIsShadowVmcs = 1;
4288 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4289 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4290 if (RT_SUCCESS(rc))
4291 { /* likely */ }
4292 else
4293 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4294 }
4295#endif
4296 }
4297 else
4298 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4299 }
4300 else
4301 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4302 }
4303 else
4304 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4305 }
4306 else
4307 {
4308#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4309 rc = hmR0VmxSetupVmcsCtlsNested(pVmcsInfo);
4310 if (RT_SUCCESS(rc))
4311 { /* likely */ }
4312 else
4313 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4314#else
4315 AssertFailed();
4316#endif
4317 }
4318 }
4319 else
4320 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4321 }
4322 else
4323 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4324
4325 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4326 if (RT_SUCCESS(rc))
4327 {
4328 rc = hmR0VmxClearVmcs(pVmcsInfo);
4329 if (RT_SUCCESS(rc))
4330 { /* likely */ }
4331 else
4332 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4333 }
4334
4335 /*
4336 * Update the last-error record both for failures and success, so we
4337 * can propagate the status code back to ring-3 for diagnostics.
4338 */
4339 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4340 NOREF(pszVmcs);
4341 return rc;
4342}
4343
4344
4345/**
4346 * Does global VT-x initialization (called during module initialization).
4347 *
4348 * @returns VBox status code.
4349 */
4350VMMR0DECL(int) VMXR0GlobalInit(void)
4351{
4352#ifdef HMVMX_USE_FUNCTION_TABLE
4353 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_aVMExitHandlers));
4354# ifdef VBOX_STRICT
4355 for (unsigned i = 0; i < RT_ELEMENTS(g_aVMExitHandlers); i++)
4356 Assert(g_aVMExitHandlers[i].pfn);
4357# endif
4358#endif
4359 return VINF_SUCCESS;
4360}
4361
4362
4363/**
4364 * Does global VT-x termination (called during module termination).
4365 */
4366VMMR0DECL(void) VMXR0GlobalTerm()
4367{
4368 /* Nothing to do currently. */
4369}
4370
4371
4372/**
4373 * Sets up and activates VT-x on the current CPU.
4374 *
4375 * @returns VBox status code.
4376 * @param pHostCpu The HM physical-CPU structure.
4377 * @param pVM The cross context VM structure. Can be
4378 * NULL after a host resume operation.
4379 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4380 * fEnabledByHost is @c true).
4381 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4382 * @a fEnabledByHost is @c true).
4383 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4384 * enable VT-x on the host.
4385 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4386 */
4387VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4388 PCSUPHWVIRTMSRS pHwvirtMsrs)
4389{
4390 AssertPtr(pHostCpu);
4391 AssertPtr(pHwvirtMsrs);
4392 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4393
4394 /* Enable VT-x if it's not already enabled by the host. */
4395 if (!fEnabledByHost)
4396 {
4397 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4398 if (RT_FAILURE(rc))
4399 return rc;
4400 }
4401
4402 /*
4403 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4404 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4405 * invalidated when flushing by VPID.
4406 */
4407 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4408 {
4409 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4410 pHostCpu->fFlushAsidBeforeUse = false;
4411 }
4412 else
4413 pHostCpu->fFlushAsidBeforeUse = true;
4414
4415 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4416 ++pHostCpu->cTlbFlushes;
4417
4418 return VINF_SUCCESS;
4419}
4420
4421
4422/**
4423 * Deactivates VT-x on the current CPU.
4424 *
4425 * @returns VBox status code.
4426 * @param pHostCpu The HM physical-CPU structure.
4427 * @param pvCpuPage Pointer to the VMXON region.
4428 * @param HCPhysCpuPage Physical address of the VMXON region.
4429 *
4430 * @remarks This function should never be called when SUPR0EnableVTx() or
4431 * similar was used to enable VT-x on the host.
4432 */
4433VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4434{
4435 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4436
4437 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4438 return hmR0VmxLeaveRootMode(pHostCpu);
4439}
4440
4441
4442/**
4443 * Does per-VM VT-x initialization.
4444 *
4445 * @returns VBox status code.
4446 * @param pVM The cross context VM structure.
4447 */
4448VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4449{
4450 AssertPtr(pVM);
4451 LogFlowFunc(("pVM=%p\n", pVM));
4452
4453 hmR0VmxStructsInit(pVM);
4454 int rc = hmR0VmxStructsAlloc(pVM);
4455 if (RT_FAILURE(rc))
4456 {
4457 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4458 return rc;
4459 }
4460
4461 /* Setup the crash dump page. */
4462#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4463 strcpy((char *)pVM->hmr0.s.vmx.pbScratch, "SCRATCH Magic");
4464 *(uint64_t *)(pVM->hmr0.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
4465#endif
4466 return VINF_SUCCESS;
4467}
4468
4469
4470/**
4471 * Does per-VM VT-x termination.
4472 *
4473 * @returns VBox status code.
4474 * @param pVM The cross context VM structure.
4475 */
4476VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4477{
4478 AssertPtr(pVM);
4479 LogFlowFunc(("pVM=%p\n", pVM));
4480
4481#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4482 if (pVM->hmr0.s.vmx.pbScratch)
4483 RT_BZERO(pVM->hmr0.s.vmx.pbScratch, X86_PAGE_4K_SIZE);
4484#endif
4485 hmR0VmxStructsFree(pVM);
4486 return VINF_SUCCESS;
4487}
4488
4489
4490/**
4491 * Sets up the VM for execution using hardware-assisted VMX.
4492 * This function is only called once per-VM during initialization.
4493 *
4494 * @returns VBox status code.
4495 * @param pVM The cross context VM structure.
4496 */
4497VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4498{
4499 AssertPtr(pVM);
4500 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4501
4502 LogFlowFunc(("pVM=%p\n", pVM));
4503
4504 /*
4505 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4506 * without causing a #GP.
4507 */
4508 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4509 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4510 { /* likely */ }
4511 else
4512 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4513
4514 /*
4515 * Check that nested paging is supported if enabled and copy over the flag to the
4516 * ring-0 only structure.
4517 */
4518 bool const fNestedPaging = pVM->hm.s.fNestedPagingCfg;
4519 AssertReturn( !fNestedPaging
4520 || (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_EPT), /** @todo use a ring-0 copy of ProcCtls2.n.allowed1 */
4521 VERR_INCOMPATIBLE_CONFIG);
4522 pVM->hmr0.s.fNestedPaging = fNestedPaging;
4523 pVM->hmr0.s.fAllow64BitGuests = pVM->hm.s.fAllow64BitGuestsCfg;
4524
4525 /*
4526 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4527 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4528 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4529 */
4530 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuestCfg;
4531 AssertReturn( !fUnrestrictedGuest
4532 || ( (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_UNRESTRICTED_GUEST)
4533 && fNestedPaging),
4534 VERR_INCOMPATIBLE_CONFIG);
4535 if ( !fUnrestrictedGuest
4536 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4537 || !pVM->hm.s.vmx.pRealModeTSS))
4538 {
4539 LogRelFunc(("Invalid real-on-v86 state.\n"));
4540 return VERR_INTERNAL_ERROR;
4541 }
4542 pVM->hmr0.s.vmx.fUnrestrictedGuest = fUnrestrictedGuest;
4543
4544 /* Initialize these always, see hmR3InitFinalizeR0().*/
4545 pVM->hm.s.ForR3.vmx.enmTlbFlushEpt = pVM->hmr0.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4546 pVM->hm.s.ForR3.vmx.enmTlbFlushVpid = pVM->hmr0.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4547
4548 /* Setup the tagged-TLB flush handlers. */
4549 int rc = hmR0VmxSetupTaggedTlb(pVM);
4550 if (RT_FAILURE(rc))
4551 {
4552 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4553 return rc;
4554 }
4555
4556 /* Determine LBR capabilities. */
4557 pVM->hmr0.s.vmx.fLbr = pVM->hm.s.vmx.fLbrCfg;
4558 if (pVM->hmr0.s.vmx.fLbr)
4559 {
4560 rc = hmR0VmxSetupLbrMsrRange(pVM);
4561 if (RT_FAILURE(rc))
4562 {
4563 LogRelFunc(("Failed to setup LBR MSR range. rc=%Rrc\n", rc));
4564 return rc;
4565 }
4566 }
4567
4568#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4569 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4570 if (pVM->hmr0.s.vmx.fUseVmcsShadowing)
4571 {
4572 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4573 if (RT_SUCCESS(rc))
4574 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4575 else
4576 {
4577 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4578 return rc;
4579 }
4580 }
4581#endif
4582
4583 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4584 {
4585 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4586 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4587
4588 pVCpu->hmr0.s.vmx.pfnStartVm = hmR0VmxStartVmSelector;
4589
4590 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4591 if (RT_SUCCESS(rc))
4592 {
4593#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4594 if (pVM->cpum.ro.GuestFeatures.fVmx)
4595 {
4596 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4597 if (RT_SUCCESS(rc))
4598 { /* likely */ }
4599 else
4600 {
4601 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4602 return rc;
4603 }
4604 }
4605#endif
4606 }
4607 else
4608 {
4609 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4610 return rc;
4611 }
4612 }
4613
4614 return VINF_SUCCESS;
4615}
4616
4617
4618/**
4619 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4620 * the VMCS.
4621 * @returns CR4 for passing along to hmR0VmxExportHostSegmentRegs.
4622 */
4623static uint64_t hmR0VmxExportHostControlRegs(void)
4624{
4625 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4626 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4627 uint64_t uHostCr4 = ASMGetCR4();
4628 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, uHostCr4); AssertRC(rc);
4629 return uHostCr4;
4630}
4631
4632
4633/**
4634 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4635 * the host-state area in the VMCS.
4636 *
4637 * @returns VBox status code.
4638 * @param pVCpu The cross context virtual CPU structure.
4639 * @param uHostCr4 The host CR4 value.
4640 */
4641static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu, uint64_t uHostCr4)
4642{
4643 /*
4644 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4645 * will be messed up. We should -not- save the messed up state without restoring
4646 * the original host-state, see @bugref{7240}.
4647 *
4648 * This apparently can happen (most likely the FPU changes), deal with it rather than
4649 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4650 */
4651 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
4652 {
4653 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hmr0.s.vmx.fRestoreHostFlags,
4654 pVCpu->idCpu));
4655 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
4656 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
4657 }
4658
4659 /*
4660 * Get all the host info.
4661 * ASSUME it is safe to use rdfsbase and friends if the CR4.FSGSBASE bit is set
4662 * without also checking the cpuid bit.
4663 */
4664 uint32_t fRestoreHostFlags;
4665#if RT_INLINE_ASM_EXTERNAL
4666 if (uHostCr4 & X86_CR4_FSGSBASE)
4667 {
4668 hmR0VmxExportHostSegmentRegsAsmHlp(&pVCpu->hmr0.s.vmx.RestoreHost, true /*fHaveFsGsBase*/);
4669 fRestoreHostFlags = VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE;
4670 }
4671 else
4672 {
4673 hmR0VmxExportHostSegmentRegsAsmHlp(&pVCpu->hmr0.s.vmx.RestoreHost, false /*fHaveFsGsBase*/);
4674 fRestoreHostFlags = 0;
4675 }
4676 RTSEL uSelES = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelES;
4677 RTSEL uSelDS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelDS;
4678 RTSEL uSelFS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelFS;
4679 RTSEL uSelGS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelGS;
4680#else
4681 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR = ASMGetTR();
4682 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS = ASMGetSS();
4683 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS = ASMGetCS();
4684 ASMGetGDTR((PRTGDTR)&pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr);
4685 ASMGetIDTR((PRTIDTR)&pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr);
4686 if (uHostCr4 & X86_CR4_FSGSBASE)
4687 {
4688 pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase = ASMGetFSBase();
4689 pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase = ASMGetGSBase();
4690 fRestoreHostFlags = VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE;
4691 }
4692 else
4693 {
4694 pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase = ASMRdMsr(MSR_K8_FS_BASE);
4695 pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase = ASMRdMsr(MSR_K8_GS_BASE);
4696 fRestoreHostFlags = 0;
4697 }
4698 RTSEL uSelES, uSelDS, uSelFS, uSelGS;
4699 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelDS = uSelDS = ASMGetDS();
4700 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelES = uSelES = ASMGetES();
4701 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelFS = uSelFS = ASMGetFS();
4702 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelGS = uSelGS = ASMGetGS();
4703#endif
4704
4705 /*
4706 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4707 * gain VM-entry and restore them before we get preempted.
4708 *
4709 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4710 */
4711 RTSEL const uSelAll = uSelFS | uSelGS | uSelES | uSelDS;
4712 if (uSelAll & (X86_SEL_RPL | X86_SEL_LDT))
4713 {
4714 if (!(uSelAll & X86_SEL_LDT))
4715 {
4716#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_uVmcsVar) \
4717 do { \
4718 (a_uVmcsVar) = pVCpu->hmr0.s.vmx.RestoreHost.uHostSel##a_Seg; \
4719 if ((a_uVmcsVar) & X86_SEL_RPL) \
4720 { \
4721 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4722 (a_uVmcsVar) = 0; \
4723 } \
4724 } while (0)
4725 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4726 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4727 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4728 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4729#undef VMXLOCAL_ADJUST_HOST_SEG
4730 }
4731 else
4732 {
4733#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_uVmcsVar) \
4734 do { \
4735 (a_uVmcsVar) = pVCpu->hmr0.s.vmx.RestoreHost.uHostSel##a_Seg; \
4736 if ((a_uVmcsVar) & (X86_SEL_RPL | X86_SEL_LDT)) \
4737 { \
4738 if (!((a_uVmcsVar) & X86_SEL_LDT)) \
4739 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4740 else \
4741 { \
4742 uint32_t const fAttr = ASMGetSegAttr(a_uVmcsVar); \
4743 if ((fAttr & X86_DESC_P) && fAttr != UINT32_MAX) \
4744 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4745 } \
4746 (a_uVmcsVar) = 0; \
4747 } \
4748 } while (0)
4749 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4750 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4751 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4752 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4753#undef VMXLOCAL_ADJUST_HOST_SEG
4754 }
4755 }
4756
4757 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4758 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR & X86_SEL_LDT)); Assert(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR);
4759 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS & X86_SEL_LDT)); Assert(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS);
4760 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS & X86_SEL_LDT));
4761 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4762 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4763 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4764 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4765
4766 /*
4767 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4768 * them to the maximum limit (0xffff) on every VM-exit.
4769 */
4770 if (pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb != 0xffff)
4771 fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4772
4773 /*
4774 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4775 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4776 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4777 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4778 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4779 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4780 * at 0xffff on hosts where we are sure it won't cause trouble.
4781 */
4782#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4783 if (pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.cb < 0x0fff)
4784#else
4785 if (pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.cb != 0xffff)
4786#endif
4787 fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4788
4789 /*
4790 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4791 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4792 * RPL should be too in most cases.
4793 */
4794 RTSEL const uSelTR = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR;
4795 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb,
4796 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb),
4797 VERR_VMX_INVALID_HOST_STATE);
4798
4799 PCX86DESCHC pDesc = (PCX86DESCHC)(pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.uAddr + (uSelTR & X86_SEL_MASK));
4800 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4801
4802 /*
4803 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4804 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4805 * restoration if the host has something else. Task switching is not supported in 64-bit
4806 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4807 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4808 *
4809 * [1] See Intel spec. 3.5 "System Descriptor Types".
4810 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4811 */
4812 Assert(pDesc->System.u4Type == 11);
4813 if ( pDesc->System.u16LimitLow != 0x67
4814 || pDesc->System.u4LimitHigh)
4815 {
4816 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4817
4818 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4819 if (g_fHmHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4820 fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4821 if (g_fHmHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4822 {
4823 /* The GDT is read-only but the writable GDT is available. */
4824 fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4825 pVCpu->hmr0.s.vmx.RestoreHost.HostGdtrRw.cb = pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb;
4826 int rc = SUPR0GetCurrentGdtRw(&pVCpu->hmr0.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4827 AssertRCReturn(rc, rc);
4828 }
4829 }
4830
4831 pVCpu->hmr0.s.vmx.fRestoreHostFlags = fRestoreHostFlags;
4832
4833 /*
4834 * Do all the VMCS updates in one block to assist nested virtualization.
4835 */
4836 int rc;
4837 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS); AssertRC(rc);
4838 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS); AssertRC(rc);
4839 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4840 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4841 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4842 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4843 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR); AssertRC(rc);
4844 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.uAddr); AssertRC(rc);
4845 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.uAddr); AssertRC(rc);
4846 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase); AssertRC(rc);
4847 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase); AssertRC(rc);
4848 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase); AssertRC(rc);
4849
4850 return VINF_SUCCESS;
4851}
4852
4853
4854/**
4855 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4856 * host-state area of the VMCS.
4857 *
4858 * These MSRs will be automatically restored on the host after every successful
4859 * VM-exit.
4860 *
4861 * @param pVCpu The cross context virtual CPU structure.
4862 *
4863 * @remarks No-long-jump zone!!!
4864 */
4865static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4866{
4867 AssertPtr(pVCpu);
4868
4869 /*
4870 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4871 * rather than swapping them on every VM-entry.
4872 */
4873 hmR0VmxLazySaveHostMsrs(pVCpu);
4874
4875 /*
4876 * Host Sysenter MSRs.
4877 */
4878 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4879 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4880 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4881
4882 /*
4883 * Host EFER MSR.
4884 *
4885 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4886 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4887 */
4888 if (g_fHmVmxSupportsVmcsEfer)
4889 {
4890 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, g_uHmVmxHostMsrEfer);
4891 AssertRC(rc);
4892 }
4893
4894 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4895 * hmR0VmxExportGuestEntryExitCtls(). */
4896}
4897
4898
4899/**
4900 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4901 *
4902 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4903 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4904 *
4905 * @returns true if we need to load guest EFER, false otherwise.
4906 * @param pVCpu The cross context virtual CPU structure.
4907 * @param pVmxTransient The VMX-transient structure.
4908 *
4909 * @remarks Requires EFER, CR4.
4910 * @remarks No-long-jump zone!!!
4911 */
4912static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4913{
4914#ifdef HMVMX_ALWAYS_SWAP_EFER
4915 RT_NOREF2(pVCpu, pVmxTransient);
4916 return true;
4917#else
4918 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4919 uint64_t const u64HostEfer = g_uHmVmxHostMsrEfer;
4920 uint64_t const u64GuestEfer = pCtx->msrEFER;
4921
4922# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4923 /*
4924 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4925 * the nested-guest.
4926 */
4927 if ( pVmxTransient->fIsNestedGuest
4928 && ( CPUMIsGuestVmxEntryCtlsSet(pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4929 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4930 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4931 return true;
4932# else
4933 RT_NOREF(pVmxTransient);
4934#endif
4935
4936 /*
4937 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4938 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4939 */
4940 if ( CPUMIsGuestInLongModeEx(pCtx)
4941 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4942 return true;
4943
4944 /*
4945 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4946 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4947 *
4948 * See Intel spec. 4.5 "IA-32e Paging".
4949 * See Intel spec. 4.1.1 "Three Paging Modes".
4950 *
4951 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4952 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4953 */
4954 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4955 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4956 if ( (pCtx->cr4 & X86_CR4_PAE)
4957 && (pCtx->cr0 & X86_CR0_PG))
4958 {
4959 /*
4960 * If nested paging is not used, verify that the guest paging mode matches the
4961 * shadow paging mode which is/will be placed in the VMCS (which is what will
4962 * actually be used while executing the guest and not the CR4 shadow value).
4963 */
4964 AssertMsg( pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging
4965 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4966 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4967 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4968 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX,
4969 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4970 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4971 {
4972 /* Verify that the host is NX capable. */
4973 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4974 return true;
4975 }
4976 }
4977
4978 return false;
4979#endif
4980}
4981
4982
4983/**
4984 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4985 * VMCS.
4986 *
4987 * This is typically required when the guest changes paging mode.
4988 *
4989 * @returns VBox status code.
4990 * @param pVCpu The cross context virtual CPU structure.
4991 * @param pVmxTransient The VMX-transient structure.
4992 *
4993 * @remarks Requires EFER.
4994 * @remarks No-long-jump zone!!!
4995 */
4996static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4997{
4998 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4999 {
5000 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5001 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5002
5003 /*
5004 * VM-entry controls.
5005 */
5006 {
5007 uint32_t fVal = g_HmMsrs.u.vmx.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5008 uint32_t const fZap = g_HmMsrs.u.vmx.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5009
5010 /*
5011 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
5012 * The first VT-x capable CPUs only supported the 1-setting of this bit.
5013 *
5014 * For nested-guests, this is a mandatory VM-entry control. It's also
5015 * required because we do not want to leak host bits to the nested-guest.
5016 */
5017 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
5018
5019 /*
5020 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
5021 *
5022 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
5023 * required to get the nested-guest working with hardware-assisted VMX execution.
5024 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
5025 * can skip intercepting changes to the EFER MSR. This is why it needs to be done
5026 * here rather than while merging the guest VMCS controls.
5027 */
5028 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
5029 {
5030 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
5031 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
5032 }
5033 else
5034 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
5035
5036 /*
5037 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
5038 *
5039 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
5040 * regardless of whether the nested-guest VMCS specifies it because we are free to
5041 * load whatever MSRs we require and we do not need to modify the guest visible copy
5042 * of the VM-entry MSR load area.
5043 */
5044 if ( g_fHmVmxSupportsVmcsEfer
5045 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
5046 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
5047 else
5048 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
5049
5050 /*
5051 * The following should -not- be set (since we're not in SMM mode):
5052 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
5053 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
5054 */
5055
5056 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
5057 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
5058
5059 if ((fVal & fZap) == fVal)
5060 { /* likely */ }
5061 else
5062 {
5063 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
5064 g_HmMsrs.u.vmx.EntryCtls.n.allowed0, fVal, fZap));
5065 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
5066 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5067 }
5068
5069 /* Commit it to the VMCS. */
5070 if (pVmcsInfo->u32EntryCtls != fVal)
5071 {
5072 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
5073 AssertRC(rc);
5074 pVmcsInfo->u32EntryCtls = fVal;
5075 }
5076 }
5077
5078 /*
5079 * VM-exit controls.
5080 */
5081 {
5082 uint32_t fVal = g_HmMsrs.u.vmx.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5083 uint32_t const fZap = g_HmMsrs.u.vmx.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5084
5085 /*
5086 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
5087 * supported the 1-setting of this bit.
5088 *
5089 * For nested-guests, we set the "save debug controls" as the converse
5090 * "load debug controls" is mandatory for nested-guests anyway.
5091 */
5092 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
5093
5094 /*
5095 * Set the host long mode active (EFER.LMA) bit (which Intel calls
5096 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
5097 * host EFER.LMA and EFER.LME bit to this value. See assertion in
5098 * hmR0VmxExportHostMsrs().
5099 *
5100 * For nested-guests, we always set this bit as we do not support 32-bit
5101 * hosts.
5102 */
5103 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5104
5105 /*
5106 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
5107 *
5108 * For nested-guests, we should use the "save IA32_EFER" control if we also
5109 * used the "load IA32_EFER" control while exporting VM-entry controls.
5110 */
5111 if ( g_fHmVmxSupportsVmcsEfer
5112 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
5113 {
5114 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
5115 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
5116 }
5117
5118 /*
5119 * Enable saving of the VMX-preemption timer value on VM-exit.
5120 * For nested-guests, currently not exposed/used.
5121 */
5122 /** @todo r=bird: Measure performance hit because of this vs. always rewriting
5123 * the timer value. */
5124 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
5125 {
5126 Assert(g_HmMsrs.u.vmx.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER);
5127 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
5128 }
5129
5130 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
5131 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
5132
5133 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5134 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5135 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5136
5137 if ((fVal & fZap) == fVal)
5138 { /* likely */ }
5139 else
5140 {
5141 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5142 g_HmMsrs.u.vmx.ExitCtls.n.allowed0, fVal, fZap));
5143 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5144 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5145 }
5146
5147 /* Commit it to the VMCS. */
5148 if (pVmcsInfo->u32ExitCtls != fVal)
5149 {
5150 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5151 AssertRC(rc);
5152 pVmcsInfo->u32ExitCtls = fVal;
5153 }
5154 }
5155
5156 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5157 }
5158 return VINF_SUCCESS;
5159}
5160
5161
5162/**
5163 * Sets the TPR threshold in the VMCS.
5164 *
5165 * @param pVmcsInfo The VMCS info. object.
5166 * @param u32TprThreshold The TPR threshold (task-priority class only).
5167 */
5168DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5169{
5170 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5171 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5172 RT_NOREF(pVmcsInfo);
5173 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5174 AssertRC(rc);
5175}
5176
5177
5178/**
5179 * Exports the guest APIC TPR state into the VMCS.
5180 *
5181 * @param pVCpu The cross context virtual CPU structure.
5182 * @param pVmxTransient The VMX-transient structure.
5183 *
5184 * @remarks No-long-jump zone!!!
5185 */
5186static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5187{
5188 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5189 {
5190 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5191
5192 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5193 if (!pVmxTransient->fIsNestedGuest)
5194 {
5195 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5196 && APICIsEnabled(pVCpu))
5197 {
5198 /*
5199 * Setup TPR shadowing.
5200 */
5201 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5202 {
5203 bool fPendingIntr = false;
5204 uint8_t u8Tpr = 0;
5205 uint8_t u8PendingIntr = 0;
5206 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5207 AssertRC(rc);
5208
5209 /*
5210 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5211 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5212 * priority of the pending interrupt so we can deliver the interrupt. If there
5213 * are no interrupts pending, set threshold to 0 to not cause any
5214 * TPR-below-threshold VM-exits.
5215 */
5216 uint32_t u32TprThreshold = 0;
5217 if (fPendingIntr)
5218 {
5219 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5220 (which is the Task-Priority Class). */
5221 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5222 const uint8_t u8TprPriority = u8Tpr >> 4;
5223 if (u8PendingPriority <= u8TprPriority)
5224 u32TprThreshold = u8PendingPriority;
5225 }
5226
5227 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
5228 }
5229 }
5230 }
5231 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5232 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5233 }
5234}
5235
5236
5237/**
5238 * Gets the guest interruptibility-state and updates related force-flags.
5239 *
5240 * @returns Guest's interruptibility-state.
5241 * @param pVCpu The cross context virtual CPU structure.
5242 *
5243 * @remarks No-long-jump zone!!!
5244 */
5245static uint32_t hmR0VmxGetGuestIntrStateAndUpdateFFs(PVMCPUCC pVCpu)
5246{
5247 /*
5248 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5249 */
5250 uint32_t fIntrState = 0;
5251 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5252 {
5253 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
5254 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
5255
5256 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5257 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5258 {
5259 if (pCtx->eflags.Bits.u1IF)
5260 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5261 else
5262 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5263 }
5264 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5265 {
5266 /*
5267 * We can clear the inhibit force flag as even if we go back to the recompiler
5268 * without executing guest code in VT-x, the flag's condition to be cleared is
5269 * met and thus the cleared state is correct.
5270 */
5271 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5272 }
5273 }
5274
5275 /*
5276 * Check if we should inhibit NMI delivery.
5277 */
5278 if (CPUMIsGuestNmiBlocking(pVCpu))
5279 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5280
5281 /*
5282 * Validate.
5283 */
5284#ifdef VBOX_STRICT
5285 /* We don't support block-by-SMI yet.*/
5286 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
5287
5288 /* Block-by-STI must not be set when interrupts are disabled. */
5289 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
5290 {
5291 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5292 Assert(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_IF);
5293 }
5294#endif
5295
5296 return fIntrState;
5297}
5298
5299
5300/**
5301 * Exports the exception intercepts required for guest execution in the VMCS.
5302 *
5303 * @param pVCpu The cross context virtual CPU structure.
5304 * @param pVmxTransient The VMX-transient structure.
5305 *
5306 * @remarks No-long-jump zone!!!
5307 */
5308static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5309{
5310 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5311 {
5312 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5313 if ( !pVmxTransient->fIsNestedGuest
5314 && pVCpu->hm.s.fGIMTrapXcptUD)
5315 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5316 else
5317 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5318
5319 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5320 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5321 }
5322}
5323
5324
5325/**
5326 * Exports the guest's RIP into the guest-state area in the VMCS.
5327 *
5328 * @param pVCpu The cross context virtual CPU structure.
5329 *
5330 * @remarks No-long-jump zone!!!
5331 */
5332static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5333{
5334 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5335 {
5336 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5337
5338 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5339 AssertRC(rc);
5340
5341 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5342 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5343 }
5344}
5345
5346
5347/**
5348 * Exports the guest's RSP into the guest-state area in the VMCS.
5349 *
5350 * @param pVCpu The cross context virtual CPU structure.
5351 *
5352 * @remarks No-long-jump zone!!!
5353 */
5354static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5355{
5356 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5357 {
5358 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5359
5360 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5361 AssertRC(rc);
5362
5363 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5364 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5365 }
5366}
5367
5368
5369/**
5370 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5371 *
5372 * @param pVCpu The cross context virtual CPU structure.
5373 * @param pVmxTransient The VMX-transient structure.
5374 *
5375 * @remarks No-long-jump zone!!!
5376 */
5377static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5378{
5379 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5380 {
5381 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5382
5383 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5384 Let us assert it as such and use 32-bit VMWRITE. */
5385 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5386 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5387 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5388 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5389
5390 /*
5391 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5392 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5393 * can run the real-mode guest code under Virtual 8086 mode.
5394 */
5395 PVMXVMCSINFOSHARED pVmcsInfo = pVmxTransient->pVmcsInfo->pShared;
5396 if (pVmcsInfo->RealMode.fRealOnV86Active)
5397 {
5398 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5399 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5400 Assert(!pVmxTransient->fIsNestedGuest);
5401 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5402 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5403 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5404 }
5405
5406 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5407 AssertRC(rc);
5408
5409 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5410 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5411 }
5412}
5413
5414
5415#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5416/**
5417 * Copies the nested-guest VMCS to the shadow VMCS.
5418 *
5419 * @returns VBox status code.
5420 * @param pVCpu The cross context virtual CPU structure.
5421 * @param pVmcsInfo The VMCS info. object.
5422 *
5423 * @remarks No-long-jump zone!!!
5424 */
5425static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5426{
5427 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5428 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5429
5430 /*
5431 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5432 * current VMCS, as we may try saving guest lazy MSRs.
5433 *
5434 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5435 * calling the import VMCS code which is currently performing the guest MSR reads
5436 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5437 * and the rest of the VMX leave session machinery.
5438 */
5439 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5440
5441 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5442 if (RT_SUCCESS(rc))
5443 {
5444 /*
5445 * Copy all guest read/write VMCS fields.
5446 *
5447 * We don't check for VMWRITE failures here for performance reasons and
5448 * because they are not expected to fail, barring irrecoverable conditions
5449 * like hardware errors.
5450 */
5451 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
5452 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5453 {
5454 uint64_t u64Val;
5455 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsFields[i];
5456 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5457 VMXWriteVmcs64(uVmcsField, u64Val);
5458 }
5459
5460 /*
5461 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5462 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5463 */
5464 if (g_HmMsrs.u.vmx.u64Misc & VMX_MISC_VMWRITE_ALL)
5465 {
5466 uint32_t const cShadowVmcsRoFields = pVM->hmr0.s.vmx.cShadowVmcsRoFields;
5467 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5468 {
5469 uint64_t u64Val;
5470 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsRoFields[i];
5471 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5472 VMXWriteVmcs64(uVmcsField, u64Val);
5473 }
5474 }
5475
5476 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5477 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5478 }
5479
5480 ASMSetFlags(fEFlags);
5481 return rc;
5482}
5483
5484
5485/**
5486 * Copies the shadow VMCS to the nested-guest VMCS.
5487 *
5488 * @returns VBox status code.
5489 * @param pVCpu The cross context virtual CPU structure.
5490 * @param pVmcsInfo The VMCS info. object.
5491 *
5492 * @remarks Called with interrupts disabled.
5493 */
5494static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5495{
5496 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5497 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5498 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5499
5500 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5501 if (RT_SUCCESS(rc))
5502 {
5503 /*
5504 * Copy guest read/write fields from the shadow VMCS.
5505 * Guest read-only fields cannot be modified, so no need to copy them.
5506 *
5507 * We don't check for VMREAD failures here for performance reasons and
5508 * because they are not expected to fail, barring irrecoverable conditions
5509 * like hardware errors.
5510 */
5511 uint32_t const cShadowVmcsFields = pVM->hmr0.s.vmx.cShadowVmcsFields;
5512 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5513 {
5514 uint64_t u64Val;
5515 uint32_t const uVmcsField = pVM->hmr0.s.vmx.paShadowVmcsFields[i];
5516 VMXReadVmcs64(uVmcsField, &u64Val);
5517 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5518 }
5519
5520 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5521 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5522 }
5523 return rc;
5524}
5525
5526
5527/**
5528 * Enables VMCS shadowing for the given VMCS info. object.
5529 *
5530 * @param pVmcsInfo The VMCS info. object.
5531 *
5532 * @remarks No-long-jump zone!!!
5533 */
5534static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5535{
5536 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5537 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5538 {
5539 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5540 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5541 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5542 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5543 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5544 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5545 Log4Func(("Enabled\n"));
5546 }
5547}
5548
5549
5550/**
5551 * Disables VMCS shadowing for the given VMCS info. object.
5552 *
5553 * @param pVmcsInfo The VMCS info. object.
5554 *
5555 * @remarks No-long-jump zone!!!
5556 */
5557static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5558{
5559 /*
5560 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5561 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5562 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5563 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5564 *
5565 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5566 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5567 */
5568 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5569 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5570 {
5571 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5572 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5573 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5574 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5575 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5576 Log4Func(("Disabled\n"));
5577 }
5578}
5579#endif
5580
5581
5582/**
5583 * Exports the guest hardware-virtualization state.
5584 *
5585 * @returns VBox status code.
5586 * @param pVCpu The cross context virtual CPU structure.
5587 * @param pVmxTransient The VMX-transient structure.
5588 *
5589 * @remarks No-long-jump zone!!!
5590 */
5591static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5592{
5593 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5594 {
5595#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5596 /*
5597 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5598 * VMCS shadowing.
5599 */
5600 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUseVmcsShadowing)
5601 {
5602 /*
5603 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5604 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5605 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5606 *
5607 * We check for VMX root mode here in case the guest executes VMXOFF without
5608 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5609 * not clear the current VMCS pointer.
5610 */
5611 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5612 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5613 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5614 && CPUMIsGuestVmxCurrentVmcsValid(&pVCpu->cpum.GstCtx))
5615 {
5616 /* Paranoia. */
5617 Assert(!pVmxTransient->fIsNestedGuest);
5618
5619 /*
5620 * For performance reasons, also check if the nested hypervisor's current VMCS
5621 * was newly loaded or modified before copying it to the shadow VMCS.
5622 */
5623 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5624 {
5625 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5626 AssertRCReturn(rc, rc);
5627 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5628 }
5629 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5630 }
5631 else
5632 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5633 }
5634#else
5635 NOREF(pVmxTransient);
5636#endif
5637 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5638 }
5639 return VINF_SUCCESS;
5640}
5641
5642
5643/**
5644 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5645 *
5646 * The guest FPU state is always pre-loaded hence we don't need to bother about
5647 * sharing FPU related CR0 bits between the guest and host.
5648 *
5649 * @returns VBox status code.
5650 * @param pVCpu The cross context virtual CPU structure.
5651 * @param pVmxTransient The VMX-transient structure.
5652 *
5653 * @remarks No-long-jump zone!!!
5654 */
5655static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5656{
5657 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5658 {
5659 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5660 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5661
5662 uint64_t fSetCr0 = g_HmMsrs.u.vmx.u64Cr0Fixed0;
5663 uint64_t const fZapCr0 = g_HmMsrs.u.vmx.u64Cr0Fixed1;
5664 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
5665 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5666 else
5667 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5668
5669 if (!pVmxTransient->fIsNestedGuest)
5670 {
5671 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5672 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5673 uint64_t const u64ShadowCr0 = u64GuestCr0;
5674 Assert(!RT_HI_U32(u64GuestCr0));
5675
5676 /*
5677 * Setup VT-x's view of the guest CR0.
5678 */
5679 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5680 if (pVM->hmr0.s.fNestedPaging)
5681 {
5682 if (CPUMIsGuestPagingEnabled(pVCpu))
5683 {
5684 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5685 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5686 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5687 }
5688 else
5689 {
5690 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5691 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5692 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5693 }
5694
5695 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5696 if (pVM->hmr0.s.vmx.fUnrestrictedGuest)
5697 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5698 }
5699 else
5700 {
5701 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5702 u64GuestCr0 |= X86_CR0_WP;
5703 }
5704
5705 /*
5706 * Guest FPU bits.
5707 *
5708 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5709 * using CR0.TS.
5710 *
5711 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5712 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5713 */
5714 u64GuestCr0 |= X86_CR0_NE;
5715
5716 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5717 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5718
5719 /*
5720 * Update exception intercepts.
5721 */
5722 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5723 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
5724 {
5725 Assert(PDMVmmDevHeapIsEnabled(pVM));
5726 Assert(pVM->hm.s.vmx.pRealModeTSS);
5727 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5728 }
5729 else
5730 {
5731 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5732 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5733 if (fInterceptMF)
5734 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5735 }
5736
5737 /* Additional intercepts for debugging, define these yourself explicitly. */
5738#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5739 uXcptBitmap |= 0
5740 | RT_BIT(X86_XCPT_BP)
5741 | RT_BIT(X86_XCPT_DE)
5742 | RT_BIT(X86_XCPT_NM)
5743 | RT_BIT(X86_XCPT_TS)
5744 | RT_BIT(X86_XCPT_UD)
5745 | RT_BIT(X86_XCPT_NP)
5746 | RT_BIT(X86_XCPT_SS)
5747 | RT_BIT(X86_XCPT_GP)
5748 | RT_BIT(X86_XCPT_PF)
5749 | RT_BIT(X86_XCPT_MF)
5750 ;
5751#elif defined(HMVMX_ALWAYS_TRAP_PF)
5752 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5753#endif
5754 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5755 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5756 Assert(pVM->hmr0.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5757
5758 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5759 u64GuestCr0 |= fSetCr0;
5760 u64GuestCr0 &= fZapCr0;
5761 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5762
5763 /* Commit the CR0 and related fields to the guest VMCS. */
5764 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5765 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5766 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5767 {
5768 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5769 AssertRC(rc);
5770 }
5771 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5772 {
5773 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5774 AssertRC(rc);
5775 }
5776
5777 /* Update our caches. */
5778 pVmcsInfo->u32ProcCtls = uProcCtls;
5779 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5780
5781 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5782 }
5783 else
5784 {
5785 /*
5786 * With nested-guests, we may have extended the guest/host mask here since we
5787 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5788 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5789 * originally supplied. We must copy those bits from the nested-guest CR0 into
5790 * the nested-guest CR0 read-shadow.
5791 */
5792 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5793 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5794 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(&pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5795 Assert(!RT_HI_U32(u64GuestCr0));
5796 Assert(u64GuestCr0 & X86_CR0_NE);
5797
5798 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5799 u64GuestCr0 |= fSetCr0;
5800 u64GuestCr0 &= fZapCr0;
5801 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5802
5803 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5804 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5805 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5806
5807 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5808 }
5809
5810 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5811 }
5812
5813 return VINF_SUCCESS;
5814}
5815
5816
5817/**
5818 * Exports the guest control registers (CR3, CR4) into the guest-state area
5819 * in the VMCS.
5820 *
5821 * @returns VBox strict status code.
5822 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5823 * without unrestricted guest access and the VMMDev is not presently
5824 * mapped (e.g. EFI32).
5825 *
5826 * @param pVCpu The cross context virtual CPU structure.
5827 * @param pVmxTransient The VMX-transient structure.
5828 *
5829 * @remarks No-long-jump zone!!!
5830 */
5831static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5832{
5833 int rc = VINF_SUCCESS;
5834 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5835
5836 /*
5837 * Guest CR2.
5838 * It's always loaded in the assembler code. Nothing to do here.
5839 */
5840
5841 /*
5842 * Guest CR3.
5843 */
5844 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5845 {
5846 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5847
5848 if (pVM->hmr0.s.fNestedPaging)
5849 {
5850 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5851 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5852
5853 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5854 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5855 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5856 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5857
5858 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5859 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5860 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5861
5862 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5863 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5864 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5865 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5866 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5867 || (g_HmMsrs.u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5868 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5869
5870 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5871 AssertRC(rc);
5872
5873 uint64_t u64GuestCr3;
5874 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5875 if ( pVM->hmr0.s.vmx.fUnrestrictedGuest
5876 || CPUMIsGuestPagingEnabledEx(pCtx))
5877 {
5878 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5879 if (CPUMIsGuestInPAEModeEx(pCtx))
5880 {
5881 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5882 AssertRC(rc);
5883 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5884 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5885 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5886 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5887 }
5888
5889 /*
5890 * The guest's view of its CR3 is unblemished with nested paging when the
5891 * guest is using paging or we have unrestricted guest execution to handle
5892 * the guest when it's not using paging.
5893 */
5894 u64GuestCr3 = pCtx->cr3;
5895 }
5896 else
5897 {
5898 /*
5899 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5900 * thinks it accesses physical memory directly, we use our identity-mapped
5901 * page table to map guest-linear to guest-physical addresses. EPT takes care
5902 * of translating it to host-physical addresses.
5903 */
5904 RTGCPHYS GCPhys;
5905 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5906
5907 /* We obtain it here every time as the guest could have relocated this PCI region. */
5908 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5909 if (RT_SUCCESS(rc))
5910 { /* likely */ }
5911 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5912 {
5913 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5914 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5915 }
5916 else
5917 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5918
5919 u64GuestCr3 = GCPhys;
5920 }
5921
5922 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5923 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5924 AssertRC(rc);
5925 }
5926 else
5927 {
5928 Assert(!pVmxTransient->fIsNestedGuest);
5929 /* Non-nested paging case, just use the hypervisor's CR3. */
5930 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5931
5932 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5933 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5934 AssertRC(rc);
5935 }
5936
5937 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5938 }
5939
5940 /*
5941 * Guest CR4.
5942 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5943 */
5944 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5945 {
5946 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5947 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5948
5949 uint64_t const fSetCr4 = g_HmMsrs.u.vmx.u64Cr4Fixed0;
5950 uint64_t const fZapCr4 = g_HmMsrs.u.vmx.u64Cr4Fixed1;
5951
5952 /*
5953 * With nested-guests, we may have extended the guest/host mask here (since we
5954 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5955 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5956 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5957 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5958 */
5959 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5960 uint64_t u64GuestCr4 = pCtx->cr4;
5961 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5962 ? pCtx->cr4
5963 : CPUMGetGuestVmxMaskedCr4(pCtx, pVmcsInfo->u64Cr4Mask);
5964 Assert(!RT_HI_U32(u64GuestCr4));
5965
5966 /*
5967 * Setup VT-x's view of the guest CR4.
5968 *
5969 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5970 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5971 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5972 *
5973 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5974 */
5975 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
5976 {
5977 Assert(pVM->hm.s.vmx.pRealModeTSS);
5978 Assert(PDMVmmDevHeapIsEnabled(pVM));
5979 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5980 }
5981
5982 if (pVM->hmr0.s.fNestedPaging)
5983 {
5984 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5985 && !pVM->hmr0.s.vmx.fUnrestrictedGuest)
5986 {
5987 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5988 u64GuestCr4 |= X86_CR4_PSE;
5989 /* Our identity mapping is a 32-bit page directory. */
5990 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5991 }
5992 /* else use guest CR4.*/
5993 }
5994 else
5995 {
5996 Assert(!pVmxTransient->fIsNestedGuest);
5997
5998 /*
5999 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
6000 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
6001 */
6002 switch (pVCpu->hm.s.enmShadowMode)
6003 {
6004 case PGMMODE_REAL: /* Real-mode. */
6005 case PGMMODE_PROTECTED: /* Protected mode without paging. */
6006 case PGMMODE_32_BIT: /* 32-bit paging. */
6007 {
6008 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
6009 break;
6010 }
6011
6012 case PGMMODE_PAE: /* PAE paging. */
6013 case PGMMODE_PAE_NX: /* PAE paging with NX. */
6014 {
6015 u64GuestCr4 |= X86_CR4_PAE;
6016 break;
6017 }
6018
6019 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
6020 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
6021 {
6022#ifdef VBOX_WITH_64_BITS_GUESTS
6023 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
6024 Assert(u64GuestCr4 & X86_CR4_PAE);
6025 break;
6026#endif
6027 }
6028 default:
6029 AssertFailed();
6030 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6031 }
6032 }
6033
6034 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
6035 u64GuestCr4 |= fSetCr4;
6036 u64GuestCr4 &= fZapCr4;
6037
6038 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
6039 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
6040 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
6041
6042 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
6043 bool const fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
6044 if (fLoadSaveGuestXcr0 != pVCpu->hmr0.s.fLoadSaveGuestXcr0)
6045 {
6046 pVCpu->hmr0.s.fLoadSaveGuestXcr0 = fLoadSaveGuestXcr0;
6047 hmR0VmxUpdateStartVmFunction(pVCpu);
6048 }
6049
6050 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
6051
6052 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
6053 }
6054 return rc;
6055}
6056
6057
6058/**
6059 * Exports the guest debug registers into the guest-state area in the VMCS.
6060 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
6061 *
6062 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
6063 *
6064 * @returns VBox status code.
6065 * @param pVCpu The cross context virtual CPU structure.
6066 * @param pVmxTransient The VMX-transient structure.
6067 *
6068 * @remarks No-long-jump zone!!!
6069 */
6070static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6071{
6072 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
6073
6074 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
6075 * stepping. */
6076 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6077 if (pVmxTransient->fIsNestedGuest)
6078 {
6079 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
6080 AssertRC(rc);
6081
6082 /*
6083 * We don't want to always intercept MOV DRx for nested-guests as it causes
6084 * problems when the nested hypervisor isn't intercepting them, see @bugref{10080}.
6085 * Instead, they are strictly only requested when the nested hypervisor intercepts
6086 * them -- handled while merging VMCS controls.
6087 *
6088 * If neither the outer nor the nested-hypervisor is intercepting MOV DRx,
6089 * then the nested-guest debug state should be actively loaded on the host so that
6090 * nested-guest reads its own debug registers without causing VM-exits.
6091 */
6092 if ( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT)
6093 && !CPUMIsGuestDebugStateActive(pVCpu))
6094 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6095 return VINF_SUCCESS;
6096 }
6097
6098#ifdef VBOX_STRICT
6099 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
6100 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
6101 {
6102 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
6103 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
6104 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
6105 }
6106#endif
6107
6108 bool fSteppingDB = false;
6109 bool fInterceptMovDRx = false;
6110 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6111 if (pVCpu->hm.s.fSingleInstruction)
6112 {
6113 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
6114 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
6115 {
6116 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
6117 Assert(fSteppingDB == false);
6118 }
6119 else
6120 {
6121 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
6122 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
6123 pVCpu->hmr0.s.fClearTrapFlag = true;
6124 fSteppingDB = true;
6125 }
6126 }
6127
6128 uint64_t u64GuestDr7;
6129 if ( fSteppingDB
6130 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
6131 {
6132 /*
6133 * Use the combined guest and host DRx values found in the hypervisor register set
6134 * because the hypervisor debugger has breakpoints active or someone is single stepping
6135 * on the host side without a monitor trap flag.
6136 *
6137 * Note! DBGF expects a clean DR6 state before executing guest code.
6138 */
6139 if (!CPUMIsHyperDebugStateActive(pVCpu))
6140 {
6141 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6142 Assert(CPUMIsHyperDebugStateActive(pVCpu));
6143 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
6144 }
6145
6146 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6147 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
6148 pVCpu->hmr0.s.fUsingHyperDR7 = true;
6149 fInterceptMovDRx = true;
6150 }
6151 else
6152 {
6153 /*
6154 * If the guest has enabled debug registers, we need to load them prior to
6155 * executing guest code so they'll trigger at the right time.
6156 */
6157 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
6158 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6159 {
6160 if (!CPUMIsGuestDebugStateActive(pVCpu))
6161 {
6162 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6163 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6164 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6165 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6166 }
6167 Assert(!fInterceptMovDRx);
6168 }
6169 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6170 {
6171 /*
6172 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6173 * must intercept #DB in order to maintain a correct DR6 guest value, and
6174 * because we need to intercept it to prevent nested #DBs from hanging the
6175 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6176 */
6177 fInterceptMovDRx = true;
6178 }
6179
6180 /* Update DR7 with the actual guest value. */
6181 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6182 pVCpu->hmr0.s.fUsingHyperDR7 = false;
6183 }
6184
6185 if (fInterceptMovDRx)
6186 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6187 else
6188 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6189
6190 /*
6191 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6192 * monitor-trap flag and update our cache.
6193 */
6194 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6195 {
6196 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6197 AssertRC(rc);
6198 pVmcsInfo->u32ProcCtls = uProcCtls;
6199 }
6200
6201 /*
6202 * Update guest DR7.
6203 */
6204 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
6205 AssertRC(rc);
6206
6207 /*
6208 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6209 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6210 *
6211 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6212 */
6213 if (fSteppingDB)
6214 {
6215 Assert(pVCpu->hm.s.fSingleInstruction);
6216 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6217
6218 uint32_t fIntrState = 0;
6219 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6220 AssertRC(rc);
6221
6222 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6223 {
6224 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6225 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6226 AssertRC(rc);
6227 }
6228 }
6229
6230 return VINF_SUCCESS;
6231}
6232
6233
6234#ifdef VBOX_STRICT
6235/**
6236 * Strict function to validate segment registers.
6237 *
6238 * @param pVCpu The cross context virtual CPU structure.
6239 * @param pVmcsInfo The VMCS info. object.
6240 *
6241 * @remarks Will import guest CR0 on strict builds during validation of
6242 * segments.
6243 */
6244static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
6245{
6246 /*
6247 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6248 *
6249 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6250 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6251 * unusable bit and doesn't change the guest-context value.
6252 */
6253 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6254 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6255 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6256 if ( !pVM->hmr0.s.vmx.fUnrestrictedGuest
6257 && ( !CPUMIsGuestInRealModeEx(pCtx)
6258 && !CPUMIsGuestInV86ModeEx(pCtx)))
6259 {
6260 /* Protected mode checks */
6261 /* CS */
6262 Assert(pCtx->cs.Attr.n.u1Present);
6263 Assert(!(pCtx->cs.Attr.u & 0xf00));
6264 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6265 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6266 || !(pCtx->cs.Attr.n.u1Granularity));
6267 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6268 || (pCtx->cs.Attr.n.u1Granularity));
6269 /* CS cannot be loaded with NULL in protected mode. */
6270 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6271 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6272 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6273 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6274 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6275 else
6276 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6277 /* SS */
6278 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6279 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6280 if ( !(pCtx->cr0 & X86_CR0_PE)
6281 || pCtx->cs.Attr.n.u4Type == 3)
6282 {
6283 Assert(!pCtx->ss.Attr.n.u2Dpl);
6284 }
6285 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6286 {
6287 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6288 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6289 Assert(pCtx->ss.Attr.n.u1Present);
6290 Assert(!(pCtx->ss.Attr.u & 0xf00));
6291 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6292 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6293 || !(pCtx->ss.Attr.n.u1Granularity));
6294 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6295 || (pCtx->ss.Attr.n.u1Granularity));
6296 }
6297 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6298 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6299 {
6300 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6301 Assert(pCtx->ds.Attr.n.u1Present);
6302 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6303 Assert(!(pCtx->ds.Attr.u & 0xf00));
6304 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6305 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6306 || !(pCtx->ds.Attr.n.u1Granularity));
6307 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6308 || (pCtx->ds.Attr.n.u1Granularity));
6309 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6310 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6311 }
6312 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6313 {
6314 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6315 Assert(pCtx->es.Attr.n.u1Present);
6316 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6317 Assert(!(pCtx->es.Attr.u & 0xf00));
6318 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6319 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6320 || !(pCtx->es.Attr.n.u1Granularity));
6321 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6322 || (pCtx->es.Attr.n.u1Granularity));
6323 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6324 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6325 }
6326 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6327 {
6328 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6329 Assert(pCtx->fs.Attr.n.u1Present);
6330 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6331 Assert(!(pCtx->fs.Attr.u & 0xf00));
6332 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6333 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6334 || !(pCtx->fs.Attr.n.u1Granularity));
6335 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6336 || (pCtx->fs.Attr.n.u1Granularity));
6337 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6338 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6339 }
6340 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6341 {
6342 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6343 Assert(pCtx->gs.Attr.n.u1Present);
6344 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6345 Assert(!(pCtx->gs.Attr.u & 0xf00));
6346 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6347 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6348 || !(pCtx->gs.Attr.n.u1Granularity));
6349 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6350 || (pCtx->gs.Attr.n.u1Granularity));
6351 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6352 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6353 }
6354 /* 64-bit capable CPUs. */
6355 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6356 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6357 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6358 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6359 }
6360 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6361 || ( CPUMIsGuestInRealModeEx(pCtx)
6362 && !pVM->hmr0.s.vmx.fUnrestrictedGuest))
6363 {
6364 /* Real and v86 mode checks. */
6365 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6366 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6367 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
6368 {
6369 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6370 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6371 }
6372 else
6373 {
6374 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6375 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6376 }
6377
6378 /* CS */
6379 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6380 Assert(pCtx->cs.u32Limit == 0xffff);
6381 Assert(u32CSAttr == 0xf3);
6382 /* SS */
6383 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6384 Assert(pCtx->ss.u32Limit == 0xffff);
6385 Assert(u32SSAttr == 0xf3);
6386 /* DS */
6387 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6388 Assert(pCtx->ds.u32Limit == 0xffff);
6389 Assert(u32DSAttr == 0xf3);
6390 /* ES */
6391 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6392 Assert(pCtx->es.u32Limit == 0xffff);
6393 Assert(u32ESAttr == 0xf3);
6394 /* FS */
6395 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6396 Assert(pCtx->fs.u32Limit == 0xffff);
6397 Assert(u32FSAttr == 0xf3);
6398 /* GS */
6399 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6400 Assert(pCtx->gs.u32Limit == 0xffff);
6401 Assert(u32GSAttr == 0xf3);
6402 /* 64-bit capable CPUs. */
6403 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6404 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6405 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6406 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6407 }
6408}
6409#endif /* VBOX_STRICT */
6410
6411
6412/**
6413 * Exports a guest segment register into the guest-state area in the VMCS.
6414 *
6415 * @returns VBox status code.
6416 * @param pVCpu The cross context virtual CPU structure.
6417 * @param pVmcsInfo The VMCS info. object.
6418 * @param iSegReg The segment register number (X86_SREG_XXX).
6419 * @param pSelReg Pointer to the segment selector.
6420 *
6421 * @remarks No-long-jump zone!!!
6422 */
6423static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint32_t iSegReg, PCCPUMSELREG pSelReg)
6424{
6425 Assert(iSegReg < X86_SREG_COUNT);
6426
6427 uint32_t u32Access = pSelReg->Attr.u;
6428 if (!pVmcsInfo->pShared->RealMode.fRealOnV86Active)
6429 {
6430 /*
6431 * The way to differentiate between whether this is really a null selector or was just
6432 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6433 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6434 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6435 * NULL selectors loaded in protected-mode have their attribute as 0.
6436 */
6437 if (u32Access)
6438 { }
6439 else
6440 u32Access = X86DESCATTR_UNUSABLE;
6441 }
6442 else
6443 {
6444 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6445 u32Access = 0xf3;
6446 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6447 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6448 RT_NOREF_PV(pVCpu);
6449 }
6450
6451 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6452 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6453 ("Access bit not set for usable segment. %.2s sel=%#x attr %#x\n", "ESCSSSDSFSGS" + iSegReg * 2, pSelReg, pSelReg->Attr.u));
6454
6455 /*
6456 * Commit it to the VMCS.
6457 */
6458 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]);
6459 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]);
6460 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
6461 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]);
6462 int rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), pSelReg->Sel); AssertRC(rc);
6463 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), pSelReg->u32Limit); AssertRC(rc);
6464 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), pSelReg->u64Base); AssertRC(rc);
6465 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), u32Access); AssertRC(rc);
6466 return VINF_SUCCESS;
6467}
6468
6469
6470/**
6471 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6472 * area in the VMCS.
6473 *
6474 * @returns VBox status code.
6475 * @param pVCpu The cross context virtual CPU structure.
6476 * @param pVmxTransient The VMX-transient structure.
6477 *
6478 * @remarks Will import guest CR0 on strict builds during validation of
6479 * segments.
6480 * @remarks No-long-jump zone!!!
6481 */
6482static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6483{
6484 int rc = VERR_INTERNAL_ERROR_5;
6485 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6486 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6487 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6488 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
6489
6490 /*
6491 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6492 */
6493 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6494 {
6495 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6496 {
6497 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6498 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6499 pVmcsInfoShared->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6500 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6501 AssertRC(rc);
6502 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6503 }
6504
6505 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6506 {
6507 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6508 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6509 pVmcsInfoShared->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6510 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6511 AssertRC(rc);
6512 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6513 }
6514
6515 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6516 {
6517 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6518 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6519 pVmcsInfoShared->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6520 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6521 AssertRC(rc);
6522 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6523 }
6524
6525 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6526 {
6527 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6528 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6529 pVmcsInfoShared->RealMode.AttrES.u = pCtx->es.Attr.u;
6530 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6531 AssertRC(rc);
6532 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6533 }
6534
6535 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6536 {
6537 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6538 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6539 pVmcsInfoShared->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6540 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6541 AssertRC(rc);
6542 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6543 }
6544
6545 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6546 {
6547 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6548 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6549 pVmcsInfoShared->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6550 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6551 AssertRC(rc);
6552 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6553 }
6554
6555#ifdef VBOX_STRICT
6556 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6557#endif
6558 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6559 pCtx->cs.Attr.u));
6560 }
6561
6562 /*
6563 * Guest TR.
6564 */
6565 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6566 {
6567 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6568
6569 /*
6570 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6571 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6572 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6573 */
6574 uint16_t u16Sel;
6575 uint32_t u32Limit;
6576 uint64_t u64Base;
6577 uint32_t u32AccessRights;
6578 if (!pVmcsInfoShared->RealMode.fRealOnV86Active)
6579 {
6580 u16Sel = pCtx->tr.Sel;
6581 u32Limit = pCtx->tr.u32Limit;
6582 u64Base = pCtx->tr.u64Base;
6583 u32AccessRights = pCtx->tr.Attr.u;
6584 }
6585 else
6586 {
6587 Assert(!pVmxTransient->fIsNestedGuest);
6588 Assert(pVM->hm.s.vmx.pRealModeTSS);
6589 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6590
6591 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6592 RTGCPHYS GCPhys;
6593 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6594 AssertRCReturn(rc, rc);
6595
6596 X86DESCATTR DescAttr;
6597 DescAttr.u = 0;
6598 DescAttr.n.u1Present = 1;
6599 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6600
6601 u16Sel = 0;
6602 u32Limit = HM_VTX_TSS_SIZE;
6603 u64Base = GCPhys;
6604 u32AccessRights = DescAttr.u;
6605 }
6606
6607 /* Validate. */
6608 Assert(!(u16Sel & RT_BIT(2)));
6609 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6610 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6611 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6612 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6613 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6614 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6615 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6616 Assert( (u32Limit & 0xfff) == 0xfff
6617 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6618 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6619 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6620
6621 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6622 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6623 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6624 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6625
6626 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6627 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6628 }
6629
6630 /*
6631 * Guest GDTR.
6632 */
6633 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6634 {
6635 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6636
6637 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6638 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6639
6640 /* Validate. */
6641 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6642
6643 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6644 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6645 }
6646
6647 /*
6648 * Guest LDTR.
6649 */
6650 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6651 {
6652 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6653
6654 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6655 uint32_t u32Access;
6656 if ( !pVmxTransient->fIsNestedGuest
6657 && !pCtx->ldtr.Attr.u)
6658 u32Access = X86DESCATTR_UNUSABLE;
6659 else
6660 u32Access = pCtx->ldtr.Attr.u;
6661
6662 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6663 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6664 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6665 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6666
6667 /* Validate. */
6668 if (!(u32Access & X86DESCATTR_UNUSABLE))
6669 {
6670 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6671 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6672 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6673 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6674 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6675 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6676 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6677 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6678 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6679 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6680 }
6681
6682 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6683 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6684 }
6685
6686 /*
6687 * Guest IDTR.
6688 */
6689 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6690 {
6691 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6692
6693 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6694 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6695
6696 /* Validate. */
6697 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6698
6699 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6700 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6701 }
6702
6703 return VINF_SUCCESS;
6704}
6705
6706
6707/**
6708 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6709 * areas.
6710 *
6711 * These MSRs will automatically be loaded to the host CPU on every successful
6712 * VM-entry and stored from the host CPU on every successful VM-exit.
6713 *
6714 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6715 * actual host MSR values are not- updated here for performance reasons. See
6716 * hmR0VmxExportHostMsrs().
6717 *
6718 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6719 *
6720 * @returns VBox status code.
6721 * @param pVCpu The cross context virtual CPU structure.
6722 * @param pVmxTransient The VMX-transient structure.
6723 *
6724 * @remarks No-long-jump zone!!!
6725 */
6726static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6727{
6728 AssertPtr(pVCpu);
6729 AssertPtr(pVmxTransient);
6730
6731 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6732 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6733
6734 /*
6735 * MSRs that we use the auto-load/store MSR area in the VMCS.
6736 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6737 * nothing to do here. The host MSR values are updated when it's safe in
6738 * hmR0VmxLazySaveHostMsrs().
6739 *
6740 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6741 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6742 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6743 * for any MSR that are not part of the lazy MSRs so we do not need to place
6744 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6745 */
6746 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6747 {
6748 /* No auto-load/store MSRs currently. */
6749 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6750 }
6751
6752 /*
6753 * Guest Sysenter MSRs.
6754 */
6755 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6756 {
6757 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6758
6759 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6760 {
6761 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6762 AssertRC(rc);
6763 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6764 }
6765
6766 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6767 {
6768 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6769 AssertRC(rc);
6770 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6771 }
6772
6773 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6774 {
6775 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6776 AssertRC(rc);
6777 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6778 }
6779 }
6780
6781 /*
6782 * Guest/host EFER MSR.
6783 */
6784 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6785 {
6786 /* Whether we are using the VMCS to swap the EFER MSR must have been
6787 determined earlier while exporting VM-entry/VM-exit controls. */
6788 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6789 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6790
6791 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6792 {
6793 /*
6794 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6795 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6796 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6797 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6798 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6799 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6800 * during VM-entry.
6801 */
6802 uint64_t uGuestEferMsr = pCtx->msrEFER;
6803 if (!pVM->hmr0.s.vmx.fUnrestrictedGuest)
6804 {
6805 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6806 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6807 else
6808 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6809 }
6810
6811 /*
6812 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6813 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6814 */
6815 if (g_fHmVmxSupportsVmcsEfer)
6816 {
6817 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6818 AssertRC(rc);
6819 }
6820 else
6821 {
6822 /*
6823 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6824 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6825 */
6826 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6827 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6828 AssertRCReturn(rc, rc);
6829 }
6830
6831 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6832 }
6833 else if (!g_fHmVmxSupportsVmcsEfer)
6834 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6835
6836 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6837 }
6838
6839 /*
6840 * Other MSRs.
6841 */
6842 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6843 {
6844 /* Speculation Control (R/W). */
6845 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6846 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6847 {
6848 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6849 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6850 AssertRCReturn(rc, rc);
6851 }
6852
6853 /* Last Branch Record. */
6854 if (pVM->hmr0.s.vmx.fLbr)
6855 {
6856 PVMXVMCSINFOSHARED const pVmcsInfoShared = pVmxTransient->pVmcsInfo->pShared;
6857 uint32_t const idFromIpMsrStart = pVM->hmr0.s.vmx.idLbrFromIpMsrFirst;
6858 uint32_t const idToIpMsrStart = pVM->hmr0.s.vmx.idLbrToIpMsrFirst;
6859 uint32_t const cLbrStack = pVM->hmr0.s.vmx.idLbrFromIpMsrLast - pVM->hmr0.s.vmx.idLbrFromIpMsrFirst + 1;
6860 Assert(cLbrStack <= 32);
6861 for (uint32_t i = 0; i < cLbrStack; i++)
6862 {
6863 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idFromIpMsrStart + i,
6864 pVmcsInfoShared->au64LbrFromIpMsr[i],
6865 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6866 AssertRCReturn(rc, rc);
6867
6868 /* Some CPUs don't have a Branch-To-IP MSR (P4 and related Xeons). */
6869 if (idToIpMsrStart != 0)
6870 {
6871 rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idToIpMsrStart + i,
6872 pVmcsInfoShared->au64LbrToIpMsr[i],
6873 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6874 AssertRCReturn(rc, rc);
6875 }
6876 }
6877
6878 /* Add LBR top-of-stack MSR (which contains the index to the most recent record). */
6879 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, pVM->hmr0.s.vmx.idLbrTosMsr,
6880 pVmcsInfoShared->u64LbrTosMsr, false /* fSetReadWrite */,
6881 false /* fUpdateHostMsr */);
6882 AssertRCReturn(rc, rc);
6883 }
6884
6885 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6886 }
6887
6888 return VINF_SUCCESS;
6889}
6890
6891
6892/**
6893 * Wrapper for running the guest code in VT-x.
6894 *
6895 * @returns VBox status code, no informational status codes.
6896 * @param pVCpu The cross context virtual CPU structure.
6897 * @param pVmxTransient The VMX-transient structure.
6898 *
6899 * @remarks No-long-jump zone!!!
6900 */
6901DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6902{
6903 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6904 pVCpu->cpum.GstCtx.fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6905
6906 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6907 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6908#ifdef VBOX_WITH_STATISTICS
6909 if (fResumeVM)
6910 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxVmResume);
6911 else
6912 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxVmLaunch);
6913#endif
6914 int rc = pVCpu->hmr0.s.vmx.pfnStartVm(pVmcsInfo, pVCpu, fResumeVM);
6915 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6916 return rc;
6917}
6918
6919
6920/**
6921 * Reports world-switch error and dumps some useful debug info.
6922 *
6923 * @param pVCpu The cross context virtual CPU structure.
6924 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6925 * @param pVmxTransient The VMX-transient structure (only
6926 * exitReason updated).
6927 */
6928static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6929{
6930 Assert(pVCpu);
6931 Assert(pVmxTransient);
6932 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6933
6934 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6935 switch (rcVMRun)
6936 {
6937 case VERR_VMX_INVALID_VMXON_PTR:
6938 AssertFailed();
6939 break;
6940 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6941 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6942 {
6943 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6944 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6945 AssertRC(rc);
6946 hmR0VmxReadExitQualVmcs(pVmxTransient);
6947
6948 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hmr0.s.idEnteredCpu;
6949 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6950 Cannot do it here as we may have been long preempted. */
6951
6952#ifdef VBOX_STRICT
6953 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6954 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6955 pVmxTransient->uExitReason));
6956 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6957 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6958 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6959 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6960 else
6961 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6962 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6963 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6964
6965 static struct
6966 {
6967 /** Name of the field to log. */
6968 const char *pszName;
6969 /** The VMCS field. */
6970 uint32_t uVmcsField;
6971 /** Whether host support of this field needs to be checked. */
6972 bool fCheckSupport;
6973 } const s_aVmcsFields[] =
6974 {
6975 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6976 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6977 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6978 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6979 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6980 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6981 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6982 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6983 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6984 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6985 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6986 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6987 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6988 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6989 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6990 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6991 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6992 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6993 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6994 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6995 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6996 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6997 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6998 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6999 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
7000 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
7001 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
7002 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
7003 /* The order of selector fields below are fixed! */
7004 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
7005 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
7006 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
7007 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
7008 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
7009 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
7010 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
7011 /* End of ordered selector fields. */
7012 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
7013 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
7014 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
7015 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
7016 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
7017 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
7018 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
7019 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
7020 };
7021
7022 RTGDTR HostGdtr;
7023 ASMGetGDTR(&HostGdtr);
7024
7025 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
7026 for (uint32_t i = 0; i < cVmcsFields; i++)
7027 {
7028 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
7029
7030 bool fSupported;
7031 if (!s_aVmcsFields[i].fCheckSupport)
7032 fSupported = true;
7033 else
7034 {
7035 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7036 switch (uVmcsField)
7037 {
7038 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hmr0.s.fNestedPaging; break;
7039 case VMX_VMCS16_VPID: fSupported = pVM->hmr0.s.vmx.fVpid; break;
7040 case VMX_VMCS32_CTRL_PROC_EXEC2:
7041 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
7042 break;
7043 default:
7044 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
7045 }
7046 }
7047
7048 if (fSupported)
7049 {
7050 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
7051 switch (uWidth)
7052 {
7053 case VMX_VMCSFIELD_WIDTH_16BIT:
7054 {
7055 uint16_t u16Val;
7056 rc = VMXReadVmcs16(uVmcsField, &u16Val);
7057 AssertRC(rc);
7058 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
7059
7060 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
7061 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
7062 {
7063 if (u16Val < HostGdtr.cbGdt)
7064 {
7065 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
7066 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
7067 "Host FS", "Host GS", "Host TR" };
7068 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
7069 Assert(idxSel < RT_ELEMENTS(s_apszSel));
7070 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
7071 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
7072 }
7073 else
7074 Log4((" Selector value exceeds GDT limit!\n"));
7075 }
7076 break;
7077 }
7078
7079 case VMX_VMCSFIELD_WIDTH_32BIT:
7080 {
7081 uint32_t u32Val;
7082 rc = VMXReadVmcs32(uVmcsField, &u32Val);
7083 AssertRC(rc);
7084 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
7085 break;
7086 }
7087
7088 case VMX_VMCSFIELD_WIDTH_64BIT:
7089 case VMX_VMCSFIELD_WIDTH_NATURAL:
7090 {
7091 uint64_t u64Val;
7092 rc = VMXReadVmcs64(uVmcsField, &u64Val);
7093 AssertRC(rc);
7094 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
7095 break;
7096 }
7097 }
7098 }
7099 }
7100
7101 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
7102 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
7103 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
7104 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
7105 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
7106 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
7107#endif /* VBOX_STRICT */
7108 break;
7109 }
7110
7111 default:
7112 /* Impossible */
7113 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
7114 break;
7115 }
7116}
7117
7118
7119/**
7120 * Sets up the usage of TSC-offsetting and updates the VMCS.
7121 *
7122 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
7123 * VMX-preemption timer.
7124 *
7125 * @returns VBox status code.
7126 * @param pVCpu The cross context virtual CPU structure.
7127 * @param pVmxTransient The VMX-transient structure.
7128 * @param idCurrentCpu The current CPU number.
7129 *
7130 * @remarks No-long-jump zone!!!
7131 */
7132static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, RTCPUID idCurrentCpu)
7133{
7134 bool fOffsettedTsc;
7135 bool fParavirtTsc;
7136 uint64_t uTscOffset;
7137 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7138 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7139
7140 if (pVM->hmr0.s.vmx.fUsePreemptTimer)
7141 {
7142 /* The TMCpuTickGetDeadlineAndTscOffset function is expensive (calling it on
7143 every entry slowed down the bs2-test1 CPUID testcase by ~33% (on an 10980xe). */
7144 uint64_t cTicksToDeadline;
7145 if ( idCurrentCpu == pVCpu->hmr0.s.idLastCpu
7146 && TMVirtualSyncIsCurrentDeadlineVersion(pVM, pVCpu->hmr0.s.vmx.uTscDeadlineVersion))
7147 {
7148 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatVmxPreemptionReusingDeadline);
7149 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7150 cTicksToDeadline = pVCpu->hmr0.s.vmx.uTscDeadline - SUPReadTsc();
7151 if ((int64_t)cTicksToDeadline > 0)
7152 { /* hopefully */ }
7153 else
7154 {
7155 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatVmxPreemptionReusingDeadlineExpired);
7156 cTicksToDeadline = 0;
7157 }
7158 }
7159 else
7160 {
7161 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatVmxPreemptionRecalcingDeadline);
7162 cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc,
7163 &pVCpu->hmr0.s.vmx.uTscDeadline,
7164 &pVCpu->hmr0.s.vmx.uTscDeadlineVersion);
7165 pVCpu->hmr0.s.vmx.uTscDeadline += cTicksToDeadline;
7166 if (cTicksToDeadline >= 128)
7167 { /* hopefully */ }
7168 else
7169 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatVmxPreemptionRecalcingDeadlineExpired);
7170 }
7171
7172 /* Make sure the returned values have sane upper and lower boundaries. */
7173 uint64_t const u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7174 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second, 15.625ms. */ /** @todo r=bird: Once real+virtual timers move to separate thread, we can raise the upper limit (16ms isn't much). ASSUMES working poke cpu function. */
7175 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 32678); /* 1/32768th of a second, ~30us. */
7176 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7177
7178 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7179 * preemption timers here. We probably need to clamp the preemption timer,
7180 * after converting the timer value to the host. */
7181 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7182 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7183 AssertRC(rc);
7184 }
7185 else
7186 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7187
7188 if (fParavirtTsc)
7189 {
7190 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7191 information before every VM-entry, hence disable it for performance sake. */
7192#if 0
7193 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7194 AssertRC(rc);
7195#endif
7196 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7197 }
7198
7199 if ( fOffsettedTsc
7200 && RT_LIKELY(!pVCpu->hmr0.s.fDebugWantRdTscExit))
7201 {
7202 if (pVmxTransient->fIsNestedGuest)
7203 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7204 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
7205 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7206 }
7207 else
7208 {
7209 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7210 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7211 }
7212}
7213
7214
7215/**
7216 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7217 * VM-exit interruption info type.
7218 *
7219 * @returns The IEM exception flags.
7220 * @param uVector The event vector.
7221 * @param uVmxEventType The VMX event type.
7222 *
7223 * @remarks This function currently only constructs flags required for
7224 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7225 * and CR2 aspects of an exception are not included).
7226 */
7227static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7228{
7229 uint32_t fIemXcptFlags;
7230 switch (uVmxEventType)
7231 {
7232 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7233 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7234 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7235 break;
7236
7237 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7238 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7239 break;
7240
7241 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7242 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7243 break;
7244
7245 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7246 {
7247 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7248 if (uVector == X86_XCPT_BP)
7249 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7250 else if (uVector == X86_XCPT_OF)
7251 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7252 else
7253 {
7254 fIemXcptFlags = 0;
7255 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7256 }
7257 break;
7258 }
7259
7260 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7261 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7262 break;
7263
7264 default:
7265 fIemXcptFlags = 0;
7266 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7267 break;
7268 }
7269 return fIemXcptFlags;
7270}
7271
7272
7273/**
7274 * Sets an event as a pending event to be injected into the guest.
7275 *
7276 * @param pVCpu The cross context virtual CPU structure.
7277 * @param u32IntInfo The VM-entry interruption-information field.
7278 * @param cbInstr The VM-entry instruction length in bytes (for
7279 * software interrupts, exceptions and privileged
7280 * software exceptions).
7281 * @param u32ErrCode The VM-entry exception error code.
7282 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7283 * page-fault.
7284 */
7285DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7286 RTGCUINTPTR GCPtrFaultAddress)
7287{
7288 Assert(!pVCpu->hm.s.Event.fPending);
7289 pVCpu->hm.s.Event.fPending = true;
7290 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7291 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7292 pVCpu->hm.s.Event.cbInstr = cbInstr;
7293 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7294}
7295
7296
7297/**
7298 * Sets an external interrupt as pending-for-injection into the VM.
7299 *
7300 * @param pVCpu The cross context virtual CPU structure.
7301 * @param u8Interrupt The external interrupt vector.
7302 */
7303DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
7304{
7305 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7306 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7307 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7308 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7309 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7310}
7311
7312
7313/**
7314 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7315 *
7316 * @param pVCpu The cross context virtual CPU structure.
7317 */
7318DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
7319{
7320 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7321 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7322 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7323 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7324 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7325}
7326
7327
7328/**
7329 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7330 *
7331 * @param pVCpu The cross context virtual CPU structure.
7332 */
7333DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
7334{
7335 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7336 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7337 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7338 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7339 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7340}
7341
7342
7343/**
7344 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7345 *
7346 * @param pVCpu The cross context virtual CPU structure.
7347 */
7348DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
7349{
7350 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7351 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7352 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7353 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7354 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7355}
7356
7357
7358/**
7359 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7360 *
7361 * @param pVCpu The cross context virtual CPU structure.
7362 */
7363DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
7364{
7365 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7366 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7367 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7368 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7369 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7370}
7371
7372
7373#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7374/**
7375 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7376 *
7377 * @param pVCpu The cross context virtual CPU structure.
7378 * @param u32ErrCode The error code for the general-protection exception.
7379 */
7380DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7381{
7382 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7383 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7384 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7385 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7386 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7387}
7388
7389
7390/**
7391 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7392 *
7393 * @param pVCpu The cross context virtual CPU structure.
7394 * @param u32ErrCode The error code for the stack exception.
7395 */
7396DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7397{
7398 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7399 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7400 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7401 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7402 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7403}
7404#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7405
7406
7407/**
7408 * Fixes up attributes for the specified segment register.
7409 *
7410 * @param pVCpu The cross context virtual CPU structure.
7411 * @param pSelReg The segment register that needs fixing.
7412 * @param pszRegName The register name (for logging and assertions).
7413 */
7414static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, const char *pszRegName)
7415{
7416 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7417
7418 /*
7419 * If VT-x marks the segment as unusable, most other bits remain undefined:
7420 * - For CS the L, D and G bits have meaning.
7421 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7422 * - For the remaining data segments no bits are defined.
7423 *
7424 * The present bit and the unusable bit has been observed to be set at the
7425 * same time (the selector was supposed to be invalid as we started executing
7426 * a V8086 interrupt in ring-0).
7427 *
7428 * What should be important for the rest of the VBox code, is that the P bit is
7429 * cleared. Some of the other VBox code recognizes the unusable bit, but
7430 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7431 * safe side here, we'll strip off P and other bits we don't care about. If
7432 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7433 *
7434 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7435 */
7436#ifdef VBOX_STRICT
7437 uint32_t const uAttr = pSelReg->Attr.u;
7438#endif
7439
7440 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7441 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7442 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7443
7444#ifdef VBOX_STRICT
7445 VMMRZCallRing3Disable(pVCpu);
7446 Log4Func(("Unusable %s: sel=%#x attr=%#x -> %#x\n", pszRegName, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7447# ifdef DEBUG_bird
7448 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7449 ("%s: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7450 pszRegName, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7451# endif
7452 VMMRZCallRing3Enable(pVCpu);
7453 NOREF(uAttr);
7454#endif
7455 RT_NOREF2(pVCpu, pszRegName);
7456}
7457
7458
7459/**
7460 * Imports a guest segment register from the current VMCS into the guest-CPU
7461 * context.
7462 *
7463 * @param pVCpu The cross context virtual CPU structure.
7464 * @param iSegReg The segment register number (X86_SREG_XXX).
7465 *
7466 * @remarks Called with interrupts and/or preemption disabled.
7467 */
7468static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint32_t iSegReg)
7469{
7470 Assert(iSegReg < X86_SREG_COUNT);
7471 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]);
7472 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]);
7473 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
7474 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]);
7475
7476 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7477
7478 uint16_t u16Sel;
7479 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), &u16Sel); AssertRC(rc);
7480 pSelReg->Sel = u16Sel;
7481 pSelReg->ValidSel = u16Sel;
7482
7483 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), &pSelReg->u32Limit); AssertRC(rc);
7484 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), &pSelReg->u64Base); AssertRC(rc);
7485
7486 uint32_t u32Attr;
7487 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), &u32Attr); AssertRC(rc);
7488 pSelReg->Attr.u = u32Attr;
7489 if (u32Attr & X86DESCATTR_UNUSABLE)
7490 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, "ES\0CS\0SS\0DS\0FS\0GS" + iSegReg * 3);
7491
7492 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7493}
7494
7495
7496/**
7497 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7498 *
7499 * @param pVCpu The cross context virtual CPU structure.
7500 *
7501 * @remarks Called with interrupts and/or preemption disabled.
7502 */
7503static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7504{
7505 uint16_t u16Sel;
7506 uint64_t u64Base;
7507 uint32_t u32Limit, u32Attr;
7508 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7509 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7510 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7511 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7512
7513 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7514 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7515 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7516 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7517 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7518 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7519 if (u32Attr & X86DESCATTR_UNUSABLE)
7520 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, "LDTR");
7521}
7522
7523
7524/**
7525 * Imports the guest TR from the current VMCS into the guest-CPU context.
7526 *
7527 * @param pVCpu The cross context virtual CPU structure.
7528 *
7529 * @remarks Called with interrupts and/or preemption disabled.
7530 */
7531static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7532{
7533 uint16_t u16Sel;
7534 uint64_t u64Base;
7535 uint32_t u32Limit, u32Attr;
7536 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7537 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7538 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7539 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7540
7541 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7542 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7543 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7544 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7545 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7546 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7547 /* TR is the only selector that can never be unusable. */
7548 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7549}
7550
7551
7552/**
7553 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7554 *
7555 * @param pVCpu The cross context virtual CPU structure.
7556 *
7557 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7558 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7559 * instead!!!
7560 */
7561static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7562{
7563 uint64_t u64Val;
7564 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7565 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7566 {
7567 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7568 AssertRC(rc);
7569
7570 pCtx->rip = u64Val;
7571 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7572 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7573 }
7574}
7575
7576
7577/**
7578 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7579 *
7580 * @param pVCpu The cross context virtual CPU structure.
7581 * @param pVmcsInfo The VMCS info. object.
7582 *
7583 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7584 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7585 * instead!!!
7586 */
7587static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7588{
7589 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7590 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7591 {
7592 uint64_t u64Val;
7593 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7594 AssertRC(rc);
7595
7596 pCtx->rflags.u64 = u64Val;
7597 PCVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7598 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
7599 {
7600 pCtx->eflags.Bits.u1VM = 0;
7601 pCtx->eflags.Bits.u2IOPL = pVmcsInfoShared->RealMode.Eflags.Bits.u2IOPL;
7602 }
7603 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7604 }
7605}
7606
7607
7608/**
7609 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7610 * context.
7611 *
7612 * @param pVCpu The cross context virtual CPU structure.
7613 * @param pVmcsInfo The VMCS info. object.
7614 *
7615 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7616 * do not log!
7617 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7618 * instead!!!
7619 */
7620static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7621{
7622 uint32_t u32Val;
7623 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7624 if (!u32Val)
7625 {
7626 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7627 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7628 CPUMSetGuestNmiBlocking(pVCpu, false);
7629 }
7630 else
7631 {
7632 /*
7633 * We must import RIP here to set our EM interrupt-inhibited state.
7634 * We also import RFLAGS as our code that evaluates pending interrupts
7635 * before VM-entry requires it.
7636 */
7637 hmR0VmxImportGuestRip(pVCpu);
7638 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7639
7640 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7641 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7642 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7643 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7644
7645 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7646 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7647 }
7648}
7649
7650
7651/**
7652 * Worker for VMXR0ImportStateOnDemand.
7653 *
7654 * @returns VBox status code.
7655 * @param pVCpu The cross context virtual CPU structure.
7656 * @param pVmcsInfo The VMCS info. object.
7657 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7658 */
7659static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7660{
7661 int rc = VINF_SUCCESS;
7662 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7663 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7664 uint32_t u32Val;
7665
7666 /*
7667 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7668 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7669 * neither are other host platforms.
7670 *
7671 * Committing this temporarily as it prevents BSOD.
7672 *
7673 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7674 */
7675#ifdef RT_OS_WINDOWS
7676 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7677 return VERR_HM_IPE_1;
7678#endif
7679
7680 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7681
7682 /*
7683 * We disable interrupts to make the updating of the state and in particular
7684 * the fExtrn modification atomic wrt to preemption hooks.
7685 */
7686 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7687
7688 fWhat &= pCtx->fExtrn;
7689 if (fWhat)
7690 {
7691 do
7692 {
7693 if (fWhat & CPUMCTX_EXTRN_RIP)
7694 hmR0VmxImportGuestRip(pVCpu);
7695
7696 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7697 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7698
7699 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7700 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7701
7702 if (fWhat & CPUMCTX_EXTRN_RSP)
7703 {
7704 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7705 AssertRC(rc);
7706 }
7707
7708 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7709 {
7710 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7711 bool const fRealOnV86Active = pVmcsInfoShared->RealMode.fRealOnV86Active;
7712 if (fWhat & CPUMCTX_EXTRN_CS)
7713 {
7714 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7715 hmR0VmxImportGuestRip(pVCpu);
7716 if (fRealOnV86Active)
7717 pCtx->cs.Attr.u = pVmcsInfoShared->RealMode.AttrCS.u;
7718 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7719 }
7720 if (fWhat & CPUMCTX_EXTRN_SS)
7721 {
7722 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7723 if (fRealOnV86Active)
7724 pCtx->ss.Attr.u = pVmcsInfoShared->RealMode.AttrSS.u;
7725 }
7726 if (fWhat & CPUMCTX_EXTRN_DS)
7727 {
7728 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7729 if (fRealOnV86Active)
7730 pCtx->ds.Attr.u = pVmcsInfoShared->RealMode.AttrDS.u;
7731 }
7732 if (fWhat & CPUMCTX_EXTRN_ES)
7733 {
7734 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7735 if (fRealOnV86Active)
7736 pCtx->es.Attr.u = pVmcsInfoShared->RealMode.AttrES.u;
7737 }
7738 if (fWhat & CPUMCTX_EXTRN_FS)
7739 {
7740 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7741 if (fRealOnV86Active)
7742 pCtx->fs.Attr.u = pVmcsInfoShared->RealMode.AttrFS.u;
7743 }
7744 if (fWhat & CPUMCTX_EXTRN_GS)
7745 {
7746 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7747 if (fRealOnV86Active)
7748 pCtx->gs.Attr.u = pVmcsInfoShared->RealMode.AttrGS.u;
7749 }
7750 }
7751
7752 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7753 {
7754 if (fWhat & CPUMCTX_EXTRN_LDTR)
7755 hmR0VmxImportGuestLdtr(pVCpu);
7756
7757 if (fWhat & CPUMCTX_EXTRN_GDTR)
7758 {
7759 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7760 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7761 pCtx->gdtr.cbGdt = u32Val;
7762 }
7763
7764 /* Guest IDTR. */
7765 if (fWhat & CPUMCTX_EXTRN_IDTR)
7766 {
7767 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7768 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7769 pCtx->idtr.cbIdt = u32Val;
7770 }
7771
7772 /* Guest TR. */
7773 if (fWhat & CPUMCTX_EXTRN_TR)
7774 {
7775 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7776 don't need to import that one. */
7777 if (!pVmcsInfo->pShared->RealMode.fRealOnV86Active)
7778 hmR0VmxImportGuestTr(pVCpu);
7779 }
7780 }
7781
7782 if (fWhat & CPUMCTX_EXTRN_DR7)
7783 {
7784 if (!pVCpu->hmr0.s.fUsingHyperDR7)
7785 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7786 }
7787
7788 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7789 {
7790 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7791 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7792 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7793 pCtx->SysEnter.cs = u32Val;
7794 }
7795
7796 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7797 {
7798 if ( pVM->hmr0.s.fAllow64BitGuests
7799 && (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7800 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7801 }
7802
7803 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7804 {
7805 if ( pVM->hmr0.s.fAllow64BitGuests
7806 && (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7807 {
7808 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7809 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7810 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7811 }
7812 }
7813
7814 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7815 {
7816 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7817 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7818 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7819 Assert(pMsrs);
7820 Assert(cMsrs <= VMX_MISC_MAX_MSRS(g_HmMsrs.u.vmx.u64Misc));
7821 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7822 for (uint32_t i = 0; i < cMsrs; i++)
7823 {
7824 uint32_t const idMsr = pMsrs[i].u32Msr;
7825 switch (idMsr)
7826 {
7827 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7828 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7829 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7830 default:
7831 {
7832 uint32_t idxLbrMsr;
7833 if (pVM->hmr0.s.vmx.fLbr)
7834 {
7835 if (hmR0VmxIsLbrBranchFromMsr(pVM, idMsr, &idxLbrMsr))
7836 {
7837 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfoShared->au64LbrFromIpMsr));
7838 pVmcsInfoShared->au64LbrFromIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7839 break;
7840 }
7841 if (hmR0VmxIsLbrBranchToMsr(pVM, idMsr, &idxLbrMsr))
7842 {
7843 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfoShared->au64LbrFromIpMsr));
7844 pVmcsInfoShared->au64LbrToIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7845 break;
7846 }
7847 if (idMsr == pVM->hmr0.s.vmx.idLbrTosMsr)
7848 {
7849 pVmcsInfoShared->u64LbrTosMsr = pMsrs[i].u64Value;
7850 break;
7851 }
7852 /* Fallthru (no break) */
7853 }
7854 pCtx->fExtrn = 0;
7855 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7856 ASMSetFlags(fEFlags);
7857 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7858 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7859 }
7860 }
7861 }
7862 }
7863
7864 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7865 {
7866 if (fWhat & CPUMCTX_EXTRN_CR0)
7867 {
7868 uint64_t u64Cr0;
7869 uint64_t u64Shadow;
7870 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7871 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7872#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7873 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7874 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7875#else
7876 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7877 {
7878 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7879 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7880 }
7881 else
7882 {
7883 /*
7884 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7885 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7886 * re-construct CR0. See @bugref{9180#c95} for details.
7887 */
7888 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
7889 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7890 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7891 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7892 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7893 }
7894#endif
7895 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7896 CPUMSetGuestCR0(pVCpu, u64Cr0);
7897 VMMRZCallRing3Enable(pVCpu);
7898 }
7899
7900 if (fWhat & CPUMCTX_EXTRN_CR4)
7901 {
7902 uint64_t u64Cr4;
7903 uint64_t u64Shadow;
7904 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7905 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7906#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7907 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7908 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7909#else
7910 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7911 {
7912 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7913 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7914 }
7915 else
7916 {
7917 /*
7918 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7919 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7920 * re-construct CR4. See @bugref{9180#c95} for details.
7921 */
7922 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
7923 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7924 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7925 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7926 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7927 }
7928#endif
7929 pCtx->cr4 = u64Cr4;
7930 }
7931
7932 if (fWhat & CPUMCTX_EXTRN_CR3)
7933 {
7934 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7935 if ( pVM->hmr0.s.vmx.fUnrestrictedGuest
7936 || ( pVM->hmr0.s.fNestedPaging
7937 && CPUMIsGuestPagingEnabledEx(pCtx)))
7938 {
7939 uint64_t u64Cr3;
7940 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7941 if (pCtx->cr3 != u64Cr3)
7942 {
7943 pCtx->cr3 = u64Cr3;
7944 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7945 }
7946
7947 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7948 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7949 if (CPUMIsGuestInPAEModeEx(pCtx))
7950 {
7951 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7952 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7953 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7954 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7955 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7956 }
7957 }
7958 }
7959 }
7960
7961#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7962 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7963 {
7964 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7965 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7966 {
7967 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7968 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7969 if (RT_SUCCESS(rc))
7970 { /* likely */ }
7971 else
7972 break;
7973 }
7974 }
7975#endif
7976 } while (0);
7977
7978 if (RT_SUCCESS(rc))
7979 {
7980 /* Update fExtrn. */
7981 pCtx->fExtrn &= ~fWhat;
7982
7983 /* If everything has been imported, clear the HM keeper bit. */
7984 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7985 {
7986 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7987 Assert(!pCtx->fExtrn);
7988 }
7989 }
7990 }
7991 else
7992 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7993
7994 /*
7995 * Restore interrupts.
7996 */
7997 ASMSetFlags(fEFlags);
7998
7999 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
8000
8001 if (RT_SUCCESS(rc))
8002 { /* likely */ }
8003 else
8004 return rc;
8005
8006 /*
8007 * Honor any pending CR3 updates.
8008 *
8009 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
8010 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
8011 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
8012 *
8013 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
8014 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
8015 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
8016 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
8017 *
8018 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
8019 */
8020 if (VMMRZCallRing3IsEnabled(pVCpu))
8021 {
8022 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
8023 {
8024 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
8025 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
8026 }
8027
8028 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
8029 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
8030
8031 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
8032 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
8033 }
8034
8035 return VINF_SUCCESS;
8036}
8037
8038
8039/**
8040 * Saves the guest state from the VMCS into the guest-CPU context.
8041 *
8042 * @returns VBox status code.
8043 * @param pVCpu The cross context virtual CPU structure.
8044 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
8045 */
8046VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
8047{
8048 AssertPtr(pVCpu);
8049 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8050 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
8051}
8052
8053
8054/**
8055 * Check per-VM and per-VCPU force flag actions that require us to go back to
8056 * ring-3 for one reason or another.
8057 *
8058 * @returns Strict VBox status code (i.e. informational status codes too)
8059 * @retval VINF_SUCCESS if we don't have any actions that require going back to
8060 * ring-3.
8061 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
8062 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
8063 * interrupts)
8064 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
8065 * all EMTs to be in ring-3.
8066 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
8067 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
8068 * to the EM loop.
8069 *
8070 * @param pVCpu The cross context virtual CPU structure.
8071 * @param pVmxTransient The VMX-transient structure.
8072 * @param fStepping Whether we are single-stepping the guest using the
8073 * hypervisor debugger.
8074 *
8075 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
8076 * is no longer in VMX non-root mode.
8077 */
8078static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, bool fStepping)
8079{
8080 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8081
8082 /*
8083 * Update pending interrupts into the APIC's IRR.
8084 */
8085 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
8086 APICUpdatePendingInterrupts(pVCpu);
8087
8088 /*
8089 * Anything pending? Should be more likely than not if we're doing a good job.
8090 */
8091 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8092 if ( !fStepping
8093 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
8094 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
8095 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
8096 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
8097 return VINF_SUCCESS;
8098
8099 /* Pending PGM C3 sync. */
8100 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
8101 {
8102 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8103 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
8104 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
8105 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
8106 if (rcStrict != VINF_SUCCESS)
8107 {
8108 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
8109 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
8110 return rcStrict;
8111 }
8112 }
8113
8114 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
8115 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
8116 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
8117 {
8118 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
8119 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
8120 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
8121 return rc;
8122 }
8123
8124 /* Pending VM request packets, such as hardware interrupts. */
8125 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
8126 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
8127 {
8128 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
8129 Log4Func(("Pending VM request forcing us back to ring-3\n"));
8130 return VINF_EM_PENDING_REQUEST;
8131 }
8132
8133 /* Pending PGM pool flushes. */
8134 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
8135 {
8136 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
8137 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
8138 return VINF_PGM_POOL_FLUSH_PENDING;
8139 }
8140
8141 /* Pending DMA requests. */
8142 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
8143 {
8144 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
8145 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
8146 return VINF_EM_RAW_TO_R3;
8147 }
8148
8149#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8150 /*
8151 * Pending nested-guest events.
8152 *
8153 * Please note the priority of these events are specified and important.
8154 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
8155 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
8156 */
8157 if (pVmxTransient->fIsNestedGuest)
8158 {
8159 /* Pending nested-guest APIC-write. */
8160 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
8161 {
8162 Log4Func(("Pending nested-guest APIC-write\n"));
8163 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
8164 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8165 return rcStrict;
8166 }
8167
8168 /* Pending nested-guest monitor-trap flag (MTF). */
8169 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
8170 {
8171 Log4Func(("Pending nested-guest MTF\n"));
8172 VBOXSTRICTRC rcStrict = IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */);
8173 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8174 return rcStrict;
8175 }
8176
8177 /* Pending nested-guest VMX-preemption timer expired. */
8178 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
8179 {
8180 Log4Func(("Pending nested-guest preempt timer\n"));
8181 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitPreemptTimer(pVCpu);
8182 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8183 return rcStrict;
8184 }
8185 }
8186#else
8187 NOREF(pVmxTransient);
8188#endif
8189
8190 return VINF_SUCCESS;
8191}
8192
8193
8194/**
8195 * Converts any TRPM trap into a pending HM event. This is typically used when
8196 * entering from ring-3 (not longjmp returns).
8197 *
8198 * @param pVCpu The cross context virtual CPU structure.
8199 */
8200static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
8201{
8202 Assert(TRPMHasTrap(pVCpu));
8203 Assert(!pVCpu->hm.s.Event.fPending);
8204
8205 uint8_t uVector;
8206 TRPMEVENT enmTrpmEvent;
8207 uint32_t uErrCode;
8208 RTGCUINTPTR GCPtrFaultAddress;
8209 uint8_t cbInstr;
8210 bool fIcebp;
8211
8212 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
8213 AssertRC(rc);
8214
8215 uint32_t u32IntInfo;
8216 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8217 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
8218
8219 rc = TRPMResetTrap(pVCpu);
8220 AssertRC(rc);
8221 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8222 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8223
8224 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8225}
8226
8227
8228/**
8229 * Converts the pending HM event into a TRPM trap.
8230 *
8231 * @param pVCpu The cross context virtual CPU structure.
8232 */
8233static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
8234{
8235 Assert(pVCpu->hm.s.Event.fPending);
8236
8237 /* If a trap was already pending, we did something wrong! */
8238 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8239
8240 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8241 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8242 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8243
8244 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8245
8246 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8247 AssertRC(rc);
8248
8249 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8250 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8251
8252 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8253 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8254 else
8255 {
8256 uint8_t const uVectorType = VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo);
8257 switch (uVectorType)
8258 {
8259 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
8260 TRPMSetTrapDueToIcebp(pVCpu);
8261 RT_FALL_THRU();
8262 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
8263 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
8264 {
8265 AssertMsg( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
8266 || ( uVector == X86_XCPT_BP /* INT3 */
8267 || uVector == X86_XCPT_OF /* INTO */
8268 || uVector == X86_XCPT_DB /* INT1 (ICEBP) */),
8269 ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uVectorType));
8270 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8271 break;
8272 }
8273 }
8274 }
8275
8276 /* We're now done converting the pending event. */
8277 pVCpu->hm.s.Event.fPending = false;
8278}
8279
8280
8281/**
8282 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8283 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8284 *
8285 * @param pVmcsInfo The VMCS info. object.
8286 */
8287static void hmR0VmxSetIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8288{
8289 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8290 {
8291 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8292 {
8293 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8294 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8295 AssertRC(rc);
8296 }
8297 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8298}
8299
8300
8301/**
8302 * Clears the interrupt-window exiting control in the VMCS.
8303 *
8304 * @param pVmcsInfo The VMCS info. object.
8305 */
8306DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8307{
8308 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8309 {
8310 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8311 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8312 AssertRC(rc);
8313 }
8314}
8315
8316
8317/**
8318 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8319 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8320 *
8321 * @param pVmcsInfo The VMCS info. object.
8322 */
8323static void hmR0VmxSetNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8324{
8325 if (g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8326 {
8327 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8328 {
8329 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8330 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8331 AssertRC(rc);
8332 Log4Func(("Setup NMI-window exiting\n"));
8333 }
8334 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8335}
8336
8337
8338/**
8339 * Clears the NMI-window exiting control in the VMCS.
8340 *
8341 * @param pVmcsInfo The VMCS info. object.
8342 */
8343DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8344{
8345 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8346 {
8347 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8348 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8349 AssertRC(rc);
8350 }
8351}
8352
8353
8354/**
8355 * Does the necessary state syncing before returning to ring-3 for any reason
8356 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8357 *
8358 * @returns VBox status code.
8359 * @param pVCpu The cross context virtual CPU structure.
8360 * @param fImportState Whether to import the guest state from the VMCS back
8361 * to the guest-CPU context.
8362 *
8363 * @remarks No-long-jmp zone!!!
8364 */
8365static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
8366{
8367 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8368 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8369
8370 RTCPUID const idCpu = RTMpCpuId();
8371 Log4Func(("HostCpuId=%u\n", idCpu));
8372
8373 /*
8374 * !!! IMPORTANT !!!
8375 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
8376 */
8377
8378 /* Save the guest state if necessary. */
8379 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8380 if (fImportState)
8381 {
8382 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8383 AssertRCReturn(rc, rc);
8384 }
8385
8386 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8387 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8388 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8389
8390 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8391#ifdef VBOX_STRICT
8392 if (CPUMIsHyperDebugStateActive(pVCpu))
8393 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8394#endif
8395 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8396 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
8397 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
8398
8399 /* Restore host-state bits that VT-x only restores partially. */
8400 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
8401 {
8402 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hmr0.s.vmx.fRestoreHostFlags, idCpu));
8403 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
8404 }
8405 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
8406
8407 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8408 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8409 {
8410 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8411 if (!fImportState)
8412 {
8413 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8414 AssertRCReturn(rc, rc);
8415 }
8416 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8417 Assert(!pVCpu->hmr0.s.vmx.fLazyMsrs);
8418 }
8419 else
8420 pVCpu->hmr0.s.vmx.fLazyMsrs = 0;
8421
8422 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8423 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
8424
8425 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8426 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8427 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8428 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8429 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8430 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8431 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8432 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8433 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8434 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8435
8436 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8437
8438 /** @todo This partially defeats the purpose of having preemption hooks.
8439 * The problem is, deregistering the hooks should be moved to a place that
8440 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8441 * context.
8442 */
8443 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8444 AssertRCReturn(rc, rc);
8445
8446#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8447 /*
8448 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8449 * clear a shadow VMCS before allowing that VMCS to become active on another
8450 * logical processor. We may or may not be importing guest state which clears
8451 * it, so cover for it here.
8452 *
8453 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8454 */
8455 if ( pVmcsInfo->pvShadowVmcs
8456 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8457 {
8458 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8459 AssertRCReturn(rc, rc);
8460 }
8461
8462 /*
8463 * Flag that we need to re-export the host state if we switch to this VMCS before
8464 * executing guest or nested-guest code.
8465 */
8466 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8467#endif
8468
8469 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8470 NOREF(idCpu);
8471 return VINF_SUCCESS;
8472}
8473
8474
8475/**
8476 * Leaves the VT-x session.
8477 *
8478 * @returns VBox status code.
8479 * @param pVCpu The cross context virtual CPU structure.
8480 *
8481 * @remarks No-long-jmp zone!!!
8482 */
8483static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8484{
8485 HM_DISABLE_PREEMPT(pVCpu);
8486 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8487 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8488 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8489
8490 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8491 and done this from the VMXR0ThreadCtxCallback(). */
8492 if (!pVCpu->hmr0.s.fLeaveDone)
8493 {
8494 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8495 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8496 pVCpu->hmr0.s.fLeaveDone = true;
8497 }
8498 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8499
8500 /*
8501 * !!! IMPORTANT !!!
8502 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8503 */
8504
8505 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8506 /** @todo Deregistering here means we need to VMCLEAR always
8507 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8508 * for calling VMMR0ThreadCtxHookDisable here! */
8509 VMMR0ThreadCtxHookDisable(pVCpu);
8510
8511 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8512 int rc = HMR0LeaveCpu(pVCpu);
8513 HM_RESTORE_PREEMPT();
8514 return rc;
8515}
8516
8517
8518/**
8519 * Does the necessary state syncing before doing a longjmp to ring-3.
8520 *
8521 * @returns VBox status code.
8522 * @param pVCpu The cross context virtual CPU structure.
8523 *
8524 * @remarks No-long-jmp zone!!!
8525 */
8526DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8527{
8528 return hmR0VmxLeaveSession(pVCpu);
8529}
8530
8531
8532/**
8533 * Take necessary actions before going back to ring-3.
8534 *
8535 * An action requires us to go back to ring-3. This function does the necessary
8536 * steps before we can safely return to ring-3. This is not the same as longjmps
8537 * to ring-3, this is voluntary and prepares the guest so it may continue
8538 * executing outside HM (recompiler/IEM).
8539 *
8540 * @returns VBox status code.
8541 * @param pVCpu The cross context virtual CPU structure.
8542 * @param rcExit The reason for exiting to ring-3. Can be
8543 * VINF_VMM_UNKNOWN_RING3_CALL.
8544 */
8545static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8546{
8547 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8548
8549 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8550 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8551 {
8552 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8553 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8554 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hmr0.s.idEnteredCpu;
8555 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8556 }
8557
8558 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8559 VMMRZCallRing3Disable(pVCpu);
8560 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8561
8562 /*
8563 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8564 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8565 *
8566 * This is because execution may continue from ring-3 and we would need to inject
8567 * the event from there (hence place it back in TRPM).
8568 */
8569 if (pVCpu->hm.s.Event.fPending)
8570 {
8571 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8572 Assert(!pVCpu->hm.s.Event.fPending);
8573
8574 /* Clear the events from the VMCS. */
8575 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc);
8576 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0); AssertRC(rc);
8577 }
8578#ifdef VBOX_STRICT
8579 /*
8580 * We check for rcExit here since for errors like VERR_VMX_UNABLE_TO_START_VM (which are
8581 * fatal), we don't care about verifying duplicate injection of events. Errors like
8582 * VERR_EM_INTERPRET are converted to their VINF_* counterparts -prior- to calling this
8583 * function so those should and will be checked below.
8584 */
8585 else if (RT_SUCCESS(rcExit))
8586 {
8587 /*
8588 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8589 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8590 * occasionally, see @bugref{9180#c42}.
8591 *
8592 * However, if the VM-entry failed, any VM entry-interruption info. field would
8593 * be left unmodified as the event would not have been injected to the guest. In
8594 * such cases, don't assert, we're not going to continue guest execution anyway.
8595 */
8596 uint32_t uExitReason;
8597 uint32_t uEntryIntInfo;
8598 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8599 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8600 AssertRC(rc);
8601 AssertMsg(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo),
8602 ("uExitReason=%#RX32 uEntryIntInfo=%#RX32 rcExit=%d\n", uExitReason, uEntryIntInfo, VBOXSTRICTRC_VAL(rcExit)));
8603 }
8604#endif
8605
8606 /*
8607 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8608 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8609 * (e.g. TPR below threshold).
8610 */
8611 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8612 {
8613 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8614 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8615 }
8616
8617 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8618 and if we're injecting an event we should have a TRPM trap pending. */
8619 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8620#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8621 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8622#endif
8623
8624 /* Save guest state and restore host state bits. */
8625 int rc = hmR0VmxLeaveSession(pVCpu);
8626 AssertRCReturn(rc, rc);
8627 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8628
8629 /* Thread-context hooks are unregistered at this point!!! */
8630 /* Ring-3 callback notifications are unregistered at this point!!! */
8631
8632 /* Sync recompiler state. */
8633 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8634 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8635 | CPUM_CHANGED_LDTR
8636 | CPUM_CHANGED_GDTR
8637 | CPUM_CHANGED_IDTR
8638 | CPUM_CHANGED_TR
8639 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8640 if ( pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging
8641 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8642 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8643
8644 Assert(!pVCpu->hmr0.s.fClearTrapFlag);
8645
8646 /* Update the exit-to-ring 3 reason. */
8647 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8648
8649 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8650 if ( rcExit != VINF_EM_RAW_INTERRUPT
8651 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8652 {
8653 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8654 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8655 }
8656
8657 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8658 VMMRZCallRing3Enable(pVCpu);
8659 return rc;
8660}
8661
8662
8663/**
8664 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8665 * longjump to ring-3 and possibly get preempted.
8666 *
8667 * @returns VBox status code.
8668 * @param pVCpu The cross context virtual CPU structure.
8669 * @param enmOperation The operation causing the ring-3 longjump.
8670 */
8671VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8672{
8673 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8674 {
8675 /*
8676 * !!! IMPORTANT !!!
8677 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8678 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8679 */
8680 VMMRZCallRing3RemoveNotification(pVCpu);
8681 VMMRZCallRing3Disable(pVCpu);
8682 HM_DISABLE_PREEMPT(pVCpu);
8683
8684 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8685 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8686 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8687 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8688
8689 /* Restore host-state bits that VT-x only restores partially. */
8690 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
8691 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
8692 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
8693
8694 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8695 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8696 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8697
8698 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8699 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
8700 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8701
8702 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8703 cleared as part of importing the guest state above. */
8704 hmR0VmxClearVmcs(pVmcsInfo);
8705
8706 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8707 VMMR0ThreadCtxHookDisable(pVCpu);
8708
8709 /* Leave HM context. This takes care of local init (term). */
8710 HMR0LeaveCpu(pVCpu);
8711 HM_RESTORE_PREEMPT();
8712 return VINF_SUCCESS;
8713 }
8714
8715 Assert(pVCpu);
8716 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8717 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8718
8719 VMMRZCallRing3Disable(pVCpu);
8720 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8721
8722 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8723
8724 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8725 AssertRCReturn(rc, rc);
8726
8727 VMMRZCallRing3Enable(pVCpu);
8728 return VINF_SUCCESS;
8729}
8730
8731
8732/**
8733 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8734 * stack.
8735 *
8736 * @returns Strict VBox status code (i.e. informational status codes too).
8737 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8738 * @param pVCpu The cross context virtual CPU structure.
8739 * @param uValue The value to push to the guest stack.
8740 */
8741static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8742{
8743 /*
8744 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8745 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8746 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8747 */
8748 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8749 if (pCtx->sp == 1)
8750 return VINF_EM_RESET;
8751 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8752 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8753 AssertRC(rc);
8754 return rc;
8755}
8756
8757
8758/**
8759 * Injects an event into the guest upon VM-entry by updating the relevant fields
8760 * in the VM-entry area in the VMCS.
8761 *
8762 * @returns Strict VBox status code (i.e. informational status codes too).
8763 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8764 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8765 *
8766 * @param pVCpu The cross context virtual CPU structure.
8767 * @param pVmxTransient The VMX-transient structure.
8768 * @param pEvent The event being injected.
8769 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8770 * will be updated if necessary. This cannot not be NULL.
8771 * @param fStepping Whether we're single-stepping guest execution and should
8772 * return VINF_EM_DBG_STEPPED if the event is injected
8773 * directly (registers modified by us, not by hardware on
8774 * VM-entry).
8775 */
8776static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8777 uint32_t *pfIntrState)
8778{
8779 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8780 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8781 Assert(pfIntrState);
8782
8783 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8784 uint32_t u32IntInfo = pEvent->u64IntInfo;
8785 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8786 uint32_t const cbInstr = pEvent->cbInstr;
8787 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8788 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8789 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8790
8791#ifdef VBOX_STRICT
8792 /*
8793 * Validate the error-code-valid bit for hardware exceptions.
8794 * No error codes for exceptions in real-mode.
8795 *
8796 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8797 */
8798 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8799 && !CPUMIsGuestInRealModeEx(pCtx))
8800 {
8801 switch (uVector)
8802 {
8803 case X86_XCPT_PF:
8804 case X86_XCPT_DF:
8805 case X86_XCPT_TS:
8806 case X86_XCPT_NP:
8807 case X86_XCPT_SS:
8808 case X86_XCPT_GP:
8809 case X86_XCPT_AC:
8810 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8811 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8812 RT_FALL_THRU();
8813 default:
8814 break;
8815 }
8816 }
8817
8818 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8819 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8820 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8821#endif
8822
8823 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8824 || uIntType == VMX_EXIT_INT_INFO_TYPE_NMI
8825 || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT
8826 || uIntType == VMX_EXIT_INT_INFO_TYPE_SW_XCPT)
8827 {
8828 Assert(uVector <= X86_XCPT_LAST);
8829 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_NMI || uVector == X86_XCPT_NMI);
8830 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT || uVector == X86_XCPT_DB);
8831 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedXcptsR0[uVector]);
8832 }
8833 else
8834 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8835
8836 /*
8837 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8838 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8839 * interrupt handler in the (real-mode) guest.
8840 *
8841 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8842 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8843 */
8844 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8845 {
8846 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest)
8847 {
8848 /*
8849 * For CPUs with unrestricted guest execution enabled and with the guest
8850 * in real-mode, we must not set the deliver-error-code bit.
8851 *
8852 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8853 */
8854 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8855 }
8856 else
8857 {
8858 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8859 Assert(PDMVmmDevHeapIsEnabled(pVM));
8860 Assert(pVM->hm.s.vmx.pRealModeTSS);
8861 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8862
8863 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8864 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8865 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8866 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8867 AssertRCReturn(rc2, rc2);
8868
8869 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8870 size_t const cbIdtEntry = sizeof(X86IDTR16);
8871 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8872 {
8873 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8874 if (uVector == X86_XCPT_DF)
8875 return VINF_EM_RESET;
8876
8877 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8878 No error codes for exceptions in real-mode. */
8879 if (uVector == X86_XCPT_GP)
8880 {
8881 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8882 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8883 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8884 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8885 HMEVENT EventXcptDf;
8886 RT_ZERO(EventXcptDf);
8887 EventXcptDf.u64IntInfo = uXcptDfInfo;
8888 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8889 }
8890
8891 /*
8892 * If we're injecting an event with no valid IDT entry, inject a #GP.
8893 * No error codes for exceptions in real-mode.
8894 *
8895 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8896 */
8897 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8898 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8899 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8900 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8901 HMEVENT EventXcptGp;
8902 RT_ZERO(EventXcptGp);
8903 EventXcptGp.u64IntInfo = uXcptGpInfo;
8904 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8905 }
8906
8907 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8908 uint16_t uGuestIp = pCtx->ip;
8909 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8910 {
8911 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8912 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8913 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8914 }
8915 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8916 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8917
8918 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8919 X86IDTR16 IdtEntry;
8920 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8921 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8922 AssertRCReturn(rc2, rc2);
8923
8924 /* Construct the stack frame for the interrupt/exception handler. */
8925 VBOXSTRICTRC rcStrict;
8926 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8927 if (rcStrict == VINF_SUCCESS)
8928 {
8929 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8930 if (rcStrict == VINF_SUCCESS)
8931 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8932 }
8933
8934 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8935 if (rcStrict == VINF_SUCCESS)
8936 {
8937 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8938 pCtx->rip = IdtEntry.offSel;
8939 pCtx->cs.Sel = IdtEntry.uSel;
8940 pCtx->cs.ValidSel = IdtEntry.uSel;
8941 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8942 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8943 && uVector == X86_XCPT_PF)
8944 pCtx->cr2 = GCPtrFault;
8945
8946 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8947 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8948 | HM_CHANGED_GUEST_RSP);
8949
8950 /*
8951 * If we delivered a hardware exception (other than an NMI) and if there was
8952 * block-by-STI in effect, we should clear it.
8953 */
8954 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8955 {
8956 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8957 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8958 Log4Func(("Clearing inhibition due to STI\n"));
8959 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8960 }
8961
8962 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8963 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8964
8965 /*
8966 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8967 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8968 */
8969 pVCpu->hm.s.Event.fPending = false;
8970
8971 /*
8972 * If we eventually support nested-guest execution without unrestricted guest execution,
8973 * we should set fInterceptEvents here.
8974 */
8975 Assert(!pVmxTransient->fIsNestedGuest);
8976
8977 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8978 if (fStepping)
8979 rcStrict = VINF_EM_DBG_STEPPED;
8980 }
8981 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8982 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8983 return rcStrict;
8984 }
8985 }
8986
8987 /*
8988 * Validate.
8989 */
8990 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8991 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8992
8993 /*
8994 * Inject the event into the VMCS.
8995 */
8996 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8997 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8998 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8999 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
9000 AssertRC(rc);
9001
9002 /*
9003 * Update guest CR2 if this is a page-fault.
9004 */
9005 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
9006 pCtx->cr2 = GCPtrFault;
9007
9008 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
9009 return VINF_SUCCESS;
9010}
9011
9012
9013/**
9014 * Evaluates the event to be delivered to the guest and sets it as the pending
9015 * event.
9016 *
9017 * Toggling of interrupt force-flags here is safe since we update TRPM on premature
9018 * exits to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must
9019 * NOT restore these force-flags.
9020 *
9021 * @returns Strict VBox status code (i.e. informational status codes too).
9022 * @param pVCpu The cross context virtual CPU structure.
9023 * @param pVmxTransient The VMX-transient structure.
9024 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
9025 */
9026static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
9027{
9028 Assert(pfIntrState);
9029 Assert(!TRPMHasTrap(pVCpu));
9030
9031 /*
9032 * Compute/update guest-interruptibility state related FFs.
9033 * The FFs will be used below while evaluating events to be injected.
9034 */
9035 *pfIntrState = hmR0VmxGetGuestIntrStateAndUpdateFFs(pVCpu);
9036
9037 /*
9038 * Evaluate if a new event needs to be injected.
9039 * An event that's already pending has already performed all necessary checks.
9040 */
9041 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9042 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
9043 if ( !pVCpu->hm.s.Event.fPending
9044 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
9045 {
9046 /** @todo SMI. SMIs take priority over NMIs. */
9047
9048 /*
9049 * NMIs.
9050 * NMIs take priority over external interrupts.
9051 */
9052 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9053 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
9054 {
9055 /*
9056 * For a guest, the FF always indicates the guest's ability to receive an NMI.
9057 *
9058 * For a nested-guest, the FF always indicates the outer guest's ability to
9059 * receive an NMI while the guest-interruptibility state bit depends on whether
9060 * the nested-hypervisor is using virtual-NMIs.
9061 */
9062 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
9063 {
9064#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9065 if ( fIsNestedGuest
9066 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_NMI_EXIT))
9067 return IEMExecVmxVmexitXcptNmi(pVCpu);
9068#endif
9069 hmR0VmxSetPendingXcptNmi(pVCpu);
9070 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
9071 Log4Func(("NMI pending injection\n"));
9072
9073 /* We've injected the NMI, bail. */
9074 return VINF_SUCCESS;
9075 }
9076 else if (!fIsNestedGuest)
9077 hmR0VmxSetNmiWindowExitVmcs(pVmcsInfo);
9078 }
9079
9080 /*
9081 * External interrupts (PIC/APIC).
9082 * Once PDMGetInterrupt() returns a valid interrupt we -must- deliver it.
9083 * We cannot re-request the interrupt from the controller again.
9084 */
9085 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9086 && !pVCpu->hm.s.fSingleInstruction)
9087 {
9088 Assert(!DBGFIsStepping(pVCpu));
9089 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
9090 AssertRC(rc);
9091
9092 /*
9093 * We must not check EFLAGS directly when executing a nested-guest, use
9094 * CPUMIsGuestPhysIntrEnabled() instead as EFLAGS.IF does not control the blocking of
9095 * external interrupts when "External interrupt exiting" is set. This fixes a nasty
9096 * SMP hang while executing nested-guest VCPUs on spinlocks which aren't rescued by
9097 * other VM-exits (like a preemption timer), see @bugref{9562#c18}.
9098 *
9099 * See Intel spec. 25.4.1 "Event Blocking".
9100 */
9101 if (CPUMIsGuestPhysIntrEnabled(pVCpu))
9102 {
9103#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9104 if ( fIsNestedGuest
9105 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9106 {
9107 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
9108 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9109 return rcStrict;
9110 }
9111#endif
9112 uint8_t u8Interrupt;
9113 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9114 if (RT_SUCCESS(rc))
9115 {
9116#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9117 if ( fIsNestedGuest
9118 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9119 {
9120 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9121 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
9122 return rcStrict;
9123 }
9124#endif
9125 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9126 Log4Func(("External interrupt (%#x) pending injection\n", u8Interrupt));
9127 }
9128 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9129 {
9130 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9131
9132 if ( !fIsNestedGuest
9133 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9134 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
9135 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
9136
9137 /*
9138 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9139 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9140 * need to re-set this force-flag here.
9141 */
9142 }
9143 else
9144 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9145
9146 /* We've injected the interrupt or taken necessary action, bail. */
9147 return VINF_SUCCESS;
9148 }
9149 if (!fIsNestedGuest)
9150 hmR0VmxSetIntWindowExitVmcs(pVmcsInfo);
9151 }
9152 }
9153 else if (!fIsNestedGuest)
9154 {
9155 /*
9156 * An event is being injected or we are in an interrupt shadow. Check if another event is
9157 * pending. If so, instruct VT-x to cause a VM-exit as soon as the guest is ready to accept
9158 * the pending event.
9159 */
9160 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
9161 hmR0VmxSetNmiWindowExitVmcs(pVmcsInfo);
9162 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9163 && !pVCpu->hm.s.fSingleInstruction)
9164 hmR0VmxSetIntWindowExitVmcs(pVmcsInfo);
9165 }
9166 /* else: for nested-guests, NMI/interrupt-window exiting will be picked up when merging VMCS controls. */
9167
9168 return VINF_SUCCESS;
9169}
9170
9171
9172/**
9173 * Injects any pending events into the guest if the guest is in a state to
9174 * receive them.
9175 *
9176 * @returns Strict VBox status code (i.e. informational status codes too).
9177 * @param pVCpu The cross context virtual CPU structure.
9178 * @param pVmxTransient The VMX-transient structure.
9179 * @param fIntrState The VT-x guest-interruptibility state.
9180 * @param fStepping Whether we are single-stepping the guest using the
9181 * hypervisor debugger and should return
9182 * VINF_EM_DBG_STEPPED if the event was dispatched
9183 * directly.
9184 */
9185static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9186{
9187 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9188 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9189
9190#ifdef VBOX_STRICT
9191 /*
9192 * Verify guest-interruptibility state.
9193 *
9194 * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
9195 * since injecting an event may modify the interruptibility state and we must thus always
9196 * use fIntrState.
9197 */
9198 {
9199 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9200 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9201 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9202 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9203 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9204 Assert(!TRPMHasTrap(pVCpu));
9205 NOREF(fBlockMovSS); NOREF(fBlockSti);
9206 }
9207#endif
9208
9209 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9210 if (pVCpu->hm.s.Event.fPending)
9211 {
9212 /*
9213 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9214 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9215 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9216 *
9217 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9218 */
9219 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9220#ifdef VBOX_STRICT
9221 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9222 {
9223 Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9224 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9225 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9226 }
9227 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9228 {
9229 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
9230 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9231 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9232 }
9233#endif
9234 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9235 uIntType));
9236
9237 /*
9238 * Inject the event and get any changes to the guest-interruptibility state.
9239 *
9240 * The guest-interruptibility state may need to be updated if we inject the event
9241 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9242 */
9243 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9244 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9245
9246 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9247 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9248 else
9249 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9250 }
9251
9252 /*
9253 * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
9254 * is an interrupt shadow (block-by-STI or block-by-MOV SS).
9255 */
9256 if ( (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9257 && !pVmxTransient->fIsNestedGuest)
9258 {
9259 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
9260
9261 if (!pVCpu->hm.s.fSingleInstruction)
9262 {
9263 /*
9264 * Set or clear the BS bit depending on whether the trap flag is active or not. We need
9265 * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
9266 */
9267 Assert(!DBGFIsStepping(pVCpu));
9268 uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
9269 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
9270 AssertRC(rc);
9271 }
9272 else
9273 {
9274 /*
9275 * We must not deliver a debug exception when single-stepping over STI/Mov-SS in the
9276 * hypervisor debugger using EFLAGS.TF but rather clear interrupt inhibition. However,
9277 * we take care of this case in hmR0VmxExportSharedDebugState and also the case if
9278 * we use MTF, so just make sure it's called before executing guest-code.
9279 */
9280 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR_MASK);
9281 }
9282 }
9283 /* else: for nested-guest currently handling while merging controls. */
9284
9285 /*
9286 * Finally, update the guest-interruptibility state.
9287 *
9288 * This is required for the real-on-v86 software interrupt injection, for
9289 * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
9290 */
9291 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9292 AssertRC(rc);
9293
9294 /*
9295 * There's no need to clear the VM-entry interruption-information field here if we're not
9296 * injecting anything. VT-x clears the valid bit on every VM-exit.
9297 *
9298 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9299 */
9300
9301 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9302 return rcStrict;
9303}
9304
9305
9306/**
9307 * Enters the VT-x session.
9308 *
9309 * @returns VBox status code.
9310 * @param pVCpu The cross context virtual CPU structure.
9311 */
9312VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
9313{
9314 AssertPtr(pVCpu);
9315 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9316 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9317
9318 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9319 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9320 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9321
9322#ifdef VBOX_STRICT
9323 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9324 RTCCUINTREG uHostCr4 = ASMGetCR4();
9325 if (!(uHostCr4 & X86_CR4_VMXE))
9326 {
9327 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9328 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9329 }
9330#endif
9331
9332 /*
9333 * Do the EMT scheduled L1D and MDS flush here if needed.
9334 */
9335 if (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_L1D_SCHED)
9336 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9337 else if (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_MDS_SCHED)
9338 hmR0MdsClear();
9339
9340 /*
9341 * Load the appropriate VMCS as the current and active one.
9342 */
9343 PVMXVMCSINFO pVmcsInfo;
9344 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9345 if (!fInNestedGuestMode)
9346 pVmcsInfo = &pVCpu->hmr0.s.vmx.VmcsInfo;
9347 else
9348 pVmcsInfo = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
9349 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9350 if (RT_SUCCESS(rc))
9351 {
9352 pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9353 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcsCopyForRing3 = fInNestedGuestMode;
9354 pVCpu->hmr0.s.fLeaveDone = false;
9355 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9356 }
9357 return rc;
9358}
9359
9360
9361/**
9362 * The thread-context callback.
9363 *
9364 * This is used together with RTThreadCtxHookCreate() on platforms which
9365 * supports it, and directly from VMMR0EmtPrepareForBlocking() and
9366 * VMMR0EmtResumeAfterBlocking() on platforms which don't.
9367 *
9368 * @param enmEvent The thread-context event.
9369 * @param pVCpu The cross context virtual CPU structure.
9370 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9371 * @thread EMT(pVCpu)
9372 */
9373VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
9374{
9375 AssertPtr(pVCpu);
9376 RT_NOREF1(fGlobalInit);
9377
9378 switch (enmEvent)
9379 {
9380 case RTTHREADCTXEVENT_OUT:
9381 {
9382 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9383 VMCPU_ASSERT_EMT(pVCpu);
9384
9385 /* No longjmps (logger flushes, locks) in this fragile context. */
9386 VMMRZCallRing3Disable(pVCpu);
9387 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9388
9389 /* Restore host-state (FPU, debug etc.) */
9390 if (!pVCpu->hmr0.s.fLeaveDone)
9391 {
9392 /*
9393 * Do -not- import the guest-state here as we might already be in the middle of importing
9394 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9395 */
9396 hmR0VmxLeave(pVCpu, false /* fImportState */);
9397 pVCpu->hmr0.s.fLeaveDone = true;
9398 }
9399
9400 /* Leave HM context, takes care of local init (term). */
9401 int rc = HMR0LeaveCpu(pVCpu);
9402 AssertRC(rc);
9403
9404 /* Restore longjmp state. */
9405 VMMRZCallRing3Enable(pVCpu);
9406 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9407 break;
9408 }
9409
9410 case RTTHREADCTXEVENT_IN:
9411 {
9412 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9413 VMCPU_ASSERT_EMT(pVCpu);
9414
9415 /* Do the EMT scheduled L1D and MDS flush here if needed. */
9416 if (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_L1D_SCHED)
9417 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9418 else if (pVCpu->hmr0.s.fWorldSwitcher & HM_WSF_MDS_SCHED)
9419 hmR0MdsClear();
9420
9421 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9422 VMMRZCallRing3Disable(pVCpu);
9423 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9424
9425 /* Initialize the bare minimum state required for HM. This takes care of
9426 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9427 int rc = hmR0EnterCpu(pVCpu);
9428 AssertRC(rc);
9429 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9430 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9431
9432 /* Load the active VMCS as the current one. */
9433 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9434 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9435 AssertRC(rc);
9436 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9437 pVCpu->hmr0.s.fLeaveDone = false;
9438
9439 /* Restore longjmp state. */
9440 VMMRZCallRing3Enable(pVCpu);
9441 break;
9442 }
9443
9444 default:
9445 break;
9446 }
9447}
9448
9449
9450/**
9451 * Exports the host state into the VMCS host-state area.
9452 * Sets up the VM-exit MSR-load area.
9453 *
9454 * The CPU state will be loaded from these fields on every successful VM-exit.
9455 *
9456 * @returns VBox status code.
9457 * @param pVCpu The cross context virtual CPU structure.
9458 *
9459 * @remarks No-long-jump zone!!!
9460 */
9461static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
9462{
9463 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9464
9465 int rc = VINF_SUCCESS;
9466 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9467 {
9468 uint64_t uHostCr4 = hmR0VmxExportHostControlRegs();
9469
9470 rc = hmR0VmxExportHostSegmentRegs(pVCpu, uHostCr4);
9471 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9472
9473 hmR0VmxExportHostMsrs(pVCpu);
9474
9475 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9476 }
9477 return rc;
9478}
9479
9480
9481/**
9482 * Saves the host state in the VMCS host-state.
9483 *
9484 * @returns VBox status code.
9485 * @param pVCpu The cross context virtual CPU structure.
9486 *
9487 * @remarks No-long-jump zone!!!
9488 */
9489VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
9490{
9491 AssertPtr(pVCpu);
9492 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9493
9494 /*
9495 * Export the host state here while entering HM context.
9496 * When thread-context hooks are used, we might get preempted and have to re-save the host
9497 * state but most of the time we won't be, so do it here before we disable interrupts.
9498 */
9499 return hmR0VmxExportHostState(pVCpu);
9500}
9501
9502
9503/**
9504 * Exports the guest state into the VMCS guest-state area.
9505 *
9506 * The will typically be done before VM-entry when the guest-CPU state and the
9507 * VMCS state may potentially be out of sync.
9508 *
9509 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9510 * VM-entry controls.
9511 * Sets up the appropriate VMX non-root function to execute guest code based on
9512 * the guest CPU mode.
9513 *
9514 * @returns VBox strict status code.
9515 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9516 * without unrestricted guest execution and the VMMDev is not presently
9517 * mapped (e.g. EFI32).
9518 *
9519 * @param pVCpu The cross context virtual CPU structure.
9520 * @param pVmxTransient The VMX-transient structure.
9521 *
9522 * @remarks No-long-jump zone!!!
9523 */
9524static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9525{
9526 AssertPtr(pVCpu);
9527 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9528 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9529
9530 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9531
9532 /*
9533 * Determine real-on-v86 mode.
9534 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9535 */
9536 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmxTransient->pVmcsInfo->pShared;
9537 if ( pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest
9538 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9539 pVmcsInfoShared->RealMode.fRealOnV86Active = false;
9540 else
9541 {
9542 Assert(!pVmxTransient->fIsNestedGuest);
9543 pVmcsInfoShared->RealMode.fRealOnV86Active = true;
9544 }
9545
9546 /*
9547 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9548 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9549 */
9550 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9551 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9552
9553 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9554 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9555
9556 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9557 if (rcStrict == VINF_SUCCESS)
9558 { /* likely */ }
9559 else
9560 {
9561 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9562 return rcStrict;
9563 }
9564
9565 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9566 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9567
9568 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9569 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9570
9571 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9572 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9573 hmR0VmxExportGuestRip(pVCpu);
9574 hmR0VmxExportGuestRsp(pVCpu);
9575 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9576
9577 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9578 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9579
9580 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9581 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9582 | HM_CHANGED_GUEST_CR2
9583 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9584 | HM_CHANGED_GUEST_X87
9585 | HM_CHANGED_GUEST_SSE_AVX
9586 | HM_CHANGED_GUEST_OTHER_XSAVE
9587 | HM_CHANGED_GUEST_XCRx
9588 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9589 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9590 | HM_CHANGED_GUEST_TSC_AUX
9591 | HM_CHANGED_GUEST_OTHER_MSRS
9592 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9593
9594 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9595 return rc;
9596}
9597
9598
9599/**
9600 * Exports the state shared between the host and guest into the VMCS.
9601 *
9602 * @param pVCpu The cross context virtual CPU structure.
9603 * @param pVmxTransient The VMX-transient structure.
9604 *
9605 * @remarks No-long-jump zone!!!
9606 */
9607static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9608{
9609 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9610 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9611
9612 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9613 {
9614 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9615 AssertRC(rc);
9616 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9617
9618 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9619 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9620 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9621 }
9622
9623 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9624 {
9625 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9626 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9627 }
9628
9629 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9630 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9631}
9632
9633
9634/**
9635 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9636 *
9637 * @returns Strict VBox status code (i.e. informational status codes too).
9638 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9639 * without unrestricted guest execution and the VMMDev is not presently
9640 * mapped (e.g. EFI32).
9641 *
9642 * @param pVCpu The cross context virtual CPU structure.
9643 * @param pVmxTransient The VMX-transient structure.
9644 *
9645 * @remarks No-long-jump zone!!!
9646 */
9647static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9648{
9649 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9650 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9651 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9652
9653#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9654 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9655#endif
9656
9657 /*
9658 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9659 * changes. First try to export only these without going through all other changed-flag checks.
9660 */
9661 VBOXSTRICTRC rcStrict;
9662 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9663 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9664 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9665
9666 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9667 if ( (fCtxChanged & fMinimalMask)
9668 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9669 {
9670 hmR0VmxExportGuestRip(pVCpu);
9671 hmR0VmxExportGuestRsp(pVCpu);
9672 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9673 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9674 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9675 }
9676 /* If anything else also changed, go through the full export routine and export as required. */
9677 else if (fCtxChanged & fCtxMask)
9678 {
9679 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9680 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9681 { /* likely */}
9682 else
9683 {
9684 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9685 VBOXSTRICTRC_VAL(rcStrict)));
9686 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9687 return rcStrict;
9688 }
9689 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9690 }
9691 /* Nothing changed, nothing to load here. */
9692 else
9693 rcStrict = VINF_SUCCESS;
9694
9695#ifdef VBOX_STRICT
9696 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9697 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9698 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9699#endif
9700 return rcStrict;
9701}
9702
9703
9704/**
9705 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9706 * and update error record fields accordingly.
9707 *
9708 * @returns VMX_IGS_* error codes.
9709 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9710 * wrong with the guest state.
9711 *
9712 * @param pVCpu The cross context virtual CPU structure.
9713 * @param pVmcsInfo The VMCS info. object.
9714 *
9715 * @remarks This function assumes our cache of the VMCS controls
9716 * are valid, i.e. hmR0VmxCheckCachedVmcsCtls() succeeded.
9717 */
9718static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9719{
9720#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9721#define HMVMX_CHECK_BREAK(expr, err) do { \
9722 if (!(expr)) { uError = (err); break; } \
9723 } while (0)
9724
9725 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9726 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9727 uint32_t uError = VMX_IGS_ERROR;
9728 uint32_t u32IntrState = 0;
9729 bool const fUnrestrictedGuest = pVM->hmr0.s.vmx.fUnrestrictedGuest;
9730 do
9731 {
9732 int rc;
9733
9734 /*
9735 * Guest-interruptibility state.
9736 *
9737 * Read this first so that any check that fails prior to those that actually
9738 * require the guest-interruptibility state would still reflect the correct
9739 * VMCS value and avoids causing further confusion.
9740 */
9741 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9742 AssertRC(rc);
9743
9744 uint32_t u32Val;
9745 uint64_t u64Val;
9746
9747 /*
9748 * CR0.
9749 */
9750 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9751 uint64_t fSetCr0 = (g_HmMsrs.u.vmx.u64Cr0Fixed0 & g_HmMsrs.u.vmx.u64Cr0Fixed1);
9752 uint64_t const fZapCr0 = (g_HmMsrs.u.vmx.u64Cr0Fixed0 | g_HmMsrs.u.vmx.u64Cr0Fixed1);
9753 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9754 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9755 if (fUnrestrictedGuest)
9756 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9757
9758 uint64_t u64GuestCr0;
9759 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9760 AssertRC(rc);
9761 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9762 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9763 if ( !fUnrestrictedGuest
9764 && (u64GuestCr0 & X86_CR0_PG)
9765 && !(u64GuestCr0 & X86_CR0_PE))
9766 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9767
9768 /*
9769 * CR4.
9770 */
9771 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9772 uint64_t const fSetCr4 = (g_HmMsrs.u.vmx.u64Cr4Fixed0 & g_HmMsrs.u.vmx.u64Cr4Fixed1);
9773 uint64_t const fZapCr4 = (g_HmMsrs.u.vmx.u64Cr4Fixed0 | g_HmMsrs.u.vmx.u64Cr4Fixed1);
9774
9775 uint64_t u64GuestCr4;
9776 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9777 AssertRC(rc);
9778 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9779 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9780
9781 /*
9782 * IA32_DEBUGCTL MSR.
9783 */
9784 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9785 AssertRC(rc);
9786 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9787 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9788 {
9789 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9790 }
9791 uint64_t u64DebugCtlMsr = u64Val;
9792
9793#ifdef VBOX_STRICT
9794 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9795 AssertRC(rc);
9796 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9797#endif
9798 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9799
9800 /*
9801 * RIP and RFLAGS.
9802 */
9803 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9804 AssertRC(rc);
9805 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9806 if ( !fLongModeGuest
9807 || !pCtx->cs.Attr.n.u1Long)
9808 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9809 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9810 * must be identical if the "IA-32e mode guest" VM-entry
9811 * control is 1 and CS.L is 1. No check applies if the
9812 * CPU supports 64 linear-address bits. */
9813
9814 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9815 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9816 AssertRC(rc);
9817 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9818 VMX_IGS_RFLAGS_RESERVED);
9819 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9820 uint32_t const u32Eflags = u64Val;
9821
9822 if ( fLongModeGuest
9823 || ( fUnrestrictedGuest
9824 && !(u64GuestCr0 & X86_CR0_PE)))
9825 {
9826 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9827 }
9828
9829 uint32_t u32EntryInfo;
9830 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9831 AssertRC(rc);
9832 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9833 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9834
9835 /*
9836 * 64-bit checks.
9837 */
9838 if (fLongModeGuest)
9839 {
9840 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9841 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9842 }
9843
9844 if ( !fLongModeGuest
9845 && (u64GuestCr4 & X86_CR4_PCIDE))
9846 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9847
9848 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9849 * 51:32 beyond the processor's physical-address width are 0. */
9850
9851 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9852 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9853 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9854
9855 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9856 AssertRC(rc);
9857 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9858
9859 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9860 AssertRC(rc);
9861 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9862
9863 /*
9864 * PERF_GLOBAL MSR.
9865 */
9866 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9867 {
9868 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9869 AssertRC(rc);
9870 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9871 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9872 }
9873
9874 /*
9875 * PAT MSR.
9876 */
9877 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9878 {
9879 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9880 AssertRC(rc);
9881 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9882 for (unsigned i = 0; i < 8; i++)
9883 {
9884 uint8_t u8Val = (u64Val & 0xff);
9885 if ( u8Val != 0 /* UC */
9886 && u8Val != 1 /* WC */
9887 && u8Val != 4 /* WT */
9888 && u8Val != 5 /* WP */
9889 && u8Val != 6 /* WB */
9890 && u8Val != 7 /* UC- */)
9891 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9892 u64Val >>= 8;
9893 }
9894 }
9895
9896 /*
9897 * EFER MSR.
9898 */
9899 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9900 {
9901 Assert(g_fHmVmxSupportsVmcsEfer);
9902 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9903 AssertRC(rc);
9904 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9905 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9906 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9907 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9908 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9909 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9910 * iemVmxVmentryCheckGuestState(). */
9911 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9912 || !(u64GuestCr0 & X86_CR0_PG)
9913 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9914 VMX_IGS_EFER_LMA_LME_MISMATCH);
9915 }
9916
9917 /*
9918 * Segment registers.
9919 */
9920 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9921 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9922 if (!(u32Eflags & X86_EFL_VM))
9923 {
9924 /* CS */
9925 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9926 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9927 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9928 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9929 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9930 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9931 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9932 /* CS cannot be loaded with NULL in protected mode. */
9933 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9934 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9935 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9936 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9937 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9938 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9939 else if (fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9940 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9941 else
9942 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9943
9944 /* SS */
9945 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9946 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9947 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9948 if ( !(pCtx->cr0 & X86_CR0_PE)
9949 || pCtx->cs.Attr.n.u4Type == 3)
9950 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9951
9952 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9953 {
9954 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9955 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9956 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9957 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9958 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9959 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9960 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9961 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9962 }
9963
9964 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9965 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9966 {
9967 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9968 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9969 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9970 || pCtx->ds.Attr.n.u4Type > 11
9971 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9972 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9973 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9974 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9975 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9976 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9977 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9978 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9979 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9980 }
9981 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9982 {
9983 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9984 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9985 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9986 || pCtx->es.Attr.n.u4Type > 11
9987 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9988 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9989 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9990 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9991 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9992 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9993 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9994 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9995 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9996 }
9997 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9998 {
9999 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
10000 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
10001 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10002 || pCtx->fs.Attr.n.u4Type > 11
10003 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
10004 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
10005 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
10006 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
10007 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10008 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
10009 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10010 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10011 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
10012 }
10013 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
10014 {
10015 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
10016 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
10017 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10018 || pCtx->gs.Attr.n.u4Type > 11
10019 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
10020 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
10021 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
10022 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
10023 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10024 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
10025 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10026 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10027 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
10028 }
10029 /* 64-bit capable CPUs. */
10030 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10031 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10032 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10033 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10034 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10035 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10036 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10037 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10038 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10039 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10040 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10041 }
10042 else
10043 {
10044 /* V86 mode checks. */
10045 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
10046 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
10047 {
10048 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
10049 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
10050 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
10051 }
10052 else
10053 {
10054 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
10055 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
10056 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
10057 }
10058
10059 /* CS */
10060 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10061 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10062 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10063 /* SS */
10064 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10065 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10066 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10067 /* DS */
10068 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10069 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10070 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10071 /* ES */
10072 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10073 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10074 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10075 /* FS */
10076 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10077 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10078 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10079 /* GS */
10080 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10081 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10082 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10083 /* 64-bit capable CPUs. */
10084 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10085 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10086 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10087 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10088 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10089 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10090 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10091 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10092 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10093 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10094 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10095 }
10096
10097 /*
10098 * TR.
10099 */
10100 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10101 /* 64-bit capable CPUs. */
10102 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10103 if (fLongModeGuest)
10104 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10105 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10106 else
10107 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10108 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10109 VMX_IGS_TR_ATTR_TYPE_INVALID);
10110 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10111 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10112 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10113 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10114 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10115 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10116 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10117 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10118
10119 /*
10120 * GDTR and IDTR (64-bit capable checks).
10121 */
10122 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10123 AssertRC(rc);
10124 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10125
10126 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10127 AssertRC(rc);
10128 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10129
10130 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10131 AssertRC(rc);
10132 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10133
10134 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10135 AssertRC(rc);
10136 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10137
10138 /*
10139 * Guest Non-Register State.
10140 */
10141 /* Activity State. */
10142 uint32_t u32ActivityState;
10143 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10144 AssertRC(rc);
10145 HMVMX_CHECK_BREAK( !u32ActivityState
10146 || (u32ActivityState & RT_BF_GET(g_HmMsrs.u.vmx.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10147 VMX_IGS_ACTIVITY_STATE_INVALID);
10148 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10149 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10150
10151 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10152 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10153 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10154
10155 /** @todo Activity state and injecting interrupts. Left as a todo since we
10156 * currently don't use activity states but ACTIVE. */
10157
10158 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10159 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10160
10161 /* Guest interruptibility-state. */
10162 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10163 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10164 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10165 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10166 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10167 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10168 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10169 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10170 {
10171 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10172 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10173 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10174 }
10175 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10176 {
10177 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10178 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10179 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10180 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10181 }
10182 /** @todo Assumes the processor is not in SMM. */
10183 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10184 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10185 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10186 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10187 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10188 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10189 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10190 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10191
10192 /* Pending debug exceptions. */
10193 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10194 AssertRC(rc);
10195 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10196 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10197 u32Val = u64Val; /* For pending debug exceptions checks below. */
10198
10199 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10200 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10201 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10202 {
10203 if ( (u32Eflags & X86_EFL_TF)
10204 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10205 {
10206 /* Bit 14 is PendingDebug.BS. */
10207 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10208 }
10209 if ( !(u32Eflags & X86_EFL_TF)
10210 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10211 {
10212 /* Bit 14 is PendingDebug.BS. */
10213 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10214 }
10215 }
10216
10217 /* VMCS link pointer. */
10218 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10219 AssertRC(rc);
10220 if (u64Val != UINT64_C(0xffffffffffffffff))
10221 {
10222 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10223 /** @todo Bits beyond the processor's physical-address width MBZ. */
10224 /** @todo SMM checks. */
10225 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10226 Assert(pVmcsInfo->pvShadowVmcs);
10227 VMXVMCSREVID VmcsRevId;
10228 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10229 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_ID),
10230 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10231 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10232 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10233 }
10234
10235 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10236 * not using nested paging? */
10237 if ( pVM->hmr0.s.fNestedPaging
10238 && !fLongModeGuest
10239 && CPUMIsGuestInPAEModeEx(pCtx))
10240 {
10241 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10242 AssertRC(rc);
10243 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10244
10245 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10246 AssertRC(rc);
10247 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10248
10249 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10250 AssertRC(rc);
10251 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10252
10253 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10254 AssertRC(rc);
10255 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10256 }
10257
10258 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10259 if (uError == VMX_IGS_ERROR)
10260 uError = VMX_IGS_REASON_NOT_FOUND;
10261 } while (0);
10262
10263 pVCpu->hm.s.u32HMError = uError;
10264 pVCpu->hm.s.vmx.LastError.u32GuestIntrState = u32IntrState;
10265 return uError;
10266
10267#undef HMVMX_ERROR_BREAK
10268#undef HMVMX_CHECK_BREAK
10269}
10270
10271
10272/**
10273 * Map the APIC-access page for virtualizing APIC accesses.
10274 *
10275 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10276 * this not done as part of exporting guest state, see @bugref{8721}.
10277 *
10278 * @returns VBox status code.
10279 * @param pVCpu The cross context virtual CPU structure.
10280 */
10281static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
10282{
10283 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10284 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10285
10286 Assert(PDMHasApic(pVM));
10287 Assert(u64MsrApicBase);
10288
10289 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10290 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10291
10292 /* Unalias the existing mapping. */
10293 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10294 AssertRCReturn(rc, rc);
10295
10296 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10297 Assert(pVM->hmr0.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10298 rc = IOMR0MmioMapMmioHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hmr0.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10299 AssertRCReturn(rc, rc);
10300
10301 /* Update the per-VCPU cache of the APIC base MSR. */
10302 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10303 return VINF_SUCCESS;
10304}
10305
10306
10307/**
10308 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10309 * CPU.
10310 *
10311 * @param idCpu The ID for the CPU the function is called on.
10312 * @param pvUser1 Null, not used.
10313 * @param pvUser2 Null, not used.
10314 */
10315static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10316{
10317 RT_NOREF3(idCpu, pvUser1, pvUser2);
10318 VMXDispatchHostNmi();
10319}
10320
10321
10322/**
10323 * Dispatching an NMI on the host CPU that received it.
10324 *
10325 * @returns VBox status code.
10326 * @param pVCpu The cross context virtual CPU structure.
10327 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10328 * executing when receiving the host NMI in VMX non-root
10329 * operation.
10330 */
10331static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
10332{
10333 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
10334 Assert(idCpu != NIL_RTCPUID);
10335
10336 /*
10337 * We don't want to delay dispatching the NMI any more than we have to. However,
10338 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10339 * after executing guest or nested-guest code for the following reasons:
10340 *
10341 * - We would need to perform VMREADs with interrupts disabled and is orders of
10342 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
10343 * supported by the host hypervisor.
10344 *
10345 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10346 * longer period of time just for handling an edge case like host NMIs which do
10347 * not occur nearly as frequently as other VM-exits.
10348 *
10349 * Let's cover the most likely scenario first. Check if we are on the target CPU
10350 * and dispatch the NMI right away. This should be much faster than calling into
10351 * RTMpOnSpecific() machinery.
10352 */
10353 bool fDispatched = false;
10354 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10355 if (idCpu == RTMpCpuId())
10356 {
10357 VMXDispatchHostNmi();
10358 fDispatched = true;
10359 }
10360 ASMSetFlags(fEFlags);
10361 if (fDispatched)
10362 {
10363 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10364 return VINF_SUCCESS;
10365 }
10366
10367 /*
10368 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10369 * there should be no race or recursion even if we are unlucky enough to be preempted
10370 * (to the target CPU) without dispatching the host NMI above.
10371 */
10372 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10373 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10374}
10375
10376
10377#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10378/**
10379 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10380 * nested-guest using hardware-assisted VMX.
10381 *
10382 * @param pVCpu The cross context virtual CPU structure.
10383 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10384 * @param pVmcsInfoGst The guest VMCS info. object.
10385 */
10386static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10387{
10388 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10389 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10390 Assert(pu64MsrBitmap);
10391
10392 /*
10393 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10394 * MSR that is intercepted by the guest is also intercepted while executing the
10395 * nested-guest using hardware-assisted VMX.
10396 *
10397 * Note! If the nested-guest is not using an MSR bitmap, every MSR must cause a
10398 * nested-guest VM-exit even if the outer guest is not intercepting some
10399 * MSRs. We cannot assume the caller has initialized the nested-guest
10400 * MSR bitmap in this case.
10401 *
10402 * The nested hypervisor may also switch whether it uses MSR bitmaps for
10403 * each of its VM-entry, hence initializing it once per-VM while setting
10404 * up the nested-guest VMCS is not sufficient.
10405 */
10406 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10407 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10408 {
10409 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10410 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10411 Assert(pu64MsrBitmapNstGst);
10412 Assert(pu64MsrBitmapGst);
10413
10414 /** @todo Detect and use EVEX.POR? */
10415 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10416 for (uint32_t i = 0; i < cFrags; i++)
10417 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10418 }
10419 else
10420 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10421}
10422
10423
10424/**
10425 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10426 * hardware-assisted VMX execution of the nested-guest.
10427 *
10428 * For a guest, we don't modify these controls once we set up the VMCS and hence
10429 * this function is never called.
10430 *
10431 * For nested-guests since the nested hypervisor provides these controls on every
10432 * nested-guest VM-entry and could potentially change them everytime we need to
10433 * merge them before every nested-guest VM-entry.
10434 *
10435 * @returns VBox status code.
10436 * @param pVCpu The cross context virtual CPU structure.
10437 */
10438static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
10439{
10440 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10441 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
10442 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10443 Assert(pVmcsNstGst);
10444
10445 /*
10446 * Merge the controls with the requirements of the guest VMCS.
10447 *
10448 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10449 * VMCS with the features supported by the physical CPU as it's already done by the
10450 * VMLAUNCH/VMRESUME instruction emulation.
10451 *
10452 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10453 * derived from the VMX features supported by the physical CPU.
10454 */
10455
10456 /* Pin-based VM-execution controls. */
10457 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10458
10459 /* Processor-based VM-execution controls. */
10460 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10461 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10462 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10463 | VMX_PROC_CTLS_MOV_DR_EXIT
10464 | VMX_PROC_CTLS_USE_TPR_SHADOW
10465 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10466
10467 /* Secondary processor-based VM-execution controls. */
10468 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10469 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10470 | VMX_PROC_CTLS2_INVPCID
10471 | VMX_PROC_CTLS2_VMCS_SHADOWING
10472 | VMX_PROC_CTLS2_RDTSCP
10473 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10474 | VMX_PROC_CTLS2_APIC_REG_VIRT
10475 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10476 | VMX_PROC_CTLS2_VMFUNC));
10477
10478 /*
10479 * VM-entry controls:
10480 * These controls contains state that depends on the nested-guest state (primarily
10481 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10482 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
10483 * properly continue executing the nested-guest if the EFER MSR changes but does not
10484 * cause a nested-guest VM-exits.
10485 *
10486 * VM-exit controls:
10487 * These controls specify the host state on return. We cannot use the controls from
10488 * the nested hypervisor state as is as it would contain the guest state rather than
10489 * the host state. Since the host state is subject to change (e.g. preemption, trips
10490 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10491 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10492 *
10493 * VM-entry MSR-load:
10494 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10495 * context by the VMLAUNCH/VMRESUME instruction emulation.
10496 *
10497 * VM-exit MSR-store:
10498 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10499 * back into the VM-exit MSR-store area.
10500 *
10501 * VM-exit MSR-load areas:
10502 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10503 * can entirely ignore what the nested hypervisor wants to load here.
10504 */
10505
10506 /*
10507 * Exception bitmap.
10508 *
10509 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10510 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10511 * code more flexible if intercepting exceptions become more dynamic in the future we do
10512 * it as part of exporting the nested-guest state.
10513 */
10514 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10515
10516 /*
10517 * CR0/CR4 guest/host mask.
10518 *
10519 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10520 * cause VM-exits, so we need to merge them here.
10521 */
10522 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10523 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10524
10525 /*
10526 * Page-fault error-code mask and match.
10527 *
10528 * Although we require unrestricted guest execution (and thereby nested-paging) for
10529 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10530 * normally intercept #PFs, it might intercept them for debugging purposes.
10531 *
10532 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10533 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10534 */
10535 uint32_t u32XcptPFMask;
10536 uint32_t u32XcptPFMatch;
10537 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10538 {
10539 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10540 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10541 }
10542 else
10543 {
10544 u32XcptPFMask = 0;
10545 u32XcptPFMatch = 0;
10546 }
10547
10548 /*
10549 * Pause-Loop exiting.
10550 */
10551 /** @todo r=bird: given that both pVM->hm.s.vmx.cPleGapTicks and
10552 * pVM->hm.s.vmx.cPleWindowTicks defaults to zero, I cannot see how
10553 * this will work... */
10554 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10555 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10556
10557 /*
10558 * Pending debug exceptions.
10559 * Currently just copy whatever the nested-guest provides us.
10560 */
10561 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10562
10563 /*
10564 * I/O Bitmap.
10565 *
10566 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10567 * intercept all I/O port accesses.
10568 */
10569 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10570 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10571
10572 /*
10573 * VMCS shadowing.
10574 *
10575 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10576 * enabled while executing the nested-guest.
10577 */
10578 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10579
10580 /*
10581 * APIC-access page.
10582 */
10583 RTHCPHYS HCPhysApicAccess;
10584 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10585 {
10586 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10587 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10588
10589 /** @todo NSTVMX: This is not really correct but currently is required to make
10590 * things work. We need to re-enable the page handler when we fallback to
10591 * IEM execution of the nested-guest! */
10592 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10593
10594 void *pvPage;
10595 PGMPAGEMAPLOCK PgLockApicAccess;
10596 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10597 if (RT_SUCCESS(rc))
10598 {
10599 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10600 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10601
10602 /** @todo Handle proper releasing of page-mapping lock later. */
10603 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10604 }
10605 else
10606 return rc;
10607 }
10608 else
10609 HCPhysApicAccess = 0;
10610
10611 /*
10612 * Virtual-APIC page and TPR threshold.
10613 */
10614 RTHCPHYS HCPhysVirtApic;
10615 uint32_t u32TprThreshold;
10616 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10617 {
10618 Assert(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10619 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10620
10621 void *pvPage;
10622 PGMPAGEMAPLOCK PgLockVirtApic;
10623 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10624 if (RT_SUCCESS(rc))
10625 {
10626 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10627 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10628
10629 /** @todo Handle proper releasing of page-mapping lock later. */
10630 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10631 }
10632 else
10633 return rc;
10634
10635 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10636 }
10637 else
10638 {
10639 HCPhysVirtApic = 0;
10640 u32TprThreshold = 0;
10641
10642 /*
10643 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10644 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10645 * be taken care of by EPT/shadow paging.
10646 */
10647 if (pVM->hmr0.s.fAllow64BitGuests)
10648 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10649 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10650 }
10651
10652 /*
10653 * Validate basic assumptions.
10654 */
10655 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
10656 Assert(pVM->hmr0.s.vmx.fUnrestrictedGuest);
10657 Assert(g_HmMsrs.u.vmx.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10658 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10659
10660 /*
10661 * Commit it to the nested-guest VMCS.
10662 */
10663 int rc = VINF_SUCCESS;
10664 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10665 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10666 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10667 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10668 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10669 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10670 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10671 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10672 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10673 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10674 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10675 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10676 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10677 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10678 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10679 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10680 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10681 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10682 {
10683 Assert(g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10684 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10685 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10686 }
10687 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10688 {
10689 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10690 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10691 }
10692 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10693 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10694 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10695 AssertRC(rc);
10696
10697 /*
10698 * Update the nested-guest VMCS cache.
10699 */
10700 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10701 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10702 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10703 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10704 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10705 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10706 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10707 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10708 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10709
10710 /*
10711 * We need to flush the TLB if we are switching the APIC-access page address.
10712 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10713 */
10714 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10715 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10716
10717 /*
10718 * MSR bitmap.
10719 *
10720 * The MSR bitmap address has already been initialized while setting up the nested-guest
10721 * VMCS, here we need to merge the MSR bitmaps.
10722 */
10723 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10724 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10725
10726 return VINF_SUCCESS;
10727}
10728#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10729
10730
10731/**
10732 * Does the preparations before executing guest code in VT-x.
10733 *
10734 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10735 * recompiler/IEM. We must be cautious what we do here regarding committing
10736 * guest-state information into the VMCS assuming we assuredly execute the
10737 * guest in VT-x mode.
10738 *
10739 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10740 * the common-state (TRPM/forceflags), we must undo those changes so that the
10741 * recompiler/IEM can (and should) use them when it resumes guest execution.
10742 * Otherwise such operations must be done when we can no longer exit to ring-3.
10743 *
10744 * @returns Strict VBox status code (i.e. informational status codes too).
10745 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10746 * have been disabled.
10747 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10748 * pending events).
10749 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10750 * double-fault into the guest.
10751 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10752 * dispatched directly.
10753 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10754 *
10755 * @param pVCpu The cross context virtual CPU structure.
10756 * @param pVmxTransient The VMX-transient structure.
10757 * @param fStepping Whether we are single-stepping the guest in the
10758 * hypervisor debugger. Makes us ignore some of the reasons
10759 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10760 * if event dispatching took place.
10761 */
10762static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10763{
10764 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10765
10766 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10767
10768#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10769 if (pVmxTransient->fIsNestedGuest)
10770 {
10771 RT_NOREF2(pVCpu, fStepping);
10772 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10773 return VINF_EM_RESCHEDULE_REM;
10774 }
10775#endif
10776
10777 /*
10778 * Check and process force flag actions, some of which might require us to go back to ring-3.
10779 */
10780 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, pVmxTransient, fStepping);
10781 if (rcStrict == VINF_SUCCESS)
10782 {
10783 /* FFs don't get set all the time. */
10784#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10785 if ( pVmxTransient->fIsNestedGuest
10786 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10787 {
10788 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10789 return VINF_VMX_VMEXIT;
10790 }
10791#endif
10792 }
10793 else
10794 return rcStrict;
10795
10796 /*
10797 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10798 */
10799 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10800 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10801 && (g_HmMsrs.u.vmx.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10802 && PDMHasApic(pVM))
10803 {
10804 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10805 AssertRCReturn(rc, rc);
10806 }
10807
10808#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10809 /*
10810 * Merge guest VMCS controls with the nested-guest VMCS controls.
10811 *
10812 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10813 * saved state), we should be okay with merging controls as we initialize the
10814 * guest VMCS controls as part of VM setup phase.
10815 */
10816 if ( pVmxTransient->fIsNestedGuest
10817 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10818 {
10819 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10820 AssertRCReturn(rc, rc);
10821 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10822 }
10823#endif
10824
10825 /*
10826 * Evaluate events to be injected into the guest.
10827 *
10828 * Events in TRPM can be injected without inspecting the guest state.
10829 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10830 * guest to cause a VM-exit the next time they are ready to receive the event.
10831 *
10832 * For nested-guests, verify that the TRPM event that we're about to inject using
10833 * hardware-assisted VMX is -not- subject to nested-hypervisor interception.
10834 * Otherwise, we should have checked and injected them manually elsewhere (IEM).
10835 */
10836 if (TRPMHasTrap(pVCpu))
10837 {
10838 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10839 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10840 }
10841
10842 uint32_t fIntrState;
10843 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10844
10845#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10846 /*
10847 * While evaluating pending events if something failed (unlikely) or if we were
10848 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10849 */
10850 if (rcStrict != VINF_SUCCESS)
10851 return rcStrict;
10852 if ( pVmxTransient->fIsNestedGuest
10853 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10854 {
10855 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10856 return VINF_VMX_VMEXIT;
10857 }
10858#else
10859 Assert(rcStrict == VINF_SUCCESS);
10860#endif
10861
10862 /*
10863 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10864 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10865 * also result in triple-faulting the VM.
10866 *
10867 * With nested-guests, the above does not apply since unrestricted guest execution is a
10868 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10869 */
10870 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10871 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10872 { /* likely */ }
10873 else
10874 {
10875 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10876 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10877 return rcStrict;
10878 }
10879
10880 /*
10881 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10882 * import CR3 themselves. We will need to update them here, as even as late as the above
10883 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10884 * the below force flags to be set.
10885 */
10886 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10887 {
10888 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10889 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10890 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10891 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10892 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10893 }
10894 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10895 {
10896 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10897 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10898 }
10899
10900#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10901 /* Paranoia. */
10902 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10903#endif
10904
10905 /*
10906 * No longjmps to ring-3 from this point on!!!
10907 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10908 * This also disables flushing of the R0-logger instance (if any).
10909 */
10910 VMMRZCallRing3Disable(pVCpu);
10911
10912 /*
10913 * Export the guest state bits.
10914 *
10915 * We cannot perform longjmps while loading the guest state because we do not preserve the
10916 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10917 * CPU migration.
10918 *
10919 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10920 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10921 */
10922 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10923 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10924 { /* likely */ }
10925 else
10926 {
10927 VMMRZCallRing3Enable(pVCpu);
10928 return rcStrict;
10929 }
10930
10931 /*
10932 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10933 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10934 * preemption disabled for a while. Since this is purely to aid the
10935 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10936 * disable interrupt on NT.
10937 *
10938 * We need to check for force-flags that could've possible been altered since we last
10939 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10940 * see @bugref{6398}).
10941 *
10942 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10943 * to ring-3 before executing guest code.
10944 */
10945 pVmxTransient->fEFlags = ASMIntDisableFlags();
10946
10947 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10948 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10949 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10950 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10951 {
10952 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10953 {
10954#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10955 /*
10956 * If we are executing a nested-guest make sure that we should intercept subsequent
10957 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10958 * the VM-exit instruction emulation happy.
10959 */
10960 if (pVmxTransient->fIsNestedGuest)
10961 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10962#endif
10963
10964 /*
10965 * We've injected any pending events. This is really the point of no return (to ring-3).
10966 *
10967 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10968 * returns from this function, so do -not- enable them here.
10969 */
10970 pVCpu->hm.s.Event.fPending = false;
10971 return VINF_SUCCESS;
10972 }
10973
10974 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10975 rcStrict = VINF_EM_RAW_INTERRUPT;
10976 }
10977 else
10978 {
10979 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10980 rcStrict = VINF_EM_RAW_TO_R3;
10981 }
10982
10983 ASMSetFlags(pVmxTransient->fEFlags);
10984 VMMRZCallRing3Enable(pVCpu);
10985
10986 return rcStrict;
10987}
10988
10989
10990/**
10991 * Final preparations before executing guest code using hardware-assisted VMX.
10992 *
10993 * We can no longer get preempted to a different host CPU and there are no returns
10994 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10995 * failures), this function is not intended to fail sans unrecoverable hardware
10996 * errors.
10997 *
10998 * @param pVCpu The cross context virtual CPU structure.
10999 * @param pVmxTransient The VMX-transient structure.
11000 *
11001 * @remarks Called with preemption disabled.
11002 * @remarks No-long-jump zone!!!
11003 */
11004static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
11005{
11006 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11007 Assert(VMMR0IsLogFlushDisabled(pVCpu));
11008 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
11009 Assert(!pVCpu->hm.s.Event.fPending);
11010
11011 /*
11012 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
11013 */
11014 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11015 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
11016
11017 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11018 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11019 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
11020 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
11021
11022 if (!CPUMIsGuestFPUStateActive(pVCpu))
11023 {
11024 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11025 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
11026 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
11027 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11028 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
11029 }
11030
11031 /*
11032 * Re-export the host state bits as we may've been preempted (only happens when
11033 * thread-context hooks are used or when the VM start function changes) or if
11034 * the host CR0 is modified while loading the guest FPU state above.
11035 *
11036 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
11037 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
11038 * see @bugref{8432}.
11039 *
11040 * This may also happen when switching to/from a nested-guest VMCS without leaving
11041 * ring-0.
11042 */
11043 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
11044 {
11045 hmR0VmxExportHostState(pVCpu);
11046 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
11047 }
11048 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
11049
11050 /*
11051 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
11052 */
11053 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
11054 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
11055 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
11056
11057 /*
11058 * Store status of the shared guest/host debug state at the time of VM-entry.
11059 */
11060 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
11061 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11062
11063 /*
11064 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11065 * more than one conditional check. The post-run side of our code shall determine
11066 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11067 */
11068 if (pVmcsInfo->pbVirtApic)
11069 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11070
11071 /*
11072 * Update the host MSRs values in the VM-exit MSR-load area.
11073 */
11074 if (!pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs)
11075 {
11076 if (pVmcsInfo->cExitMsrLoad > 0)
11077 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11078 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = true;
11079 }
11080
11081 /*
11082 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11083 * VMX-preemption timer based on the next virtual sync clock deadline.
11084 */
11085 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11086 || idCurrentCpu != pVCpu->hmr0.s.idLastCpu)
11087 {
11088 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient, idCurrentCpu);
11089 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11090 }
11091
11092 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11093 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11094 if (!fIsRdtscIntercepted)
11095 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11096 else
11097 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11098
11099 ASMAtomicUoWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11100 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11101 Assert(idCurrentCpu == pVCpu->hmr0.s.idLastCpu);
11102 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
11103 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
11104 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
11105
11106 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11107
11108 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11109 as we're about to start executing the guest. */
11110
11111 /*
11112 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11113 *
11114 * This is done this late as updating the TSC offsetting/preemption timer above
11115 * figures out if we can skip intercepting RDTSCP by calculating the number of
11116 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11117 */
11118 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11119 && !fIsRdtscIntercepted)
11120 {
11121 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11122
11123 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11124 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11125 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11126 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11127 AssertRC(rc);
11128 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11129 pVmxTransient->fRemoveTscAuxMsr = true;
11130 }
11131
11132#ifdef VBOX_STRICT
11133 Assert(pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs);
11134 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11135 hmR0VmxCheckHostEferMsr(pVmcsInfo);
11136 AssertRC(hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11137#endif
11138
11139#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11140 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11141 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11142 * see @bugref{9180#c54}. */
11143 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11144 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11145 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11146#endif
11147}
11148
11149
11150/**
11151 * First C routine invoked after running guest code using hardware-assisted VMX.
11152 *
11153 * @param pVCpu The cross context virtual CPU structure.
11154 * @param pVmxTransient The VMX-transient structure.
11155 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11156 *
11157 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11158 *
11159 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11160 * unconditionally when it is safe to do so.
11161 */
11162static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11163{
11164 ASMAtomicUoWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11165 ASMAtomicIncU32(&pVCpu->hmr0.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11166 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11167 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11168 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11169 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11170
11171 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11172 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11173 {
11174 uint64_t uGstTsc;
11175 if (!pVmxTransient->fIsNestedGuest)
11176 uGstTsc = pVCpu->hmr0.s.uTscExit + pVmcsInfo->u64TscOffset;
11177 else
11178 {
11179 uint64_t const uNstGstTsc = pVCpu->hmr0.s.uTscExit + pVmcsInfo->u64TscOffset;
11180 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11181 }
11182 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11183 }
11184
11185 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11186 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu, pVCpu->hmr0.s.uTscExit); /* Notify TM that the guest is no longer running. */
11187 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11188
11189 pVCpu->hmr0.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11190 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11191#ifdef VBOX_STRICT
11192 hmR0VmxCheckHostEferMsr(pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11193#endif
11194 Assert(!ASMIntAreEnabled());
11195 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11196 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11197
11198#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11199 /*
11200 * Clean all the VMCS fields in the transient structure before reading
11201 * anything from the VMCS.
11202 */
11203 pVmxTransient->uExitReason = 0;
11204 pVmxTransient->uExitIntErrorCode = 0;
11205 pVmxTransient->uExitQual = 0;
11206 pVmxTransient->uGuestLinearAddr = 0;
11207 pVmxTransient->uExitIntInfo = 0;
11208 pVmxTransient->cbExitInstr = 0;
11209 pVmxTransient->ExitInstrInfo.u = 0;
11210 pVmxTransient->uEntryIntInfo = 0;
11211 pVmxTransient->uEntryXcptErrorCode = 0;
11212 pVmxTransient->cbEntryInstr = 0;
11213 pVmxTransient->uIdtVectoringInfo = 0;
11214 pVmxTransient->uIdtVectoringErrorCode = 0;
11215#endif
11216
11217 /*
11218 * Save the basic VM-exit reason and check if the VM-entry failed.
11219 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11220 */
11221 uint32_t uExitReason;
11222 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11223 AssertRC(rc);
11224 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11225 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11226
11227 /*
11228 * Log the VM-exit before logging anything else as otherwise it might be a
11229 * tad confusing what happens before and after the world-switch.
11230 */
11231 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11232
11233 /*
11234 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11235 * bitmap permissions, if it was added before VM-entry.
11236 */
11237 if (pVmxTransient->fRemoveTscAuxMsr)
11238 {
11239 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11240 pVmxTransient->fRemoveTscAuxMsr = false;
11241 }
11242
11243 /*
11244 * Check if VMLAUNCH/VMRESUME succeeded.
11245 * If this failed, we cause a guru meditation and cease further execution.
11246 *
11247 * However, if we are executing a nested-guest we might fail if we use the
11248 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11249 */
11250 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11251 {
11252 /*
11253 * Update the VM-exit history array here even if the VM-entry failed due to:
11254 * - Invalid guest state.
11255 * - MSR loading.
11256 * - Machine-check event.
11257 *
11258 * In any of the above cases we will still have a "valid" VM-exit reason
11259 * despite @a fVMEntryFailed being false.
11260 *
11261 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11262 *
11263 * Note! We don't have CS or RIP at this point. Will probably address that later
11264 * by amending the history entry added here.
11265 */
11266 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11267 UINT64_MAX, pVCpu->hmr0.s.uTscExit);
11268
11269 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11270 {
11271 VMMRZCallRing3Enable(pVCpu);
11272
11273 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11274 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11275
11276#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
11277 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
11278#endif
11279
11280 /*
11281 * Import the guest-interruptibility state always as we need it while evaluating
11282 * injecting events on re-entry.
11283 *
11284 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11285 * checking for real-mode while exporting the state because all bits that cause
11286 * mode changes wrt CR0 are intercepted.
11287 */
11288 uint64_t const fImportMask = CPUMCTX_EXTRN_HM_VMX_INT_STATE
11289#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11290 | HMVMX_CPUMCTX_EXTRN_ALL
11291#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11292 | CPUMCTX_EXTRN_RFLAGS
11293#endif
11294 ;
11295 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImportMask);
11296 AssertRC(rc);
11297
11298 /*
11299 * Sync the TPR shadow with our APIC state.
11300 */
11301 if ( !pVmxTransient->fIsNestedGuest
11302 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
11303 {
11304 Assert(pVmcsInfo->pbVirtApic);
11305 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11306 {
11307 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11308 AssertRC(rc);
11309 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11310 }
11311 }
11312
11313 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11314 Assert( pVmxTransient->fWasGuestDebugStateActive == false
11315 || pVmxTransient->fWasHyperDebugStateActive == false);
11316 return;
11317 }
11318 }
11319#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11320 else if (pVmxTransient->fIsNestedGuest)
11321 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11322#endif
11323 else
11324 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11325
11326 VMMRZCallRing3Enable(pVCpu);
11327}
11328
11329
11330/**
11331 * Runs the guest code using hardware-assisted VMX the normal way.
11332 *
11333 * @returns VBox status code.
11334 * @param pVCpu The cross context virtual CPU structure.
11335 * @param pcLoops Pointer to the number of executed loops.
11336 */
11337static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
11338{
11339 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
11340 Assert(pcLoops);
11341 Assert(*pcLoops <= cMaxResumeLoops);
11342 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11343
11344#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11345 /*
11346 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11347 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11348 * guest VMCS while entering the VMX ring-0 session.
11349 */
11350 if (pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
11351 {
11352 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11353 if (RT_SUCCESS(rc))
11354 { /* likely */ }
11355 else
11356 {
11357 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11358 return rc;
11359 }
11360 }
11361#endif
11362
11363 VMXTRANSIENT VmxTransient;
11364 RT_ZERO(VmxTransient);
11365 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11366
11367 /* Paranoia. */
11368 Assert(VmxTransient.pVmcsInfo == &pVCpu->hmr0.s.vmx.VmcsInfo);
11369
11370 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11371 for (;;)
11372 {
11373 Assert(!HMR0SuspendPending());
11374 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11375 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11376
11377 /*
11378 * Preparatory work for running nested-guest code, this may force us to
11379 * return to ring-3.
11380 *
11381 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11382 */
11383 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11384 if (rcStrict != VINF_SUCCESS)
11385 break;
11386
11387 /* Interrupts are disabled at this point! */
11388 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11389 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11390 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11391 /* Interrupts are re-enabled at this point! */
11392
11393 /*
11394 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11395 */
11396 if (RT_SUCCESS(rcRun))
11397 { /* very likely */ }
11398 else
11399 {
11400 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11401 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11402 return rcRun;
11403 }
11404
11405 /*
11406 * Profile the VM-exit.
11407 */
11408 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11409 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11410 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11411 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11412 HMVMX_START_EXIT_DISPATCH_PROF();
11413
11414 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11415
11416 /*
11417 * Handle the VM-exit.
11418 */
11419#ifdef HMVMX_USE_FUNCTION_TABLE
11420 rcStrict = g_aVMExitHandlers[VmxTransient.uExitReason].pfn(pVCpu, &VmxTransient);
11421#else
11422 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11423#endif
11424 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11425 if (rcStrict == VINF_SUCCESS)
11426 {
11427 if (++(*pcLoops) <= cMaxResumeLoops)
11428 continue;
11429 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11430 rcStrict = VINF_EM_RAW_INTERRUPT;
11431 }
11432 break;
11433 }
11434
11435 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11436 return rcStrict;
11437}
11438
11439
11440#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11441/**
11442 * Runs the nested-guest code using hardware-assisted VMX.
11443 *
11444 * @returns VBox status code.
11445 * @param pVCpu The cross context virtual CPU structure.
11446 * @param pcLoops Pointer to the number of executed loops.
11447 *
11448 * @sa hmR0VmxRunGuestCodeNormal.
11449 */
11450static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
11451{
11452 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
11453 Assert(pcLoops);
11454 Assert(*pcLoops <= cMaxResumeLoops);
11455 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11456
11457 /*
11458 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11459 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11460 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11461 */
11462 if (!pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
11463 {
11464 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11465 if (RT_SUCCESS(rc))
11466 { /* likely */ }
11467 else
11468 {
11469 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11470 return rc;
11471 }
11472 }
11473
11474 VMXTRANSIENT VmxTransient;
11475 RT_ZERO(VmxTransient);
11476 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11477 VmxTransient.fIsNestedGuest = true;
11478
11479 /* Paranoia. */
11480 Assert(VmxTransient.pVmcsInfo == &pVCpu->hmr0.s.vmx.VmcsInfoNstGst);
11481
11482 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11483 for (;;)
11484 {
11485 Assert(!HMR0SuspendPending());
11486 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11487 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11488
11489 /*
11490 * Preparatory work for running guest code, this may force us to
11491 * return to ring-3.
11492 *
11493 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11494 */
11495 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11496 if (rcStrict != VINF_SUCCESS)
11497 break;
11498
11499 /* Interrupts are disabled at this point! */
11500 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11501 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11502 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11503 /* Interrupts are re-enabled at this point! */
11504
11505 /*
11506 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11507 */
11508 if (RT_SUCCESS(rcRun))
11509 { /* very likely */ }
11510 else
11511 {
11512 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11513 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11514 return rcRun;
11515 }
11516
11517 /*
11518 * Profile the VM-exit.
11519 */
11520 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11521 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11522 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11523 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11524 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11525 HMVMX_START_EXIT_DISPATCH_PROF();
11526
11527 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11528
11529 /*
11530 * Handle the VM-exit.
11531 */
11532 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11533 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11534 if (rcStrict == VINF_SUCCESS)
11535 {
11536 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11537 {
11538 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11539 rcStrict = VINF_VMX_VMEXIT;
11540 }
11541 else
11542 {
11543 if (++(*pcLoops) <= cMaxResumeLoops)
11544 continue;
11545 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11546 rcStrict = VINF_EM_RAW_INTERRUPT;
11547 }
11548 }
11549 else
11550 Assert(rcStrict != VINF_VMX_VMEXIT);
11551 break;
11552 }
11553
11554 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11555 return rcStrict;
11556}
11557#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11558
11559
11560/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11561 * probes.
11562 *
11563 * The following few functions and associated structure contains the bloat
11564 * necessary for providing detailed debug events and dtrace probes as well as
11565 * reliable host side single stepping. This works on the principle of
11566 * "subclassing" the normal execution loop and workers. We replace the loop
11567 * method completely and override selected helpers to add necessary adjustments
11568 * to their core operation.
11569 *
11570 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11571 * any performance for debug and analysis features.
11572 *
11573 * @{
11574 */
11575
11576/**
11577 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11578 * the debug run loop.
11579 */
11580typedef struct VMXRUNDBGSTATE
11581{
11582 /** The RIP we started executing at. This is for detecting that we stepped. */
11583 uint64_t uRipStart;
11584 /** The CS we started executing with. */
11585 uint16_t uCsStart;
11586
11587 /** Whether we've actually modified the 1st execution control field. */
11588 bool fModifiedProcCtls : 1;
11589 /** Whether we've actually modified the 2nd execution control field. */
11590 bool fModifiedProcCtls2 : 1;
11591 /** Whether we've actually modified the exception bitmap. */
11592 bool fModifiedXcptBitmap : 1;
11593
11594 /** We desire the modified the CR0 mask to be cleared. */
11595 bool fClearCr0Mask : 1;
11596 /** We desire the modified the CR4 mask to be cleared. */
11597 bool fClearCr4Mask : 1;
11598 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11599 uint32_t fCpe1Extra;
11600 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11601 uint32_t fCpe1Unwanted;
11602 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11603 uint32_t fCpe2Extra;
11604 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11605 uint32_t bmXcptExtra;
11606 /** The sequence number of the Dtrace provider settings the state was
11607 * configured against. */
11608 uint32_t uDtraceSettingsSeqNo;
11609 /** VM-exits to check (one bit per VM-exit). */
11610 uint32_t bmExitsToCheck[3];
11611
11612 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11613 uint32_t fProcCtlsInitial;
11614 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11615 uint32_t fProcCtls2Initial;
11616 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11617 uint32_t bmXcptInitial;
11618} VMXRUNDBGSTATE;
11619AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11620typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11621
11622
11623/**
11624 * Initializes the VMXRUNDBGSTATE structure.
11625 *
11626 * @param pVCpu The cross context virtual CPU structure of the
11627 * calling EMT.
11628 * @param pVmxTransient The VMX-transient structure.
11629 * @param pDbgState The debug state to initialize.
11630 */
11631static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11632{
11633 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11634 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11635
11636 pDbgState->fModifiedProcCtls = false;
11637 pDbgState->fModifiedProcCtls2 = false;
11638 pDbgState->fModifiedXcptBitmap = false;
11639 pDbgState->fClearCr0Mask = false;
11640 pDbgState->fClearCr4Mask = false;
11641 pDbgState->fCpe1Extra = 0;
11642 pDbgState->fCpe1Unwanted = 0;
11643 pDbgState->fCpe2Extra = 0;
11644 pDbgState->bmXcptExtra = 0;
11645 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11646 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11647 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11648}
11649
11650
11651/**
11652 * Updates the VMSC fields with changes requested by @a pDbgState.
11653 *
11654 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11655 * immediately before executing guest code, i.e. when interrupts are disabled.
11656 * We don't check status codes here as we cannot easily assert or return in the
11657 * latter case.
11658 *
11659 * @param pVCpu The cross context virtual CPU structure.
11660 * @param pVmxTransient The VMX-transient structure.
11661 * @param pDbgState The debug state.
11662 */
11663static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11664{
11665 /*
11666 * Ensure desired flags in VMCS control fields are set.
11667 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11668 *
11669 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11670 * there should be no stale data in pCtx at this point.
11671 */
11672 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11673 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11674 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11675 {
11676 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11677 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11678 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11679 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11680 pDbgState->fModifiedProcCtls = true;
11681 }
11682
11683 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11684 {
11685 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11686 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11687 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11688 pDbgState->fModifiedProcCtls2 = true;
11689 }
11690
11691 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11692 {
11693 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11694 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11695 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11696 pDbgState->fModifiedXcptBitmap = true;
11697 }
11698
11699 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11700 {
11701 pVmcsInfo->u64Cr0Mask = 0;
11702 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11703 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11704 }
11705
11706 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11707 {
11708 pVmcsInfo->u64Cr4Mask = 0;
11709 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11710 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11711 }
11712
11713 NOREF(pVCpu);
11714}
11715
11716
11717/**
11718 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11719 * re-entry next time around.
11720 *
11721 * @returns Strict VBox status code (i.e. informational status codes too).
11722 * @param pVCpu The cross context virtual CPU structure.
11723 * @param pVmxTransient The VMX-transient structure.
11724 * @param pDbgState The debug state.
11725 * @param rcStrict The return code from executing the guest using single
11726 * stepping.
11727 */
11728static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11729 VBOXSTRICTRC rcStrict)
11730{
11731 /*
11732 * Restore VM-exit control settings as we may not reenter this function the
11733 * next time around.
11734 */
11735 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11736
11737 /* We reload the initial value, trigger what we can of recalculations the
11738 next time around. From the looks of things, that's all that's required atm. */
11739 if (pDbgState->fModifiedProcCtls)
11740 {
11741 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11742 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11743 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11744 AssertRC(rc2);
11745 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11746 }
11747
11748 /* We're currently the only ones messing with this one, so just restore the
11749 cached value and reload the field. */
11750 if ( pDbgState->fModifiedProcCtls2
11751 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11752 {
11753 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11754 AssertRC(rc2);
11755 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11756 }
11757
11758 /* If we've modified the exception bitmap, we restore it and trigger
11759 reloading and partial recalculation the next time around. */
11760 if (pDbgState->fModifiedXcptBitmap)
11761 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11762
11763 return rcStrict;
11764}
11765
11766
11767/**
11768 * Configures VM-exit controls for current DBGF and DTrace settings.
11769 *
11770 * This updates @a pDbgState and the VMCS execution control fields to reflect
11771 * the necessary VM-exits demanded by DBGF and DTrace.
11772 *
11773 * @param pVCpu The cross context virtual CPU structure.
11774 * @param pVmxTransient The VMX-transient structure. May update
11775 * fUpdatedTscOffsettingAndPreemptTimer.
11776 * @param pDbgState The debug state.
11777 */
11778static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11779{
11780 /*
11781 * Take down the dtrace serial number so we can spot changes.
11782 */
11783 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11784 ASMCompilerBarrier();
11785
11786 /*
11787 * We'll rebuild most of the middle block of data members (holding the
11788 * current settings) as we go along here, so start by clearing it all.
11789 */
11790 pDbgState->bmXcptExtra = 0;
11791 pDbgState->fCpe1Extra = 0;
11792 pDbgState->fCpe1Unwanted = 0;
11793 pDbgState->fCpe2Extra = 0;
11794 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11795 pDbgState->bmExitsToCheck[i] = 0;
11796
11797 /*
11798 * Software interrupts (INT XXh) - no idea how to trigger these...
11799 */
11800 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11801 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11802 || VBOXVMM_INT_SOFTWARE_ENABLED())
11803 {
11804 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11805 }
11806
11807 /*
11808 * INT3 breakpoints - triggered by #BP exceptions.
11809 */
11810 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11811 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11812
11813 /*
11814 * Exception bitmap and XCPT events+probes.
11815 */
11816 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11817 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11818 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11819
11820 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11821 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11822 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11823 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11824 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11825 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11826 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11827 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11828 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11829 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11830 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11831 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11832 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11833 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11834 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11835 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11836 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11837 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11838
11839 if (pDbgState->bmXcptExtra)
11840 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11841
11842 /*
11843 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11844 *
11845 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11846 * So, when adding/changing/removing please don't forget to update it.
11847 *
11848 * Some of the macros are picking up local variables to save horizontal space,
11849 * (being able to see it in a table is the lesser evil here).
11850 */
11851#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11852 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11853 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11854#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11855 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11856 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11857 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11858 } else do { } while (0)
11859#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11860 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11861 { \
11862 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11863 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11864 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11865 } else do { } while (0)
11866#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11867 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11868 { \
11869 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11870 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11871 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11872 } else do { } while (0)
11873#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11874 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11875 { \
11876 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11877 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11878 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11879 } else do { } while (0)
11880
11881 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11882 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11883 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11884 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11885 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11886
11887 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11888 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11889 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11890 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11891 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11892 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11893 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11894 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11895 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11896 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11897 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11898 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11899 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11900 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11901 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11902 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11903 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11904 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11905 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11906 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11907 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11908 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11909 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11910 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11911 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11912 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11913 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11914 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11915 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11916 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11917 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11918 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11919 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11920 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11921 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11922 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11923
11924 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11925 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11926 {
11927 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11928 | CPUMCTX_EXTRN_APIC_TPR);
11929 AssertRC(rc);
11930
11931#if 0 /** @todo fix me */
11932 pDbgState->fClearCr0Mask = true;
11933 pDbgState->fClearCr4Mask = true;
11934#endif
11935 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11936 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11937 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11938 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11939 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11940 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11941 require clearing here and in the loop if we start using it. */
11942 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11943 }
11944 else
11945 {
11946 if (pDbgState->fClearCr0Mask)
11947 {
11948 pDbgState->fClearCr0Mask = false;
11949 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11950 }
11951 if (pDbgState->fClearCr4Mask)
11952 {
11953 pDbgState->fClearCr4Mask = false;
11954 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11955 }
11956 }
11957 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11958 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11959
11960 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11961 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11962 {
11963 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11964 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11965 }
11966 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11967 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11968
11969 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11970 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11971 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11972 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11973 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11974 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11975 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11976 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11977#if 0 /** @todo too slow, fix handler. */
11978 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11979#endif
11980 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11981
11982 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11983 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11984 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11985 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11986 {
11987 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11988 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11989 }
11990 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11991 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11992 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11993 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11994
11995 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11996 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11997 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11998 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11999 {
12000 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12001 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
12002 }
12003 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
12004 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
12005 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
12006 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
12007
12008 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
12009 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
12010 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
12011 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
12012 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
12013 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
12014 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
12015 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
12016 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
12017 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
12018 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
12019 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
12020 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
12021 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
12022 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
12023 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
12024 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
12025 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
12026 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
12027 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
12028 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
12029 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
12030
12031#undef IS_EITHER_ENABLED
12032#undef SET_ONLY_XBM_IF_EITHER_EN
12033#undef SET_CPE1_XBM_IF_EITHER_EN
12034#undef SET_CPEU_XBM_IF_EITHER_EN
12035#undef SET_CPE2_XBM_IF_EITHER_EN
12036
12037 /*
12038 * Sanitize the control stuff.
12039 */
12040 pDbgState->fCpe2Extra &= g_HmMsrs.u.vmx.ProcCtls2.n.allowed1;
12041 if (pDbgState->fCpe2Extra)
12042 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
12043 pDbgState->fCpe1Extra &= g_HmMsrs.u.vmx.ProcCtls.n.allowed1;
12044 pDbgState->fCpe1Unwanted &= ~g_HmMsrs.u.vmx.ProcCtls.n.allowed0;
12045 if (pVCpu->hmr0.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
12046 {
12047 pVCpu->hmr0.s.fDebugWantRdTscExit ^= true;
12048 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
12049 }
12050
12051 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
12052 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
12053 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
12054 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
12055}
12056
12057
12058/**
12059 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
12060 * appropriate.
12061 *
12062 * The caller has checked the VM-exit against the
12063 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12064 * already, so we don't have to do that either.
12065 *
12066 * @returns Strict VBox status code (i.e. informational status codes too).
12067 * @param pVCpu The cross context virtual CPU structure.
12068 * @param pVmxTransient The VMX-transient structure.
12069 * @param uExitReason The VM-exit reason.
12070 *
12071 * @remarks The name of this function is displayed by dtrace, so keep it short
12072 * and to the point. No longer than 33 chars long, please.
12073 */
12074static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12075{
12076 /*
12077 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12078 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12079 *
12080 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12081 * does. Must add/change/remove both places. Same ordering, please.
12082 *
12083 * Added/removed events must also be reflected in the next section
12084 * where we dispatch dtrace events.
12085 */
12086 bool fDtrace1 = false;
12087 bool fDtrace2 = false;
12088 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12089 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12090 uint32_t uEventArg = 0;
12091#define SET_EXIT(a_EventSubName) \
12092 do { \
12093 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12094 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12095 } while (0)
12096#define SET_BOTH(a_EventSubName) \
12097 do { \
12098 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12099 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12100 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12101 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12102 } while (0)
12103 switch (uExitReason)
12104 {
12105 case VMX_EXIT_MTF:
12106 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12107
12108 case VMX_EXIT_XCPT_OR_NMI:
12109 {
12110 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12111 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12112 {
12113 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12114 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12115 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12116 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12117 {
12118 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12119 {
12120 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12121 uEventArg = pVmxTransient->uExitIntErrorCode;
12122 }
12123 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12124 switch (enmEvent1)
12125 {
12126 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12127 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12128 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12129 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12130 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12131 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12132 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12133 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12134 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12135 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12136 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12137 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12138 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12139 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12140 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12141 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12142 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12143 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12144 default: break;
12145 }
12146 }
12147 else
12148 AssertFailed();
12149 break;
12150
12151 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12152 uEventArg = idxVector;
12153 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12154 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12155 break;
12156 }
12157 break;
12158 }
12159
12160 case VMX_EXIT_TRIPLE_FAULT:
12161 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12162 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12163 break;
12164 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12165 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12166 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12167 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12168 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12169
12170 /* Instruction specific VM-exits: */
12171 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12172 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12173 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12174 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12175 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12176 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12177 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12178 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12179 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12180 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12181 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12182 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12183 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12184 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12185 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12186 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12187 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12188 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12189 case VMX_EXIT_MOV_CRX:
12190 hmR0VmxReadExitQualVmcs(pVmxTransient);
12191 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12192 SET_BOTH(CRX_READ);
12193 else
12194 SET_BOTH(CRX_WRITE);
12195 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12196 break;
12197 case VMX_EXIT_MOV_DRX:
12198 hmR0VmxReadExitQualVmcs(pVmxTransient);
12199 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12200 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12201 SET_BOTH(DRX_READ);
12202 else
12203 SET_BOTH(DRX_WRITE);
12204 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12205 break;
12206 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12207 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12208 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12209 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12210 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12211 case VMX_EXIT_GDTR_IDTR_ACCESS:
12212 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12213 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12214 {
12215 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12216 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12217 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12218 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12219 }
12220 break;
12221
12222 case VMX_EXIT_LDTR_TR_ACCESS:
12223 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12224 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12225 {
12226 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12227 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12228 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12229 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12230 }
12231 break;
12232
12233 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12234 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12235 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12236 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12237 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12238 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12239 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12240 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12241 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12242 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12243 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12244
12245 /* Events that aren't relevant at this point. */
12246 case VMX_EXIT_EXT_INT:
12247 case VMX_EXIT_INT_WINDOW:
12248 case VMX_EXIT_NMI_WINDOW:
12249 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12250 case VMX_EXIT_PREEMPT_TIMER:
12251 case VMX_EXIT_IO_INSTR:
12252 break;
12253
12254 /* Errors and unexpected events. */
12255 case VMX_EXIT_INIT_SIGNAL:
12256 case VMX_EXIT_SIPI:
12257 case VMX_EXIT_IO_SMI:
12258 case VMX_EXIT_SMI:
12259 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12260 case VMX_EXIT_ERR_MSR_LOAD:
12261 case VMX_EXIT_ERR_MACHINE_CHECK:
12262 case VMX_EXIT_PML_FULL:
12263 case VMX_EXIT_VIRTUALIZED_EOI:
12264 break;
12265
12266 default:
12267 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12268 break;
12269 }
12270#undef SET_BOTH
12271#undef SET_EXIT
12272
12273 /*
12274 * Dtrace tracepoints go first. We do them here at once so we don't
12275 * have to copy the guest state saving and stuff a few dozen times.
12276 * Down side is that we've got to repeat the switch, though this time
12277 * we use enmEvent since the probes are a subset of what DBGF does.
12278 */
12279 if (fDtrace1 || fDtrace2)
12280 {
12281 hmR0VmxReadExitQualVmcs(pVmxTransient);
12282 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12283 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12284 switch (enmEvent1)
12285 {
12286 /** @todo consider which extra parameters would be helpful for each probe. */
12287 case DBGFEVENT_END: break;
12288 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12289 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12290 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12291 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12292 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12293 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12294 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12295 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12296 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12297 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12298 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12299 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12300 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12301 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12302 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12303 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12304 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12305 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12306 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12307 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12308 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12309 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12310 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12311 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12312 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12313 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12314 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12315 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12316 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12317 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12318 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12319 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12320 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12321 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12322 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12323 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12324 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12325 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12326 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12327 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12328 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12329 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12330 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12331 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12332 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12333 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12334 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12335 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12336 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12337 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12338 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12339 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12340 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12341 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12342 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12343 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12344 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12345 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12346 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12347 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12348 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12349 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12350 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12351 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12352 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12353 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12354 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12355 }
12356 switch (enmEvent2)
12357 {
12358 /** @todo consider which extra parameters would be helpful for each probe. */
12359 case DBGFEVENT_END: break;
12360 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12361 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12362 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12363 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12364 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12365 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12366 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12367 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12368 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12369 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12370 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12371 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12372 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12373 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12374 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12375 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12376 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12377 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12378 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12379 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12380 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12381 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12382 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12383 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12384 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12385 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12386 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12387 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12388 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12389 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12390 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12391 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12392 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12393 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12394 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12395 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12396 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12397 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12398 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12399 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12400 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12401 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12402 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12403 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12404 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12405 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12406 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12407 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12408 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12409 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12410 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12411 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12412 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12413 }
12414 }
12415
12416 /*
12417 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12418 * the DBGF call will do a full check).
12419 *
12420 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12421 * Note! If we have to events, we prioritize the first, i.e. the instruction
12422 * one, in order to avoid event nesting.
12423 */
12424 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
12425 if ( enmEvent1 != DBGFEVENT_END
12426 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12427 {
12428 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12429 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12430 if (rcStrict != VINF_SUCCESS)
12431 return rcStrict;
12432 }
12433 else if ( enmEvent2 != DBGFEVENT_END
12434 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12435 {
12436 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12437 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12438 if (rcStrict != VINF_SUCCESS)
12439 return rcStrict;
12440 }
12441
12442 return VINF_SUCCESS;
12443}
12444
12445
12446/**
12447 * Single-stepping VM-exit filtering.
12448 *
12449 * This is preprocessing the VM-exits and deciding whether we've gotten far
12450 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12451 * handling is performed.
12452 *
12453 * @returns Strict VBox status code (i.e. informational status codes too).
12454 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12455 * @param pVmxTransient The VMX-transient structure.
12456 * @param pDbgState The debug state.
12457 */
12458DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12459{
12460 /*
12461 * Expensive (saves context) generic dtrace VM-exit probe.
12462 */
12463 uint32_t const uExitReason = pVmxTransient->uExitReason;
12464 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12465 { /* more likely */ }
12466 else
12467 {
12468 hmR0VmxReadExitQualVmcs(pVmxTransient);
12469 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12470 AssertRC(rc);
12471 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12472 }
12473
12474 /*
12475 * Check for host NMI, just to get that out of the way.
12476 */
12477 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12478 { /* normally likely */ }
12479 else
12480 {
12481 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12482 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12483 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12484 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12485 }
12486
12487 /*
12488 * Check for single stepping event if we're stepping.
12489 */
12490 if (pVCpu->hm.s.fSingleInstruction)
12491 {
12492 switch (uExitReason)
12493 {
12494 case VMX_EXIT_MTF:
12495 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12496
12497 /* Various events: */
12498 case VMX_EXIT_XCPT_OR_NMI:
12499 case VMX_EXIT_EXT_INT:
12500 case VMX_EXIT_TRIPLE_FAULT:
12501 case VMX_EXIT_INT_WINDOW:
12502 case VMX_EXIT_NMI_WINDOW:
12503 case VMX_EXIT_TASK_SWITCH:
12504 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12505 case VMX_EXIT_APIC_ACCESS:
12506 case VMX_EXIT_EPT_VIOLATION:
12507 case VMX_EXIT_EPT_MISCONFIG:
12508 case VMX_EXIT_PREEMPT_TIMER:
12509
12510 /* Instruction specific VM-exits: */
12511 case VMX_EXIT_CPUID:
12512 case VMX_EXIT_GETSEC:
12513 case VMX_EXIT_HLT:
12514 case VMX_EXIT_INVD:
12515 case VMX_EXIT_INVLPG:
12516 case VMX_EXIT_RDPMC:
12517 case VMX_EXIT_RDTSC:
12518 case VMX_EXIT_RSM:
12519 case VMX_EXIT_VMCALL:
12520 case VMX_EXIT_VMCLEAR:
12521 case VMX_EXIT_VMLAUNCH:
12522 case VMX_EXIT_VMPTRLD:
12523 case VMX_EXIT_VMPTRST:
12524 case VMX_EXIT_VMREAD:
12525 case VMX_EXIT_VMRESUME:
12526 case VMX_EXIT_VMWRITE:
12527 case VMX_EXIT_VMXOFF:
12528 case VMX_EXIT_VMXON:
12529 case VMX_EXIT_MOV_CRX:
12530 case VMX_EXIT_MOV_DRX:
12531 case VMX_EXIT_IO_INSTR:
12532 case VMX_EXIT_RDMSR:
12533 case VMX_EXIT_WRMSR:
12534 case VMX_EXIT_MWAIT:
12535 case VMX_EXIT_MONITOR:
12536 case VMX_EXIT_PAUSE:
12537 case VMX_EXIT_GDTR_IDTR_ACCESS:
12538 case VMX_EXIT_LDTR_TR_ACCESS:
12539 case VMX_EXIT_INVEPT:
12540 case VMX_EXIT_RDTSCP:
12541 case VMX_EXIT_INVVPID:
12542 case VMX_EXIT_WBINVD:
12543 case VMX_EXIT_XSETBV:
12544 case VMX_EXIT_RDRAND:
12545 case VMX_EXIT_INVPCID:
12546 case VMX_EXIT_VMFUNC:
12547 case VMX_EXIT_RDSEED:
12548 case VMX_EXIT_XSAVES:
12549 case VMX_EXIT_XRSTORS:
12550 {
12551 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12552 AssertRCReturn(rc, rc);
12553 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12554 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12555 return VINF_EM_DBG_STEPPED;
12556 break;
12557 }
12558
12559 /* Errors and unexpected events: */
12560 case VMX_EXIT_INIT_SIGNAL:
12561 case VMX_EXIT_SIPI:
12562 case VMX_EXIT_IO_SMI:
12563 case VMX_EXIT_SMI:
12564 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12565 case VMX_EXIT_ERR_MSR_LOAD:
12566 case VMX_EXIT_ERR_MACHINE_CHECK:
12567 case VMX_EXIT_PML_FULL:
12568 case VMX_EXIT_VIRTUALIZED_EOI:
12569 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12570 break;
12571
12572 default:
12573 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12574 break;
12575 }
12576 }
12577
12578 /*
12579 * Check for debugger event breakpoints and dtrace probes.
12580 */
12581 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12582 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12583 {
12584 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12585 if (rcStrict != VINF_SUCCESS)
12586 return rcStrict;
12587 }
12588
12589 /*
12590 * Normal processing.
12591 */
12592#ifdef HMVMX_USE_FUNCTION_TABLE
12593 return g_aVMExitHandlers[uExitReason].pfn(pVCpu, pVmxTransient);
12594#else
12595 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12596#endif
12597}
12598
12599
12600/**
12601 * Single steps guest code using hardware-assisted VMX.
12602 *
12603 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12604 * but single-stepping through the hypervisor debugger.
12605 *
12606 * @returns Strict VBox status code (i.e. informational status codes too).
12607 * @param pVCpu The cross context virtual CPU structure.
12608 * @param pcLoops Pointer to the number of executed loops.
12609 *
12610 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12611 */
12612static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12613{
12614 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hmr0.s.cMaxResumeLoops;
12615 Assert(pcLoops);
12616 Assert(*pcLoops <= cMaxResumeLoops);
12617
12618 VMXTRANSIENT VmxTransient;
12619 RT_ZERO(VmxTransient);
12620 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12621
12622 /* Set HMCPU indicators. */
12623 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12624 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12625 pVCpu->hmr0.s.fDebugWantRdTscExit = false;
12626 pVCpu->hmr0.s.fUsingDebugLoop = true;
12627
12628 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12629 VMXRUNDBGSTATE DbgState;
12630 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12631 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12632
12633 /*
12634 * The loop.
12635 */
12636 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12637 for (;;)
12638 {
12639 Assert(!HMR0SuspendPending());
12640 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12641 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12642 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12643
12644 /* Set up VM-execution controls the next two can respond to. */
12645 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12646
12647 /*
12648 * Preparatory work for running guest code, this may force us to
12649 * return to ring-3.
12650 *
12651 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12652 */
12653 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12654 if (rcStrict != VINF_SUCCESS)
12655 break;
12656
12657 /* Interrupts are disabled at this point! */
12658 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12659
12660 /* Override any obnoxious code in the above two calls. */
12661 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12662
12663 /*
12664 * Finally execute the guest.
12665 */
12666 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12667
12668 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12669 /* Interrupts are re-enabled at this point! */
12670
12671 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12672 if (RT_SUCCESS(rcRun))
12673 { /* very likely */ }
12674 else
12675 {
12676 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12677 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12678 return rcRun;
12679 }
12680
12681 /* Profile the VM-exit. */
12682 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12683 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12684 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12685 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12686 HMVMX_START_EXIT_DISPATCH_PROF();
12687
12688 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12689
12690 /*
12691 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12692 */
12693 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12694 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12695 if (rcStrict != VINF_SUCCESS)
12696 break;
12697 if (++(*pcLoops) > cMaxResumeLoops)
12698 {
12699 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12700 rcStrict = VINF_EM_RAW_INTERRUPT;
12701 break;
12702 }
12703
12704 /*
12705 * Stepping: Did the RIP change, if so, consider it a single step.
12706 * Otherwise, make sure one of the TFs gets set.
12707 */
12708 if (fStepping)
12709 {
12710 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12711 AssertRC(rc);
12712 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12713 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12714 {
12715 rcStrict = VINF_EM_DBG_STEPPED;
12716 break;
12717 }
12718 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12719 }
12720
12721 /*
12722 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12723 */
12724 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12725 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12726
12727 /* Restore all controls applied by hmR0VmxPreRunGuestDebugStateApply above. */
12728 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12729 Assert(rcStrict == VINF_SUCCESS);
12730 }
12731
12732 /*
12733 * Clear the X86_EFL_TF if necessary.
12734 */
12735 if (pVCpu->hmr0.s.fClearTrapFlag)
12736 {
12737 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12738 AssertRC(rc);
12739 pVCpu->hmr0.s.fClearTrapFlag = false;
12740 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12741 }
12742 /** @todo there seems to be issues with the resume flag when the monitor trap
12743 * flag is pending without being used. Seen early in bios init when
12744 * accessing APIC page in protected mode. */
12745
12746 /* Restore HMCPU indicators. */
12747 pVCpu->hmr0.s.fUsingDebugLoop = false;
12748 pVCpu->hmr0.s.fDebugWantRdTscExit = false;
12749 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12750
12751 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12752 return rcStrict;
12753}
12754
12755
12756/** @} */
12757
12758
12759/**
12760 * Checks if any expensive dtrace probes are enabled and we should go to the
12761 * debug loop.
12762 *
12763 * @returns true if we should use debug loop, false if not.
12764 */
12765static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12766{
12767 /* It's probably faster to OR the raw 32-bit counter variables together.
12768 Since the variables are in an array and the probes are next to one
12769 another (more or less), we have good locality. So, better read
12770 eight-nine cache lines ever time and only have one conditional, than
12771 128+ conditionals, right? */
12772 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12773 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12774 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12775 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12776 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12777 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12778 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12779 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12780 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12781 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12782 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12783 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12784 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12785 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12786 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12787 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12788 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12789 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12790 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12791 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12792 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12793 ) != 0
12794 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12795 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12796 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12797 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12798 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12799 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12800 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12801 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12802 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12803 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12804 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12805 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12806 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12807 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12808 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12809 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12810 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12811 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12812 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12813 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12814 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12815 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12816 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12817 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12818 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12819 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12820 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12821 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12822 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12823 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12824 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12825 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12826 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12827 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12828 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12829 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12830 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12831 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12832 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12833 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12834 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12835 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12836 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12837 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12838 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12839 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12840 ) != 0
12841 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12842 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12843 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12844 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12845 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12846 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12847 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12848 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12849 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12850 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12851 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12852 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12853 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12854 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12855 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12856 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12857 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12858 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12859 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12860 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12861 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12862 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12863 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12864 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12865 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12866 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12867 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12868 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12869 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12870 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12871 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12872 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12873 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12874 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12875 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12876 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12877 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12878 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12879 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12880 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12881 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12882 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12883 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12884 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12885 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12886 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12887 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12888 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12889 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12890 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12891 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12892 ) != 0;
12893}
12894
12895
12896/**
12897 * Runs the guest using hardware-assisted VMX.
12898 *
12899 * @returns Strict VBox status code (i.e. informational status codes too).
12900 * @param pVCpu The cross context virtual CPU structure.
12901 */
12902VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12903{
12904 AssertPtr(pVCpu);
12905 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12906 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12907 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12908 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12909
12910 VBOXSTRICTRC rcStrict;
12911 uint32_t cLoops = 0;
12912 for (;;)
12913 {
12914#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12915 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12916#else
12917 NOREF(pCtx);
12918 bool const fInNestedGuestMode = false;
12919#endif
12920 if (!fInNestedGuestMode)
12921 {
12922 if ( !pVCpu->hm.s.fUseDebugLoop
12923 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12924 && !DBGFIsStepping(pVCpu)
12925 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12926 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12927 else
12928 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12929 }
12930#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12931 else
12932 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12933
12934 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12935 {
12936 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12937 continue;
12938 }
12939 if (rcStrict == VINF_VMX_VMEXIT)
12940 {
12941 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12942 continue;
12943 }
12944#endif
12945 break;
12946 }
12947
12948 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12949 switch (rcLoop)
12950 {
12951 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12952 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12953 }
12954
12955 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12956 if (RT_FAILURE(rc2))
12957 {
12958 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12959 rcStrict = rc2;
12960 }
12961 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12962 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12963 return rcStrict;
12964}
12965
12966
12967#ifndef HMVMX_USE_FUNCTION_TABLE
12968/**
12969 * Handles a guest VM-exit from hardware-assisted VMX execution.
12970 *
12971 * @returns Strict VBox status code (i.e. informational status codes too).
12972 * @param pVCpu The cross context virtual CPU structure.
12973 * @param pVmxTransient The VMX-transient structure.
12974 */
12975DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12976{
12977#ifdef DEBUG_ramshankar
12978# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12979 do { \
12980 if (a_fSave != 0) \
12981 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12982 VBOXSTRICTRC rcStrict = a_CallExpr; \
12983 if (a_fSave != 0) \
12984 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12985 return rcStrict; \
12986 } while (0)
12987#else
12988# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12989#endif
12990 uint32_t const uExitReason = pVmxTransient->uExitReason;
12991 switch (uExitReason)
12992 {
12993 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12994 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12995 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12996 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12997 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12998 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12999 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
13000 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
13001 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
13002 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
13003 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
13004 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
13005 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
13006 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
13007 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
13008 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
13009 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
13010 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
13011 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
13012 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
13013 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
13014 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
13015 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
13016 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
13017 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
13018 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
13019 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
13020 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
13021 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
13022 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
13023#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13024 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
13025 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
13026 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
13027 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
13028 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
13029 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
13030 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
13031 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
13032 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
13033 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
13034 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
13035#else
13036 case VMX_EXIT_VMCLEAR:
13037 case VMX_EXIT_VMLAUNCH:
13038 case VMX_EXIT_VMPTRLD:
13039 case VMX_EXIT_VMPTRST:
13040 case VMX_EXIT_VMREAD:
13041 case VMX_EXIT_VMRESUME:
13042 case VMX_EXIT_VMWRITE:
13043 case VMX_EXIT_VMXOFF:
13044 case VMX_EXIT_VMXON:
13045 case VMX_EXIT_INVVPID:
13046 case VMX_EXIT_INVEPT:
13047 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
13048#endif
13049
13050 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
13051 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
13052 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
13053
13054 case VMX_EXIT_INIT_SIGNAL:
13055 case VMX_EXIT_SIPI:
13056 case VMX_EXIT_IO_SMI:
13057 case VMX_EXIT_SMI:
13058 case VMX_EXIT_ERR_MSR_LOAD:
13059 case VMX_EXIT_ERR_MACHINE_CHECK:
13060 case VMX_EXIT_PML_FULL:
13061 case VMX_EXIT_VIRTUALIZED_EOI:
13062 case VMX_EXIT_GDTR_IDTR_ACCESS:
13063 case VMX_EXIT_LDTR_TR_ACCESS:
13064 case VMX_EXIT_APIC_WRITE:
13065 case VMX_EXIT_RDRAND:
13066 case VMX_EXIT_RSM:
13067 case VMX_EXIT_VMFUNC:
13068 case VMX_EXIT_ENCLS:
13069 case VMX_EXIT_RDSEED:
13070 case VMX_EXIT_XSAVES:
13071 case VMX_EXIT_XRSTORS:
13072 case VMX_EXIT_UMWAIT:
13073 case VMX_EXIT_TPAUSE:
13074 default:
13075 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13076 }
13077#undef VMEXIT_CALL_RET
13078}
13079#endif /* !HMVMX_USE_FUNCTION_TABLE */
13080
13081
13082#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13083/**
13084 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13085 *
13086 * @returns Strict VBox status code (i.e. informational status codes too).
13087 * @param pVCpu The cross context virtual CPU structure.
13088 * @param pVmxTransient The VMX-transient structure.
13089 */
13090DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13091{
13092 uint32_t const uExitReason = pVmxTransient->uExitReason;
13093 switch (uExitReason)
13094 {
13095 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13096 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13097 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13098 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13099 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13100
13101 /*
13102 * We shouldn't direct host physical interrupts to the nested-guest.
13103 */
13104 case VMX_EXIT_EXT_INT:
13105 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13106
13107 /*
13108 * Instructions that cause VM-exits unconditionally or the condition is
13109 * always is taken solely from the nested hypervisor (meaning if the VM-exit
13110 * happens, it's guaranteed to be a nested-guest VM-exit).
13111 *
13112 * - Provides VM-exit instruction length ONLY.
13113 */
13114 case VMX_EXIT_CPUID: /* Unconditional. */
13115 case VMX_EXIT_VMCALL:
13116 case VMX_EXIT_GETSEC:
13117 case VMX_EXIT_INVD:
13118 case VMX_EXIT_XSETBV:
13119 case VMX_EXIT_VMLAUNCH:
13120 case VMX_EXIT_VMRESUME:
13121 case VMX_EXIT_VMXOFF:
13122 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
13123 case VMX_EXIT_VMFUNC:
13124 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13125
13126 /*
13127 * Instructions that cause VM-exits unconditionally or the condition is
13128 * always is taken solely from the nested hypervisor (meaning if the VM-exit
13129 * happens, it's guaranteed to be a nested-guest VM-exit).
13130 *
13131 * - Provides VM-exit instruction length.
13132 * - Provides VM-exit information.
13133 * - Optionally provides Exit qualification.
13134 *
13135 * Since Exit qualification is 0 for all VM-exits where it is not
13136 * applicable, reading and passing it to the guest should produce
13137 * defined behavior.
13138 *
13139 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13140 */
13141 case VMX_EXIT_INVEPT: /* Unconditional. */
13142 case VMX_EXIT_INVVPID:
13143 case VMX_EXIT_VMCLEAR:
13144 case VMX_EXIT_VMPTRLD:
13145 case VMX_EXIT_VMPTRST:
13146 case VMX_EXIT_VMXON:
13147 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
13148 case VMX_EXIT_LDTR_TR_ACCESS:
13149 case VMX_EXIT_RDRAND:
13150 case VMX_EXIT_RDSEED:
13151 case VMX_EXIT_XSAVES:
13152 case VMX_EXIT_XRSTORS:
13153 case VMX_EXIT_UMWAIT:
13154 case VMX_EXIT_TPAUSE:
13155 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13156
13157 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13158 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13159 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13160 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13161 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13162 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13163 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13164 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13165 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13166 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13167 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13168 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13169 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13170 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13171 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13172 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13173 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13174 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13175 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13176
13177 case VMX_EXIT_PREEMPT_TIMER:
13178 {
13179 /** @todo NSTVMX: Preempt timer. */
13180 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13181 }
13182
13183 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13184 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13185
13186 case VMX_EXIT_VMREAD:
13187 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13188
13189 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13190 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13191
13192 case VMX_EXIT_INIT_SIGNAL:
13193 case VMX_EXIT_SIPI:
13194 case VMX_EXIT_IO_SMI:
13195 case VMX_EXIT_SMI:
13196 case VMX_EXIT_ERR_MSR_LOAD:
13197 case VMX_EXIT_ERR_MACHINE_CHECK:
13198 case VMX_EXIT_PML_FULL:
13199 case VMX_EXIT_RSM:
13200 default:
13201 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13202 }
13203}
13204#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13205
13206
13207/** @name VM-exit helpers.
13208 * @{
13209 */
13210/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13211/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13212/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13213
13214/** Macro for VM-exits called unexpectedly. */
13215#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13216 do { \
13217 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13218 return VERR_VMX_UNEXPECTED_EXIT; \
13219 } while (0)
13220
13221#ifdef VBOX_STRICT
13222/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13223# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13224 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13225
13226# define HMVMX_ASSERT_PREEMPT_CPUID() \
13227 do { \
13228 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13229 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13230 } while (0)
13231
13232# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13233 do { \
13234 AssertPtr((a_pVCpu)); \
13235 AssertPtr((a_pVmxTransient)); \
13236 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13237 Assert((a_pVmxTransient)->pVmcsInfo); \
13238 Assert(ASMIntAreEnabled()); \
13239 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13240 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13241 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13242 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13243 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13244 HMVMX_ASSERT_PREEMPT_CPUID(); \
13245 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13246 } while (0)
13247
13248# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13249 do { \
13250 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13251 Assert((a_pVmxTransient)->fIsNestedGuest); \
13252 } while (0)
13253
13254# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13255 do { \
13256 Log4Func(("\n")); \
13257 } while (0)
13258#else
13259# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13260 do { \
13261 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13262 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13263 } while (0)
13264
13265# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13266 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13267
13268# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13269#endif
13270
13271#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13272/** Macro that does the necessary privilege checks and intercepted VM-exits for
13273 * guests that attempted to execute a VMX instruction. */
13274# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13275 do \
13276 { \
13277 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13278 if (rcStrictTmp == VINF_SUCCESS) \
13279 { /* likely */ } \
13280 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13281 { \
13282 Assert((a_pVCpu)->hm.s.Event.fPending); \
13283 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13284 return VINF_SUCCESS; \
13285 } \
13286 else \
13287 { \
13288 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13289 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13290 } \
13291 } while (0)
13292
13293/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13294# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13295 do \
13296 { \
13297 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13298 (a_pGCPtrEffAddr)); \
13299 if (rcStrictTmp == VINF_SUCCESS) \
13300 { /* likely */ } \
13301 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13302 { \
13303 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13304 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13305 NOREF(uXcptTmp); \
13306 return VINF_SUCCESS; \
13307 } \
13308 else \
13309 { \
13310 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13311 return rcStrictTmp; \
13312 } \
13313 } while (0)
13314#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13315
13316
13317/**
13318 * Advances the guest RIP by the specified number of bytes.
13319 *
13320 * @param pVCpu The cross context virtual CPU structure.
13321 * @param cbInstr Number of bytes to advance the RIP by.
13322 *
13323 * @remarks No-long-jump zone!!!
13324 */
13325DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
13326{
13327 /* Advance the RIP. */
13328 pVCpu->cpum.GstCtx.rip += cbInstr;
13329 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13330
13331 /* Update interrupt inhibition. */
13332 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13333 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13334 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13335}
13336
13337
13338/**
13339 * Advances the guest RIP after reading it from the VMCS.
13340 *
13341 * @returns VBox status code, no informational status codes.
13342 * @param pVCpu The cross context virtual CPU structure.
13343 * @param pVmxTransient The VMX-transient structure.
13344 *
13345 * @remarks No-long-jump zone!!!
13346 */
13347static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13348{
13349 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13350 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13351 AssertRCReturn(rc, rc);
13352
13353 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
13354 return VINF_SUCCESS;
13355}
13356
13357
13358/**
13359 * Handle a condition that occurred while delivering an event through the guest or
13360 * nested-guest IDT.
13361 *
13362 * @returns Strict VBox status code (i.e. informational status codes too).
13363 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13364 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13365 * to continue execution of the guest which will delivery the \#DF.
13366 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13367 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13368 *
13369 * @param pVCpu The cross context virtual CPU structure.
13370 * @param pVmxTransient The VMX-transient structure.
13371 *
13372 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13373 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13374 * is due to an EPT violation, PML full or SPP-related event.
13375 *
13376 * @remarks No-long-jump zone!!!
13377 */
13378static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13379{
13380 Assert(!pVCpu->hm.s.Event.fPending);
13381 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13382 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13383 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13384 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13385 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13386
13387 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13388 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13389 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13390 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13391 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13392 {
13393 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13394 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13395
13396 /*
13397 * If the event was a software interrupt (generated with INT n) or a software exception
13398 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13399 * can handle the VM-exit and continue guest execution which will re-execute the
13400 * instruction rather than re-injecting the exception, as that can cause premature
13401 * trips to ring-3 before injection and involve TRPM which currently has no way of
13402 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13403 * the problem).
13404 */
13405 IEMXCPTRAISE enmRaise;
13406 IEMXCPTRAISEINFO fRaiseInfo;
13407 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13408 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13409 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13410 {
13411 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13412 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13413 }
13414 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13415 {
13416 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13417 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13418 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13419
13420 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13421 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13422
13423 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13424
13425 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13426 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13427 {
13428 pVmxTransient->fVectoringPF = true;
13429 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13430 }
13431 }
13432 else
13433 {
13434 /*
13435 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13436 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13437 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13438 */
13439 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13440 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13441 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13442 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13443 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13444 }
13445
13446 /*
13447 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13448 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13449 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13450 * subsequent VM-entry would fail, see @bugref{7445}.
13451 *
13452 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13453 */
13454 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13455 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13456 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13457 && CPUMIsGuestNmiBlocking(pVCpu))
13458 {
13459 CPUMSetGuestNmiBlocking(pVCpu, false);
13460 }
13461
13462 switch (enmRaise)
13463 {
13464 case IEMXCPTRAISE_CURRENT_XCPT:
13465 {
13466 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13467 Assert(rcStrict == VINF_SUCCESS);
13468 break;
13469 }
13470
13471 case IEMXCPTRAISE_PREV_EVENT:
13472 {
13473 uint32_t u32ErrCode;
13474 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13475 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13476 else
13477 u32ErrCode = 0;
13478
13479 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13480 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13481 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13482 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13483
13484 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13485 pVCpu->hm.s.Event.u32ErrCode));
13486 Assert(rcStrict == VINF_SUCCESS);
13487 break;
13488 }
13489
13490 case IEMXCPTRAISE_REEXEC_INSTR:
13491 Assert(rcStrict == VINF_SUCCESS);
13492 break;
13493
13494 case IEMXCPTRAISE_DOUBLE_FAULT:
13495 {
13496 /*
13497 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13498 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13499 */
13500 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13501 {
13502 pVmxTransient->fVectoringDoublePF = true;
13503 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13504 pVCpu->cpum.GstCtx.cr2));
13505 rcStrict = VINF_SUCCESS;
13506 }
13507 else
13508 {
13509 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13510 hmR0VmxSetPendingXcptDF(pVCpu);
13511 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13512 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13513 rcStrict = VINF_HM_DOUBLE_FAULT;
13514 }
13515 break;
13516 }
13517
13518 case IEMXCPTRAISE_TRIPLE_FAULT:
13519 {
13520 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13521 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13522 rcStrict = VINF_EM_RESET;
13523 break;
13524 }
13525
13526 case IEMXCPTRAISE_CPU_HANG:
13527 {
13528 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13529 rcStrict = VERR_EM_GUEST_CPU_HANG;
13530 break;
13531 }
13532
13533 default:
13534 {
13535 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13536 rcStrict = VERR_VMX_IPE_2;
13537 break;
13538 }
13539 }
13540 }
13541 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13542 && !CPUMIsGuestNmiBlocking(pVCpu))
13543 {
13544 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13545 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13546 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13547 {
13548 /*
13549 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13550 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13551 * that virtual NMIs remain blocked until the IRET execution is completed.
13552 *
13553 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13554 */
13555 CPUMSetGuestNmiBlocking(pVCpu, true);
13556 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13557 }
13558 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13559 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13560 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13561 {
13562 /*
13563 * Execution of IRET caused an EPT violation, page-modification log-full event or
13564 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13565 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13566 * that virtual NMIs remain blocked until the IRET execution is completed.
13567 *
13568 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13569 */
13570 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13571 {
13572 CPUMSetGuestNmiBlocking(pVCpu, true);
13573 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13574 }
13575 }
13576 }
13577
13578 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13579 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13580 return rcStrict;
13581}
13582
13583
13584#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13585/**
13586 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13587 * guest attempting to execute a VMX instruction.
13588 *
13589 * @returns Strict VBox status code (i.e. informational status codes too).
13590 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13591 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13592 *
13593 * @param pVCpu The cross context virtual CPU structure.
13594 * @param uExitReason The VM-exit reason.
13595 *
13596 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13597 * @remarks No-long-jump zone!!!
13598 */
13599static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13600{
13601 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13602 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13603
13604 /*
13605 * The physical CPU would have already checked the CPU mode/code segment.
13606 * We shall just assert here for paranoia.
13607 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13608 */
13609 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13610 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13611 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13612
13613 if (uExitReason == VMX_EXIT_VMXON)
13614 {
13615 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13616
13617 /*
13618 * We check CR4.VMXE because it is required to be always set while in VMX operation
13619 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13620 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13621 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13622 */
13623 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13624 {
13625 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13626 hmR0VmxSetPendingXcptUD(pVCpu);
13627 return VINF_HM_PENDING_XCPT;
13628 }
13629 }
13630 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13631 {
13632 /*
13633 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13634 * (other than VMXON), we need to raise a #UD.
13635 */
13636 Log4Func(("Not in VMX root mode -> #UD\n"));
13637 hmR0VmxSetPendingXcptUD(pVCpu);
13638 return VINF_HM_PENDING_XCPT;
13639 }
13640
13641 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13642 return VINF_SUCCESS;
13643}
13644
13645
13646/**
13647 * Decodes the memory operand of an instruction that caused a VM-exit.
13648 *
13649 * The Exit qualification field provides the displacement field for memory
13650 * operand instructions, if any.
13651 *
13652 * @returns Strict VBox status code (i.e. informational status codes too).
13653 * @retval VINF_SUCCESS if the operand was successfully decoded.
13654 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13655 * operand.
13656 * @param pVCpu The cross context virtual CPU structure.
13657 * @param uExitInstrInfo The VM-exit instruction information field.
13658 * @param enmMemAccess The memory operand's access type (read or write).
13659 * @param GCPtrDisp The instruction displacement field, if any. For
13660 * RIP-relative addressing pass RIP + displacement here.
13661 * @param pGCPtrMem Where to store the effective destination memory address.
13662 *
13663 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13664 * virtual-8086 mode hence skips those checks while verifying if the
13665 * segment is valid.
13666 */
13667static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13668 PRTGCPTR pGCPtrMem)
13669{
13670 Assert(pGCPtrMem);
13671 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13672 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13673 | CPUMCTX_EXTRN_CR0);
13674
13675 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13676 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13677 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13678
13679 VMXEXITINSTRINFO ExitInstrInfo;
13680 ExitInstrInfo.u = uExitInstrInfo;
13681 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13682 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13683 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13684 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13685 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13686 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13687 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13688 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13689 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13690
13691 /*
13692 * Validate instruction information.
13693 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13694 */
13695 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13696 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13697 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13698 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13699 AssertLogRelMsgReturn(fIsMemOperand,
13700 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13701
13702 /*
13703 * Compute the complete effective address.
13704 *
13705 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13706 * See AMD spec. 4.5.2 "Segment Registers".
13707 */
13708 RTGCPTR GCPtrMem = GCPtrDisp;
13709 if (fBaseRegValid)
13710 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13711 if (fIdxRegValid)
13712 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13713
13714 RTGCPTR const GCPtrOff = GCPtrMem;
13715 if ( !fIsLongMode
13716 || iSegReg >= X86_SREG_FS)
13717 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13718 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13719
13720 /*
13721 * Validate effective address.
13722 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13723 */
13724 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13725 Assert(cbAccess > 0);
13726 if (fIsLongMode)
13727 {
13728 if (X86_IS_CANONICAL(GCPtrMem))
13729 {
13730 *pGCPtrMem = GCPtrMem;
13731 return VINF_SUCCESS;
13732 }
13733
13734 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13735 * "Data Limit Checks in 64-bit Mode". */
13736 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13737 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13738 return VINF_HM_PENDING_XCPT;
13739 }
13740
13741 /*
13742 * This is a watered down version of iemMemApplySegment().
13743 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13744 * and segment CPL/DPL checks are skipped.
13745 */
13746 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13747 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13748 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13749
13750 /* Check if the segment is present and usable. */
13751 if ( pSel->Attr.n.u1Present
13752 && !pSel->Attr.n.u1Unusable)
13753 {
13754 Assert(pSel->Attr.n.u1DescType);
13755 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13756 {
13757 /* Check permissions for the data segment. */
13758 if ( enmMemAccess == VMXMEMACCESS_WRITE
13759 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13760 {
13761 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13762 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13763 return VINF_HM_PENDING_XCPT;
13764 }
13765
13766 /* Check limits if it's a normal data segment. */
13767 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13768 {
13769 if ( GCPtrFirst32 > pSel->u32Limit
13770 || GCPtrLast32 > pSel->u32Limit)
13771 {
13772 Log4Func(("Data segment limit exceeded. "
13773 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13774 GCPtrLast32, pSel->u32Limit));
13775 if (iSegReg == X86_SREG_SS)
13776 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13777 else
13778 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13779 return VINF_HM_PENDING_XCPT;
13780 }
13781 }
13782 else
13783 {
13784 /* Check limits if it's an expand-down data segment.
13785 Note! The upper boundary is defined by the B bit, not the G bit! */
13786 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13787 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13788 {
13789 Log4Func(("Expand-down data segment limit exceeded. "
13790 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13791 GCPtrLast32, pSel->u32Limit));
13792 if (iSegReg == X86_SREG_SS)
13793 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13794 else
13795 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13796 return VINF_HM_PENDING_XCPT;
13797 }
13798 }
13799 }
13800 else
13801 {
13802 /* Check permissions for the code segment. */
13803 if ( enmMemAccess == VMXMEMACCESS_WRITE
13804 || ( enmMemAccess == VMXMEMACCESS_READ
13805 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13806 {
13807 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13808 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13809 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13810 return VINF_HM_PENDING_XCPT;
13811 }
13812
13813 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13814 if ( GCPtrFirst32 > pSel->u32Limit
13815 || GCPtrLast32 > pSel->u32Limit)
13816 {
13817 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13818 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13819 if (iSegReg == X86_SREG_SS)
13820 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13821 else
13822 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13823 return VINF_HM_PENDING_XCPT;
13824 }
13825 }
13826 }
13827 else
13828 {
13829 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13830 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13831 return VINF_HM_PENDING_XCPT;
13832 }
13833
13834 *pGCPtrMem = GCPtrMem;
13835 return VINF_SUCCESS;
13836}
13837#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13838
13839
13840/**
13841 * VM-exit helper for LMSW.
13842 */
13843static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13844{
13845 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13846 AssertRCReturn(rc, rc);
13847
13848 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13849 AssertMsg( rcStrict == VINF_SUCCESS
13850 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13851
13852 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13853 if (rcStrict == VINF_IEM_RAISED_XCPT)
13854 {
13855 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13856 rcStrict = VINF_SUCCESS;
13857 }
13858
13859 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13860 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13861 return rcStrict;
13862}
13863
13864
13865/**
13866 * VM-exit helper for CLTS.
13867 */
13868static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13869{
13870 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13871 AssertRCReturn(rc, rc);
13872
13873 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13874 AssertMsg( rcStrict == VINF_SUCCESS
13875 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13876
13877 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13878 if (rcStrict == VINF_IEM_RAISED_XCPT)
13879 {
13880 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13881 rcStrict = VINF_SUCCESS;
13882 }
13883
13884 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13885 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13886 return rcStrict;
13887}
13888
13889
13890/**
13891 * VM-exit helper for MOV from CRx (CRx read).
13892 */
13893static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13894{
13895 Assert(iCrReg < 16);
13896 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13897
13898 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13899 AssertRCReturn(rc, rc);
13900
13901 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13902 AssertMsg( rcStrict == VINF_SUCCESS
13903 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13904
13905 if (iGReg == X86_GREG_xSP)
13906 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13907 else
13908 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13909#ifdef VBOX_WITH_STATISTICS
13910 switch (iCrReg)
13911 {
13912 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13913 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13914 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13915 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13916 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13917 }
13918#endif
13919 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13920 return rcStrict;
13921}
13922
13923
13924/**
13925 * VM-exit helper for MOV to CRx (CRx write).
13926 */
13927static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13928{
13929 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13930 AssertRCReturn(rc, rc);
13931
13932 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13933 AssertMsg( rcStrict == VINF_SUCCESS
13934 || rcStrict == VINF_IEM_RAISED_XCPT
13935 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13936
13937 switch (iCrReg)
13938 {
13939 case 0:
13940 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13941 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13942 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13943 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13944 break;
13945
13946 case 2:
13947 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13948 /* Nothing to do here, CR2 it's not part of the VMCS. */
13949 break;
13950
13951 case 3:
13952 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13953 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13954 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13955 break;
13956
13957 case 4:
13958 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13959 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13960 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13961 pVCpu->cpum.GstCtx.cr4, pVCpu->hmr0.s.fLoadSaveGuestXcr0));
13962 break;
13963
13964 case 8:
13965 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13966 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13967 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13968 break;
13969
13970 default:
13971 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13972 break;
13973 }
13974
13975 if (rcStrict == VINF_IEM_RAISED_XCPT)
13976 {
13977 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13978 rcStrict = VINF_SUCCESS;
13979 }
13980 return rcStrict;
13981}
13982
13983
13984/**
13985 * VM-exit exception handler for \#PF (Page-fault exception).
13986 *
13987 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13988 */
13989static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13990{
13991 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13992 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13993 hmR0VmxReadExitQualVmcs(pVmxTransient);
13994
13995 if (!pVM->hmr0.s.fNestedPaging)
13996 { /* likely */ }
13997 else
13998 {
13999#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
14000 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hmr0.s.fUsingDebugLoop);
14001#endif
14002 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
14003 if (!pVmxTransient->fVectoringDoublePF)
14004 {
14005 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14006 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
14007 }
14008 else
14009 {
14010 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14011 Assert(!pVmxTransient->fIsNestedGuest);
14012 hmR0VmxSetPendingXcptDF(pVCpu);
14013 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
14014 }
14015 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14016 return VINF_SUCCESS;
14017 }
14018
14019 Assert(!pVmxTransient->fIsNestedGuest);
14020
14021 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
14022 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
14023 if (pVmxTransient->fVectoringPF)
14024 {
14025 Assert(pVCpu->hm.s.Event.fPending);
14026 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14027 }
14028
14029 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14030 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14031 AssertRCReturn(rc, rc);
14032
14033 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
14034 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
14035
14036 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
14037 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
14038
14039 Log4Func(("#PF: rc=%Rrc\n", rc));
14040 if (rc == VINF_SUCCESS)
14041 {
14042 /*
14043 * This is typically a shadow page table sync or a MMIO instruction. But we may have
14044 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
14045 */
14046 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14047 TRPMResetTrap(pVCpu);
14048 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
14049 return rc;
14050 }
14051
14052 if (rc == VINF_EM_RAW_GUEST_TRAP)
14053 {
14054 if (!pVmxTransient->fVectoringDoublePF)
14055 {
14056 /* It's a guest page fault and needs to be reflected to the guest. */
14057 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
14058 TRPMResetTrap(pVCpu);
14059 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
14060 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14061 uGstErrorCode, pVmxTransient->uExitQual);
14062 }
14063 else
14064 {
14065 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14066 TRPMResetTrap(pVCpu);
14067 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14068 hmR0VmxSetPendingXcptDF(pVCpu);
14069 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14070 }
14071
14072 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14073 return VINF_SUCCESS;
14074 }
14075
14076 TRPMResetTrap(pVCpu);
14077 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14078 return rc;
14079}
14080
14081
14082/**
14083 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14084 *
14085 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14086 */
14087static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14088{
14089 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14090 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14091
14092 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14093 AssertRCReturn(rc, rc);
14094
14095 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14096 {
14097 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14098 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14099
14100 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14101 * provides VM-exit instruction length. If this causes problem later,
14102 * disassemble the instruction like it's done on AMD-V. */
14103 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14104 AssertRCReturn(rc2, rc2);
14105 return rc;
14106 }
14107
14108 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
14109 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14110 return VINF_SUCCESS;
14111}
14112
14113
14114/**
14115 * VM-exit exception handler for \#BP (Breakpoint exception).
14116 *
14117 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14118 */
14119static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14120{
14121 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14122 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14123
14124 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14125 AssertRCReturn(rc, rc);
14126
14127 if (!pVmxTransient->fIsNestedGuest)
14128 rc = DBGFTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
14129 else
14130 rc = VINF_EM_RAW_GUEST_TRAP;
14131
14132 if (rc == VINF_EM_RAW_GUEST_TRAP)
14133 {
14134 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14135 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14136 rc = VINF_SUCCESS;
14137 }
14138
14139 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
14140 return rc;
14141}
14142
14143
14144/**
14145 * VM-exit exception handler for \#AC (Alignment-check exception).
14146 *
14147 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14148 */
14149static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14150{
14151 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14152
14153 /*
14154 * Detect #ACs caused by host having enabled split-lock detection.
14155 * Emulate such instructions.
14156 */
14157 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo,
14158 CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS);
14159 AssertRCReturn(rc, rc);
14160 /** @todo detect split lock in cpu feature? */
14161 if ( /* 1. If 486-style alignment checks aren't enabled, then this must be a split-lock exception */
14162 !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_AM)
14163 /* 2. #AC cannot happen in rings 0-2 except for split-lock detection. */
14164 || CPUMGetGuestCPL(pVCpu) != 3
14165 /* 3. When the EFLAGS.AC != 0 this can only be a split-lock case. */
14166 || !(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_AC) )
14167 {
14168 /*
14169 * Check for debug/trace events and import state accordingly.
14170 */
14171 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitGuestACSplitLock);
14172 PVMCC pVM = pVCpu->pVMR0;
14173 if ( !DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_VMX_SPLIT_LOCK)
14174 && !VBOXVMM_VMX_SPLIT_LOCK_ENABLED())
14175 {
14176 if (pVM->cCpus == 1)
14177 {
14178#if 0 /** @todo r=bird: This is potentially wrong. Might have to just do a whole state sync above and mark everything changed to be safe... */
14179 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14180#else
14181 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14182#endif
14183 AssertRCReturn(rc, rc);
14184 }
14185 }
14186 else
14187 {
14188 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14189 AssertRCReturn(rc, rc);
14190
14191 VBOXVMM_XCPT_DF(pVCpu, &pVCpu->cpum.GstCtx);
14192
14193 if (DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_VMX_SPLIT_LOCK))
14194 {
14195 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, DBGFEVENT_VMX_SPLIT_LOCK, DBGFEVENTCTX_HM, 0);
14196 if (rcStrict != VINF_SUCCESS)
14197 return rcStrict;
14198 }
14199 }
14200
14201 /*
14202 * Emulate the instruction.
14203 *
14204 * We have to ignore the LOCK prefix here as we must not retrigger the
14205 * detection on the host. This isn't all that satisfactory, though...
14206 */
14207 if (pVM->cCpus == 1)
14208 {
14209 Log8Func(("cs:rip=%#04x:%#RX64 rflags=%#RX64 cr0=%#RX64 split-lock #AC\n", pVCpu->cpum.GstCtx.cs.Sel,
14210 pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.rflags, pVCpu->cpum.GstCtx.cr0));
14211
14212 /** @todo For SMP configs we should do a rendezvous here. */
14213 VBOXSTRICTRC rcStrict = IEMExecOneIgnoreLock(pVCpu);
14214 if (rcStrict == VINF_SUCCESS)
14215#if 0 /** @todo r=bird: This is potentially wrong. Might have to just do a whole state sync above and mark everything changed to be safe... */
14216 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
14217 HM_CHANGED_GUEST_RIP
14218 | HM_CHANGED_GUEST_RFLAGS
14219 | HM_CHANGED_GUEST_GPRS_MASK
14220 | HM_CHANGED_GUEST_CS
14221 | HM_CHANGED_GUEST_SS);
14222#else
14223 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14224#endif
14225 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14226 {
14227 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14228 rcStrict = VINF_SUCCESS;
14229 }
14230 return rcStrict;
14231 }
14232 Log8Func(("cs:rip=%#04x:%#RX64 rflags=%#RX64 cr0=%#RX64 split-lock #AC -> VINF_EM_EMULATE_SPLIT_LOCK\n",
14233 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.rflags, pVCpu->cpum.GstCtx.cr0));
14234 return VINF_EM_EMULATE_SPLIT_LOCK;
14235 }
14236
14237 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14238 Log8Func(("cs:rip=%#04x:%#RX64 rflags=%#RX64 cr0=%#RX64 cpl=%d -> #AC\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14239 pVCpu->cpum.GstCtx.rflags, pVCpu->cpum.GstCtx.cr0, CPUMGetGuestCPL(pVCpu) ));
14240
14241 /* Re-inject it. We'll detect any nesting before getting here. */
14242 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14243 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14244 return VINF_SUCCESS;
14245}
14246
14247
14248/**
14249 * VM-exit exception handler for \#DB (Debug exception).
14250 *
14251 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14252 */
14253static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14254{
14255 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14256 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14257
14258 /*
14259 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14260 */
14261 hmR0VmxReadExitQualVmcs(pVmxTransient);
14262
14263 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14264 uint64_t const uDR6 = X86_DR6_INIT_VAL
14265 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14266 | X86_DR6_BD | X86_DR6_BS));
14267
14268 int rc;
14269 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14270 if (!pVmxTransient->fIsNestedGuest)
14271 {
14272 rc = DBGFTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14273
14274 /*
14275 * Prevents stepping twice over the same instruction when the guest is stepping using
14276 * EFLAGS.TF and the hypervisor debugger is stepping using MTF.
14277 * Testcase: DOSQEMM, break (using "ba x 1") at cs:rip 0x70:0x774 and step (using "t").
14278 */
14279 if ( rc == VINF_EM_DBG_STEPPED
14280 && (pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MONITOR_TRAP_FLAG))
14281 {
14282 Assert(pVCpu->hm.s.fSingleInstruction);
14283 rc = VINF_EM_RAW_GUEST_TRAP;
14284 }
14285 }
14286 else
14287 rc = VINF_EM_RAW_GUEST_TRAP;
14288 Log6Func(("rc=%Rrc\n", rc));
14289 if (rc == VINF_EM_RAW_GUEST_TRAP)
14290 {
14291 /*
14292 * The exception was for the guest. Update DR6, DR7.GD and
14293 * IA32_DEBUGCTL.LBR before forwarding it.
14294 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14295 */
14296 VMMRZCallRing3Disable(pVCpu);
14297 HM_DISABLE_PREEMPT(pVCpu);
14298
14299 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14300 pCtx->dr[6] |= uDR6;
14301 if (CPUMIsGuestDebugStateActive(pVCpu))
14302 ASMSetDR6(pCtx->dr[6]);
14303
14304 HM_RESTORE_PREEMPT();
14305 VMMRZCallRing3Enable(pVCpu);
14306
14307 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14308 AssertRCReturn(rc, rc);
14309
14310 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14311 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
14312
14313 /* Paranoia. */
14314 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
14315 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14316
14317 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
14318 AssertRC(rc);
14319
14320 /*
14321 * Raise #DB in the guest.
14322 *
14323 * It is important to reflect exactly what the VM-exit gave us (preserving the
14324 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14325 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14326 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14327 *
14328 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14329 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14330 */
14331 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14332 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14333 return VINF_SUCCESS;
14334 }
14335
14336 /*
14337 * Not a guest trap, must be a hypervisor related debug event then.
14338 * Update DR6 in case someone is interested in it.
14339 */
14340 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14341 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14342 CPUMSetHyperDR6(pVCpu, uDR6);
14343
14344 return rc;
14345}
14346
14347
14348/**
14349 * Hacks its way around the lovely mesa driver's backdoor accesses.
14350 *
14351 * @sa hmR0SvmHandleMesaDrvGp.
14352 */
14353static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14354{
14355 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14356 RT_NOREF(pCtx);
14357
14358 /* For now we'll just skip the instruction. */
14359 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14360}
14361
14362
14363/**
14364 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14365 * backdoor logging w/o checking what it is running inside.
14366 *
14367 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14368 * backdoor port and magic numbers loaded in registers.
14369 *
14370 * @returns true if it is, false if it isn't.
14371 * @sa hmR0SvmIsMesaDrvGp.
14372 */
14373DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14374{
14375 /* 0xed: IN eAX,dx */
14376 uint8_t abInstr[1];
14377 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
14378 return false;
14379
14380 /* Check that it is #GP(0). */
14381 if (pVmxTransient->uExitIntErrorCode != 0)
14382 return false;
14383
14384 /* Check magic and port. */
14385 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14386 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14387 if (pCtx->rax != UINT32_C(0x564d5868))
14388 return false;
14389 if (pCtx->dx != UINT32_C(0x5658))
14390 return false;
14391
14392 /* Flat ring-3 CS. */
14393 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14394 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14395 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14396 if (pCtx->cs.Attr.n.u2Dpl != 3)
14397 return false;
14398 if (pCtx->cs.u64Base != 0)
14399 return false;
14400
14401 /* Check opcode. */
14402 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14403 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14404 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14405 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14406 if (RT_FAILURE(rc))
14407 return false;
14408 if (abInstr[0] != 0xed)
14409 return false;
14410
14411 return true;
14412}
14413
14414
14415/**
14416 * VM-exit exception handler for \#GP (General-protection exception).
14417 *
14418 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14419 */
14420static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14421{
14422 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14423 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14424
14425 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14426 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14427 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
14428 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
14429 { /* likely */ }
14430 else
14431 {
14432#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14433 Assert(pVCpu->hmr0.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14434#endif
14435 /*
14436 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14437 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14438 */
14439 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14440 AssertRCReturn(rc, rc);
14441 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14442 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14443
14444 if ( pVmxTransient->fIsNestedGuest
14445 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14446 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14447 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14448 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14449 else
14450 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14451 return rc;
14452 }
14453
14454 Assert(CPUMIsGuestInRealModeEx(pCtx));
14455 Assert(!pVCpu->CTX_SUFF(pVM)->hmr0.s.vmx.fUnrestrictedGuest);
14456 Assert(!pVmxTransient->fIsNestedGuest);
14457
14458 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14459 AssertRCReturn(rc, rc);
14460
14461 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14462 if (rcStrict == VINF_SUCCESS)
14463 {
14464 if (!CPUMIsGuestInRealModeEx(pCtx))
14465 {
14466 /*
14467 * The guest is no longer in real-mode, check if we can continue executing the
14468 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14469 */
14470 pVmcsInfoShared->RealMode.fRealOnV86Active = false;
14471 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
14472 {
14473 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14474 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14475 }
14476 else
14477 {
14478 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14479 rcStrict = VINF_EM_RESCHEDULE;
14480 }
14481 }
14482 else
14483 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14484 }
14485 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14486 {
14487 rcStrict = VINF_SUCCESS;
14488 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14489 }
14490 return VBOXSTRICTRC_VAL(rcStrict);
14491}
14492
14493
14494/**
14495 * VM-exit exception handler wrapper for all other exceptions that are not handled
14496 * by a specific handler.
14497 *
14498 * This simply re-injects the exception back into the VM without any special
14499 * processing.
14500 *
14501 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14502 */
14503static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14504{
14505 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14506
14507#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14508 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14509 AssertMsg(pVCpu->hmr0.s.fUsingDebugLoop || pVmcsInfo->pShared->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14510 ("uVector=%#x u32XcptBitmap=%#X32\n",
14511 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14512 NOREF(pVmcsInfo);
14513#endif
14514
14515 /*
14516 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14517 * would have been handled while checking exits due to event delivery.
14518 */
14519 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14520
14521#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14522 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14523 AssertRCReturn(rc, rc);
14524 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14525#endif
14526
14527#ifdef VBOX_WITH_STATISTICS
14528 switch (uVector)
14529 {
14530 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14531 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14532 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14533 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14534 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14535 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14536 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14537 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14538 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14539 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14540 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14541 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14542 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14543 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14544 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14545 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14546 default:
14547 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14548 break;
14549 }
14550#endif
14551
14552 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14553 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14554 NOREF(uVector);
14555
14556 /* Re-inject the original exception into the guest. */
14557 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14558 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14559 return VINF_SUCCESS;
14560}
14561
14562
14563/**
14564 * VM-exit exception handler for all exceptions (except NMIs!).
14565 *
14566 * @remarks This may be called for both guests and nested-guests. Take care to not
14567 * make assumptions and avoid doing anything that is not relevant when
14568 * executing a nested-guest (e.g., Mesa driver hacks).
14569 */
14570static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14571{
14572 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14573
14574 /*
14575 * If this VM-exit occurred while delivering an event through the guest IDT, take
14576 * action based on the return code and additional hints (e.g. for page-faults)
14577 * that will be updated in the VMX transient structure.
14578 */
14579 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14580 if (rcStrict == VINF_SUCCESS)
14581 {
14582 /*
14583 * If an exception caused a VM-exit due to delivery of an event, the original
14584 * event may have to be re-injected into the guest. We shall reinject it and
14585 * continue guest execution. However, page-fault is a complicated case and
14586 * needs additional processing done in hmR0VmxExitXcptPF().
14587 */
14588 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14589 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14590 if ( !pVCpu->hm.s.Event.fPending
14591 || uVector == X86_XCPT_PF)
14592 {
14593 switch (uVector)
14594 {
14595 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14596 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14597 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14598 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14599 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14600 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14601 default:
14602 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14603 }
14604 }
14605 /* else: inject pending event before resuming guest execution. */
14606 }
14607 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14608 {
14609 Assert(pVCpu->hm.s.Event.fPending);
14610 rcStrict = VINF_SUCCESS;
14611 }
14612
14613 return rcStrict;
14614}
14615/** @} */
14616
14617
14618/** @name VM-exit handlers.
14619 * @{
14620 */
14621/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14622/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14623/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14624
14625/**
14626 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14627 */
14628HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14629{
14630 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14631 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14632 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14633 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14634 return VINF_SUCCESS;
14635 return VINF_EM_RAW_INTERRUPT;
14636}
14637
14638
14639/**
14640 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14641 * VM-exit.
14642 */
14643HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14644{
14645 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14646 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14647
14648 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14649
14650 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14651 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14652 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14653
14654 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14655 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14656 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14657 NOREF(pVmcsInfo);
14658
14659 VBOXSTRICTRC rcStrict;
14660 switch (uExitIntType)
14661 {
14662 /*
14663 * Host physical NMIs:
14664 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14665 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14666 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14667 *
14668 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14669 * See Intel spec. 27.5.5 "Updating Non-Register State".
14670 */
14671 case VMX_EXIT_INT_INFO_TYPE_NMI:
14672 {
14673 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14674 break;
14675 }
14676
14677 /*
14678 * Privileged software exceptions (#DB from ICEBP),
14679 * Software exceptions (#BP and #OF),
14680 * Hardware exceptions:
14681 * Process the required exceptions and resume guest execution if possible.
14682 */
14683 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14684 Assert(uVector == X86_XCPT_DB);
14685 RT_FALL_THRU();
14686 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14687 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14688 RT_FALL_THRU();
14689 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14690 {
14691 NOREF(uVector);
14692 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14693 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14694 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14695 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14696
14697 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14698 break;
14699 }
14700
14701 default:
14702 {
14703 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14704 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14705 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14706 break;
14707 }
14708 }
14709
14710 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14711 return rcStrict;
14712}
14713
14714
14715/**
14716 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14717 */
14718HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14719{
14720 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14721
14722 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14723 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14724 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14725
14726 /* Evaluate and deliver pending events and resume guest execution. */
14727 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14728 return VINF_SUCCESS;
14729}
14730
14731
14732/**
14733 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14734 */
14735HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14736{
14737 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14738
14739 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14740 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14741 {
14742 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14743 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14744 }
14745
14746 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14747
14748 /*
14749 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14750 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14751 */
14752 uint32_t fIntrState;
14753 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14754 AssertRC(rc);
14755 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14756 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14757 {
14758 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14759 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14760
14761 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14762 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14763 AssertRC(rc);
14764 }
14765
14766 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14767 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14768
14769 /* Evaluate and deliver pending events and resume guest execution. */
14770 return VINF_SUCCESS;
14771}
14772
14773
14774/**
14775 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14776 */
14777HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14778{
14779 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14780 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14781}
14782
14783
14784/**
14785 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14786 */
14787HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14788{
14789 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14790 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14791}
14792
14793
14794/**
14795 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14796 */
14797HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14798{
14799 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14800
14801 /*
14802 * Get the state we need and update the exit history entry.
14803 */
14804 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14805 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14806
14807 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14808 AssertRCReturn(rc, rc);
14809
14810 VBOXSTRICTRC rcStrict;
14811 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14812 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14813 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14814 if (!pExitRec)
14815 {
14816 /*
14817 * Regular CPUID instruction execution.
14818 */
14819 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14820 if (rcStrict == VINF_SUCCESS)
14821 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14822 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14823 {
14824 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14825 rcStrict = VINF_SUCCESS;
14826 }
14827 }
14828 else
14829 {
14830 /*
14831 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14832 */
14833 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14834 AssertRCReturn(rc2, rc2);
14835
14836 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14837 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14838
14839 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14840 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14841
14842 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14843 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14844 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14845 }
14846 return rcStrict;
14847}
14848
14849
14850/**
14851 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14852 */
14853HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14854{
14855 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14856
14857 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14858 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14859 AssertRCReturn(rc, rc);
14860
14861 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14862 return VINF_EM_RAW_EMULATE_INSTR;
14863
14864 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14865 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14866}
14867
14868
14869/**
14870 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14871 */
14872HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14873{
14874 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14875
14876 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14877 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14878 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14879 AssertRCReturn(rc, rc);
14880
14881 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14882 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14883 {
14884 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14885 we must reset offsetting on VM-entry. See @bugref{6634}. */
14886 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14887 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14888 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14889 }
14890 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14891 {
14892 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14893 rcStrict = VINF_SUCCESS;
14894 }
14895 return rcStrict;
14896}
14897
14898
14899/**
14900 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14901 */
14902HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14903{
14904 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14905
14906 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14907 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14908 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14909 AssertRCReturn(rc, rc);
14910
14911 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14912 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14913 {
14914 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14915 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14916 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14917 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14918 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14919 }
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}
14927
14928
14929/**
14930 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14931 */
14932HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14933{
14934 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14935
14936 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14937 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14938 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14939 AssertRCReturn(rc, rc);
14940
14941 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14942 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14943 if (RT_LIKELY(rc == VINF_SUCCESS))
14944 {
14945 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14946 Assert(pVmxTransient->cbExitInstr == 2);
14947 }
14948 else
14949 {
14950 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14951 rc = VERR_EM_INTERPRETER;
14952 }
14953 return rc;
14954}
14955
14956
14957/**
14958 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14959 */
14960HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14961{
14962 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14963
14964 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14965 if (EMAreHypercallInstructionsEnabled(pVCpu))
14966 {
14967 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14968 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14969 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14970 AssertRCReturn(rc, rc);
14971
14972 /* Perform the hypercall. */
14973 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14974 if (rcStrict == VINF_SUCCESS)
14975 {
14976 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14977 AssertRCReturn(rc, rc);
14978 }
14979 else
14980 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14981 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14982 || RT_FAILURE(rcStrict));
14983
14984 /* If the hypercall changes anything other than guest's general-purpose registers,
14985 we would need to reload the guest changed bits here before VM-entry. */
14986 }
14987 else
14988 Log4Func(("Hypercalls not enabled\n"));
14989
14990 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14991 if (RT_FAILURE(rcStrict))
14992 {
14993 hmR0VmxSetPendingXcptUD(pVCpu);
14994 rcStrict = VINF_SUCCESS;
14995 }
14996
14997 return rcStrict;
14998}
14999
15000
15001/**
15002 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
15003 */
15004HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15005{
15006 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15007 Assert(!pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging || pVCpu->hmr0.s.fUsingDebugLoop);
15008
15009 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15010 hmR0VmxReadExitQualVmcs(pVmxTransient);
15011 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15012 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15013 AssertRCReturn(rc, rc);
15014
15015 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
15016
15017 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
15018 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15019 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15020 {
15021 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15022 rcStrict = VINF_SUCCESS;
15023 }
15024 else
15025 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
15026 VBOXSTRICTRC_VAL(rcStrict)));
15027 return rcStrict;
15028}
15029
15030
15031/**
15032 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
15033 */
15034HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15035{
15036 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15037
15038 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15039 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15040 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
15041 AssertRCReturn(rc, rc);
15042
15043 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
15044 if (rcStrict == VINF_SUCCESS)
15045 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15046 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15047 {
15048 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15049 rcStrict = VINF_SUCCESS;
15050 }
15051
15052 return rcStrict;
15053}
15054
15055
15056/**
15057 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
15058 */
15059HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15060{
15061 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15062
15063 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15064 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15065 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15066 AssertRCReturn(rc, rc);
15067
15068 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
15069 if (RT_SUCCESS(rcStrict))
15070 {
15071 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15072 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
15073 rcStrict = VINF_SUCCESS;
15074 }
15075
15076 return rcStrict;
15077}
15078
15079
15080/**
15081 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
15082 * VM-exit.
15083 */
15084HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15085{
15086 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15087 return VINF_EM_RESET;
15088}
15089
15090
15091/**
15092 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
15093 */
15094HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15095{
15096 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15097
15098 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15099 AssertRCReturn(rc, rc);
15100
15101 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
15102 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
15103 rc = VINF_SUCCESS;
15104 else
15105 rc = VINF_EM_HALT;
15106
15107 if (rc != VINF_SUCCESS)
15108 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
15109 return rc;
15110}
15111
15112
15113/**
15114 * VM-exit handler for instructions that result in a \#UD exception delivered to
15115 * the guest.
15116 */
15117HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15118{
15119 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15120 hmR0VmxSetPendingXcptUD(pVCpu);
15121 return VINF_SUCCESS;
15122}
15123
15124
15125/**
15126 * VM-exit handler for expiry of the VMX-preemption timer.
15127 */
15128HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15129{
15130 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15131
15132 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
15133 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15134Log12(("hmR0VmxExitPreemptTimer:\n"));
15135
15136 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
15137 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15138 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
15139 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
15140 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
15141}
15142
15143
15144/**
15145 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
15146 */
15147HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15148{
15149 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15150
15151 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15152 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15153 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15154 AssertRCReturn(rc, rc);
15155
15156 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
15157 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15158 : HM_CHANGED_RAISED_XCPT_MASK);
15159
15160 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15161 bool const fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15162 if (fLoadSaveGuestXcr0 != pVCpu->hmr0.s.fLoadSaveGuestXcr0)
15163 {
15164 pVCpu->hmr0.s.fLoadSaveGuestXcr0 = fLoadSaveGuestXcr0;
15165 hmR0VmxUpdateStartVmFunction(pVCpu);
15166 }
15167
15168 return rcStrict;
15169}
15170
15171
15172/**
15173 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15174 */
15175HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15176{
15177 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15178
15179 /** @todo Enable the new code after finding a reliably guest test-case. */
15180#if 1
15181 return VERR_EM_INTERPRETER;
15182#else
15183 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15184 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15185 hmR0VmxReadExitQualVmcs(pVmxTransient);
15186 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15187 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15188 AssertRCReturn(rc, rc);
15189
15190 /* Paranoia. Ensure this has a memory operand. */
15191 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
15192
15193 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
15194 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
15195 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
15196 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
15197
15198 RTGCPTR GCPtrDesc;
15199 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
15200
15201 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
15202 GCPtrDesc, uType);
15203 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15204 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15205 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15206 {
15207 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15208 rcStrict = VINF_SUCCESS;
15209 }
15210 return rcStrict;
15211#endif
15212}
15213
15214
15215/**
15216 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15217 * VM-exit.
15218 */
15219HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15220{
15221 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15222 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15223 AssertRCReturn(rc, rc);
15224
15225 rc = hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15226 if (RT_FAILURE(rc))
15227 return rc;
15228
15229 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15230 NOREF(uInvalidReason);
15231
15232#ifdef VBOX_STRICT
15233 uint32_t fIntrState;
15234 uint64_t u64Val;
15235 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15236 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15237 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15238
15239 Log4(("uInvalidReason %u\n", uInvalidReason));
15240 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15241 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15242 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15243
15244 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
15245 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15246 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
15247 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
15248 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
15249 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
15250 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
15251 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
15252 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
15253 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
15254 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
15255 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
15256 if (pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging)
15257 {
15258 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15259 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15260 }
15261 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
15262#endif
15263
15264 return VERR_VMX_INVALID_GUEST_STATE;
15265}
15266
15267/**
15268 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15269 */
15270HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15271{
15272 /*
15273 * Cumulative notes of all recognized but unexpected VM-exits.
15274 *
15275 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
15276 * nested-paging is used.
15277 *
15278 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15279 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15280 * this function (and thereby stop VM execution) for handling such instructions.
15281 *
15282 *
15283 * VMX_EXIT_INIT_SIGNAL:
15284 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15285 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15286 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15287 *
15288 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15289 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15290 * See Intel spec. "23.8 Restrictions on VMX operation".
15291 *
15292 * VMX_EXIT_SIPI:
15293 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15294 * activity state is used. We don't make use of it as our guests don't have direct
15295 * access to the host local APIC.
15296 *
15297 * See Intel spec. 25.3 "Other Causes of VM-exits".
15298 *
15299 * VMX_EXIT_IO_SMI:
15300 * VMX_EXIT_SMI:
15301 * This can only happen if we support dual-monitor treatment of SMI, which can be
15302 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15303 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15304 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15305 *
15306 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15307 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15308 *
15309 * VMX_EXIT_ERR_MSR_LOAD:
15310 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15311 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15312 * execution.
15313 *
15314 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15315 *
15316 * VMX_EXIT_ERR_MACHINE_CHECK:
15317 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15318 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15319 * #MC exception abort class exception is raised. We thus cannot assume a
15320 * reasonable chance of continuing any sort of execution and we bail.
15321 *
15322 * See Intel spec. 15.1 "Machine-check Architecture".
15323 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15324 *
15325 * VMX_EXIT_PML_FULL:
15326 * VMX_EXIT_VIRTUALIZED_EOI:
15327 * VMX_EXIT_APIC_WRITE:
15328 * We do not currently support any of these features and thus they are all unexpected
15329 * VM-exits.
15330 *
15331 * VMX_EXIT_GDTR_IDTR_ACCESS:
15332 * VMX_EXIT_LDTR_TR_ACCESS:
15333 * VMX_EXIT_RDRAND:
15334 * VMX_EXIT_RSM:
15335 * VMX_EXIT_VMFUNC:
15336 * VMX_EXIT_ENCLS:
15337 * VMX_EXIT_RDSEED:
15338 * VMX_EXIT_XSAVES:
15339 * VMX_EXIT_XRSTORS:
15340 * VMX_EXIT_UMWAIT:
15341 * VMX_EXIT_TPAUSE:
15342 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15343 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15344 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15345 *
15346 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15347 */
15348 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15349 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15350 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15351}
15352
15353
15354/**
15355 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15356 */
15357HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15358{
15359 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15360
15361 /** @todo Optimize this: We currently drag in the whole MSR state
15362 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15363 * MSRs required. That would require changes to IEM and possibly CPUM too.
15364 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15365 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15366 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15367 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15368 switch (idMsr)
15369 {
15370 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15371 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15372 }
15373
15374 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15375 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15376 AssertRCReturn(rc, rc);
15377
15378 Log4Func(("ecx=%#RX32\n", idMsr));
15379
15380#ifdef VBOX_STRICT
15381 Assert(!pVmxTransient->fIsNestedGuest);
15382 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15383 {
15384 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15385 && idMsr != MSR_K6_EFER)
15386 {
15387 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15388 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15389 }
15390 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15391 {
15392 Assert(pVmcsInfo->pvMsrBitmap);
15393 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15394 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15395 {
15396 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15397 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15398 }
15399 }
15400 }
15401#endif
15402
15403 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
15404 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15405 if (rcStrict == VINF_SUCCESS)
15406 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15407 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15408 {
15409 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15410 rcStrict = VINF_SUCCESS;
15411 }
15412 else
15413 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ || rcStrict == VINF_EM_TRIPLE_FAULT,
15414 ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15415
15416 return rcStrict;
15417}
15418
15419
15420/**
15421 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15422 */
15423HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15424{
15425 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15426
15427 /** @todo Optimize this: We currently drag in the whole MSR state
15428 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15429 * MSRs required. That would require changes to IEM and possibly CPUM too.
15430 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15431 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15432 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15433
15434 /*
15435 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15436 * Although we don't need to fetch the base as it will be overwritten shortly, while
15437 * loading guest-state we would also load the entire segment register including limit
15438 * and attributes and thus we need to load them here.
15439 */
15440 switch (idMsr)
15441 {
15442 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15443 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15444 }
15445
15446 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15447 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15448 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15449 AssertRCReturn(rc, rc);
15450
15451 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15452
15453 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
15454 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15455
15456 if (rcStrict == VINF_SUCCESS)
15457 {
15458 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15459
15460 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15461 if ( idMsr == MSR_IA32_APICBASE
15462 || ( idMsr >= MSR_IA32_X2APIC_START
15463 && idMsr <= MSR_IA32_X2APIC_END))
15464 {
15465 /*
15466 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15467 * When full APIC register virtualization is implemented we'll have to make
15468 * sure APIC state is saved from the VMCS before IEM changes it.
15469 */
15470 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15471 }
15472 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15473 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15474 else if (idMsr == MSR_K6_EFER)
15475 {
15476 /*
15477 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15478 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15479 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15480 */
15481 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15482 }
15483
15484 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15485 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15486 {
15487 switch (idMsr)
15488 {
15489 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15490 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15491 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15492 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15493 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15494 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15495 default:
15496 {
15497 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15498 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15499 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15500 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15501 break;
15502 }
15503 }
15504 }
15505#ifdef VBOX_STRICT
15506 else
15507 {
15508 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15509 switch (idMsr)
15510 {
15511 case MSR_IA32_SYSENTER_CS:
15512 case MSR_IA32_SYSENTER_EIP:
15513 case MSR_IA32_SYSENTER_ESP:
15514 case MSR_K8_FS_BASE:
15515 case MSR_K8_GS_BASE:
15516 {
15517 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15518 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15519 }
15520
15521 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15522 default:
15523 {
15524 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15525 {
15526 /* EFER MSR writes are always intercepted. */
15527 if (idMsr != MSR_K6_EFER)
15528 {
15529 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15530 idMsr));
15531 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15532 }
15533 }
15534
15535 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15536 {
15537 Assert(pVmcsInfo->pvMsrBitmap);
15538 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15539 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15540 {
15541 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15542 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15543 }
15544 }
15545 break;
15546 }
15547 }
15548 }
15549#endif /* VBOX_STRICT */
15550 }
15551 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15552 {
15553 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15554 rcStrict = VINF_SUCCESS;
15555 }
15556 else
15557 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE || rcStrict == VINF_EM_TRIPLE_FAULT,
15558 ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15559
15560 return rcStrict;
15561}
15562
15563
15564/**
15565 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15566 */
15567HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15568{
15569 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15570
15571 /** @todo The guest has likely hit a contended spinlock. We might want to
15572 * poke a schedule different guest VCPU. */
15573 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15574 if (RT_SUCCESS(rc))
15575 return VINF_EM_RAW_INTERRUPT;
15576
15577 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15578 return rc;
15579}
15580
15581
15582/**
15583 * VM-exit handler for when the TPR value is lowered below the specified
15584 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15585 */
15586HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15587{
15588 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15589 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15590
15591 /*
15592 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15593 * We'll re-evaluate pending interrupts and inject them before the next VM
15594 * entry so we can just continue execution here.
15595 */
15596 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15597 return VINF_SUCCESS;
15598}
15599
15600
15601/**
15602 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15603 * VM-exit.
15604 *
15605 * @retval VINF_SUCCESS when guest execution can continue.
15606 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15607 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15608 * incompatible guest state for VMX execution (real-on-v86 case).
15609 */
15610HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15611{
15612 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15613 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15614
15615 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15616 hmR0VmxReadExitQualVmcs(pVmxTransient);
15617 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15618
15619 VBOXSTRICTRC rcStrict;
15620 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15621 uint64_t const uExitQual = pVmxTransient->uExitQual;
15622 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15623 switch (uAccessType)
15624 {
15625 /*
15626 * MOV to CRx.
15627 */
15628 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15629 {
15630 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15631 AssertRCReturn(rc, rc);
15632
15633 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15634 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15635 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15636 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15637
15638 /*
15639 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15640 * - When nested paging isn't used.
15641 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15642 * - We are executing in the VM debug loop.
15643 */
15644 Assert( iCrReg != 3
15645 || !pVM->hmr0.s.fNestedPaging
15646 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15647 || pVCpu->hmr0.s.fUsingDebugLoop);
15648
15649 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15650 Assert( iCrReg != 8
15651 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15652
15653 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15654 AssertMsg( rcStrict == VINF_SUCCESS
15655 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15656
15657 /*
15658 * This is a kludge for handling switches back to real mode when we try to use
15659 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15660 * deal with special selector values, so we have to return to ring-3 and run
15661 * there till the selector values are V86 mode compatible.
15662 *
15663 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15664 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15665 * this function.
15666 */
15667 if ( iCrReg == 0
15668 && rcStrict == VINF_SUCCESS
15669 && !pVM->hmr0.s.vmx.fUnrestrictedGuest
15670 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15671 && (uOldCr0 & X86_CR0_PE)
15672 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15673 {
15674 /** @todo Check selectors rather than returning all the time. */
15675 Assert(!pVmxTransient->fIsNestedGuest);
15676 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15677 rcStrict = VINF_EM_RESCHEDULE_REM;
15678 }
15679 break;
15680 }
15681
15682 /*
15683 * MOV from CRx.
15684 */
15685 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15686 {
15687 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15688 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15689
15690 /*
15691 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15692 * - When nested paging isn't used.
15693 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15694 * - We are executing in the VM debug loop.
15695 */
15696 Assert( iCrReg != 3
15697 || !pVM->hmr0.s.fNestedPaging
15698 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15699 || pVCpu->hmr0.s.fLeaveDone);
15700
15701 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15702 Assert( iCrReg != 8
15703 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15704
15705 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15706 break;
15707 }
15708
15709 /*
15710 * CLTS (Clear Task-Switch Flag in CR0).
15711 */
15712 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15713 {
15714 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15715 break;
15716 }
15717
15718 /*
15719 * LMSW (Load Machine-Status Word into CR0).
15720 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15721 */
15722 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15723 {
15724 RTGCPTR GCPtrEffDst;
15725 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15726 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15727 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15728 if (fMemOperand)
15729 {
15730 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15731 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15732 }
15733 else
15734 GCPtrEffDst = NIL_RTGCPTR;
15735 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15736 break;
15737 }
15738
15739 default:
15740 {
15741 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15742 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15743 }
15744 }
15745
15746 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15747 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15748 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15749
15750 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15751 NOREF(pVM);
15752 return rcStrict;
15753}
15754
15755
15756/**
15757 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15758 * VM-exit.
15759 */
15760HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15761{
15762 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15763 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15764
15765 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15766 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15767 hmR0VmxReadExitQualVmcs(pVmxTransient);
15768 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15769 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15770 | CPUMCTX_EXTRN_EFER);
15771 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15772 AssertRCReturn(rc, rc);
15773
15774 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15775 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15776 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15777 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15778 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15779 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15780 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15781 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15782
15783 /*
15784 * Update exit history to see if this exit can be optimized.
15785 */
15786 VBOXSTRICTRC rcStrict;
15787 PCEMEXITREC pExitRec = NULL;
15788 if ( !fGstStepping
15789 && !fDbgStepping)
15790 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15791 !fIOString
15792 ? !fIOWrite
15793 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15794 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15795 : !fIOWrite
15796 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15797 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15798 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15799 if (!pExitRec)
15800 {
15801 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15802 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15803
15804 uint32_t const cbValue = s_aIOSizes[uIOSize];
15805 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15806 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15807 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15808 if (fIOString)
15809 {
15810 /*
15811 * INS/OUTS - I/O String instruction.
15812 *
15813 * Use instruction-information if available, otherwise fall back on
15814 * interpreting the instruction.
15815 */
15816 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15817 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15818 bool const fInsOutsInfo = RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15819 if (fInsOutsInfo)
15820 {
15821 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15822 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15823 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15824 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15825 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15826 if (fIOWrite)
15827 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15828 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15829 else
15830 {
15831 /*
15832 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15833 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15834 * See Intel Instruction spec. for "INS".
15835 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15836 */
15837 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15838 }
15839 }
15840 else
15841 rcStrict = IEMExecOne(pVCpu);
15842
15843 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15844 fUpdateRipAlready = true;
15845 }
15846 else
15847 {
15848 /*
15849 * IN/OUT - I/O instruction.
15850 */
15851 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15852 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15853 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15854 if (fIOWrite)
15855 {
15856 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15857 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15858 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15859 && !pCtx->eflags.Bits.u1TF)
15860 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15861 }
15862 else
15863 {
15864 uint32_t u32Result = 0;
15865 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15866 if (IOM_SUCCESS(rcStrict))
15867 {
15868 /* Save result of I/O IN instr. in AL/AX/EAX. */
15869 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15870 }
15871 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15872 && !pCtx->eflags.Bits.u1TF)
15873 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15874 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15875 }
15876 }
15877
15878 if (IOM_SUCCESS(rcStrict))
15879 {
15880 if (!fUpdateRipAlready)
15881 {
15882 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15883 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15884 }
15885
15886 /*
15887 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15888 * while booting Fedora 17 64-bit guest.
15889 *
15890 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15891 */
15892 if (fIOString)
15893 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15894
15895 /*
15896 * If any I/O breakpoints are armed, we need to check if one triggered
15897 * and take appropriate action.
15898 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15899 */
15900 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15901 AssertRCReturn(rc, rc);
15902
15903 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15904 * execution engines about whether hyper BPs and such are pending. */
15905 uint32_t const uDr7 = pCtx->dr[7];
15906 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15907 && X86_DR7_ANY_RW_IO(uDr7)
15908 && (pCtx->cr4 & X86_CR4_DE))
15909 || DBGFBpIsHwIoArmed(pVM)))
15910 {
15911 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15912
15913 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15914 VMMRZCallRing3Disable(pVCpu);
15915 HM_DISABLE_PREEMPT(pVCpu);
15916
15917 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15918
15919 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15920 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15921 {
15922 /* Raise #DB. */
15923 if (fIsGuestDbgActive)
15924 ASMSetDR6(pCtx->dr[6]);
15925 if (pCtx->dr[7] != uDr7)
15926 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15927
15928 hmR0VmxSetPendingXcptDB(pVCpu);
15929 }
15930 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15931 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15932 else if ( rcStrict2 != VINF_SUCCESS
15933 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15934 rcStrict = rcStrict2;
15935 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15936
15937 HM_RESTORE_PREEMPT();
15938 VMMRZCallRing3Enable(pVCpu);
15939 }
15940 }
15941
15942#ifdef VBOX_STRICT
15943 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15944 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15945 Assert(!fIOWrite);
15946 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15947 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15948 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15949 Assert(fIOWrite);
15950 else
15951 {
15952# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15953 * statuses, that the VMM device and some others may return. See
15954 * IOM_SUCCESS() for guidance. */
15955 AssertMsg( RT_FAILURE(rcStrict)
15956 || rcStrict == VINF_SUCCESS
15957 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15958 || rcStrict == VINF_EM_DBG_BREAKPOINT
15959 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15960 || rcStrict == VINF_EM_RAW_TO_R3
15961 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15962# endif
15963 }
15964#endif
15965 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15966 }
15967 else
15968 {
15969 /*
15970 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15971 */
15972 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15973 AssertRCReturn(rc2, rc2);
15974 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15975 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15976 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15977 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15978 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15979 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15980
15981 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15982 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15983
15984 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15985 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15986 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15987 }
15988 return rcStrict;
15989}
15990
15991
15992/**
15993 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15994 * VM-exit.
15995 */
15996HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15997{
15998 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15999
16000 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
16001 hmR0VmxReadExitQualVmcs(pVmxTransient);
16002 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
16003 {
16004 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16005 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16006 {
16007 uint32_t uErrCode;
16008 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
16009 {
16010 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16011 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
16012 }
16013 else
16014 uErrCode = 0;
16015
16016 RTGCUINTPTR GCPtrFaultAddress;
16017 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
16018 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
16019 else
16020 GCPtrFaultAddress = 0;
16021
16022 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16023
16024 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
16025 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
16026
16027 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
16028 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
16029 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16030 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16031 }
16032 }
16033
16034 /* Fall back to the interpreter to emulate the task-switch. */
16035 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16036 return VERR_EM_INTERPRETER;
16037}
16038
16039
16040/**
16041 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
16042 */
16043HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16044{
16045 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16046
16047 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16048 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
16049 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16050 AssertRC(rc);
16051 return VINF_EM_DBG_STEPPED;
16052}
16053
16054
16055/**
16056 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
16057 */
16058HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16059{
16060 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16061 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
16062
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 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
16076 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
16077 {
16078 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16079 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16080 }
16081 }
16082 else
16083 {
16084 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16085 return rcStrict;
16086 }
16087
16088 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
16089 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16090 hmR0VmxReadExitQualVmcs(pVmxTransient);
16091 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16092 AssertRCReturn(rc, rc);
16093
16094 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
16095 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
16096 switch (uAccessType)
16097 {
16098 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
16099 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
16100 {
16101 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
16102 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
16103 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
16104
16105 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
16106 GCPhys &= PAGE_BASE_GC_MASK;
16107 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
16108 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
16109 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
16110
16111 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
16112 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
16113 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16114 if ( rcStrict == VINF_SUCCESS
16115 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16116 || rcStrict == VERR_PAGE_NOT_PRESENT)
16117 {
16118 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16119 | HM_CHANGED_GUEST_APIC_TPR);
16120 rcStrict = VINF_SUCCESS;
16121 }
16122 break;
16123 }
16124
16125 default:
16126 {
16127 Log4Func(("uAccessType=%#x\n", uAccessType));
16128 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
16129 break;
16130 }
16131 }
16132
16133 if (rcStrict != VINF_SUCCESS)
16134 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
16135 return rcStrict;
16136}
16137
16138
16139/**
16140 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
16141 * VM-exit.
16142 */
16143HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16144{
16145 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16146 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16147
16148 /*
16149 * We might also get this VM-exit if the nested-guest isn't intercepting MOV DRx accesses.
16150 * In such a case, rather than disabling MOV DRx intercepts and resuming execution, we
16151 * must emulate the MOV DRx access.
16152 */
16153 if (!pVmxTransient->fIsNestedGuest)
16154 {
16155 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16156 if (pVmxTransient->fWasGuestDebugStateActive)
16157 {
16158 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16159 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16160 }
16161
16162 if ( !pVCpu->hm.s.fSingleInstruction
16163 && !pVmxTransient->fWasHyperDebugStateActive)
16164 {
16165 Assert(!DBGFIsStepping(pVCpu));
16166 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16167
16168 /* Don't intercept MOV DRx any more. */
16169 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16170 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16171 AssertRC(rc);
16172
16173 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16174 VMMRZCallRing3Disable(pVCpu);
16175 HM_DISABLE_PREEMPT(pVCpu);
16176
16177 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16178 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16179 Assert(CPUMIsGuestDebugStateActive(pVCpu));
16180
16181 HM_RESTORE_PREEMPT();
16182 VMMRZCallRing3Enable(pVCpu);
16183
16184#ifdef VBOX_WITH_STATISTICS
16185 hmR0VmxReadExitQualVmcs(pVmxTransient);
16186 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16187 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16188 else
16189 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16190#endif
16191 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16192 return VINF_SUCCESS;
16193 }
16194 }
16195
16196 /*
16197 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16198 * The EFER MSR is always up-to-date.
16199 * Update the segment registers and DR7 from the CPU.
16200 */
16201 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16202 hmR0VmxReadExitQualVmcs(pVmxTransient);
16203 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16204 AssertRCReturn(rc, rc);
16205 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16206
16207 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16208 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16209 {
16210 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16211 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16212 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16213 if (RT_SUCCESS(rc))
16214 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16215 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16216 }
16217 else
16218 {
16219 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16220 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16221 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16222 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16223 }
16224
16225 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16226 if (RT_SUCCESS(rc))
16227 {
16228 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16229 AssertRCReturn(rc2, rc2);
16230 return VINF_SUCCESS;
16231 }
16232 return rc;
16233}
16234
16235
16236/**
16237 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16238 * Conditional VM-exit.
16239 */
16240HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16241{
16242 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16243 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16244
16245 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16246 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16247 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16248 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16249 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16250
16251 /*
16252 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16253 */
16254 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16255 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16256 {
16257 /*
16258 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16259 * instruction emulation to inject the original event. Otherwise, injecting the original event
16260 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
16261 */
16262 if (!pVCpu->hm.s.Event.fPending)
16263 { /* likely */ }
16264 else
16265 {
16266 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16267#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16268 /** @todo NSTVMX: Think about how this should be handled. */
16269 if (pVmxTransient->fIsNestedGuest)
16270 return VERR_VMX_IPE_3;
16271#endif
16272 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16273 }
16274 }
16275 else
16276 {
16277 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16278 return rcStrict;
16279 }
16280
16281 /*
16282 * Get sufficient state and update the exit history entry.
16283 */
16284 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16285 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16286 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16287 AssertRCReturn(rc, rc);
16288
16289 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16290 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16291 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16292 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16293 if (!pExitRec)
16294 {
16295 /*
16296 * If we succeed, resume guest execution.
16297 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16298 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16299 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16300 * weird case. See @bugref{6043}.
16301 */
16302 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16303 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16304/** @todo bird: We can probably just go straight to IOM here and assume that
16305 * it's MMIO, then fall back on PGM if that hunch didn't work out so
16306 * well. However, we need to address that aliasing workarounds that
16307 * PGMR0Trap0eHandlerNPMisconfig implements. So, some care is needed.
16308 *
16309 * Might also be interesting to see if we can get this done more or
16310 * less locklessly inside IOM. Need to consider the lookup table
16311 * updating and use a bit more carefully first (or do all updates via
16312 * rendezvous) */
16313 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16314 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16315 if ( rcStrict == VINF_SUCCESS
16316 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16317 || rcStrict == VERR_PAGE_NOT_PRESENT)
16318 {
16319 /* Successfully handled MMIO operation. */
16320 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16321 | HM_CHANGED_GUEST_APIC_TPR);
16322 rcStrict = VINF_SUCCESS;
16323 }
16324 }
16325 else
16326 {
16327 /*
16328 * Frequent exit or something needing probing. Call EMHistoryExec.
16329 */
16330 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16331 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16332
16333 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16334 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16335
16336 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16337 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16338 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16339 }
16340 return rcStrict;
16341}
16342
16343
16344/**
16345 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16346 * VM-exit.
16347 */
16348HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16349{
16350 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16351 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16352
16353 hmR0VmxReadExitQualVmcs(pVmxTransient);
16354 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16355 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16356 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16357 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16358 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16359
16360 /*
16361 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16362 */
16363 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16364 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16365 {
16366 /*
16367 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16368 * we shall resolve the nested #PF and re-inject the original event.
16369 */
16370 if (pVCpu->hm.s.Event.fPending)
16371 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16372 }
16373 else
16374 {
16375 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16376 return rcStrict;
16377 }
16378
16379 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16380 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16381 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16382 AssertRCReturn(rc, rc);
16383
16384 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16385 uint64_t const uExitQual = pVmxTransient->uExitQual;
16386 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16387
16388 RTGCUINT uErrorCode = 0;
16389 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16390 uErrorCode |= X86_TRAP_PF_ID;
16391 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16392 uErrorCode |= X86_TRAP_PF_RW;
16393 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16394 uErrorCode |= X86_TRAP_PF_P;
16395
16396 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16397 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16398 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16399
16400 /*
16401 * Handle the pagefault trap for the nested shadow table.
16402 */
16403 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16404 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16405 TRPMResetTrap(pVCpu);
16406
16407 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16408 if ( rcStrict == VINF_SUCCESS
16409 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16410 || rcStrict == VERR_PAGE_NOT_PRESENT)
16411 {
16412 /* Successfully synced our nested page tables. */
16413 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16414 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16415 return VINF_SUCCESS;
16416 }
16417
16418 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16419 return rcStrict;
16420}
16421
16422
16423#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16424/**
16425 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16426 */
16427HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16428{
16429 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16430
16431 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16432 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16433 hmR0VmxReadExitQualVmcs(pVmxTransient);
16434 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16435 | CPUMCTX_EXTRN_HWVIRT
16436 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16437 AssertRCReturn(rc, rc);
16438
16439 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16440
16441 VMXVEXITINFO ExitInfo;
16442 RT_ZERO(ExitInfo);
16443 ExitInfo.uReason = pVmxTransient->uExitReason;
16444 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16445 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16446 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16447 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16448
16449 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16450 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16451 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16452 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16453 {
16454 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16455 rcStrict = VINF_SUCCESS;
16456 }
16457 return rcStrict;
16458}
16459
16460
16461/**
16462 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16463 */
16464HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16465{
16466 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16467
16468 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16469 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16470 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16471 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16472 AssertRCReturn(rc, rc);
16473
16474 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16475
16476 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16477 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
16478 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16479 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16480 {
16481 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16482 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16483 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16484 }
16485 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16486 return rcStrict;
16487}
16488
16489
16490/**
16491 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16492 */
16493HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16494{
16495 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16496
16497 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16498 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16499 hmR0VmxReadExitQualVmcs(pVmxTransient);
16500 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16501 | CPUMCTX_EXTRN_HWVIRT
16502 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16503 AssertRCReturn(rc, rc);
16504
16505 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16506
16507 VMXVEXITINFO ExitInfo;
16508 RT_ZERO(ExitInfo);
16509 ExitInfo.uReason = pVmxTransient->uExitReason;
16510 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16511 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16512 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16513 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16514
16515 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16516 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16517 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16518 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16519 {
16520 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16521 rcStrict = VINF_SUCCESS;
16522 }
16523 return rcStrict;
16524}
16525
16526
16527/**
16528 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16529 */
16530HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16531{
16532 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16533
16534 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16535 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16536 hmR0VmxReadExitQualVmcs(pVmxTransient);
16537 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16538 | CPUMCTX_EXTRN_HWVIRT
16539 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16540 AssertRCReturn(rc, rc);
16541
16542 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16543
16544 VMXVEXITINFO ExitInfo;
16545 RT_ZERO(ExitInfo);
16546 ExitInfo.uReason = pVmxTransient->uExitReason;
16547 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16548 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16549 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16550 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16551
16552 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16553 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16554 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16555 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16556 {
16557 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16558 rcStrict = VINF_SUCCESS;
16559 }
16560 return rcStrict;
16561}
16562
16563
16564/**
16565 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16566 */
16567HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16568{
16569 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16570
16571 /*
16572 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16573 * thus might not need to import the shadow VMCS state, it's safer just in case
16574 * code elsewhere dares look at unsynced VMCS fields.
16575 */
16576 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16577 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16578 hmR0VmxReadExitQualVmcs(pVmxTransient);
16579 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16580 | CPUMCTX_EXTRN_HWVIRT
16581 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16582 AssertRCReturn(rc, rc);
16583
16584 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16585
16586 VMXVEXITINFO ExitInfo;
16587 RT_ZERO(ExitInfo);
16588 ExitInfo.uReason = pVmxTransient->uExitReason;
16589 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16590 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16591 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16592 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16593 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16594
16595 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16596 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16597 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16598 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16599 {
16600 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16601 rcStrict = VINF_SUCCESS;
16602 }
16603 return rcStrict;
16604}
16605
16606
16607/**
16608 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16609 */
16610HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16611{
16612 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16613
16614 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16615 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16616 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16617 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16618 AssertRCReturn(rc, rc);
16619
16620 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16621
16622 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16623 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16624 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16625 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16626 {
16627 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16628 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16629 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16630 }
16631 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16632 return rcStrict;
16633}
16634
16635
16636/**
16637 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16638 */
16639HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16640{
16641 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16642
16643 /*
16644 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16645 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16646 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16647 */
16648 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16649 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16650 hmR0VmxReadExitQualVmcs(pVmxTransient);
16651 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16652 | CPUMCTX_EXTRN_HWVIRT
16653 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16654 AssertRCReturn(rc, rc);
16655
16656 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16657
16658 VMXVEXITINFO ExitInfo;
16659 RT_ZERO(ExitInfo);
16660 ExitInfo.uReason = pVmxTransient->uExitReason;
16661 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16662 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16663 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16664 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16665 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16666
16667 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16668 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16669 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16670 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16671 {
16672 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16673 rcStrict = VINF_SUCCESS;
16674 }
16675 return rcStrict;
16676}
16677
16678
16679/**
16680 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16681 */
16682HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16683{
16684 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16685
16686 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16687 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16688 | CPUMCTX_EXTRN_HWVIRT
16689 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16690 AssertRCReturn(rc, rc);
16691
16692 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16693
16694 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16695 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16696 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16697 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16698 {
16699 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16700 rcStrict = VINF_SUCCESS;
16701 }
16702 return rcStrict;
16703}
16704
16705
16706/**
16707 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16708 */
16709HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16710{
16711 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16712
16713 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16714 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16715 hmR0VmxReadExitQualVmcs(pVmxTransient);
16716 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16717 | CPUMCTX_EXTRN_HWVIRT
16718 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16719 AssertRCReturn(rc, rc);
16720
16721 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16722
16723 VMXVEXITINFO ExitInfo;
16724 RT_ZERO(ExitInfo);
16725 ExitInfo.uReason = pVmxTransient->uExitReason;
16726 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16727 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16728 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16729 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16730
16731 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16732 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16733 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16734 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16735 {
16736 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16737 rcStrict = VINF_SUCCESS;
16738 }
16739 return rcStrict;
16740}
16741
16742
16743/**
16744 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16745 */
16746HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16747{
16748 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16749
16750 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16751 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16752 hmR0VmxReadExitQualVmcs(pVmxTransient);
16753 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16754 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16755 AssertRCReturn(rc, rc);
16756
16757 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16758
16759 VMXVEXITINFO ExitInfo;
16760 RT_ZERO(ExitInfo);
16761 ExitInfo.uReason = pVmxTransient->uExitReason;
16762 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16763 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16764 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16765 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16766
16767 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16768 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16769 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16770 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16771 {
16772 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16773 rcStrict = VINF_SUCCESS;
16774 }
16775 return rcStrict;
16776}
16777#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16778/** @} */
16779
16780
16781#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16782/** @name Nested-guest VM-exit handlers.
16783 * @{
16784 */
16785/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16786/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16787/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16788
16789/**
16790 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16791 * Conditional VM-exit.
16792 */
16793HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16794{
16795 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16796
16797 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16798
16799 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16800 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16801 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16802
16803 switch (uExitIntType)
16804 {
16805 /*
16806 * Physical NMIs:
16807 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16808 */
16809 case VMX_EXIT_INT_INFO_TYPE_NMI:
16810 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16811
16812 /*
16813 * Hardware exceptions,
16814 * Software exceptions,
16815 * Privileged software exceptions:
16816 * Figure out if the exception must be delivered to the guest or the nested-guest.
16817 */
16818 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16819 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16820 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16821 {
16822 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16823 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16824 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16825 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16826
16827 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16828 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16829 pVmxTransient->uExitIntErrorCode);
16830 if (fIntercept)
16831 {
16832 /* Exit qualification is required for debug and page-fault exceptions. */
16833 hmR0VmxReadExitQualVmcs(pVmxTransient);
16834
16835 /*
16836 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16837 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16838 * length. However, if delivery of a software interrupt, software exception or privileged
16839 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16840 */
16841 VMXVEXITINFO ExitInfo;
16842 RT_ZERO(ExitInfo);
16843 ExitInfo.uReason = pVmxTransient->uExitReason;
16844 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16845 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16846
16847 VMXVEXITEVENTINFO ExitEventInfo;
16848 RT_ZERO(ExitEventInfo);
16849 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16850 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16851 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16852 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16853
16854#ifdef DEBUG_ramshankar
16855 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16856 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16857 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16858 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16859 {
16860 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16861 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16862 }
16863#endif
16864 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16865 }
16866
16867 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16868 Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
16869 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16870 }
16871
16872 /*
16873 * Software interrupts:
16874 * VM-exits cannot be caused by software interrupts.
16875 *
16876 * External interrupts:
16877 * This should only happen when "acknowledge external interrupts on VM-exit"
16878 * control is set. However, we never set this when executing a guest or
16879 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16880 * the guest.
16881 */
16882 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16883 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16884 default:
16885 {
16886 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16887 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16888 }
16889 }
16890}
16891
16892
16893/**
16894 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16895 * Unconditional VM-exit.
16896 */
16897HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16898{
16899 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16900 return IEMExecVmxVmexitTripleFault(pVCpu);
16901}
16902
16903
16904/**
16905 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16906 */
16907HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16908{
16909 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16910
16911 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16912 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16913 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16914}
16915
16916
16917/**
16918 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16919 */
16920HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16921{
16922 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16923
16924 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16925 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16926 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16927}
16928
16929
16930/**
16931 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16932 * Unconditional VM-exit.
16933 */
16934HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16935{
16936 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16937
16938 hmR0VmxReadExitQualVmcs(pVmxTransient);
16939 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16940 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16941 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16942
16943 VMXVEXITINFO ExitInfo;
16944 RT_ZERO(ExitInfo);
16945 ExitInfo.uReason = pVmxTransient->uExitReason;
16946 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16947 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16948
16949 VMXVEXITEVENTINFO ExitEventInfo;
16950 RT_ZERO(ExitEventInfo);
16951 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16952 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16953 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16954}
16955
16956
16957/**
16958 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16959 */
16960HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16961{
16962 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16963
16964 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16965 {
16966 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16967 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16968 }
16969 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16970}
16971
16972
16973/**
16974 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16975 */
16976HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16977{
16978 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16979
16980 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16981 {
16982 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16983 hmR0VmxReadExitQualVmcs(pVmxTransient);
16984
16985 VMXVEXITINFO ExitInfo;
16986 RT_ZERO(ExitInfo);
16987 ExitInfo.uReason = pVmxTransient->uExitReason;
16988 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16989 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16990 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16991 }
16992 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16993}
16994
16995
16996/**
16997 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16998 */
16999HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17000{
17001 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17002
17003 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
17004 {
17005 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17006 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17007 }
17008 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
17009}
17010
17011
17012/**
17013 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
17014 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
17015 */
17016HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17017{
17018 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17019
17020 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
17021 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
17022
17023 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17024
17025 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
17026 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17027 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17028
17029 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
17030 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
17031 u64VmcsField &= UINT64_C(0xffffffff);
17032
17033 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
17034 {
17035 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17036 hmR0VmxReadExitQualVmcs(pVmxTransient);
17037
17038 VMXVEXITINFO ExitInfo;
17039 RT_ZERO(ExitInfo);
17040 ExitInfo.uReason = pVmxTransient->uExitReason;
17041 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17042 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17043 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17044 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17045 }
17046
17047 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
17048 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
17049 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
17050}
17051
17052
17053/**
17054 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
17055 */
17056HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17057{
17058 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17059
17060 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17061 {
17062 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17063 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17064 }
17065
17066 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
17067}
17068
17069
17070/**
17071 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
17072 * Conditional VM-exit.
17073 */
17074HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17075{
17076 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17077
17078 hmR0VmxReadExitQualVmcs(pVmxTransient);
17079 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17080
17081 VBOXSTRICTRC rcStrict;
17082 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
17083 switch (uAccessType)
17084 {
17085 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
17086 {
17087 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17088 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17089 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17090 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17091
17092 bool fIntercept;
17093 switch (iCrReg)
17094 {
17095 case 0:
17096 case 4:
17097 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(&pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
17098 break;
17099
17100 case 3:
17101 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
17102 break;
17103
17104 case 8:
17105 fIntercept = CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
17106 break;
17107
17108 default:
17109 fIntercept = false;
17110 break;
17111 }
17112 if (fIntercept)
17113 {
17114 VMXVEXITINFO ExitInfo;
17115 RT_ZERO(ExitInfo);
17116 ExitInfo.uReason = pVmxTransient->uExitReason;
17117 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17118 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17119 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17120 }
17121 else
17122 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
17123 break;
17124 }
17125
17126 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
17127 {
17128 /*
17129 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
17130 * CR2 reads do not cause a VM-exit.
17131 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
17132 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
17133 */
17134 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17135 if ( iCrReg == 3
17136 || iCrReg == 8)
17137 {
17138 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
17139 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
17140 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
17141 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uIntercept))
17142 {
17143 VMXVEXITINFO ExitInfo;
17144 RT_ZERO(ExitInfo);
17145 ExitInfo.uReason = pVmxTransient->uExitReason;
17146 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17147 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17148 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17149 }
17150 else
17151 {
17152 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17153 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
17154 }
17155 }
17156 else
17157 {
17158 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17159 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17160 }
17161 break;
17162 }
17163
17164 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17165 {
17166 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17167 Assert(pVmcsNstGst);
17168 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17169 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17170 if ( (uGstHostMask & X86_CR0_TS)
17171 && (uReadShadow & X86_CR0_TS))
17172 {
17173 VMXVEXITINFO ExitInfo;
17174 RT_ZERO(ExitInfo);
17175 ExitInfo.uReason = pVmxTransient->uExitReason;
17176 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17177 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17178 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17179 }
17180 else
17181 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
17182 break;
17183 }
17184
17185 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17186 {
17187 RTGCPTR GCPtrEffDst;
17188 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17189 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17190 if (fMemOperand)
17191 {
17192 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17193 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17194 }
17195 else
17196 GCPtrEffDst = NIL_RTGCPTR;
17197
17198 if (CPUMIsGuestVmxLmswInterceptSet(&pVCpu->cpum.GstCtx, uNewMsw))
17199 {
17200 VMXVEXITINFO ExitInfo;
17201 RT_ZERO(ExitInfo);
17202 ExitInfo.uReason = pVmxTransient->uExitReason;
17203 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17204 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17205 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17206 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17207 }
17208 else
17209 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
17210 break;
17211 }
17212
17213 default:
17214 {
17215 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17216 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17217 }
17218 }
17219
17220 if (rcStrict == VINF_IEM_RAISED_XCPT)
17221 {
17222 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17223 rcStrict = VINF_SUCCESS;
17224 }
17225 return rcStrict;
17226}
17227
17228
17229/**
17230 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17231 * Conditional VM-exit.
17232 */
17233HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17234{
17235 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17236
17237 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17238 {
17239 hmR0VmxReadExitQualVmcs(pVmxTransient);
17240 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17241
17242 VMXVEXITINFO ExitInfo;
17243 RT_ZERO(ExitInfo);
17244 ExitInfo.uReason = pVmxTransient->uExitReason;
17245 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17246 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17247 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17248 }
17249 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17250}
17251
17252
17253/**
17254 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17255 * Conditional VM-exit.
17256 */
17257HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17258{
17259 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17260
17261 hmR0VmxReadExitQualVmcs(pVmxTransient);
17262
17263 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17264 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17265 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17266
17267 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17268 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17269 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17270 {
17271 /*
17272 * IN/OUT instruction:
17273 * - Provides VM-exit instruction length.
17274 *
17275 * INS/OUTS instruction:
17276 * - Provides VM-exit instruction length.
17277 * - Provides Guest-linear address.
17278 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17279 */
17280 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
17281 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17282
17283 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17284 pVmxTransient->ExitInstrInfo.u = 0;
17285 pVmxTransient->uGuestLinearAddr = 0;
17286
17287 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17288 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17289 if (fIOString)
17290 {
17291 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17292 if (fVmxInsOutsInfo)
17293 {
17294 Assert(RT_BF_GET(g_HmMsrs.u.vmx.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17295 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17296 }
17297 }
17298
17299 VMXVEXITINFO ExitInfo;
17300 RT_ZERO(ExitInfo);
17301 ExitInfo.uReason = pVmxTransient->uExitReason;
17302 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17303 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17304 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17305 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17306 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17307 }
17308 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17309}
17310
17311
17312/**
17313 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17314 */
17315HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17316{
17317 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17318
17319 uint32_t fMsrpm;
17320 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17321 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17322 else
17323 fMsrpm = VMXMSRPM_EXIT_RD;
17324
17325 if (fMsrpm & VMXMSRPM_EXIT_RD)
17326 {
17327 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17328 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17329 }
17330 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17331}
17332
17333
17334/**
17335 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17336 */
17337HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17338{
17339 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17340
17341 uint32_t fMsrpm;
17342 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17343 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17344 else
17345 fMsrpm = VMXMSRPM_EXIT_WR;
17346
17347 if (fMsrpm & VMXMSRPM_EXIT_WR)
17348 {
17349 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17350 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17351 }
17352 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17353}
17354
17355
17356/**
17357 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17358 */
17359HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17360{
17361 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17362
17363 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17364 {
17365 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17366 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17367 }
17368 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17369}
17370
17371
17372/**
17373 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17374 * VM-exit.
17375 */
17376HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17377{
17378 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17379
17380 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17381 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17382 VMXVEXITINFO ExitInfo;
17383 RT_ZERO(ExitInfo);
17384 ExitInfo.uReason = pVmxTransient->uExitReason;
17385 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17386 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17387}
17388
17389
17390/**
17391 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17392 */
17393HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17394{
17395 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17396
17397 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17398 {
17399 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17400 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17401 }
17402 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17403}
17404
17405
17406/**
17407 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17408 */
17409HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17410{
17411 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17412
17413 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17414 * PAUSE when executing a nested-guest? If it does not, we would not need
17415 * to check for the intercepts here. Just call VM-exit... */
17416
17417 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17418 if ( CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17419 || CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17420 {
17421 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17422 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17423 }
17424 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17425}
17426
17427
17428/**
17429 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17430 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17431 */
17432HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17433{
17434 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17435
17436 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17437 {
17438 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17439 VMXVEXITINFO ExitInfo;
17440 RT_ZERO(ExitInfo);
17441 ExitInfo.uReason = pVmxTransient->uExitReason;
17442 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17443 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17444 }
17445 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17446}
17447
17448
17449/**
17450 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17451 * VM-exit.
17452 */
17453HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17454{
17455 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17456
17457 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17458 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17459 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17460 hmR0VmxReadExitQualVmcs(pVmxTransient);
17461
17462 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17463
17464 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
17465 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
17466
17467 VMXVEXITINFO ExitInfo;
17468 RT_ZERO(ExitInfo);
17469 ExitInfo.uReason = pVmxTransient->uExitReason;
17470 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17471 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17472
17473 VMXVEXITEVENTINFO ExitEventInfo;
17474 RT_ZERO(ExitEventInfo);
17475 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17476 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17477 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17478}
17479
17480
17481/**
17482 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17483 * Conditional VM-exit.
17484 */
17485HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17486{
17487 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17488
17489 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17490 hmR0VmxReadExitQualVmcs(pVmxTransient);
17491 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17492}
17493
17494
17495/**
17496 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17497 * Conditional VM-exit.
17498 */
17499HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17500{
17501 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17502
17503 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17504 hmR0VmxReadExitQualVmcs(pVmxTransient);
17505 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17506}
17507
17508
17509/**
17510 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17511 */
17512HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17513{
17514 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17515
17516 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17517 {
17518 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17519 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17520 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17521 }
17522 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17523}
17524
17525
17526/**
17527 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17528 */
17529HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17530{
17531 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17532
17533 if (CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17534 {
17535 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17536 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17537 }
17538 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17539}
17540
17541
17542/**
17543 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17544 */
17545HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17546{
17547 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17548
17549 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17550 {
17551 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17552 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17553 hmR0VmxReadExitQualVmcs(pVmxTransient);
17554 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17555
17556 VMXVEXITINFO ExitInfo;
17557 RT_ZERO(ExitInfo);
17558 ExitInfo.uReason = pVmxTransient->uExitReason;
17559 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17560 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17561 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17562 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17563 }
17564 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17565}
17566
17567
17568/**
17569 * Nested-guest VM-exit handler for invalid-guest state
17570 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17571 */
17572HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17573{
17574 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17575
17576 /*
17577 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17578 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17579 * Handle it like it's in an invalid guest state of the outer guest.
17580 *
17581 * When the fast path is implemented, this should be changed to cause the corresponding
17582 * nested-guest VM-exit.
17583 */
17584 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17585}
17586
17587
17588/**
17589 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17590 * and only provide the instruction length.
17591 *
17592 * Unconditional VM-exit.
17593 */
17594HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17595{
17596 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17597
17598#ifdef VBOX_STRICT
17599 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17600 switch (pVmxTransient->uExitReason)
17601 {
17602 case VMX_EXIT_ENCLS:
17603 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17604 break;
17605
17606 case VMX_EXIT_VMFUNC:
17607 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_VMFUNC));
17608 break;
17609 }
17610#endif
17611
17612 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17613 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17614}
17615
17616
17617/**
17618 * Nested-guest VM-exit handler for instructions that provide instruction length as
17619 * well as more information.
17620 *
17621 * Unconditional VM-exit.
17622 */
17623HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17624{
17625 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17626
17627#ifdef VBOX_STRICT
17628 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17629 switch (pVmxTransient->uExitReason)
17630 {
17631 case VMX_EXIT_GDTR_IDTR_ACCESS:
17632 case VMX_EXIT_LDTR_TR_ACCESS:
17633 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17634 break;
17635
17636 case VMX_EXIT_RDRAND:
17637 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17638 break;
17639
17640 case VMX_EXIT_RDSEED:
17641 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17642 break;
17643
17644 case VMX_EXIT_XSAVES:
17645 case VMX_EXIT_XRSTORS:
17646 /** @todo NSTVMX: Verify XSS-bitmap. */
17647 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17648 break;
17649
17650 case VMX_EXIT_UMWAIT:
17651 case VMX_EXIT_TPAUSE:
17652 Assert(CPUMIsGuestVmxProcCtlsSet(pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17653 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17654 break;
17655 }
17656#endif
17657
17658 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17659 hmR0VmxReadExitQualVmcs(pVmxTransient);
17660 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17661
17662 VMXVEXITINFO ExitInfo;
17663 RT_ZERO(ExitInfo);
17664 ExitInfo.uReason = pVmxTransient->uExitReason;
17665 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17666 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17667 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17668 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17669}
17670
17671/** @} */
17672#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17673
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