VirtualBox

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

Last change on this file since 81916 was 81861, checked in by vboxsync, 5 years ago

VMM/HM: Spaces.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 708.9 KB
Line 
1/* $Id: HMVMXR0.cpp 81861 2019-11-15 03:58:56Z vboxsync $ */
2/** @file
3 * HM VMX (Intel VT-x) - Host Context Ring-0.
4 */
5
6/*
7 * Copyright (C) 2012-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_HM
23#define VMCPU_INCL_CPUM_GST_CTX
24#include <iprt/x86.h>
25#include <iprt/asm-amd64-x86.h>
26#include <iprt/thread.h>
27#include <iprt/mem.h>
28#include <iprt/mp.h>
29
30#include <VBox/vmm/pdmapi.h>
31#include <VBox/vmm/dbgf.h>
32#include <VBox/vmm/iem.h>
33#include <VBox/vmm/iom.h>
34#include <VBox/vmm/tm.h>
35#include <VBox/vmm/em.h>
36#include <VBox/vmm/gim.h>
37#include <VBox/vmm/apic.h>
38#include "HMInternal.h"
39#include <VBox/vmm/vmcc.h>
40#include <VBox/vmm/hmvmxinline.h>
41#include "HMVMXR0.h"
42#include "dtrace/VBoxVMM.h"
43
44#ifdef DEBUG_ramshankar
45# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
46# define HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
47# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
48# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
49# define HMVMX_ALWAYS_CLEAN_TRANSIENT
50# define HMVMX_ALWAYS_CHECK_GUEST_STATE
51# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
52# define HMVMX_ALWAYS_TRAP_PF
53# define HMVMX_ALWAYS_FLUSH_TLB
54# define HMVMX_ALWAYS_SWAP_EFER
55#endif
56
57
58/*********************************************************************************************************************************
59* Defined Constants And Macros *
60*********************************************************************************************************************************/
61/** Use the function table. */
62#define HMVMX_USE_FUNCTION_TABLE
63
64/** Determine which tagged-TLB flush handler to use. */
65#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
66#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
67#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
68#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
69
70/**
71 * Flags to skip redundant reads of some common VMCS fields that are not part of
72 * the guest-CPU or VCPU state but are needed while handling VM-exits.
73 */
74#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
75#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
76#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
77#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
78#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
79#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
80#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
81#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
82#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
83#define HMVMX_READ_GUEST_PENDING_DBG_XCPTS RT_BIT_32(9)
84
85/** All the VMCS fields required for processing of exception/NMI VM-exits. */
86#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
87 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
88 | HMVMX_READ_EXIT_INSTR_LEN \
89 | HMVMX_READ_IDT_VECTORING_INFO \
90 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
91
92/** Assert that all the given fields have been read from the VMCS. */
93#ifdef VBOX_STRICT
94# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
95 do { \
96 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
97 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
98 } while (0)
99#else
100# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
101#endif
102
103/**
104 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
105 * guest using hardware-assisted VMX.
106 *
107 * This excludes state like GPRs (other than RSP) which are always are
108 * swapped and restored across the world-switch and also registers like EFER,
109 * MSR which cannot be modified by the guest without causing a VM-exit.
110 */
111#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
112 | CPUMCTX_EXTRN_RFLAGS \
113 | CPUMCTX_EXTRN_RSP \
114 | CPUMCTX_EXTRN_SREG_MASK \
115 | CPUMCTX_EXTRN_TABLE_MASK \
116 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
117 | CPUMCTX_EXTRN_SYSCALL_MSRS \
118 | CPUMCTX_EXTRN_SYSENTER_MSRS \
119 | CPUMCTX_EXTRN_TSC_AUX \
120 | CPUMCTX_EXTRN_OTHER_MSRS \
121 | CPUMCTX_EXTRN_CR0 \
122 | CPUMCTX_EXTRN_CR3 \
123 | CPUMCTX_EXTRN_CR4 \
124 | CPUMCTX_EXTRN_DR7 \
125 | CPUMCTX_EXTRN_HWVIRT \
126 | CPUMCTX_EXTRN_HM_VMX_MASK)
127
128/**
129 * Exception bitmap mask for real-mode guests (real-on-v86).
130 *
131 * We need to intercept all exceptions manually except:
132 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
133 * due to bugs in Intel CPUs.
134 * - \#PF need not be intercepted even in real-mode if we have nested paging
135 * support.
136 */
137#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
138 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
139 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
140 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
141 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
142 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
143 | RT_BIT(X86_XCPT_XF))
144
145/** Maximum VM-instruction error number. */
146#define HMVMX_INSTR_ERROR_MAX 28
147
148/** Profiling macro. */
149#ifdef HM_PROFILE_EXIT_DISPATCH
150# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
151# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
152#else
153# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
154# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
155#endif
156
157/** Assert that preemption is disabled or covered by thread-context hooks. */
158#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
159 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
160
161/** Assert that we haven't migrated CPUs when thread-context hooks are not
162 * used. */
163#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
164 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
165 ("Illegal migration! Entered on CPU %u Current %u\n", \
166 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
167
168/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
169 * context. */
170#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
171 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
172 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
173
174/** Log the VM-exit reason with an easily visible marker to identify it in a
175 * potential sea of logging data. */
176#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
177 do { \
178 Log4(("VM-exit: vcpu[%RU32] %85s -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-\n", (a_pVCpu)->idCpu, \
179 HMGetVmxExitName(a_uExitReason))); \
180 } while (0) \
181
182
183/*********************************************************************************************************************************
184* Structures and Typedefs *
185*********************************************************************************************************************************/
186/**
187 * VMX per-VCPU transient state.
188 *
189 * A state structure for holding miscellaneous information across
190 * VMX non-root operation and restored after the transition.
191 *
192 * Note: The members are ordered and aligned such that the most
193 * frequently used ones (in the guest execution loop) fall within
194 * the first cache line.
195 */
196typedef struct VMXTRANSIENT
197{
198 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
199 uint32_t fVmcsFieldsRead;
200 /** The guest's TPR value used for TPR shadowing. */
201 uint8_t u8GuestTpr;
202 uint8_t abAlignment0[3];
203
204 /** Whether the VM-exit was caused by a page-fault during delivery of an
205 * external interrupt or NMI. */
206 bool fVectoringPF;
207 /** Whether the VM-exit was caused by a page-fault during delivery of a
208 * contributory exception or a page-fault. */
209 bool fVectoringDoublePF;
210 /** Whether the VM-entry failed or not. */
211 bool fVMEntryFailed;
212 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
213 * area after VM-exit. */
214 bool fRemoveTscAuxMsr;
215 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
216 bool fUpdatedTscOffsettingAndPreemptTimer;
217 /** Whether we are currently executing a nested-guest. */
218 bool fIsNestedGuest;
219 /** Whether the guest debug state was active at the time of VM-exit. */
220 bool fWasGuestDebugStateActive;
221 /** Whether the hyper debug state was active at the time of VM-exit. */
222 bool fWasHyperDebugStateActive;
223
224 /** The basic VM-exit reason. */
225 uint32_t uExitReason;
226 /** The VM-exit interruption error code. */
227 uint32_t uExitIntErrorCode;
228
229 /** The host's rflags/eflags. */
230 RTCCUINTREG fEFlags;
231
232 /** The VM-exit exit code qualification. */
233 uint64_t uExitQual;
234
235 /** The VMCS info. object. */
236 PVMXVMCSINFO pVmcsInfo;
237
238 /** The VM-exit interruption-information field. */
239 uint32_t uExitIntInfo;
240 /** The VM-exit instruction-length field. */
241 uint32_t cbExitInstr;
242
243 /** The VM-exit instruction-information field. */
244 VMXEXITINSTRINFO ExitInstrInfo;
245 /** IDT-vectoring information field. */
246 uint32_t uIdtVectoringInfo;
247
248 /** IDT-vectoring error code. */
249 uint32_t uIdtVectoringErrorCode;
250 uint32_t u32Alignment0;
251
252 /** The Guest-linear address. */
253 uint64_t uGuestLinearAddr;
254
255 /** The Guest-physical address. */
256 uint64_t uGuestPhysicalAddr;
257
258 /** The Guest pending-debug exceptions. */
259 uint64_t uGuestPendingDbgXcpts;
260
261 /** The VM-entry interruption-information field. */
262 uint32_t uEntryIntInfo;
263 /** The VM-entry exception error code field. */
264 uint32_t uEntryXcptErrorCode;
265
266 /** The VM-entry instruction length field. */
267 uint32_t cbEntryInstr;
268} VMXTRANSIENT;
269AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, fVmcsFieldsRead, 8);
271AssertCompileMemberAlignment(VMXTRANSIENT, fVectoringPF, 8);
272AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, 8);
273AssertCompileMemberAlignment(VMXTRANSIENT, fEFlags, 8);
274AssertCompileMemberAlignment(VMXTRANSIENT, uExitQual, 8);
275AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, 8);
276AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, 8);
277AssertCompileMemberAlignment(VMXTRANSIENT, ExitInstrInfo, 8);
278AssertCompileMemberAlignment(VMXTRANSIENT, uIdtVectoringErrorCode, 8);
279AssertCompileMemberAlignment(VMXTRANSIENT, uGuestLinearAddr, 8);
280AssertCompileMemberAlignment(VMXTRANSIENT, uGuestPhysicalAddr, 8);
281AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, 8);
282AssertCompileMemberAlignment(VMXTRANSIENT, cbEntryInstr, 8);
283/** Pointer to VMX transient state. */
284typedef VMXTRANSIENT *PVMXTRANSIENT;
285/** Pointer to a const VMX transient state. */
286typedef const VMXTRANSIENT *PCVMXTRANSIENT;
287
288/**
289 * VMX page allocation information.
290 */
291typedef struct
292{
293 uint32_t fValid; /**< Whether to allocate this page (e.g, based on a CPU feature). */
294 uint32_t uPadding0; /**< Padding to ensure array of these structs are aligned to a multiple of 8. */
295 PRTHCPHYS pHCPhys; /**< Where to store the host-physical address of the allocation. */
296 PRTR0PTR ppVirt; /**< Where to store the host-virtual address of the allocation. */
297} VMXPAGEALLOCINFO;
298/** Pointer to VMX page-allocation info. */
299typedef VMXPAGEALLOCINFO *PVMXPAGEALLOCINFO;
300/** Pointer to a const VMX page-allocation info. */
301typedef const VMXPAGEALLOCINFO *PCVMXPAGEALLOCINFO;
302AssertCompileSizeAlignment(VMXPAGEALLOCINFO, 8);
303
304/**
305 * Memory operand read or write access.
306 */
307typedef enum VMXMEMACCESS
308{
309 VMXMEMACCESS_READ = 0,
310 VMXMEMACCESS_WRITE = 1
311} VMXMEMACCESS;
312
313/**
314 * VMX VM-exit handler.
315 *
316 * @returns Strict VBox status code (i.e. informational status codes too).
317 * @param pVCpu The cross context virtual CPU structure.
318 * @param pVmxTransient The VMX-transient structure.
319 */
320#ifndef HMVMX_USE_FUNCTION_TABLE
321typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
322#else
323typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
324/** Pointer to VM-exit handler. */
325typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
326#endif
327
328/**
329 * VMX VM-exit handler, non-strict status code.
330 *
331 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
332 *
333 * @returns VBox status code, no informational status code returned.
334 * @param pVCpu The cross context virtual CPU structure.
335 * @param pVmxTransient The VMX-transient structure.
336 *
337 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
338 * use of that status code will be replaced with VINF_EM_SOMETHING
339 * later when switching over to IEM.
340 */
341#ifndef HMVMX_USE_FUNCTION_TABLE
342typedef int FNVMXEXITHANDLERNSRC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
343#else
344typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
345#endif
346
347
348/*********************************************************************************************************************************
349* Internal Functions *
350*********************************************************************************************************************************/
351#ifndef HMVMX_USE_FUNCTION_TABLE
352DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
353# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
354# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
355#else
356# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
357# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
358#endif
359#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
360DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
361#endif
362
363static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
364
365/** @name VM-exit handler prototypes.
366 * @{
367 */
368static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
369static FNVMXEXITHANDLER hmR0VmxExitExtInt;
370static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
371static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
372static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
373static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
374static FNVMXEXITHANDLER hmR0VmxExitCpuid;
375static FNVMXEXITHANDLER hmR0VmxExitGetsec;
376static FNVMXEXITHANDLER hmR0VmxExitHlt;
377static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
378static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
379static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
380static FNVMXEXITHANDLER hmR0VmxExitVmcall;
381#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
382static FNVMXEXITHANDLER hmR0VmxExitVmclear;
383static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
384static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
385static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
386static FNVMXEXITHANDLER hmR0VmxExitVmread;
387static FNVMXEXITHANDLER hmR0VmxExitVmresume;
388static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
389static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
390static FNVMXEXITHANDLER hmR0VmxExitVmxon;
391static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
392#endif
393static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
394static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
395static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
396static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
397static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
398static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
399static FNVMXEXITHANDLER hmR0VmxExitMwait;
400static FNVMXEXITHANDLER hmR0VmxExitMtf;
401static FNVMXEXITHANDLER hmR0VmxExitMonitor;
402static FNVMXEXITHANDLER hmR0VmxExitPause;
403static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
404static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
405static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
406static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
407static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
408static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
409static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
410static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
411static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
412static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
413static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
414static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
415/** @} */
416
417#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
418/** @name Nested-guest VM-exit handler prototypes.
419 * @{
420 */
421static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
422static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
423static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
424static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
425static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
426static FNVMXEXITHANDLER hmR0VmxExitHltNested;
427static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
428static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
429static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
430static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
431static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
432static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
433static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
434static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
435static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
436static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
437static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
438static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
439static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
440static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
441static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
442static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
443static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
444static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
445static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
446static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
447static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
448static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
449static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
450/** @} */
451#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
452
453
454/*********************************************************************************************************************************
455* Global Variables *
456*********************************************************************************************************************************/
457#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
458/**
459 * Array of all VMCS fields.
460 * Any fields added to the VT-x spec. should be added here.
461 *
462 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
463 * of nested-guests.
464 */
465static const uint32_t g_aVmcsFields[] =
466{
467 /* 16-bit control fields. */
468 VMX_VMCS16_VPID,
469 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
470 VMX_VMCS16_EPTP_INDEX,
471
472 /* 16-bit guest-state fields. */
473 VMX_VMCS16_GUEST_ES_SEL,
474 VMX_VMCS16_GUEST_CS_SEL,
475 VMX_VMCS16_GUEST_SS_SEL,
476 VMX_VMCS16_GUEST_DS_SEL,
477 VMX_VMCS16_GUEST_FS_SEL,
478 VMX_VMCS16_GUEST_GS_SEL,
479 VMX_VMCS16_GUEST_LDTR_SEL,
480 VMX_VMCS16_GUEST_TR_SEL,
481 VMX_VMCS16_GUEST_INTR_STATUS,
482 VMX_VMCS16_GUEST_PML_INDEX,
483
484 /* 16-bits host-state fields. */
485 VMX_VMCS16_HOST_ES_SEL,
486 VMX_VMCS16_HOST_CS_SEL,
487 VMX_VMCS16_HOST_SS_SEL,
488 VMX_VMCS16_HOST_DS_SEL,
489 VMX_VMCS16_HOST_FS_SEL,
490 VMX_VMCS16_HOST_GS_SEL,
491 VMX_VMCS16_HOST_TR_SEL,
492
493 /* 64-bit control fields. */
494 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
495 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
496 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
497 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
498 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
499 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
500 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
501 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
502 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
503 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
504 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
505 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
506 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
507 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
508 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
509 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
510 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
511 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
512 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
513 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
514 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
515 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
516 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
517 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
518 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
519 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
520 VMX_VMCS64_CTRL_EPTP_FULL,
521 VMX_VMCS64_CTRL_EPTP_HIGH,
522 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
523 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
524 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
525 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
526 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
527 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
528 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
529 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
530 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
531 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
532 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
533 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
534 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
535 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
536 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
537 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
538 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
539 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
540 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
541 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
542 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
543 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
544
545 /* 64-bit read-only data fields. */
546 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
547 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
548
549 /* 64-bit guest-state fields. */
550 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
551 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
552 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
553 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
554 VMX_VMCS64_GUEST_PAT_FULL,
555 VMX_VMCS64_GUEST_PAT_HIGH,
556 VMX_VMCS64_GUEST_EFER_FULL,
557 VMX_VMCS64_GUEST_EFER_HIGH,
558 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
559 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
560 VMX_VMCS64_GUEST_PDPTE0_FULL,
561 VMX_VMCS64_GUEST_PDPTE0_HIGH,
562 VMX_VMCS64_GUEST_PDPTE1_FULL,
563 VMX_VMCS64_GUEST_PDPTE1_HIGH,
564 VMX_VMCS64_GUEST_PDPTE2_FULL,
565 VMX_VMCS64_GUEST_PDPTE2_HIGH,
566 VMX_VMCS64_GUEST_PDPTE3_FULL,
567 VMX_VMCS64_GUEST_PDPTE3_HIGH,
568 VMX_VMCS64_GUEST_BNDCFGS_FULL,
569 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
570
571 /* 64-bit host-state fields. */
572 VMX_VMCS64_HOST_PAT_FULL,
573 VMX_VMCS64_HOST_PAT_HIGH,
574 VMX_VMCS64_HOST_EFER_FULL,
575 VMX_VMCS64_HOST_EFER_HIGH,
576 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
577 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
578
579 /* 32-bit control fields. */
580 VMX_VMCS32_CTRL_PIN_EXEC,
581 VMX_VMCS32_CTRL_PROC_EXEC,
582 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
583 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
584 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
585 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
586 VMX_VMCS32_CTRL_EXIT,
587 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
588 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
589 VMX_VMCS32_CTRL_ENTRY,
590 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
591 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
592 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
593 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
594 VMX_VMCS32_CTRL_TPR_THRESHOLD,
595 VMX_VMCS32_CTRL_PROC_EXEC2,
596 VMX_VMCS32_CTRL_PLE_GAP,
597 VMX_VMCS32_CTRL_PLE_WINDOW,
598
599 /* 32-bits read-only fields. */
600 VMX_VMCS32_RO_VM_INSTR_ERROR,
601 VMX_VMCS32_RO_EXIT_REASON,
602 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
603 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
604 VMX_VMCS32_RO_IDT_VECTORING_INFO,
605 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
606 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
607 VMX_VMCS32_RO_EXIT_INSTR_INFO,
608
609 /* 32-bit guest-state fields. */
610 VMX_VMCS32_GUEST_ES_LIMIT,
611 VMX_VMCS32_GUEST_CS_LIMIT,
612 VMX_VMCS32_GUEST_SS_LIMIT,
613 VMX_VMCS32_GUEST_DS_LIMIT,
614 VMX_VMCS32_GUEST_FS_LIMIT,
615 VMX_VMCS32_GUEST_GS_LIMIT,
616 VMX_VMCS32_GUEST_LDTR_LIMIT,
617 VMX_VMCS32_GUEST_TR_LIMIT,
618 VMX_VMCS32_GUEST_GDTR_LIMIT,
619 VMX_VMCS32_GUEST_IDTR_LIMIT,
620 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
621 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
622 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
623 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
624 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
625 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
626 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
627 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
628 VMX_VMCS32_GUEST_INT_STATE,
629 VMX_VMCS32_GUEST_ACTIVITY_STATE,
630 VMX_VMCS32_GUEST_SMBASE,
631 VMX_VMCS32_GUEST_SYSENTER_CS,
632 VMX_VMCS32_PREEMPT_TIMER_VALUE,
633
634 /* 32-bit host-state fields. */
635 VMX_VMCS32_HOST_SYSENTER_CS,
636
637 /* Natural-width control fields. */
638 VMX_VMCS_CTRL_CR0_MASK,
639 VMX_VMCS_CTRL_CR4_MASK,
640 VMX_VMCS_CTRL_CR0_READ_SHADOW,
641 VMX_VMCS_CTRL_CR4_READ_SHADOW,
642 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
643 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
644 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
645 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
646
647 /* Natural-width read-only data fields. */
648 VMX_VMCS_RO_EXIT_QUALIFICATION,
649 VMX_VMCS_RO_IO_RCX,
650 VMX_VMCS_RO_IO_RSI,
651 VMX_VMCS_RO_IO_RDI,
652 VMX_VMCS_RO_IO_RIP,
653 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
654
655 /* Natural-width guest-state field */
656 VMX_VMCS_GUEST_CR0,
657 VMX_VMCS_GUEST_CR3,
658 VMX_VMCS_GUEST_CR4,
659 VMX_VMCS_GUEST_ES_BASE,
660 VMX_VMCS_GUEST_CS_BASE,
661 VMX_VMCS_GUEST_SS_BASE,
662 VMX_VMCS_GUEST_DS_BASE,
663 VMX_VMCS_GUEST_FS_BASE,
664 VMX_VMCS_GUEST_GS_BASE,
665 VMX_VMCS_GUEST_LDTR_BASE,
666 VMX_VMCS_GUEST_TR_BASE,
667 VMX_VMCS_GUEST_GDTR_BASE,
668 VMX_VMCS_GUEST_IDTR_BASE,
669 VMX_VMCS_GUEST_DR7,
670 VMX_VMCS_GUEST_RSP,
671 VMX_VMCS_GUEST_RIP,
672 VMX_VMCS_GUEST_RFLAGS,
673 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
674 VMX_VMCS_GUEST_SYSENTER_ESP,
675 VMX_VMCS_GUEST_SYSENTER_EIP,
676
677 /* Natural-width host-state fields */
678 VMX_VMCS_HOST_CR0,
679 VMX_VMCS_HOST_CR3,
680 VMX_VMCS_HOST_CR4,
681 VMX_VMCS_HOST_FS_BASE,
682 VMX_VMCS_HOST_GS_BASE,
683 VMX_VMCS_HOST_TR_BASE,
684 VMX_VMCS_HOST_GDTR_BASE,
685 VMX_VMCS_HOST_IDTR_BASE,
686 VMX_VMCS_HOST_SYSENTER_ESP,
687 VMX_VMCS_HOST_SYSENTER_EIP,
688 VMX_VMCS_HOST_RSP,
689 VMX_VMCS_HOST_RIP
690};
691#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
692
693static const uint32_t g_aVmcsSegBase[] =
694{
695 VMX_VMCS_GUEST_ES_BASE,
696 VMX_VMCS_GUEST_CS_BASE,
697 VMX_VMCS_GUEST_SS_BASE,
698 VMX_VMCS_GUEST_DS_BASE,
699 VMX_VMCS_GUEST_FS_BASE,
700 VMX_VMCS_GUEST_GS_BASE
701};
702static const uint32_t g_aVmcsSegSel[] =
703{
704 VMX_VMCS16_GUEST_ES_SEL,
705 VMX_VMCS16_GUEST_CS_SEL,
706 VMX_VMCS16_GUEST_SS_SEL,
707 VMX_VMCS16_GUEST_DS_SEL,
708 VMX_VMCS16_GUEST_FS_SEL,
709 VMX_VMCS16_GUEST_GS_SEL
710};
711static const uint32_t g_aVmcsSegLimit[] =
712{
713 VMX_VMCS32_GUEST_ES_LIMIT,
714 VMX_VMCS32_GUEST_CS_LIMIT,
715 VMX_VMCS32_GUEST_SS_LIMIT,
716 VMX_VMCS32_GUEST_DS_LIMIT,
717 VMX_VMCS32_GUEST_FS_LIMIT,
718 VMX_VMCS32_GUEST_GS_LIMIT
719};
720static const uint32_t g_aVmcsSegAttr[] =
721{
722 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
723 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
724 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
725 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
726 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
727 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
728};
729AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
730AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
731AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
732AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
733
734#ifdef HMVMX_USE_FUNCTION_TABLE
735/**
736 * VMX_EXIT dispatch table.
737 */
738static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
739{
740 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
741 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
742 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
743 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
744 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
745 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
746 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
747 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
748 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
749 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
750 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
751 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
752 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
753 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
754 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
755 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
756 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
757 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
758 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
759#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
760 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
761 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
762 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
763 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
764 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
765 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
766 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
767 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
768 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
769#else
770 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
771 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
772 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
773 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
774 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
775 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
776 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
777 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
778 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
779#endif
780 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
781 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
782 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
783 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
784 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
785 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
786 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
787 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
788 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
789 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
790 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
791 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
792 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
793 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
794 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
795 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
796 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
797 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
798 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
799 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
800 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
801 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
802 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
803 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
804 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
805#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
806 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
807#else
808 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
809#endif
810 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
811 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
812 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
813 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
814 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
815 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
816 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
817 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
818 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
819 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
820 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
821 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
822 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
823 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
824 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
825};
826#endif /* HMVMX_USE_FUNCTION_TABLE */
827
828#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
829static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
830{
831 /* 0 */ "(Not Used)",
832 /* 1 */ "VMCALL executed in VMX root operation.",
833 /* 2 */ "VMCLEAR with invalid physical address.",
834 /* 3 */ "VMCLEAR with VMXON pointer.",
835 /* 4 */ "VMLAUNCH with non-clear VMCS.",
836 /* 5 */ "VMRESUME with non-launched VMCS.",
837 /* 6 */ "VMRESUME after VMXOFF",
838 /* 7 */ "VM-entry with invalid control fields.",
839 /* 8 */ "VM-entry with invalid host state fields.",
840 /* 9 */ "VMPTRLD with invalid physical address.",
841 /* 10 */ "VMPTRLD with VMXON pointer.",
842 /* 11 */ "VMPTRLD with incorrect revision identifier.",
843 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
844 /* 13 */ "VMWRITE to read-only VMCS component.",
845 /* 14 */ "(Not Used)",
846 /* 15 */ "VMXON executed in VMX root operation.",
847 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
848 /* 17 */ "VM-entry with non-launched executing VMCS.",
849 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
850 /* 19 */ "VMCALL with non-clear VMCS.",
851 /* 20 */ "VMCALL with invalid VM-exit control fields.",
852 /* 21 */ "(Not Used)",
853 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
854 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
855 /* 24 */ "VMCALL with invalid SMM-monitor features.",
856 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
857 /* 26 */ "VM-entry with events blocked by MOV SS.",
858 /* 27 */ "(Not Used)",
859 /* 28 */ "Invalid operand to INVEPT/INVVPID."
860};
861#endif /* VBOX_STRICT && LOG_ENABLED */
862
863
864/**
865 * Gets the CR0 guest/host mask.
866 *
867 * These bits typically does not change through the lifetime of a VM. Any bit set in
868 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
869 * by the guest.
870 *
871 * @returns The CR0 guest/host mask.
872 * @param pVCpu The cross context virtual CPU structure.
873 */
874static uint64_t hmR0VmxGetFixedCr0Mask(PCVMCPUCC pVCpu)
875{
876 /*
877 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
878 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
879 *
880 * Furthermore, modifications to any bits that are reserved/unspecified currently
881 * by the Intel spec. must also cause a VM-exit. This prevents unpredictable behavior
882 * when future CPUs specify and use currently reserved/unspecified bits.
883 */
884 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
885 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
886 * and @bugref{6944}. */
887 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
888 return ( X86_CR0_PE
889 | X86_CR0_NE
890 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
891 | X86_CR0_PG
892 | VMX_EXIT_HOST_CR0_IGNORE_MASK);
893}
894
895
896/**
897 * Gets the CR4 guest/host mask.
898 *
899 * These bits typically does not change through the lifetime of a VM. Any bit set in
900 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
901 * by the guest.
902 *
903 * @returns The CR4 guest/host mask.
904 * @param pVCpu The cross context virtual CPU structure.
905 */
906static uint64_t hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
907{
908 /*
909 * We construct a mask of all CR4 bits that the guest can modify without causing
910 * a VM-exit. Then invert this mask to obtain all CR4 bits that should cause
911 * a VM-exit when the guest attempts to modify them when executing using
912 * hardware-assisted VMX.
913 *
914 * When a feature is not exposed to the guest (and may be present on the host),
915 * we want to intercept guest modifications to the bit so we can emulate proper
916 * behavior (e.g., #GP).
917 *
918 * Furthermore, only modifications to those bits that don't require immediate
919 * emulation is allowed. For e.g., PCIDE is excluded because the behavior
920 * depends on CR3 which might not always be the guest value while executing
921 * using hardware-assisted VMX.
922 */
923 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
924 bool const fFsGsBase = pVM->cpum.ro.GuestFeatures.fFsGsBase;
925 bool const fXSaveRstor = pVM->cpum.ro.GuestFeatures.fXSaveRstor;
926 bool const fFxSaveRstor = pVM->cpum.ro.GuestFeatures.fFxSaveRstor;
927
928 /*
929 * Paranoia.
930 * Ensure features exposed to the guest are present on the host.
931 */
932 Assert(!fFsGsBase || pVM->cpum.ro.HostFeatures.fFsGsBase);
933 Assert(!fXSaveRstor || pVM->cpum.ro.HostFeatures.fXSaveRstor);
934 Assert(!fFxSaveRstor || pVM->cpum.ro.HostFeatures.fFxSaveRstor);
935
936 uint64_t const fGstMask = ( X86_CR4_PVI
937 | X86_CR4_TSD
938 | X86_CR4_DE
939 | X86_CR4_MCE
940 | X86_CR4_PCE
941 | X86_CR4_OSXMMEEXCPT
942 | (fFsGsBase ? X86_CR4_FSGSBASE : 0)
943 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
944 | (fFxSaveRstor ? X86_CR4_OSFXSR : 0));
945 return ~fGstMask;
946}
947
948
949/**
950 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
951 * area.
952 *
953 * @returns @c true if it's different, @c false otherwise.
954 * @param pVmcsInfo The VMCS info. object.
955 */
956DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
957{
958 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
959 && pVmcsInfo->pvGuestMsrStore);
960}
961
962
963/**
964 * Sets the given Processor-based VM-execution controls.
965 *
966 * @param pVmxTransient The VMX-transient structure.
967 * @param uProcCtls The Processor-based VM-execution controls to set.
968 */
969static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
970{
971 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
972 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
973 {
974 pVmcsInfo->u32ProcCtls |= uProcCtls;
975 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
976 AssertRC(rc);
977 }
978}
979
980
981/**
982 * Removes the given Processor-based VM-execution controls.
983 *
984 * @param pVCpu The cross context virtual CPU structure.
985 * @param pVmxTransient The VMX-transient structure.
986 * @param uProcCtls The Processor-based VM-execution controls to remove.
987 *
988 * @remarks When executing a nested-guest, this will not remove any of the specified
989 * controls if the nested hypervisor has set any one of them.
990 */
991static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
992{
993 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
994 if (pVmcsInfo->u32ProcCtls & uProcCtls)
995 {
996#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
997 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
998 ? true
999 : !CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uProcCtls);
1000#else
1001 NOREF(pVCpu);
1002 bool const fRemoveCtls = true;
1003#endif
1004 if (fRemoveCtls)
1005 {
1006 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
1007 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1008 AssertRC(rc);
1009 }
1010 }
1011}
1012
1013
1014/**
1015 * Sets the TSC offset for the current VMCS.
1016 *
1017 * @param uTscOffset The TSC offset to set.
1018 * @param pVmcsInfo The VMCS info. object.
1019 */
1020static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
1021{
1022 if (pVmcsInfo->u64TscOffset != uTscOffset)
1023 {
1024 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
1025 AssertRC(rc);
1026 pVmcsInfo->u64TscOffset = uTscOffset;
1027 }
1028}
1029
1030
1031/**
1032 * Adds one or more exceptions to the exception bitmap and commits it to the current
1033 * VMCS.
1034 *
1035 * @param pVmxTransient The VMX-transient structure.
1036 * @param uXcptMask The exception(s) to add.
1037 */
1038static void hmR0VmxAddXcptInterceptMask(PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1039{
1040 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1041 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1042 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1043 {
1044 uXcptBitmap |= uXcptMask;
1045 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1046 AssertRC(rc);
1047 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1048 }
1049}
1050
1051
1052/**
1053 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1054 *
1055 * @param pVmxTransient The VMX-transient structure.
1056 * @param uXcpt The exception to add.
1057 */
1058static void hmR0VmxAddXcptIntercept(PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1059{
1060 Assert(uXcpt <= X86_XCPT_LAST);
1061 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1062}
1063
1064
1065/**
1066 * Remove one or more exceptions from the exception bitmap and commits it to the
1067 * current VMCS.
1068 *
1069 * This takes care of not removing the exception intercept if a nested-guest
1070 * requires the exception to be intercepted.
1071 *
1072 * @returns VBox status code.
1073 * @param pVCpu The cross context virtual CPU structure.
1074 * @param pVmxTransient The VMX-transient structure.
1075 * @param uXcptMask The exception(s) to remove.
1076 */
1077static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1078{
1079 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1080 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1081 if (u32XcptBitmap & uXcptMask)
1082 {
1083#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1084 if (!pVmxTransient->fIsNestedGuest)
1085 { /* likely */ }
1086 else
1087 {
1088 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1089 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1090 }
1091#endif
1092#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1093 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1094 | RT_BIT(X86_XCPT_DE)
1095 | RT_BIT(X86_XCPT_NM)
1096 | RT_BIT(X86_XCPT_TS)
1097 | RT_BIT(X86_XCPT_UD)
1098 | RT_BIT(X86_XCPT_NP)
1099 | RT_BIT(X86_XCPT_SS)
1100 | RT_BIT(X86_XCPT_GP)
1101 | RT_BIT(X86_XCPT_PF)
1102 | RT_BIT(X86_XCPT_MF));
1103#elif defined(HMVMX_ALWAYS_TRAP_PF)
1104 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1105#endif
1106 if (uXcptMask)
1107 {
1108 /* Validate we are not removing any essential exception intercepts. */
1109 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1110 NOREF(pVCpu);
1111 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1112 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1113
1114 /* Remove it from the exception bitmap. */
1115 u32XcptBitmap &= ~uXcptMask;
1116
1117 /* Commit and update the cache if necessary. */
1118 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1119 {
1120 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1121 AssertRC(rc);
1122 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1123 }
1124 }
1125 }
1126 return VINF_SUCCESS;
1127}
1128
1129
1130/**
1131 * Remove an exceptions from the exception bitmap and commits it to the current
1132 * VMCS.
1133 *
1134 * @returns VBox status code.
1135 * @param pVCpu The cross context virtual CPU structure.
1136 * @param pVmxTransient The VMX-transient structure.
1137 * @param uXcpt The exception to remove.
1138 */
1139static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1140{
1141 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1142}
1143
1144
1145/**
1146 * Loads the VMCS specified by the VMCS info. object.
1147 *
1148 * @returns VBox status code.
1149 * @param pVmcsInfo The VMCS info. object.
1150 *
1151 * @remarks Can be called with interrupts disabled.
1152 */
1153static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1154{
1155 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1156 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1157
1158 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1159 if (RT_SUCCESS(rc))
1160 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1161 return rc;
1162}
1163
1164
1165/**
1166 * Clears the VMCS specified by the VMCS info. object.
1167 *
1168 * @returns VBox status code.
1169 * @param pVmcsInfo The VMCS info. object.
1170 *
1171 * @remarks Can be called with interrupts disabled.
1172 */
1173static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1174{
1175 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1176 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1177
1178 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1179 if (RT_SUCCESS(rc))
1180 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1181 return rc;
1182}
1183
1184
1185#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1186/**
1187 * Loads the shadow VMCS specified by the VMCS info. object.
1188 *
1189 * @returns VBox status code.
1190 * @param pVmcsInfo The VMCS info. object.
1191 *
1192 * @remarks Can be called with interrupts disabled.
1193 */
1194static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1195{
1196 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1197 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1198
1199 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1200 if (RT_SUCCESS(rc))
1201 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1202 return rc;
1203}
1204
1205
1206/**
1207 * Clears the shadow VMCS specified by the VMCS info. object.
1208 *
1209 * @returns VBox status code.
1210 * @param pVmcsInfo The VMCS info. object.
1211 *
1212 * @remarks Can be called with interrupts disabled.
1213 */
1214static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1215{
1216 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1217 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1218
1219 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1220 if (RT_SUCCESS(rc))
1221 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1222 return rc;
1223}
1224
1225
1226/**
1227 * Switches from and to the specified VMCSes.
1228 *
1229 * @returns VBox status code.
1230 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1231 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1232 *
1233 * @remarks Called with interrupts disabled.
1234 */
1235static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1236{
1237 /*
1238 * Clear the VMCS we are switching out if it has not already been cleared.
1239 * This will sync any CPU internal data back to the VMCS.
1240 */
1241 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1242 {
1243 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1244 if (RT_SUCCESS(rc))
1245 {
1246 /*
1247 * The shadow VMCS, if any, would not be active at this point since we
1248 * would have cleared it while importing the virtual hardware-virtualization
1249 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1250 * clear the shadow VMCS here, just assert for safety.
1251 */
1252 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1253 }
1254 else
1255 return rc;
1256 }
1257
1258 /*
1259 * Clear the VMCS we are switching to if it has not already been cleared.
1260 * This will initialize the VMCS launch state to "clear" required for loading it.
1261 *
1262 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1263 */
1264 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1265 {
1266 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1267 if (RT_SUCCESS(rc))
1268 { /* likely */ }
1269 else
1270 return rc;
1271 }
1272
1273 /*
1274 * Finally, load the VMCS we are switching to.
1275 */
1276 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1277}
1278
1279
1280/**
1281 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1282 * caller.
1283 *
1284 * @returns VBox status code.
1285 * @param pVCpu The cross context virtual CPU structure.
1286 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1287 * true) or guest VMCS (pass false).
1288 */
1289static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1290{
1291 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1292 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1293
1294 PVMXVMCSINFO pVmcsInfoFrom;
1295 PVMXVMCSINFO pVmcsInfoTo;
1296 if (fSwitchToNstGstVmcs)
1297 {
1298 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1299 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1300 }
1301 else
1302 {
1303 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1304 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1305 }
1306
1307 /*
1308 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1309 * preemption hook code path acquires the current VMCS.
1310 */
1311 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1312
1313 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1314 if (RT_SUCCESS(rc))
1315 {
1316 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1317
1318 /*
1319 * If we are switching to a VMCS that was executed on a different host CPU or was
1320 * never executed before, flag that we need to export the host state before executing
1321 * guest/nested-guest code using hardware-assisted VMX.
1322 *
1323 * This could probably be done in a preemptible context since the preemption hook
1324 * will flag the necessary change in host context. However, since preemption is
1325 * already disabled and to avoid making assumptions about host specific code in
1326 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1327 * disabled.
1328 */
1329 if (pVmcsInfoTo->idHostCpuState == RTMpCpuId())
1330 { /* likely */ }
1331 else
1332 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1333
1334 ASMSetFlags(fEFlags);
1335
1336 /*
1337 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1338 * flag that we need to update the host MSR values there. Even if we decide in the
1339 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1340 * if its content differs, we would have to update the host MSRs anyway.
1341 */
1342 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1343 }
1344 else
1345 ASMSetFlags(fEFlags);
1346 return rc;
1347}
1348#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1349
1350
1351/**
1352 * Updates the VM's last error record.
1353 *
1354 * If there was a VMX instruction error, reads the error data from the VMCS and
1355 * updates VCPU's last error record as well.
1356 *
1357 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1358 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1359 * VERR_VMX_INVALID_VMCS_FIELD.
1360 * @param rc The error code.
1361 */
1362static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1363{
1364 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1365 || rc == VERR_VMX_UNABLE_TO_START_VM)
1366 {
1367 AssertPtrReturnVoid(pVCpu);
1368 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1369 }
1370 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1371}
1372
1373
1374#ifdef VBOX_STRICT
1375/**
1376 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1377 * transient structure.
1378 *
1379 * @param pVmxTransient The VMX-transient structure.
1380 */
1381DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1382{
1383 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1384 AssertRC(rc);
1385}
1386
1387
1388/**
1389 * Reads the VM-entry exception error code field from the VMCS into
1390 * the VMX transient structure.
1391 *
1392 * @param pVmxTransient The VMX-transient structure.
1393 */
1394DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1395{
1396 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1397 AssertRC(rc);
1398}
1399
1400
1401/**
1402 * Reads the VM-entry exception error code field from the VMCS into
1403 * the VMX transient structure.
1404 *
1405 * @param pVmxTransient The VMX-transient structure.
1406 */
1407DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1408{
1409 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1410 AssertRC(rc);
1411}
1412#endif /* VBOX_STRICT */
1413
1414
1415/**
1416 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1417 * transient structure.
1418 *
1419 * @param pVmxTransient The VMX-transient structure.
1420 */
1421DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1422{
1423 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1424 {
1425 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1426 AssertRC(rc);
1427 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1428 }
1429}
1430
1431
1432/**
1433 * Reads the VM-exit interruption error code from the VMCS into the VMX
1434 * transient structure.
1435 *
1436 * @param pVmxTransient The VMX-transient structure.
1437 */
1438DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1439{
1440 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1441 {
1442 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1443 AssertRC(rc);
1444 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1445 }
1446}
1447
1448
1449/**
1450 * Reads the VM-exit instruction length field from the VMCS into the VMX
1451 * transient structure.
1452 *
1453 * @param pVmxTransient The VMX-transient structure.
1454 */
1455DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1456{
1457 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1458 {
1459 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1460 AssertRC(rc);
1461 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1462 }
1463}
1464
1465
1466/**
1467 * Reads the VM-exit instruction-information field from the VMCS into
1468 * the VMX transient structure.
1469 *
1470 * @param pVmxTransient The VMX-transient structure.
1471 */
1472DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1473{
1474 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1475 {
1476 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1477 AssertRC(rc);
1478 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1479 }
1480}
1481
1482
1483/**
1484 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1485 *
1486 * @param pVmxTransient The VMX-transient structure.
1487 */
1488DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1489{
1490 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1491 {
1492 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1493 AssertRC(rc);
1494 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1495 }
1496}
1497
1498
1499/**
1500 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1501 *
1502 * @param pVmxTransient The VMX-transient structure.
1503 */
1504DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1505{
1506 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1507 {
1508 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1509 AssertRC(rc);
1510 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1511 }
1512}
1513
1514
1515/**
1516 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1517 *
1518 * @param pVmxTransient The VMX-transient structure.
1519 */
1520DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1521{
1522 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1523 {
1524 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1525 AssertRC(rc);
1526 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1527 }
1528}
1529
1530#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1531/**
1532 * Reads the Guest pending-debug exceptions from the VMCS into the VMX transient
1533 * structure.
1534 *
1535 * @param pVmxTransient The VMX-transient structure.
1536 */
1537DECLINLINE(void) hmR0VmxReadGuestPendingDbgXctps(PVMXTRANSIENT pVmxTransient)
1538{
1539 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PENDING_DBG_XCPTS))
1540 {
1541 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &pVmxTransient->uGuestPendingDbgXcpts);
1542 AssertRC(rc);
1543 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PENDING_DBG_XCPTS;
1544 }
1545}
1546#endif
1547
1548/**
1549 * Reads the IDT-vectoring information field from the VMCS into the VMX
1550 * transient structure.
1551 *
1552 * @param pVmxTransient The VMX-transient structure.
1553 *
1554 * @remarks No-long-jump zone!!!
1555 */
1556DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1557{
1558 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1559 {
1560 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1561 AssertRC(rc);
1562 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1563 }
1564}
1565
1566
1567/**
1568 * Reads the IDT-vectoring error code from the VMCS into the VMX
1569 * transient structure.
1570 *
1571 * @param pVmxTransient The VMX-transient structure.
1572 */
1573DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1574{
1575 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1576 {
1577 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1578 AssertRC(rc);
1579 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1580 }
1581}
1582
1583#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1584/**
1585 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1586 *
1587 * @param pVmxTransient The VMX-transient structure.
1588 */
1589static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1590{
1591 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1592 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1593 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1594 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1595 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1596 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1597 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1598 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1599 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1600 AssertRC(rc);
1601 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1602 | HMVMX_READ_EXIT_INSTR_LEN
1603 | HMVMX_READ_EXIT_INSTR_INFO
1604 | HMVMX_READ_IDT_VECTORING_INFO
1605 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1606 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1607 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1608 | HMVMX_READ_GUEST_LINEAR_ADDR
1609 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1610}
1611#endif
1612
1613/**
1614 * Enters VMX root mode operation on the current CPU.
1615 *
1616 * @returns VBox status code.
1617 * @param pHostCpu The HM physical-CPU structure.
1618 * @param pVM The cross context VM structure. Can be
1619 * NULL, after a resume.
1620 * @param HCPhysCpuPage Physical address of the VMXON region.
1621 * @param pvCpuPage Pointer to the VMXON region.
1622 */
1623static int hmR0VmxEnterRootMode(PHMPHYSCPU pHostCpu, PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1624{
1625 Assert(pHostCpu);
1626 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1627 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1628 Assert(pvCpuPage);
1629 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1630
1631 if (pVM)
1632 {
1633 /* Write the VMCS revision identifier to the VMXON region. */
1634 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1635 }
1636
1637 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1638 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1639
1640 /* Enable the VMX bit in CR4 if necessary. */
1641 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1642
1643 /* Record whether VMXE was already prior to us enabling it above. */
1644 pHostCpu->fVmxeAlreadyEnabled = RT_BOOL(uOldCr4 & X86_CR4_VMXE);
1645
1646 /* Enter VMX root mode. */
1647 int rc = VMXEnable(HCPhysCpuPage);
1648 if (RT_FAILURE(rc))
1649 {
1650 /* Restore CR4.VMXE if it was not set prior to our attempt to set it above. */
1651 if (!pHostCpu->fVmxeAlreadyEnabled)
1652 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1653
1654 if (pVM)
1655 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1656 }
1657
1658 /* Restore interrupts. */
1659 ASMSetFlags(fEFlags);
1660 return rc;
1661}
1662
1663
1664/**
1665 * Exits VMX root mode operation on the current CPU.
1666 *
1667 * @returns VBox status code.
1668 * @param pHostCpu The HM physical-CPU structure.
1669 */
1670static int hmR0VmxLeaveRootMode(PHMPHYSCPU pHostCpu)
1671{
1672 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1673
1674 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1675 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1676
1677 /* If we're for some reason not in VMX root mode, then don't leave it. */
1678 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1679
1680 int rc;
1681 if (uHostCr4 & X86_CR4_VMXE)
1682 {
1683 /* Exit VMX root mode and clear the VMX bit in CR4. */
1684 VMXDisable();
1685
1686 /* Clear CR4.VMXE only if it was clear prior to use setting it. */
1687 if (!pHostCpu->fVmxeAlreadyEnabled)
1688 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1689
1690 rc = VINF_SUCCESS;
1691 }
1692 else
1693 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1694
1695 /* Restore interrupts. */
1696 ASMSetFlags(fEFlags);
1697 return rc;
1698}
1699
1700
1701/**
1702 * Allocates pages specified as specified by an array of VMX page allocation info
1703 * objects.
1704 *
1705 * The pages contents are zero'd after allocation.
1706 *
1707 * @returns VBox status code.
1708 * @param hMemObj The ring-0 memory object associated with the allocation.
1709 * @param paAllocInfo The pointer to the first element of the VMX
1710 * page-allocation info object array.
1711 * @param cEntries The number of elements in the @a paAllocInfo array.
1712 */
1713static int hmR0VmxPagesAllocZ(RTR0MEMOBJ hMemObj, PVMXPAGEALLOCINFO paAllocInfo, uint32_t cEntries)
1714{
1715 /* Figure out how many pages to allocate. */
1716 uint32_t cPages = 0;
1717 for (uint32_t iPage = 0; iPage < cEntries; iPage++)
1718 cPages += !!paAllocInfo[iPage].fValid;
1719
1720 /* Allocate the pages. */
1721 if (cPages)
1722 {
1723 size_t const cbPages = cPages << X86_PAGE_4K_SHIFT;
1724 int rc = RTR0MemObjAllocPage(&hMemObj, cbPages, false /* fExecutable */);
1725 if (RT_FAILURE(rc))
1726 return rc;
1727
1728 /* Zero the contents and assign each page to the corresponding VMX page-allocation entry. */
1729 void *pvFirstPage = RTR0MemObjAddress(hMemObj);
1730 ASMMemZero32(pvFirstPage, cbPages);
1731
1732 uint32_t iPage = 0;
1733 for (uint32_t i = 0; i < cEntries; i++)
1734 if (paAllocInfo[i].fValid)
1735 {
1736 RTHCPHYS const HCPhysPage = RTR0MemObjGetPagePhysAddr(hMemObj, iPage);
1737 void *pvPage = (void *)((uintptr_t)pvFirstPage + (iPage << X86_PAGE_4K_SHIFT));
1738 Assert(HCPhysPage && HCPhysPage != NIL_RTHCPHYS);
1739 AssertPtr(pvPage);
1740
1741 Assert(paAllocInfo[iPage].pHCPhys);
1742 Assert(paAllocInfo[iPage].ppVirt);
1743 *paAllocInfo[iPage].pHCPhys = HCPhysPage;
1744 *paAllocInfo[iPage].ppVirt = pvPage;
1745
1746 /* Move to next page. */
1747 ++iPage;
1748 }
1749
1750 /* Make sure all valid (requested) pages have been assigned. */
1751 Assert(iPage == cPages);
1752 }
1753 return VINF_SUCCESS;
1754}
1755
1756
1757/**
1758 * Frees pages allocated using hmR0VmxPagesAllocZ.
1759 *
1760 * @param hMemObj The ring-0 memory object associated with the allocation.
1761 */
1762DECL_FORCE_INLINE(void) hmR0VmxPagesFree(RTR0MEMOBJ hMemObj)
1763{
1764 /* We can cleanup wholesale since it's all one allocation. */
1765 RTR0MemObjFree(hMemObj, true /* fFreeMappings */);
1766}
1767
1768
1769/**
1770 * Initializes a VMCS info. object.
1771 *
1772 * @param pVmcsInfo The VMCS info. object.
1773 */
1774static void hmR0VmxVmcsInfoInit(PVMXVMCSINFO pVmcsInfo)
1775{
1776 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1777
1778 Assert(pVmcsInfo->hMemObj == NIL_RTR0MEMOBJ);
1779 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1780 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1781 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1782 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1783 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1784 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1785 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1786 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1787 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1788 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
1789 pVmcsInfo->idHostCpuExec = NIL_RTCPUID;
1790}
1791
1792
1793/**
1794 * Frees the VT-x structures for a VMCS info. object.
1795 *
1796 * @param pVmcsInfo The VMCS info. object.
1797 */
1798static void hmR0VmxVmcsInfoFree(PVMXVMCSINFO pVmcsInfo)
1799{
1800 if (pVmcsInfo->hMemObj != NIL_RTR0MEMOBJ)
1801 {
1802 hmR0VmxPagesFree(pVmcsInfo->hMemObj);
1803 hmR0VmxVmcsInfoInit(pVmcsInfo);
1804 }
1805}
1806
1807
1808/**
1809 * Allocates the VT-x structures for a VMCS info. object.
1810 *
1811 * @returns VBox status code.
1812 * @param pVCpu The cross context virtual CPU structure.
1813 * @param pVmcsInfo The VMCS info. object.
1814 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1815 *
1816 * @remarks The caller is expected to take care of any and all allocation failures.
1817 * This function will not perform any cleanup for failures half-way
1818 * through.
1819 */
1820static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1821{
1822 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1823
1824 bool const fMsrBitmaps = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS);
1825 bool const fShadowVmcs = !fIsNstGstVmcs ? pVM->hm.s.vmx.fUseVmcsShadowing : pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing;
1826 Assert(!pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing); /* VMCS shadowing is not yet exposed to the guest. */
1827 VMXPAGEALLOCINFO aAllocInfo[] = {
1828 { true, 0 /* Unused */, &pVmcsInfo->HCPhysVmcs, &pVmcsInfo->pvVmcs },
1829 { true, 0 /* Unused */, &pVmcsInfo->HCPhysGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad },
1830 { true, 0 /* Unused */, &pVmcsInfo->HCPhysHostMsrLoad, &pVmcsInfo->pvHostMsrLoad },
1831 { fMsrBitmaps, 0 /* Unused */, &pVmcsInfo->HCPhysMsrBitmap, &pVmcsInfo->pvMsrBitmap },
1832 { fShadowVmcs, 0 /* Unused */, &pVmcsInfo->HCPhysShadowVmcs, &pVmcsInfo->pvShadowVmcs },
1833 };
1834
1835 int rc = hmR0VmxPagesAllocZ(pVmcsInfo->hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1836 if (RT_FAILURE(rc))
1837 return rc;
1838
1839 /*
1840 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1841 * Because they contain a symmetric list of guest MSRs to load on VM-entry and store on VM-exit.
1842 */
1843 AssertCompile(RT_ELEMENTS(aAllocInfo) > 0);
1844 Assert(pVmcsInfo->HCPhysGuestMsrLoad != NIL_RTHCPHYS);
1845 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1846 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1847
1848 /*
1849 * Get the virtual-APIC page rather than allocating them again.
1850 */
1851 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1852 {
1853 if (!fIsNstGstVmcs)
1854 {
1855 if (PDMHasApic(pVM))
1856 {
1857 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1858 if (RT_FAILURE(rc))
1859 return rc;
1860 Assert(pVmcsInfo->pbVirtApic);
1861 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1862 }
1863 }
1864 else
1865 {
1866 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(&pVCpu->cpum.GstCtx, &pVmcsInfo->HCPhysVirtApic);
1867 Assert(pVmcsInfo->pbVirtApic);
1868 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1869 }
1870 }
1871
1872 return VINF_SUCCESS;
1873}
1874
1875
1876/**
1877 * Free all VT-x structures for the VM.
1878 *
1879 * @returns IPRT status code.
1880 * @param pVM The cross context VM structure.
1881 */
1882static void hmR0VmxStructsFree(PVMCC pVM)
1883{
1884 hmR0VmxPagesFree(pVM->hm.s.vmx.hMemObj);
1885#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1886 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1887 {
1888 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1889 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1890 }
1891#endif
1892
1893 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1894 {
1895 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1896 hmR0VmxVmcsInfoFree(&pVCpu->hm.s.vmx.VmcsInfo);
1897#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1898 if (pVM->cpum.ro.GuestFeatures.fVmx)
1899 hmR0VmxVmcsInfoFree(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1900#endif
1901 }
1902}
1903
1904
1905/**
1906 * Allocate all VT-x structures for the VM.
1907 *
1908 * @returns IPRT status code.
1909 * @param pVM The cross context VM structure.
1910 *
1911 * @remarks This functions will cleanup on memory allocation failures.
1912 */
1913static int hmR0VmxStructsAlloc(PVMCC pVM)
1914{
1915 /*
1916 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1917 * The VMCS size cannot be more than 4096 bytes.
1918 *
1919 * See Intel spec. Appendix A.1 "Basic VMX Information".
1920 */
1921 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1922 if (cbVmcs <= X86_PAGE_4K_SIZE)
1923 { /* likely */ }
1924 else
1925 {
1926 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1927 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1928 }
1929
1930 /*
1931 * Allocate per-VM VT-x structures.
1932 */
1933 bool const fVirtApicAccess = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
1934 bool const fUseVmcsShadowing = pVM->hm.s.vmx.fUseVmcsShadowing;
1935 VMXPAGEALLOCINFO aAllocInfo[] = {
1936 { fVirtApicAccess, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess },
1937 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap },
1938 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap },
1939#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1940 { true, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysScratch, &(PRTR0PTR)pVM->hm.s.vmx.pbScratch },
1941#endif
1942 };
1943
1944 int rc = hmR0VmxPagesAllocZ(pVM->hm.s.vmx.hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1945 if (RT_FAILURE(rc))
1946 goto cleanup;
1947
1948#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1949 /* Allocate the shadow VMCS-fields array. */
1950 if (fUseVmcsShadowing)
1951 {
1952 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
1953 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
1954 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1955 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1956 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
1957 && pVM->hm.s.vmx.paShadowVmcsRoFields))
1958 { /* likely */ }
1959 else
1960 {
1961 rc = VERR_NO_MEMORY;
1962 goto cleanup;
1963 }
1964 }
1965#endif
1966
1967 /*
1968 * Allocate per-VCPU VT-x structures.
1969 */
1970 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1971 {
1972 /* Allocate the guest VMCS structures. */
1973 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1974 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
1975 if (RT_FAILURE(rc))
1976 goto cleanup;
1977
1978#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1979 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
1980 if (pVM->cpum.ro.GuestFeatures.fVmx)
1981 {
1982 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
1983 if (RT_FAILURE(rc))
1984 goto cleanup;
1985 }
1986#endif
1987 }
1988
1989 return VINF_SUCCESS;
1990
1991cleanup:
1992 hmR0VmxStructsFree(pVM);
1993 Assert(rc != VINF_SUCCESS);
1994 return rc;
1995}
1996
1997
1998/**
1999 * Pre-initializes non-zero fields in VMX structures that will be allocated.
2000 *
2001 * @param pVM The cross context VM structure.
2002 */
2003static void hmR0VmxStructsInit(PVMCC pVM)
2004{
2005 /* Paranoia. */
2006 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
2007#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2008 Assert(pVM->hm.s.vmx.pbScratch == NULL);
2009#endif
2010
2011 /*
2012 * Initialize members up-front so we can cleanup en masse on allocation failures.
2013 */
2014#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2015 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
2016#endif
2017 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
2018 pVM->hm.s.vmx.HCPhysVmreadBitmap = NIL_RTHCPHYS;
2019 pVM->hm.s.vmx.HCPhysVmwriteBitmap = NIL_RTHCPHYS;
2020 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2021 {
2022 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2023 hmR0VmxVmcsInfoInit(&pVCpu->hm.s.vmx.VmcsInfo);
2024 hmR0VmxVmcsInfoInit(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
2025 }
2026}
2027
2028#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2029/**
2030 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2031 *
2032 * @returns @c true if the MSR is intercepted, @c false otherwise.
2033 * @param pvMsrBitmap The MSR bitmap.
2034 * @param offMsr The MSR byte offset.
2035 * @param iBit The bit offset from the byte offset.
2036 */
2037DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2038{
2039 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2040 Assert(pbMsrBitmap);
2041 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2042 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2043}
2044#endif
2045
2046/**
2047 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2048 *
2049 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2050 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2051 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2052 * the read/write access of this MSR.
2053 *
2054 * @param pVCpu The cross context virtual CPU structure.
2055 * @param pVmcsInfo The VMCS info. object.
2056 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2057 * @param idMsr The MSR value.
2058 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2059 * include both a read -and- a write permission!
2060 *
2061 * @sa CPUMGetVmxMsrPermission.
2062 * @remarks Can be called with interrupts disabled.
2063 */
2064static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2065{
2066 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2067 Assert(pbMsrBitmap);
2068 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2069
2070 /*
2071 * MSR-bitmap Layout:
2072 * Byte index MSR range Interpreted as
2073 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2074 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2075 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2076 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2077 *
2078 * A bit corresponding to an MSR within the above range causes a VM-exit
2079 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2080 * the MSR range, it always cause a VM-exit.
2081 *
2082 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2083 */
2084 uint16_t const offBitmapRead = 0;
2085 uint16_t const offBitmapWrite = 0x800;
2086 uint16_t offMsr;
2087 int32_t iBit;
2088 if (idMsr <= UINT32_C(0x00001fff))
2089 {
2090 offMsr = 0;
2091 iBit = idMsr;
2092 }
2093 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2094 {
2095 offMsr = 0x400;
2096 iBit = idMsr - UINT32_C(0xc0000000);
2097 }
2098 else
2099 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2100
2101 /*
2102 * Set the MSR read permission.
2103 */
2104 uint16_t const offMsrRead = offBitmapRead + offMsr;
2105 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2106 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2107 {
2108#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2109 bool const fClear = !fIsNstGstVmcs ? true
2110 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2111#else
2112 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2113 bool const fClear = true;
2114#endif
2115 if (fClear)
2116 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2117 }
2118 else
2119 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2120
2121 /*
2122 * Set the MSR write permission.
2123 */
2124 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2125 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2126 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2127 {
2128#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2129 bool const fClear = !fIsNstGstVmcs ? true
2130 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2131#else
2132 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2133 bool const fClear = true;
2134#endif
2135 if (fClear)
2136 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2137 }
2138 else
2139 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2140}
2141
2142
2143/**
2144 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2145 * area.
2146 *
2147 * @returns VBox status code.
2148 * @param pVCpu The cross context virtual CPU structure.
2149 * @param pVmcsInfo The VMCS info. object.
2150 * @param cMsrs The number of MSRs.
2151 */
2152static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2153{
2154 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2155 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2156 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2157 {
2158 /* Commit the MSR counts to the VMCS and update the cache. */
2159 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2160 {
2161 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2162 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2163 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2164 pVmcsInfo->cEntryMsrLoad = cMsrs;
2165 pVmcsInfo->cExitMsrStore = cMsrs;
2166 pVmcsInfo->cExitMsrLoad = cMsrs;
2167 }
2168 return VINF_SUCCESS;
2169 }
2170
2171 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2172 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2173 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2174}
2175
2176
2177/**
2178 * Adds a new (or updates the value of an existing) guest/host MSR
2179 * pair to be swapped during the world-switch as part of the
2180 * auto-load/store MSR area in the VMCS.
2181 *
2182 * @returns VBox status code.
2183 * @param pVCpu The cross context virtual CPU structure.
2184 * @param pVmxTransient The VMX-transient structure.
2185 * @param idMsr The MSR.
2186 * @param uGuestMsrValue Value of the guest MSR.
2187 * @param fSetReadWrite Whether to set the guest read/write access of this
2188 * MSR (thus not causing a VM-exit).
2189 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2190 * necessary.
2191 */
2192static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2193 bool fSetReadWrite, bool fUpdateHostMsr)
2194{
2195 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2196 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2197 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2198 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2199 uint32_t i;
2200
2201 /* Paranoia. */
2202 Assert(pGuestMsrLoad);
2203
2204 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2205
2206 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2207 for (i = 0; i < cMsrs; i++)
2208 {
2209 if (pGuestMsrLoad[i].u32Msr == idMsr)
2210 break;
2211 }
2212
2213 bool fAdded = false;
2214 if (i == cMsrs)
2215 {
2216 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2217 ++cMsrs;
2218 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2219 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2220
2221 /* Set the guest to read/write this MSR without causing VM-exits. */
2222 if ( fSetReadWrite
2223 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2224 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2225
2226 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2227 fAdded = true;
2228 }
2229
2230 /* Update the MSR value for the newly added or already existing MSR. */
2231 pGuestMsrLoad[i].u32Msr = idMsr;
2232 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2233
2234 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2235 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2236 {
2237 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2238 pGuestMsrStore[i].u32Msr = idMsr;
2239 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2240 }
2241
2242 /* Update the corresponding slot in the host MSR area. */
2243 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2244 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2245 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2246 pHostMsr[i].u32Msr = idMsr;
2247
2248 /*
2249 * Only if the caller requests to update the host MSR value AND we've newly added the
2250 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2251 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2252 *
2253 * We do this for performance reasons since reading MSRs may be quite expensive.
2254 */
2255 if (fAdded)
2256 {
2257 if (fUpdateHostMsr)
2258 {
2259 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2260 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2261 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2262 }
2263 else
2264 {
2265 /* Someone else can do the work. */
2266 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2267 }
2268 }
2269 return VINF_SUCCESS;
2270}
2271
2272
2273/**
2274 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2275 * auto-load/store MSR area in the VMCS.
2276 *
2277 * @returns VBox status code.
2278 * @param pVCpu The cross context virtual CPU structure.
2279 * @param pVmxTransient The VMX-transient structure.
2280 * @param idMsr The MSR.
2281 */
2282static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2283{
2284 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2285 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2286 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2287 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2288
2289 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2290
2291 for (uint32_t i = 0; i < cMsrs; i++)
2292 {
2293 /* Find the MSR. */
2294 if (pGuestMsrLoad[i].u32Msr == idMsr)
2295 {
2296 /*
2297 * If it's the last MSR, we only need to reduce the MSR count.
2298 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2299 */
2300 if (i < cMsrs - 1)
2301 {
2302 /* Remove it from the VM-entry MSR-load area. */
2303 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2304 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2305
2306 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2307 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2308 {
2309 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2310 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2311 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2312 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2313 }
2314
2315 /* Remove it from the VM-exit MSR-load area. */
2316 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2317 Assert(pHostMsr[i].u32Msr == idMsr);
2318 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2319 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2320 }
2321
2322 /* Reduce the count to reflect the removed MSR and bail. */
2323 --cMsrs;
2324 break;
2325 }
2326 }
2327
2328 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2329 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2330 {
2331 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2332 AssertRCReturn(rc, rc);
2333
2334 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2335 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2336 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2337
2338 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2339 return VINF_SUCCESS;
2340 }
2341
2342 return VERR_NOT_FOUND;
2343}
2344
2345
2346/**
2347 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2348 *
2349 * @returns @c true if found, @c false otherwise.
2350 * @param pVmcsInfo The VMCS info. object.
2351 * @param idMsr The MSR to find.
2352 */
2353static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2354{
2355 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2356 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2357 Assert(pMsrs);
2358 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2359 for (uint32_t i = 0; i < cMsrs; i++)
2360 {
2361 if (pMsrs[i].u32Msr == idMsr)
2362 return true;
2363 }
2364 return false;
2365}
2366
2367
2368/**
2369 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2370 *
2371 * @param pVCpu The cross context virtual CPU structure.
2372 * @param pVmcsInfo The VMCS info. object.
2373 *
2374 * @remarks No-long-jump zone!!!
2375 */
2376static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2377{
2378 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2379
2380 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2381 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2382 Assert(pHostMsrLoad);
2383 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2384 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2385 for (uint32_t i = 0; i < cMsrs; i++)
2386 {
2387 /*
2388 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2389 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2390 */
2391 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2392 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2393 else
2394 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2395 }
2396}
2397
2398
2399/**
2400 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2401 * perform lazy restoration of the host MSRs while leaving VT-x.
2402 *
2403 * @param pVCpu The cross context virtual CPU structure.
2404 *
2405 * @remarks No-long-jump zone!!!
2406 */
2407static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2408{
2409 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2410
2411 /*
2412 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2413 */
2414 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2415 {
2416 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2417 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2418 {
2419 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2420 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2421 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2422 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2423 }
2424 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2425 }
2426}
2427
2428
2429/**
2430 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2431 * lazily while leaving VT-x.
2432 *
2433 * @returns true if it does, false otherwise.
2434 * @param pVCpu The cross context virtual CPU structure.
2435 * @param idMsr The MSR to check.
2436 */
2437static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2438{
2439 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2440 {
2441 switch (idMsr)
2442 {
2443 case MSR_K8_LSTAR:
2444 case MSR_K6_STAR:
2445 case MSR_K8_SF_MASK:
2446 case MSR_K8_KERNEL_GS_BASE:
2447 return true;
2448 }
2449 }
2450 return false;
2451}
2452
2453
2454/**
2455 * Loads a set of guests MSRs to allow read/passthru to the guest.
2456 *
2457 * The name of this function is slightly confusing. This function does NOT
2458 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2459 * common prefix for functions dealing with "lazy restoration" of the shared
2460 * MSRs.
2461 *
2462 * @param pVCpu The cross context virtual CPU structure.
2463 *
2464 * @remarks No-long-jump zone!!!
2465 */
2466static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2467{
2468 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2469 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2470
2471 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2472 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2473 {
2474 /*
2475 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2476 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2477 * we can skip a few MSR writes.
2478 *
2479 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2480 * guest MSR values in the guest-CPU context might be different to what's currently
2481 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2482 * CPU, see @bugref{8728}.
2483 */
2484 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2485 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2486 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2487 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2488 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2489 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2490 {
2491#ifdef VBOX_STRICT
2492 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2493 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2494 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2495 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2496#endif
2497 }
2498 else
2499 {
2500 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2501 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2502 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2503 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2504 }
2505 }
2506 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2507}
2508
2509
2510/**
2511 * Performs lazy restoration of the set of host MSRs if they were previously
2512 * loaded with guest MSR values.
2513 *
2514 * @param pVCpu The cross context virtual CPU structure.
2515 *
2516 * @remarks No-long-jump zone!!!
2517 * @remarks The guest MSRs should have been saved back into the guest-CPU
2518 * context by hmR0VmxImportGuestState()!!!
2519 */
2520static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2521{
2522 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2523 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2524
2525 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2526 {
2527 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2528 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2529 {
2530 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2531 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2532 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2533 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2534 }
2535 }
2536 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2537}
2538
2539
2540/**
2541 * Verifies that our cached values of the VMCS fields are all consistent with
2542 * what's actually present in the VMCS.
2543 *
2544 * @returns VBox status code.
2545 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2546 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2547 * VMCS content. HMCPU error-field is
2548 * updated, see VMX_VCI_XXX.
2549 * @param pVCpu The cross context virtual CPU structure.
2550 * @param pVmcsInfo The VMCS info. object.
2551 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2552 */
2553static int hmR0VmxCheckCachedVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2554{
2555 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2556
2557 uint32_t u32Val;
2558 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2559 AssertRC(rc);
2560 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2561 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2562 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2563 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2564
2565 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2566 AssertRC(rc);
2567 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2568 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2569 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2570 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2571
2572 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2573 AssertRC(rc);
2574 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2575 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2576 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2577 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2578
2579 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2580 AssertRC(rc);
2581 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2582 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2583 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2584 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2585
2586 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2587 {
2588 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2589 AssertRC(rc);
2590 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2591 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2592 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2593 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2594 }
2595
2596 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2597 AssertRC(rc);
2598 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2599 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2600 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2601 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2602
2603 uint64_t u64Val;
2604 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2605 AssertRC(rc);
2606 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2607 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2608 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2609 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2610
2611 NOREF(pcszVmcs);
2612 return VINF_SUCCESS;
2613}
2614
2615
2616#ifdef VBOX_STRICT
2617/**
2618 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2619 *
2620 * @param pVCpu The cross context virtual CPU structure.
2621 * @param pVmcsInfo The VMCS info. object.
2622 */
2623static void hmR0VmxCheckHostEferMsr(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2624{
2625 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2626
2627 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2628 {
2629 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2630 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2631 uint64_t uVmcsEferMsrVmcs;
2632 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2633 AssertRC(rc);
2634
2635 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2636 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2637 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2638 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2639 }
2640}
2641
2642
2643/**
2644 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2645 * VMCS are correct.
2646 *
2647 * @param pVCpu The cross context virtual CPU structure.
2648 * @param pVmcsInfo The VMCS info. object.
2649 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2650 */
2651static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2652{
2653 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2654
2655 /* Read the various MSR-area counts from the VMCS. */
2656 uint32_t cEntryLoadMsrs;
2657 uint32_t cExitStoreMsrs;
2658 uint32_t cExitLoadMsrs;
2659 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2660 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2661 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2662
2663 /* Verify all the MSR counts are the same. */
2664 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2665 Assert(cExitStoreMsrs == cExitLoadMsrs);
2666 uint32_t const cMsrs = cExitLoadMsrs;
2667
2668 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2669 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2670
2671 /* Verify the MSR counts are within the allocated page size. */
2672 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2673
2674 /* Verify the relevant contents of the MSR areas match. */
2675 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2676 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2677 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2678 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2679 for (uint32_t i = 0; i < cMsrs; i++)
2680 {
2681 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2682 if (fSeparateExitMsrStorePage)
2683 {
2684 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2685 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2686 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2687 }
2688
2689 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2690 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2691 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2692
2693 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2694 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2695 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2696 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2697
2698 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2699 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2700 if (fIsEferMsr)
2701 {
2702 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2703 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2704 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2705 }
2706
2707 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2708 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2709 {
2710 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2711 if (fIsEferMsr)
2712 {
2713 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2714 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2715 }
2716 else
2717 {
2718 if (!fIsNstGstVmcs)
2719 {
2720 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2721 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2722 }
2723 else
2724 {
2725 /*
2726 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2727 * execute a nested-guest with MSR passthrough.
2728 *
2729 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2730 * allow passthrough too.
2731 */
2732 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2733 Assert(pvMsrBitmapNstGst);
2734 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2735 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2736 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2737 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2738 }
2739 }
2740 }
2741
2742 /* Move to the next MSR. */
2743 pHostMsrLoad++;
2744 pGuestMsrLoad++;
2745 pGuestMsrStore++;
2746 }
2747}
2748#endif /* VBOX_STRICT */
2749
2750
2751/**
2752 * Flushes the TLB using EPT.
2753 *
2754 * @returns VBox status code.
2755 * @param pVCpu The cross context virtual CPU structure of the calling
2756 * EMT. Can be NULL depending on @a enmTlbFlush.
2757 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2758 * enmTlbFlush.
2759 * @param enmTlbFlush Type of flush.
2760 *
2761 * @remarks Caller is responsible for making sure this function is called only
2762 * when NestedPaging is supported and providing @a enmTlbFlush that is
2763 * supported by the CPU.
2764 * @remarks Can be called with interrupts disabled.
2765 */
2766static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2767{
2768 uint64_t au64Descriptor[2];
2769 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2770 au64Descriptor[0] = 0;
2771 else
2772 {
2773 Assert(pVCpu);
2774 Assert(pVmcsInfo);
2775 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2776 }
2777 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2778
2779 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2780 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2781
2782 if ( RT_SUCCESS(rc)
2783 && pVCpu)
2784 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2785}
2786
2787
2788/**
2789 * Flushes the TLB using VPID.
2790 *
2791 * @returns VBox status code.
2792 * @param pVCpu The cross context virtual CPU structure of the calling
2793 * EMT. Can be NULL depending on @a enmTlbFlush.
2794 * @param enmTlbFlush Type of flush.
2795 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2796 * on @a enmTlbFlush).
2797 *
2798 * @remarks Can be called with interrupts disabled.
2799 */
2800static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2801{
2802 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2803
2804 uint64_t au64Descriptor[2];
2805 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2806 {
2807 au64Descriptor[0] = 0;
2808 au64Descriptor[1] = 0;
2809 }
2810 else
2811 {
2812 AssertPtr(pVCpu);
2813 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2814 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2815 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2816 au64Descriptor[1] = GCPtr;
2817 }
2818
2819 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2820 AssertMsg(rc == VINF_SUCCESS,
2821 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2822
2823 if ( RT_SUCCESS(rc)
2824 && pVCpu)
2825 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2826 NOREF(rc);
2827}
2828
2829
2830/**
2831 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2832 * otherwise there is nothing really to invalidate.
2833 *
2834 * @returns VBox status code.
2835 * @param pVCpu The cross context virtual CPU structure.
2836 * @param GCVirt Guest virtual address of the page to invalidate.
2837 */
2838VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2839{
2840 AssertPtr(pVCpu);
2841 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2842
2843 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2844 {
2845 /*
2846 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2847 * the EPT case. See @bugref{6043} and @bugref{6177}.
2848 *
2849 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2850 * as this function maybe called in a loop with individual addresses.
2851 */
2852 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2853 if (pVM->hm.s.vmx.fVpid)
2854 {
2855 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2856 if (fVpidFlush)
2857 {
2858 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2859 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2860 }
2861 else
2862 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2863 }
2864 else if (pVM->hm.s.fNestedPaging)
2865 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2866 }
2867
2868 return VINF_SUCCESS;
2869}
2870
2871
2872/**
2873 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2874 * case where neither EPT nor VPID is supported by the CPU.
2875 *
2876 * @param pHostCpu The HM physical-CPU structure.
2877 * @param pVCpu The cross context virtual CPU structure.
2878 *
2879 * @remarks Called with interrupts disabled.
2880 */
2881static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2882{
2883 AssertPtr(pVCpu);
2884 AssertPtr(pHostCpu);
2885
2886 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2887
2888 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2889 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2890 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2891 pVCpu->hm.s.fForceTLBFlush = false;
2892 return;
2893}
2894
2895
2896/**
2897 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2898 *
2899 * @param pHostCpu The HM physical-CPU structure.
2900 * @param pVCpu The cross context virtual CPU structure.
2901 * @param pVmcsInfo The VMCS info. object.
2902 *
2903 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2904 * nomenclature. The reason is, to avoid confusion in compare statements
2905 * since the host-CPU copies are named "ASID".
2906 *
2907 * @remarks Called with interrupts disabled.
2908 */
2909static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2910{
2911#ifdef VBOX_WITH_STATISTICS
2912 bool fTlbFlushed = false;
2913# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2914# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2915 if (!fTlbFlushed) \
2916 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2917 } while (0)
2918#else
2919# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2920# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2921#endif
2922
2923 AssertPtr(pVCpu);
2924 AssertPtr(pHostCpu);
2925 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2926
2927 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2928 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2929 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2930 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2931
2932 /*
2933 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2934 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2935 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2936 * cannot reuse the current ASID anymore.
2937 */
2938 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2939 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2940 {
2941 ++pHostCpu->uCurrentAsid;
2942 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2943 {
2944 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2945 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2946 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2947 }
2948
2949 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2950 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2951 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2952
2953 /*
2954 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2955 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2956 */
2957 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2958 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2959 HMVMX_SET_TAGGED_TLB_FLUSHED();
2960 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2961 }
2962 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2963 {
2964 /*
2965 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2966 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2967 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2968 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2969 * mappings, see @bugref{6568}.
2970 *
2971 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2972 */
2973 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2974 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2975 HMVMX_SET_TAGGED_TLB_FLUSHED();
2976 }
2977 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
2978 {
2979 /*
2980 * The nested-guest specifies its own guest-physical address to use as the APIC-access
2981 * address which requires flushing the TLB of EPT cached structures.
2982 *
2983 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
2984 */
2985 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2986 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
2987 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
2988 HMVMX_SET_TAGGED_TLB_FLUSHED();
2989 }
2990
2991
2992 pVCpu->hm.s.fForceTLBFlush = false;
2993 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
2994
2995 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
2996 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
2997 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2998 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
2999 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3000 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3001 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3002 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3003 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3004
3005 /* Update VMCS with the VPID. */
3006 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3007 AssertRC(rc);
3008
3009#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3010}
3011
3012
3013/**
3014 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3015 *
3016 * @param pHostCpu The HM physical-CPU structure.
3017 * @param pVCpu The cross context virtual CPU structure.
3018 * @param pVmcsInfo The VMCS info. object.
3019 *
3020 * @remarks Called with interrupts disabled.
3021 */
3022static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3023{
3024 AssertPtr(pVCpu);
3025 AssertPtr(pHostCpu);
3026 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3027 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3028 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3029
3030 /*
3031 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3032 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3033 */
3034 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3035 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3036 {
3037 pVCpu->hm.s.fForceTLBFlush = true;
3038 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3039 }
3040
3041 /* Check for explicit TLB flushes. */
3042 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3043 {
3044 pVCpu->hm.s.fForceTLBFlush = true;
3045 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3046 }
3047
3048 /* Check for TLB flushes while switching to/from a nested-guest. */
3049 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3050 {
3051 pVCpu->hm.s.fForceTLBFlush = true;
3052 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3053 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3054 }
3055
3056 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3057 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3058
3059 if (pVCpu->hm.s.fForceTLBFlush)
3060 {
3061 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3062 pVCpu->hm.s.fForceTLBFlush = false;
3063 }
3064}
3065
3066
3067/**
3068 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3069 *
3070 * @param pHostCpu The HM physical-CPU structure.
3071 * @param pVCpu The cross context virtual CPU structure.
3072 *
3073 * @remarks Called with interrupts disabled.
3074 */
3075static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3076{
3077 AssertPtr(pVCpu);
3078 AssertPtr(pHostCpu);
3079 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3080 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3081 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3082
3083 /*
3084 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3085 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3086 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3087 * cannot reuse the current ASID anymore.
3088 */
3089 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3090 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3091 {
3092 pVCpu->hm.s.fForceTLBFlush = true;
3093 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3094 }
3095
3096 /* Check for explicit TLB flushes. */
3097 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3098 {
3099 /*
3100 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3101 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3102 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3103 * include fExplicitFlush's too) - an obscure corner case.
3104 */
3105 pVCpu->hm.s.fForceTLBFlush = true;
3106 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3107 }
3108
3109 /* Check for TLB flushes while switching to/from a nested-guest. */
3110 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3111 {
3112 pVCpu->hm.s.fForceTLBFlush = true;
3113 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3114 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3115 }
3116
3117 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3118 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3119 if (pVCpu->hm.s.fForceTLBFlush)
3120 {
3121 ++pHostCpu->uCurrentAsid;
3122 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3123 {
3124 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3125 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3126 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3127 }
3128
3129 pVCpu->hm.s.fForceTLBFlush = false;
3130 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3131 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3132 if (pHostCpu->fFlushAsidBeforeUse)
3133 {
3134 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3135 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3136 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3137 {
3138 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3139 pHostCpu->fFlushAsidBeforeUse = false;
3140 }
3141 else
3142 {
3143 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3144 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3145 }
3146 }
3147 }
3148
3149 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3150 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3151 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3152 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3153 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3154 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3155 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3156
3157 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3158 AssertRC(rc);
3159}
3160
3161
3162/**
3163 * Flushes the guest TLB entry based on CPU capabilities.
3164 *
3165 * @param pHostCpu The HM physical-CPU structure.
3166 * @param pVCpu The cross context virtual CPU structure.
3167 * @param pVmcsInfo The VMCS info. object.
3168 *
3169 * @remarks Called with interrupts disabled.
3170 */
3171static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3172{
3173#ifdef HMVMX_ALWAYS_FLUSH_TLB
3174 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3175#endif
3176 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3177 switch (pVM->hm.s.vmx.enmTlbFlushType)
3178 {
3179 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3180 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3181 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3182 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3183 default:
3184 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3185 break;
3186 }
3187 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3188}
3189
3190
3191/**
3192 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3193 * TLB entries from the host TLB before VM-entry.
3194 *
3195 * @returns VBox status code.
3196 * @param pVM The cross context VM structure.
3197 */
3198static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3199{
3200 /*
3201 * Determine optimal flush type for nested paging.
3202 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3203 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3204 */
3205 if (pVM->hm.s.fNestedPaging)
3206 {
3207 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3208 {
3209 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3210 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3211 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3212 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3213 else
3214 {
3215 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3216 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3217 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3218 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3219 }
3220
3221 /* Make sure the write-back cacheable memory type for EPT is supported. */
3222 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3223 {
3224 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3225 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3226 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3227 }
3228
3229 /* EPT requires a page-walk length of 4. */
3230 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3231 {
3232 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3233 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3234 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3235 }
3236 }
3237 else
3238 {
3239 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3240 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3241 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3242 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3243 }
3244 }
3245
3246 /*
3247 * Determine optimal flush type for VPID.
3248 */
3249 if (pVM->hm.s.vmx.fVpid)
3250 {
3251 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3252 {
3253 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3254 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3255 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3256 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3257 else
3258 {
3259 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3260 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3261 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3262 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3263 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3264 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3265 pVM->hm.s.vmx.fVpid = false;
3266 }
3267 }
3268 else
3269 {
3270 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3271 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3272 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3273 pVM->hm.s.vmx.fVpid = false;
3274 }
3275 }
3276
3277 /*
3278 * Setup the handler for flushing tagged-TLBs.
3279 */
3280 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3281 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3282 else if (pVM->hm.s.fNestedPaging)
3283 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3284 else if (pVM->hm.s.vmx.fVpid)
3285 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3286 else
3287 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3288 return VINF_SUCCESS;
3289}
3290
3291
3292#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3293/**
3294 * Sets up the shadow VMCS fields arrays.
3295 *
3296 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3297 * executing the guest.
3298 *
3299 * @returns VBox status code.
3300 * @param pVM The cross context VM structure.
3301 */
3302static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3303{
3304 /*
3305 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3306 * when the host does not support it.
3307 */
3308 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3309 if ( !fGstVmwriteAll
3310 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3311 { /* likely. */ }
3312 else
3313 {
3314 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3315 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3316 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3317 }
3318
3319 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3320 uint32_t cRwFields = 0;
3321 uint32_t cRoFields = 0;
3322 for (uint32_t i = 0; i < cVmcsFields; i++)
3323 {
3324 VMXVMCSFIELD VmcsField;
3325 VmcsField.u = g_aVmcsFields[i];
3326
3327 /*
3328 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3329 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3330 * in the shadow VMCS fields array as they would be redundant.
3331 *
3332 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3333 * we must not include it in the shadow VMCS fields array. Guests attempting to
3334 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3335 * the required behavior.
3336 */
3337 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3338 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3339 {
3340 /*
3341 * Read-only fields are placed in a separate array so that while syncing shadow
3342 * VMCS fields later (which is more performance critical) we can avoid branches.
3343 *
3344 * However, if the guest can write to all fields (including read-only fields),
3345 * we treat it a as read/write field. Otherwise, writing to these fields would
3346 * cause a VMWRITE instruction error while syncing the shadow VMCS.
3347 */
3348 if ( fGstVmwriteAll
3349 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3350 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3351 else
3352 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3353 }
3354 }
3355
3356 /* Update the counts. */
3357 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3358 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3359 return VINF_SUCCESS;
3360}
3361
3362
3363/**
3364 * Sets up the VMREAD and VMWRITE bitmaps.
3365 *
3366 * @param pVM The cross context VM structure.
3367 */
3368static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3369{
3370 /*
3371 * By default, ensure guest attempts to access any VMCS fields cause VM-exits.
3372 */
3373 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3374 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3375 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3376 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3377 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3378
3379 /*
3380 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3381 * VMREAD and VMWRITE bitmaps.
3382 */
3383 {
3384 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3385 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3386 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3387 {
3388 uint32_t const uVmcsField = paShadowVmcsFields[i];
3389 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3390 Assert(uVmcsField >> 3 < cbBitmap);
3391 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3392 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3393 }
3394 }
3395
3396 /*
3397 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3398 * if the host supports VMWRITE to all supported VMCS fields.
3399 */
3400 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3401 {
3402 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3403 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3404 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3405 {
3406 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3407 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3408 Assert(uVmcsField >> 3 < cbBitmap);
3409 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3410 }
3411 }
3412}
3413#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3414
3415
3416/**
3417 * Sets up the virtual-APIC page address for the VMCS.
3418 *
3419 * @param pVmcsInfo The VMCS info. object.
3420 */
3421DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3422{
3423 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3424 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3425 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3426 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3427 AssertRC(rc);
3428}
3429
3430
3431/**
3432 * Sets up the MSR-bitmap address for the VMCS.
3433 *
3434 * @param pVmcsInfo The VMCS info. object.
3435 */
3436DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3437{
3438 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3439 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3440 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3441 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3442 AssertRC(rc);
3443}
3444
3445
3446/**
3447 * Sets up the APIC-access page address for the VMCS.
3448 *
3449 * @param pVCpu The cross context virtual CPU structure.
3450 */
3451DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3452{
3453 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3454 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3455 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3456 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3457 AssertRC(rc);
3458}
3459
3460
3461#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3462/**
3463 * Sets up the VMREAD bitmap address for the VMCS.
3464 *
3465 * @param pVCpu The cross context virtual CPU structure.
3466 */
3467DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3468{
3469 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3470 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3471 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3472 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3473 AssertRC(rc);
3474}
3475
3476
3477/**
3478 * Sets up the VMWRITE bitmap address for the VMCS.
3479 *
3480 * @param pVCpu The cross context virtual CPU structure.
3481 */
3482DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3483{
3484 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3485 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3486 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3487 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3488 AssertRC(rc);
3489}
3490#endif
3491
3492
3493/**
3494 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3495 * in the VMCS.
3496 *
3497 * @returns VBox status code.
3498 * @param pVmcsInfo The VMCS info. object.
3499 */
3500DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3501{
3502 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3503 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3504 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3505
3506 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3507 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3508 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3509
3510 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3511 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3512 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3513
3514 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3515 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3516 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3517 return VINF_SUCCESS;
3518}
3519
3520
3521/**
3522 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3523 *
3524 * @param pVCpu The cross context virtual CPU structure.
3525 * @param pVmcsInfo The VMCS info. object.
3526 */
3527static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3528{
3529 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3530
3531 /*
3532 * By default, ensure guest attempts to access any MSR cause VM-exits.
3533 * This shall later be relaxed for specific MSRs as necessary.
3534 *
3535 * Note: For nested-guests, the entire bitmap will be merged prior to
3536 * executing the nested-guest using hardware-assisted VMX and hence there
3537 * is no need to perform this operation. See hmR0VmxMergeMsrBitmapNested.
3538 */
3539 Assert(pVmcsInfo->pvMsrBitmap);
3540 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
3541
3542 /*
3543 * The guest can access the following MSRs (read, write) without causing
3544 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3545 */
3546 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3547 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3548 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3549 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3550 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3551 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3552
3553 /*
3554 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3555 * associated with then. We never need to intercept access (writes need to be
3556 * executed without causing a VM-exit, reads will #GP fault anyway).
3557 *
3558 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3559 * read/write them. We swap the the guest/host MSR value using the
3560 * auto-load/store MSR area.
3561 */
3562 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3563 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3564 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3565 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3566 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3567 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3568
3569 /*
3570 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3571 * required for 64-bit guests.
3572 */
3573 if (pVM->hm.s.fAllow64BitGuests)
3574 {
3575 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3576 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3577 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3578 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3579 }
3580
3581 /*
3582 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3583 */
3584#ifdef VBOX_STRICT
3585 Assert(pVmcsInfo->pvMsrBitmap);
3586 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3587 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3588#endif
3589}
3590
3591
3592/**
3593 * Sets up pin-based VM-execution controls in the VMCS.
3594 *
3595 * @returns VBox status code.
3596 * @param pVCpu The cross context virtual CPU structure.
3597 * @param pVmcsInfo The VMCS info. object.
3598 */
3599static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3600{
3601 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3602 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3603 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3604
3605 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3606 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3607
3608 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3609 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3610
3611 /* Enable the VMX-preemption timer. */
3612 if (pVM->hm.s.vmx.fUsePreemptTimer)
3613 {
3614 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3615 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3616 }
3617
3618#if 0
3619 /* Enable posted-interrupt processing. */
3620 if (pVM->hm.s.fPostedIntrs)
3621 {
3622 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3623 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3624 fVal |= VMX_PIN_CTLS_POSTED_INT;
3625 }
3626#endif
3627
3628 if ((fVal & fZap) != fVal)
3629 {
3630 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3631 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3632 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3633 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3634 }
3635
3636 /* Commit it to the VMCS and update our cache. */
3637 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3638 AssertRC(rc);
3639 pVmcsInfo->u32PinCtls = fVal;
3640
3641 return VINF_SUCCESS;
3642}
3643
3644
3645/**
3646 * Sets up secondary processor-based VM-execution controls in the VMCS.
3647 *
3648 * @returns VBox status code.
3649 * @param pVCpu The cross context virtual CPU structure.
3650 * @param pVmcsInfo The VMCS info. object.
3651 */
3652static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3653{
3654 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3655 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3656 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3657
3658 /* WBINVD causes a VM-exit. */
3659 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3660 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3661
3662 /* Enable EPT (aka nested-paging). */
3663 if (pVM->hm.s.fNestedPaging)
3664 fVal |= VMX_PROC_CTLS2_EPT;
3665
3666 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3667 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3668 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3669 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3670 fVal |= VMX_PROC_CTLS2_INVPCID;
3671
3672 /* Enable VPID. */
3673 if (pVM->hm.s.vmx.fVpid)
3674 fVal |= VMX_PROC_CTLS2_VPID;
3675
3676 /* Enable unrestricted guest execution. */
3677 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3678 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3679
3680#if 0
3681 if (pVM->hm.s.fVirtApicRegs)
3682 {
3683 /* Enable APIC-register virtualization. */
3684 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3685 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3686
3687 /* Enable virtual-interrupt delivery. */
3688 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3689 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3690 }
3691#endif
3692
3693 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3694 where the TPR shadow resides. */
3695 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3696 * done dynamically. */
3697 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3698 {
3699 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3700 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3701 }
3702
3703 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3704 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3705 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3706 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3707 fVal |= VMX_PROC_CTLS2_RDTSCP;
3708
3709 /* Enable Pause-Loop exiting. */
3710 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3711 && pVM->hm.s.vmx.cPleGapTicks
3712 && pVM->hm.s.vmx.cPleWindowTicks)
3713 {
3714 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3715
3716 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3717 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3718 }
3719
3720 if ((fVal & fZap) != fVal)
3721 {
3722 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3723 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3724 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3725 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3726 }
3727
3728 /* Commit it to the VMCS and update our cache. */
3729 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3730 AssertRC(rc);
3731 pVmcsInfo->u32ProcCtls2 = fVal;
3732
3733 return VINF_SUCCESS;
3734}
3735
3736
3737/**
3738 * Sets up processor-based VM-execution controls in the VMCS.
3739 *
3740 * @returns VBox status code.
3741 * @param pVCpu The cross context virtual CPU structure.
3742 * @param pVmcsInfo The VMCS info. object.
3743 */
3744static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3745{
3746 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3747 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3748 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3749
3750 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3751 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3752 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3753 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3754 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3755 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3756 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3757
3758 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3759 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3760 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3761 {
3762 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3763 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3764 }
3765
3766 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3767 if (!pVM->hm.s.fNestedPaging)
3768 {
3769 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3770 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3771 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3772 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3773 }
3774
3775 /* Use TPR shadowing if supported by the CPU. */
3776 if ( PDMHasApic(pVM)
3777 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3778 {
3779 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3780 /* CR8 writes cause a VM-exit based on TPR threshold. */
3781 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3782 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3783 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3784 }
3785 else
3786 {
3787 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3788 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3789 if (pVM->hm.s.fAllow64BitGuests)
3790 {
3791 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3792 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3793 }
3794 }
3795
3796 /* Use MSR-bitmaps if supported by the CPU. */
3797 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3798 {
3799 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3800 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3801 }
3802
3803 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3804 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3805 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3806
3807 if ((fVal & fZap) != fVal)
3808 {
3809 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3810 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3811 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3812 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3813 }
3814
3815 /* Commit it to the VMCS and update our cache. */
3816 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3817 AssertRC(rc);
3818 pVmcsInfo->u32ProcCtls = fVal;
3819
3820 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3821 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3822 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3823
3824 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3825 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3826 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3827
3828 /* Sanity check, should not really happen. */
3829 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3830 { /* likely */ }
3831 else
3832 {
3833 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3834 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3835 }
3836
3837 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3838 return VINF_SUCCESS;
3839}
3840
3841
3842/**
3843 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3844 * Processor-based VM-execution) control fields in the VMCS.
3845 *
3846 * @returns VBox status code.
3847 * @param pVCpu The cross context virtual CPU structure.
3848 * @param pVmcsInfo The VMCS info. object.
3849 */
3850static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3851{
3852#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3853 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3854 {
3855 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3856 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3857 }
3858#endif
3859
3860 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3861 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3862 AssertRC(rc);
3863
3864 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3865 if (RT_SUCCESS(rc))
3866 {
3867 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3868 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3869
3870 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
3871 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
3872
3873 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3874 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3875 return VINF_SUCCESS;
3876 }
3877 else
3878 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3879 return rc;
3880}
3881
3882
3883/**
3884 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3885 *
3886 * We shall setup those exception intercepts that don't change during the
3887 * lifetime of the VM here. The rest are done dynamically while loading the
3888 * guest state.
3889 *
3890 * @param pVCpu The cross context virtual CPU structure.
3891 * @param pVmcsInfo The VMCS info. object.
3892 */
3893static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3894{
3895 /*
3896 * The following exceptions are always intercepted:
3897 *
3898 * #AC - To prevent the guest from hanging the CPU.
3899 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3900 * recursive #DBs can cause a CPU hang.
3901 * #PF - To sync our shadow page tables when nested-paging is not used.
3902 */
3903 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3904 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3905 | RT_BIT(X86_XCPT_DB)
3906 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3907
3908 /* Commit it to the VMCS. */
3909 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3910 AssertRC(rc);
3911
3912 /* Update our cache of the exception bitmap. */
3913 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3914}
3915
3916
3917#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3918/**
3919 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3920 *
3921 * @returns VBox status code.
3922 * @param pVCpu The cross context virtual CPU structure.
3923 * @param pVmcsInfo The VMCS info. object.
3924 */
3925static int hmR0VmxSetupVmcsCtlsNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3926{
3927 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3928 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3929 AssertRC(rc);
3930
3931 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3932 if (RT_SUCCESS(rc))
3933 {
3934 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3935 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3936
3937 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
3938 Assert(!pVmcsInfo->u64Cr0Mask);
3939 Assert(!pVmcsInfo->u64Cr4Mask);
3940 return VINF_SUCCESS;
3941 }
3942 else
3943 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3944 return rc;
3945}
3946#endif
3947
3948
3949/**
3950 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
3951 * VMX.
3952 *
3953 * @returns VBox status code.
3954 * @param pVCpu The cross context virtual CPU structure.
3955 * @param pVmcsInfo The VMCS info. object.
3956 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
3957 */
3958static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
3959{
3960 Assert(pVmcsInfo->pvVmcs);
3961 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3962
3963 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
3964 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3965 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3966 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
3967
3968 LogFlowFunc(("\n"));
3969
3970 /*
3971 * Initialize the VMCS using VMCLEAR before loading the VMCS.
3972 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
3973 */
3974 int rc = hmR0VmxClearVmcs(pVmcsInfo);
3975 if (RT_SUCCESS(rc))
3976 {
3977 rc = hmR0VmxLoadVmcs(pVmcsInfo);
3978 if (RT_SUCCESS(rc))
3979 {
3980 if (!fIsNstGstVmcs)
3981 {
3982 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
3983 if (RT_SUCCESS(rc))
3984 {
3985 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
3986 if (RT_SUCCESS(rc))
3987 {
3988 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
3989 if (RT_SUCCESS(rc))
3990 {
3991 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
3992#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3993 /*
3994 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
3995 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
3996 * making it fit for use when VMCS shadowing is later enabled.
3997 */
3998 if (pVmcsInfo->pvShadowVmcs)
3999 {
4000 VMXVMCSREVID VmcsRevId;
4001 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4002 VmcsRevId.n.fIsShadowVmcs = 1;
4003 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4004 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4005 if (RT_SUCCESS(rc))
4006 { /* likely */ }
4007 else
4008 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4009 }
4010#endif
4011 }
4012 else
4013 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4014 }
4015 else
4016 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4017 }
4018 else
4019 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4020 }
4021 else
4022 {
4023#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4024 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4025 if (RT_SUCCESS(rc))
4026 { /* likely */ }
4027 else
4028 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4029#else
4030 AssertFailed();
4031#endif
4032 }
4033 }
4034 else
4035 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4036 }
4037 else
4038 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4039
4040 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4041 if (RT_SUCCESS(rc))
4042 {
4043 rc = hmR0VmxClearVmcs(pVmcsInfo);
4044 if (RT_SUCCESS(rc))
4045 { /* likely */ }
4046 else
4047 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4048 }
4049
4050 /*
4051 * Update the last-error record both for failures and success, so we
4052 * can propagate the status code back to ring-3 for diagnostics.
4053 */
4054 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4055 NOREF(pszVmcs);
4056 return rc;
4057}
4058
4059
4060/**
4061 * Does global VT-x initialization (called during module initialization).
4062 *
4063 * @returns VBox status code.
4064 */
4065VMMR0DECL(int) VMXR0GlobalInit(void)
4066{
4067#ifdef HMVMX_USE_FUNCTION_TABLE
4068 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4069# ifdef VBOX_STRICT
4070 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4071 Assert(g_apfnVMExitHandlers[i]);
4072# endif
4073#endif
4074 return VINF_SUCCESS;
4075}
4076
4077
4078/**
4079 * Does global VT-x termination (called during module termination).
4080 */
4081VMMR0DECL(void) VMXR0GlobalTerm()
4082{
4083 /* Nothing to do currently. */
4084}
4085
4086
4087/**
4088 * Sets up and activates VT-x on the current CPU.
4089 *
4090 * @returns VBox status code.
4091 * @param pHostCpu The HM physical-CPU structure.
4092 * @param pVM The cross context VM structure. Can be
4093 * NULL after a host resume operation.
4094 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4095 * fEnabledByHost is @c true).
4096 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4097 * @a fEnabledByHost is @c true).
4098 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4099 * enable VT-x on the host.
4100 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4101 */
4102VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4103 PCSUPHWVIRTMSRS pHwvirtMsrs)
4104{
4105 AssertPtr(pHostCpu);
4106 AssertPtr(pHwvirtMsrs);
4107 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4108
4109 /* Enable VT-x if it's not already enabled by the host. */
4110 if (!fEnabledByHost)
4111 {
4112 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4113 if (RT_FAILURE(rc))
4114 return rc;
4115 }
4116
4117 /*
4118 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4119 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4120 * invalidated when flushing by VPID.
4121 */
4122 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4123 {
4124 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4125 pHostCpu->fFlushAsidBeforeUse = false;
4126 }
4127 else
4128 pHostCpu->fFlushAsidBeforeUse = true;
4129
4130 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4131 ++pHostCpu->cTlbFlushes;
4132
4133 return VINF_SUCCESS;
4134}
4135
4136
4137/**
4138 * Deactivates VT-x on the current CPU.
4139 *
4140 * @returns VBox status code.
4141 * @param pHostCpu The HM physical-CPU structure.
4142 * @param pvCpuPage Pointer to the VMXON region.
4143 * @param HCPhysCpuPage Physical address of the VMXON region.
4144 *
4145 * @remarks This function should never be called when SUPR0EnableVTx() or
4146 * similar was used to enable VT-x on the host.
4147 */
4148VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4149{
4150 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4151
4152 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4153 return hmR0VmxLeaveRootMode(pHostCpu);
4154}
4155
4156
4157/**
4158 * Does per-VM VT-x initialization.
4159 *
4160 * @returns VBox status code.
4161 * @param pVM The cross context VM structure.
4162 */
4163VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4164{
4165 AssertPtr(pVM);
4166 LogFlowFunc(("pVM=%p\n", pVM));
4167
4168 hmR0VmxStructsInit(pVM);
4169 int rc = hmR0VmxStructsAlloc(pVM);
4170 if (RT_FAILURE(rc))
4171 {
4172 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4173 return rc;
4174 }
4175
4176 /* Setup the crash dump page. */
4177#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4178 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
4179 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
4180#endif
4181 return VINF_SUCCESS;
4182}
4183
4184
4185/**
4186 * Does per-VM VT-x termination.
4187 *
4188 * @returns VBox status code.
4189 * @param pVM The cross context VM structure.
4190 */
4191VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4192{
4193 AssertPtr(pVM);
4194 LogFlowFunc(("pVM=%p\n", pVM));
4195
4196#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4197 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4198 {
4199 Assert(pVM->hm.s.vmx.pvScratch);
4200 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4201 }
4202#endif
4203 hmR0VmxStructsFree(pVM);
4204 return VINF_SUCCESS;
4205}
4206
4207
4208/**
4209 * Sets up the VM for execution using hardware-assisted VMX.
4210 * This function is only called once per-VM during initialization.
4211 *
4212 * @returns VBox status code.
4213 * @param pVM The cross context VM structure.
4214 */
4215VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4216{
4217 AssertPtr(pVM);
4218 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4219
4220 LogFlowFunc(("pVM=%p\n", pVM));
4221
4222 /*
4223 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4224 * without causing a #GP.
4225 */
4226 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4227 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4228 { /* likely */ }
4229 else
4230 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4231
4232 /*
4233 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4234 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4235 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4236 */
4237 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4238 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4239 || !pVM->hm.s.vmx.pRealModeTSS))
4240 {
4241 LogRelFunc(("Invalid real-on-v86 state.\n"));
4242 return VERR_INTERNAL_ERROR;
4243 }
4244
4245 /* Initialize these always, see hmR3InitFinalizeR0().*/
4246 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4247 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4248
4249 /* Setup the tagged-TLB flush handlers. */
4250 int rc = hmR0VmxSetupTaggedTlb(pVM);
4251 if (RT_FAILURE(rc))
4252 {
4253 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4254 return rc;
4255 }
4256
4257#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4258 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4259 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4260 {
4261 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4262 if (RT_SUCCESS(rc))
4263 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4264 else
4265 {
4266 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4267 return rc;
4268 }
4269 }
4270#endif
4271
4272 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4273 {
4274 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4275 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4276
4277 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4278 if (RT_SUCCESS(rc))
4279 {
4280#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4281 if (pVM->cpum.ro.GuestFeatures.fVmx)
4282 {
4283 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4284 if (RT_SUCCESS(rc))
4285 { /* likely */ }
4286 else
4287 {
4288 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4289 return rc;
4290 }
4291 }
4292#endif
4293 }
4294 else
4295 {
4296 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4297 return rc;
4298 }
4299 }
4300
4301 return VINF_SUCCESS;
4302}
4303
4304
4305/**
4306 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4307 * the VMCS.
4308 */
4309static void hmR0VmxExportHostControlRegs(void)
4310{
4311 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4312 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4313 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, ASMGetCR4()); AssertRC(rc);
4314}
4315
4316
4317/**
4318 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4319 * the host-state area in the VMCS.
4320 *
4321 * @returns VBox status code.
4322 * @param pVCpu The cross context virtual CPU structure.
4323 */
4324static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu)
4325{
4326/**
4327 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4328 * requirements. See hmR0VmxExportHostSegmentRegs().
4329 */
4330#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_selValue) \
4331 if ((a_selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4332 { \
4333 bool fValidSelector = true; \
4334 if ((a_selValue) & X86_SEL_LDT) \
4335 { \
4336 uint32_t const uAttr = ASMGetSegAttr(a_selValue); \
4337 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4338 } \
4339 if (fValidSelector) \
4340 { \
4341 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4342 pVCpu->hm.s.vmx.RestoreHost.uHostSel##a_Seg = (a_selValue); \
4343 } \
4344 (a_selValue) = 0; \
4345 }
4346
4347 /*
4348 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4349 * will be messed up. We should -not- save the messed up state without restoring
4350 * the original host-state, see @bugref{7240}.
4351 *
4352 * This apparently can happen (most likely the FPU changes), deal with it rather than
4353 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4354 */
4355 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4356 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4357 {
4358 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4359 pVCpu->idCpu));
4360 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4361 }
4362 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4363
4364 /*
4365 * Host segment registers.
4366 */
4367 RTSEL uSelES = ASMGetES();
4368 RTSEL uSelCS = ASMGetCS();
4369 RTSEL uSelSS = ASMGetSS();
4370 RTSEL uSelDS = ASMGetDS();
4371 RTSEL uSelFS = ASMGetFS();
4372 RTSEL uSelGS = ASMGetGS();
4373 RTSEL uSelTR = ASMGetTR();
4374
4375 /*
4376 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4377 * gain VM-entry and restore them before we get preempted.
4378 *
4379 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4380 */
4381 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4382 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4383 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4384 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4385
4386 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4387 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4388 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4389 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4390 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4391 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4392 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4393 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4394 Assert(uSelCS);
4395 Assert(uSelTR);
4396
4397 /* Write these host selector fields into the host-state area in the VMCS. */
4398 int rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, uSelCS); AssertRC(rc);
4399 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, uSelSS); AssertRC(rc);
4400 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4401 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4402 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4403 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4404 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, uSelTR); AssertRC(rc);
4405
4406 /*
4407 * Host GDTR and IDTR.
4408 */
4409 RTGDTR Gdtr;
4410 RTIDTR Idtr;
4411 RT_ZERO(Gdtr);
4412 RT_ZERO(Idtr);
4413 ASMGetGDTR(&Gdtr);
4414 ASMGetIDTR(&Idtr);
4415 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt); AssertRC(rc);
4416 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt); AssertRC(rc);
4417
4418 /*
4419 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4420 * them to the maximum limit (0xffff) on every VM-exit.
4421 */
4422 if (Gdtr.cbGdt != 0xffff)
4423 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4424
4425 /*
4426 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4427 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4428 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4429 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4430 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4431 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4432 * at 0xffff on hosts where we are sure it won't cause trouble.
4433 */
4434#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4435 if (Idtr.cbIdt < 0x0fff)
4436#else
4437 if (Idtr.cbIdt != 0xffff)
4438#endif
4439 {
4440 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4441 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4442 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4443 }
4444
4445 /*
4446 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4447 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4448 * RPL should be too in most cases.
4449 */
4450 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4451 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4452
4453 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4454 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4455
4456 /*
4457 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4458 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4459 * restoration if the host has something else. Task switching is not supported in 64-bit
4460 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4461 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4462 *
4463 * [1] See Intel spec. 3.5 "System Descriptor Types".
4464 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4465 */
4466 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4467 Assert(pDesc->System.u4Type == 11);
4468 if ( pDesc->System.u16LimitLow != 0x67
4469 || pDesc->System.u4LimitHigh)
4470 {
4471 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4472 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4473 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4474 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4475 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4476 }
4477
4478 /*
4479 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4480 */
4481 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4482 {
4483 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4484 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4485 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4486 {
4487 /* The GDT is read-only but the writable GDT is available. */
4488 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4489 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4490 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4491 AssertRCReturn(rc, rc);
4492 }
4493 }
4494
4495 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase);
4496 AssertRC(rc);
4497
4498 /*
4499 * Host FS base and GS base.
4500 */
4501 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4502 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4503 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, u64FSBase); AssertRC(rc);
4504 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, u64GSBase); AssertRC(rc);
4505
4506 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4507 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4508 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4509 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4510 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4511
4512 return VINF_SUCCESS;
4513#undef VMXLOCAL_ADJUST_HOST_SEG
4514}
4515
4516
4517/**
4518 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4519 * host-state area of the VMCS.
4520 *
4521 * These MSRs will be automatically restored on the host after every successful
4522 * VM-exit.
4523 *
4524 * @param pVCpu The cross context virtual CPU structure.
4525 *
4526 * @remarks No-long-jump zone!!!
4527 */
4528static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4529{
4530 AssertPtr(pVCpu);
4531
4532 /*
4533 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4534 * rather than swapping them on every VM-entry.
4535 */
4536 hmR0VmxLazySaveHostMsrs(pVCpu);
4537
4538 /*
4539 * Host Sysenter MSRs.
4540 */
4541 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4542 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4543 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4544
4545 /*
4546 * Host EFER MSR.
4547 *
4548 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4549 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4550 */
4551 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4552 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4553 {
4554 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4555 AssertRC(rc);
4556 }
4557
4558 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4559 * hmR0VmxExportGuestEntryExitCtls(). */
4560}
4561
4562
4563/**
4564 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4565 *
4566 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4567 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4568 *
4569 * @returns true if we need to load guest EFER, false otherwise.
4570 * @param pVCpu The cross context virtual CPU structure.
4571 * @param pVmxTransient The VMX-transient structure.
4572 *
4573 * @remarks Requires EFER, CR4.
4574 * @remarks No-long-jump zone!!!
4575 */
4576static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4577{
4578#ifdef HMVMX_ALWAYS_SWAP_EFER
4579 RT_NOREF2(pVCpu, pVmxTransient);
4580 return true;
4581#else
4582 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4583 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4584 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4585 uint64_t const u64GuestEfer = pCtx->msrEFER;
4586
4587# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4588 /*
4589 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4590 * the nested-guest.
4591 */
4592 if ( pVmxTransient->fIsNestedGuest
4593 && ( CPUMIsGuestVmxEntryCtlsSet(pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4594 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4595 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4596 return true;
4597# else
4598 RT_NOREF(pVmxTransient);
4599#endif
4600
4601 /*
4602 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4603 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4604 */
4605 if ( CPUMIsGuestInLongModeEx(pCtx)
4606 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4607 return true;
4608
4609 /*
4610 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4611 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4612 *
4613 * See Intel spec. 4.5 "IA-32e Paging".
4614 * See Intel spec. 4.1.1 "Three Paging Modes".
4615 *
4616 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4617 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4618 */
4619 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4620 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4621 if ( (pCtx->cr4 & X86_CR4_PAE)
4622 && (pCtx->cr0 & X86_CR0_PG))
4623 {
4624 /*
4625 * If nested paging is not used, verify that the guest paging mode matches the
4626 * shadow paging mode which is/will be placed in the VMCS (which is what will
4627 * actually be used while executing the guest and not the CR4 shadow value).
4628 */
4629 AssertMsg(pVM->hm.s.fNestedPaging || ( pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4630 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4631 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4632 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX),
4633 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4634 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4635 {
4636 /* Verify that the host is NX capable. */
4637 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4638 return true;
4639 }
4640 }
4641
4642 return false;
4643#endif
4644}
4645
4646
4647/**
4648 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4649 * VMCS.
4650 *
4651 * This is typically required when the guest changes paging mode.
4652 *
4653 * @returns VBox status code.
4654 * @param pVCpu The cross context virtual CPU structure.
4655 * @param pVmxTransient The VMX-transient structure.
4656 *
4657 * @remarks Requires EFER.
4658 * @remarks No-long-jump zone!!!
4659 */
4660static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4661{
4662 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4663 {
4664 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4665 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4666 bool const fGstInLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
4667
4668 /*
4669 * VMRUN function.
4670 * If the guest is in long mode, use the 64-bit guest handler, else the 32-bit guest handler.
4671 * The host is always 64-bit since we no longer support 32-bit hosts.
4672 */
4673 if (fGstInLongMode)
4674 {
4675#ifndef VBOX_WITH_64_BITS_GUESTS
4676 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
4677#else
4678 Assert(pVM->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
4679 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
4680#endif
4681 }
4682 else
4683 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
4684
4685 /*
4686 * VM-entry controls.
4687 */
4688 {
4689 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4690 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4691
4692 /*
4693 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4694 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4695 *
4696 * For nested-guests, this is a mandatory VM-entry control. It's also
4697 * required because we do not want to leak host bits to the nested-guest.
4698 */
4699 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4700
4701 /*
4702 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4703 *
4704 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4705 * required to get the nested-guest working with hardware-assisted VMX execution.
4706 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
4707 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4708 * here rather than while merging the guest VMCS controls.
4709 */
4710 if (fGstInLongMode)
4711 {
4712 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
4713 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4714 }
4715 else
4716 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4717
4718 /*
4719 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4720 *
4721 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4722 * regardless of whether the nested-guest VMCS specifies it because we are free to
4723 * load whatever MSRs we require and we do not need to modify the guest visible copy
4724 * of the VM-entry MSR load area.
4725 */
4726 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4727 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4728 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4729 else
4730 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4731
4732 /*
4733 * The following should -not- be set (since we're not in SMM mode):
4734 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4735 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4736 */
4737
4738 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4739 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4740
4741 if ((fVal & fZap) == fVal)
4742 { /* likely */ }
4743 else
4744 {
4745 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4746 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4747 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4748 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4749 }
4750
4751 /* Commit it to the VMCS. */
4752 if (pVmcsInfo->u32EntryCtls != fVal)
4753 {
4754 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4755 AssertRC(rc);
4756 pVmcsInfo->u32EntryCtls = fVal;
4757 }
4758 }
4759
4760 /*
4761 * VM-exit controls.
4762 */
4763 {
4764 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4765 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4766
4767 /*
4768 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4769 * supported the 1-setting of this bit.
4770 *
4771 * For nested-guests, we set the "save debug controls" as the converse
4772 * "load debug controls" is mandatory for nested-guests anyway.
4773 */
4774 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4775
4776 /*
4777 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4778 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4779 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4780 * hmR0VmxExportHostMsrs().
4781 *
4782 * For nested-guests, we always set this bit as we do not support 32-bit
4783 * hosts.
4784 */
4785 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4786
4787 /*
4788 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4789 *
4790 * For nested-guests, we should use the "save IA32_EFER" control if we also
4791 * used the "load IA32_EFER" control while exporting VM-entry controls.
4792 */
4793 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4794 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4795 {
4796 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4797 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4798 }
4799
4800 /*
4801 * Enable saving of the VMX-preemption timer value on VM-exit.
4802 * For nested-guests, currently not exposed/used.
4803 */
4804 if ( pVM->hm.s.vmx.fUsePreemptTimer
4805 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4806 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4807
4808 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4809 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4810
4811 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
4812 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
4813 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
4814
4815 if ((fVal & fZap) == fVal)
4816 { /* likely */ }
4817 else
4818 {
4819 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
4820 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
4821 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
4822 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4823 }
4824
4825 /* Commit it to the VMCS. */
4826 if (pVmcsInfo->u32ExitCtls != fVal)
4827 {
4828 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
4829 AssertRC(rc);
4830 pVmcsInfo->u32ExitCtls = fVal;
4831 }
4832 }
4833
4834 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
4835 }
4836 return VINF_SUCCESS;
4837}
4838
4839
4840/**
4841 * Sets the TPR threshold in the VMCS.
4842 *
4843 * @param pVmcsInfo The VMCS info. object.
4844 * @param u32TprThreshold The TPR threshold (task-priority class only).
4845 */
4846DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
4847{
4848 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
4849 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
4850 RT_NOREF(pVmcsInfo);
4851 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
4852 AssertRC(rc);
4853}
4854
4855
4856/**
4857 * Exports the guest APIC TPR state into the VMCS.
4858 *
4859 * @param pVCpu The cross context virtual CPU structure.
4860 * @param pVmxTransient The VMX-transient structure.
4861 *
4862 * @remarks No-long-jump zone!!!
4863 */
4864static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4865{
4866 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
4867 {
4868 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
4869
4870 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4871 if (!pVmxTransient->fIsNestedGuest)
4872 {
4873 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
4874 && APICIsEnabled(pVCpu))
4875 {
4876 /*
4877 * Setup TPR shadowing.
4878 */
4879 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
4880 {
4881 bool fPendingIntr = false;
4882 uint8_t u8Tpr = 0;
4883 uint8_t u8PendingIntr = 0;
4884 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
4885 AssertRC(rc);
4886
4887 /*
4888 * If there are interrupts pending but masked by the TPR, instruct VT-x to
4889 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
4890 * priority of the pending interrupt so we can deliver the interrupt. If there
4891 * are no interrupts pending, set threshold to 0 to not cause any
4892 * TPR-below-threshold VM-exits.
4893 */
4894 uint32_t u32TprThreshold = 0;
4895 if (fPendingIntr)
4896 {
4897 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
4898 (which is the Task-Priority Class). */
4899 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
4900 const uint8_t u8TprPriority = u8Tpr >> 4;
4901 if (u8PendingPriority <= u8TprPriority)
4902 u32TprThreshold = u8PendingPriority;
4903 }
4904
4905 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
4906 }
4907 }
4908 }
4909 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
4910 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
4911 }
4912}
4913
4914
4915/**
4916 * Gets the guest interruptibility-state.
4917 *
4918 * @returns Guest's interruptibility-state.
4919 * @param pVCpu The cross context virtual CPU structure.
4920 * @param pVmxTransient The VMX-transient structure.
4921 *
4922 * @remarks No-long-jump zone!!!
4923 */
4924static uint32_t hmR0VmxGetGuestIntrState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4925{
4926 /*
4927 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
4928 */
4929 uint32_t fIntrState = 0;
4930 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4931 {
4932 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
4933 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
4934
4935 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4936 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
4937 {
4938 if (pCtx->eflags.Bits.u1IF)
4939 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
4940 else
4941 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
4942 }
4943 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4944 {
4945 /*
4946 * We can clear the inhibit force flag as even if we go back to the recompiler
4947 * without executing guest code in VT-x, the flag's condition to be cleared is
4948 * met and thus the cleared state is correct.
4949 */
4950 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
4951 }
4952 }
4953
4954 /*
4955 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
4956 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
4957 * setting this would block host-NMIs and IRET will not clear the blocking.
4958 *
4959 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
4960 *
4961 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
4962 */
4963 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4964 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
4965 && CPUMIsGuestNmiBlocking(pVCpu))
4966 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
4967
4968 return fIntrState;
4969}
4970
4971
4972/**
4973 * Exports the exception intercepts required for guest execution in the VMCS.
4974 *
4975 * @param pVCpu The cross context virtual CPU structure.
4976 * @param pVmxTransient The VMX-transient structure.
4977 *
4978 * @remarks No-long-jump zone!!!
4979 */
4980static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4981{
4982 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
4983 {
4984 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
4985 if ( !pVmxTransient->fIsNestedGuest
4986 && pVCpu->hm.s.fGIMTrapXcptUD)
4987 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
4988 else
4989 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
4990
4991 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
4992 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
4993 }
4994}
4995
4996
4997/**
4998 * Exports the guest's RIP into the guest-state area in the VMCS.
4999 *
5000 * @param pVCpu The cross context virtual CPU structure.
5001 *
5002 * @remarks No-long-jump zone!!!
5003 */
5004static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5005{
5006 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5007 {
5008 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5009
5010 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5011 AssertRC(rc);
5012
5013 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5014 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5015 }
5016}
5017
5018
5019/**
5020 * Exports the guest's RSP into the guest-state area in the VMCS.
5021 *
5022 * @param pVCpu The cross context virtual CPU structure.
5023 *
5024 * @remarks No-long-jump zone!!!
5025 */
5026static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5027{
5028 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5029 {
5030 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5031
5032 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5033 AssertRC(rc);
5034
5035 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5036 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5037 }
5038}
5039
5040
5041/**
5042 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5043 *
5044 * @param pVCpu The cross context virtual CPU structure.
5045 * @param pVmxTransient The VMX-transient structure.
5046 *
5047 * @remarks No-long-jump zone!!!
5048 */
5049static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5050{
5051 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5052 {
5053 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5054
5055 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5056 Let us assert it as such and use 32-bit VMWRITE. */
5057 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5058 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5059 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5060 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5061
5062 /*
5063 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5064 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5065 * can run the real-mode guest code under Virtual 8086 mode.
5066 */
5067 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5068 if (pVmcsInfo->RealMode.fRealOnV86Active)
5069 {
5070 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5071 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5072 Assert(!pVmxTransient->fIsNestedGuest);
5073 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5074 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5075 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5076 }
5077
5078 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5079 AssertRC(rc);
5080
5081 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5082 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5083 }
5084}
5085
5086
5087#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5088/**
5089 * Copies the nested-guest VMCS to the shadow VMCS.
5090 *
5091 * @returns VBox status code.
5092 * @param pVCpu The cross context virtual CPU structure.
5093 * @param pVmcsInfo The VMCS info. object.
5094 *
5095 * @remarks No-long-jump zone!!!
5096 */
5097static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5098{
5099 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5100 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5101
5102 /*
5103 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5104 * current VMCS, as we may try saving guest lazy MSRs.
5105 *
5106 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5107 * calling the import VMCS code which is currently performing the guest MSR reads
5108 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5109 * and the rest of the VMX leave session machinery.
5110 */
5111 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5112
5113 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5114 if (RT_SUCCESS(rc))
5115 {
5116 /*
5117 * Copy all guest read/write VMCS fields.
5118 *
5119 * We don't check for VMWRITE failures here for performance reasons and
5120 * because they are not expected to fail, barring irrecoverable conditions
5121 * like hardware errors.
5122 */
5123 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5124 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5125 {
5126 uint64_t u64Val;
5127 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5128 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5129 VMXWriteVmcs64(uVmcsField, u64Val);
5130 }
5131
5132 /*
5133 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5134 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5135 */
5136 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5137 {
5138 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5139 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5140 {
5141 uint64_t u64Val;
5142 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5143 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5144 VMXWriteVmcs64(uVmcsField, u64Val);
5145 }
5146 }
5147
5148 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5149 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5150 }
5151
5152 ASMSetFlags(fEFlags);
5153 return rc;
5154}
5155
5156
5157/**
5158 * Copies the shadow VMCS to the nested-guest VMCS.
5159 *
5160 * @returns VBox status code.
5161 * @param pVCpu The cross context virtual CPU structure.
5162 * @param pVmcsInfo The VMCS info. object.
5163 *
5164 * @remarks Called with interrupts disabled.
5165 */
5166static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5167{
5168 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5169 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5170 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5171
5172 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5173 if (RT_SUCCESS(rc))
5174 {
5175 /*
5176 * Copy guest read/write fields from the shadow VMCS.
5177 * Guest read-only fields cannot be modified, so no need to copy them.
5178 *
5179 * We don't check for VMREAD failures here for performance reasons and
5180 * because they are not expected to fail, barring irrecoverable conditions
5181 * like hardware errors.
5182 */
5183 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5184 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5185 {
5186 uint64_t u64Val;
5187 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5188 VMXReadVmcs64(uVmcsField, &u64Val);
5189 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5190 }
5191
5192 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5193 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5194 }
5195 return rc;
5196}
5197
5198
5199/**
5200 * Enables VMCS shadowing for the given VMCS info. object.
5201 *
5202 * @param pVmcsInfo The VMCS info. object.
5203 *
5204 * @remarks No-long-jump zone!!!
5205 */
5206static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5207{
5208 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5209 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5210 {
5211 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5212 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5213 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5214 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5215 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5216 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5217 Log4Func(("Enabled\n"));
5218 }
5219}
5220
5221
5222/**
5223 * Disables VMCS shadowing for the given VMCS info. object.
5224 *
5225 * @param pVmcsInfo The VMCS info. object.
5226 *
5227 * @remarks No-long-jump zone!!!
5228 */
5229static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5230{
5231 /*
5232 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5233 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5234 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5235 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5236 *
5237 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5238 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5239 */
5240 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5241 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5242 {
5243 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5244 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5245 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5246 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5247 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5248 Log4Func(("Disabled\n"));
5249 }
5250}
5251#endif
5252
5253
5254/**
5255 * Exports the guest hardware-virtualization state.
5256 *
5257 * @returns VBox status code.
5258 * @param pVCpu The cross context virtual CPU structure.
5259 * @param pVmxTransient The VMX-transient structure.
5260 *
5261 * @remarks No-long-jump zone!!!
5262 */
5263static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5264{
5265 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5266 {
5267#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5268 /*
5269 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5270 * VMCS shadowing.
5271 */
5272 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5273 {
5274 /*
5275 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5276 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5277 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5278 *
5279 * We check for VMX root mode here in case the guest executes VMXOFF without
5280 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5281 * not clear the current VMCS pointer.
5282 */
5283 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5284 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5285 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5286 && CPUMIsGuestVmxCurrentVmcsValid(&pVCpu->cpum.GstCtx))
5287 {
5288 /* Paranoia. */
5289 Assert(!pVmxTransient->fIsNestedGuest);
5290
5291 /*
5292 * For performance reasons, also check if the nested hypervisor's current VMCS
5293 * was newly loaded or modified before copying it to the shadow VMCS.
5294 */
5295 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5296 {
5297 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5298 AssertRCReturn(rc, rc);
5299 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5300 }
5301 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5302 }
5303 else
5304 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5305 }
5306#else
5307 NOREF(pVmxTransient);
5308#endif
5309 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5310 }
5311 return VINF_SUCCESS;
5312}
5313
5314
5315/**
5316 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5317 *
5318 * The guest FPU state is always pre-loaded hence we don't need to bother about
5319 * sharing FPU related CR0 bits between the guest and host.
5320 *
5321 * @returns VBox status code.
5322 * @param pVCpu The cross context virtual CPU structure.
5323 * @param pVmxTransient The VMX-transient structure.
5324 *
5325 * @remarks No-long-jump zone!!!
5326 */
5327static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5328{
5329 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5330 {
5331 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5332 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5333
5334 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
5335 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5336 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5337 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5338 else
5339 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5340
5341 if (!pVmxTransient->fIsNestedGuest)
5342 {
5343 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5344 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5345 uint64_t const u64ShadowCr0 = u64GuestCr0;
5346 Assert(!RT_HI_U32(u64GuestCr0));
5347
5348 /*
5349 * Setup VT-x's view of the guest CR0.
5350 */
5351 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5352 if (pVM->hm.s.fNestedPaging)
5353 {
5354 if (CPUMIsGuestPagingEnabled(pVCpu))
5355 {
5356 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5357 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5358 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5359 }
5360 else
5361 {
5362 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5363 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5364 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5365 }
5366
5367 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5368 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5369 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5370 }
5371 else
5372 {
5373 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5374 u64GuestCr0 |= X86_CR0_WP;
5375 }
5376
5377 /*
5378 * Guest FPU bits.
5379 *
5380 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5381 * using CR0.TS.
5382 *
5383 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5384 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5385 */
5386 u64GuestCr0 |= X86_CR0_NE;
5387
5388 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5389 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5390
5391 /*
5392 * Update exception intercepts.
5393 */
5394 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5395 if (pVmcsInfo->RealMode.fRealOnV86Active)
5396 {
5397 Assert(PDMVmmDevHeapIsEnabled(pVM));
5398 Assert(pVM->hm.s.vmx.pRealModeTSS);
5399 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5400 }
5401 else
5402 {
5403 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5404 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5405 if (fInterceptMF)
5406 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5407 }
5408
5409 /* Additional intercepts for debugging, define these yourself explicitly. */
5410#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5411 uXcptBitmap |= 0
5412 | RT_BIT(X86_XCPT_BP)
5413 | RT_BIT(X86_XCPT_DE)
5414 | RT_BIT(X86_XCPT_NM)
5415 | RT_BIT(X86_XCPT_TS)
5416 | RT_BIT(X86_XCPT_UD)
5417 | RT_BIT(X86_XCPT_NP)
5418 | RT_BIT(X86_XCPT_SS)
5419 | RT_BIT(X86_XCPT_GP)
5420 | RT_BIT(X86_XCPT_PF)
5421 | RT_BIT(X86_XCPT_MF)
5422 ;
5423#elif defined(HMVMX_ALWAYS_TRAP_PF)
5424 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5425#endif
5426 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5427 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5428 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5429
5430 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5431 u64GuestCr0 |= fSetCr0;
5432 u64GuestCr0 &= fZapCr0;
5433 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5434
5435 /* Commit the CR0 and related fields to the guest VMCS. */
5436 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5437 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5438 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5439 {
5440 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5441 AssertRC(rc);
5442 }
5443 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5444 {
5445 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5446 AssertRC(rc);
5447 }
5448
5449 /* Update our caches. */
5450 pVmcsInfo->u32ProcCtls = uProcCtls;
5451 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5452
5453 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5454 }
5455 else
5456 {
5457 /*
5458 * With nested-guests, we may have extended the guest/host mask here since we
5459 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5460 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5461 * originally supplied. We must copy those bits from the nested-guest CR0 into
5462 * the nested-guest CR0 read-shadow.
5463 */
5464 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5465 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5466 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(&pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5467 Assert(!RT_HI_U32(u64GuestCr0));
5468 Assert(u64GuestCr0 & X86_CR0_NE);
5469
5470 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5471 u64GuestCr0 |= fSetCr0;
5472 u64GuestCr0 &= fZapCr0;
5473 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5474
5475 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5476 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5477 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5478
5479 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5480 }
5481
5482 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5483 }
5484
5485 return VINF_SUCCESS;
5486}
5487
5488
5489/**
5490 * Exports the guest control registers (CR3, CR4) into the guest-state area
5491 * in the VMCS.
5492 *
5493 * @returns VBox strict status code.
5494 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5495 * without unrestricted guest access and the VMMDev is not presently
5496 * mapped (e.g. EFI32).
5497 *
5498 * @param pVCpu The cross context virtual CPU structure.
5499 * @param pVmxTransient The VMX-transient structure.
5500 *
5501 * @remarks No-long-jump zone!!!
5502 */
5503static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5504{
5505 int rc = VINF_SUCCESS;
5506 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5507
5508 /*
5509 * Guest CR2.
5510 * It's always loaded in the assembler code. Nothing to do here.
5511 */
5512
5513 /*
5514 * Guest CR3.
5515 */
5516 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5517 {
5518 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5519
5520 if (pVM->hm.s.fNestedPaging)
5521 {
5522 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5523 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5524
5525 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5526 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5527 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5528 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5529
5530 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5531 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5532 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5533
5534 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5535 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5536 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5537 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5538 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5539 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5540 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5541
5542 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5543 AssertRC(rc);
5544
5545 uint64_t u64GuestCr3;
5546 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5547 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5548 || CPUMIsGuestPagingEnabledEx(pCtx))
5549 {
5550 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5551 if (CPUMIsGuestInPAEModeEx(pCtx))
5552 {
5553 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5554 AssertRC(rc);
5555 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5556 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5557 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5558 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5559 }
5560
5561 /*
5562 * The guest's view of its CR3 is unblemished with nested paging when the
5563 * guest is using paging or we have unrestricted guest execution to handle
5564 * the guest when it's not using paging.
5565 */
5566 u64GuestCr3 = pCtx->cr3;
5567 }
5568 else
5569 {
5570 /*
5571 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5572 * thinks it accesses physical memory directly, we use our identity-mapped
5573 * page table to map guest-linear to guest-physical addresses. EPT takes care
5574 * of translating it to host-physical addresses.
5575 */
5576 RTGCPHYS GCPhys;
5577 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5578
5579 /* We obtain it here every time as the guest could have relocated this PCI region. */
5580 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5581 if (RT_SUCCESS(rc))
5582 { /* likely */ }
5583 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5584 {
5585 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5586 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5587 }
5588 else
5589 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5590
5591 u64GuestCr3 = GCPhys;
5592 }
5593
5594 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5595 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5596 AssertRC(rc);
5597 }
5598 else
5599 {
5600 Assert(!pVmxTransient->fIsNestedGuest);
5601 /* Non-nested paging case, just use the hypervisor's CR3. */
5602 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5603
5604 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5605 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5606 AssertRC(rc);
5607 }
5608
5609 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5610 }
5611
5612 /*
5613 * Guest CR4.
5614 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5615 */
5616 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5617 {
5618 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5619 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5620
5621 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
5622 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5623
5624 /*
5625 * With nested-guests, we may have extended the guest/host mask here (since we
5626 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5627 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5628 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5629 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5630 */
5631 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5632 uint64_t u64GuestCr4 = pCtx->cr4;
5633 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5634 ? pCtx->cr4
5635 : CPUMGetGuestVmxMaskedCr4(pCtx, pVmcsInfo->u64Cr4Mask);
5636 Assert(!RT_HI_U32(u64GuestCr4));
5637
5638 /*
5639 * Setup VT-x's view of the guest CR4.
5640 *
5641 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5642 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5643 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5644 *
5645 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5646 */
5647 if (pVmcsInfo->RealMode.fRealOnV86Active)
5648 {
5649 Assert(pVM->hm.s.vmx.pRealModeTSS);
5650 Assert(PDMVmmDevHeapIsEnabled(pVM));
5651 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5652 }
5653
5654 if (pVM->hm.s.fNestedPaging)
5655 {
5656 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5657 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5658 {
5659 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5660 u64GuestCr4 |= X86_CR4_PSE;
5661 /* Our identity mapping is a 32-bit page directory. */
5662 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5663 }
5664 /* else use guest CR4.*/
5665 }
5666 else
5667 {
5668 Assert(!pVmxTransient->fIsNestedGuest);
5669
5670 /*
5671 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5672 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5673 */
5674 switch (pVCpu->hm.s.enmShadowMode)
5675 {
5676 case PGMMODE_REAL: /* Real-mode. */
5677 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5678 case PGMMODE_32_BIT: /* 32-bit paging. */
5679 {
5680 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5681 break;
5682 }
5683
5684 case PGMMODE_PAE: /* PAE paging. */
5685 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5686 {
5687 u64GuestCr4 |= X86_CR4_PAE;
5688 break;
5689 }
5690
5691 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5692 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5693 {
5694#ifdef VBOX_WITH_64_BITS_GUESTS
5695 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
5696 Assert(u64GuestCr4 & X86_CR4_PAE);
5697 break;
5698#endif
5699 }
5700 default:
5701 AssertFailed();
5702 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5703 }
5704 }
5705
5706 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
5707 u64GuestCr4 |= fSetCr4;
5708 u64GuestCr4 &= fZapCr4;
5709
5710 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
5711 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
5712 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
5713
5714 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5715 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5716
5717 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5718
5719 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5720 }
5721 return rc;
5722}
5723
5724
5725/**
5726 * Exports the guest debug registers into the guest-state area in the VMCS.
5727 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5728 *
5729 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5730 *
5731 * @returns VBox status code.
5732 * @param pVCpu The cross context virtual CPU structure.
5733 * @param pVmxTransient The VMX-transient structure.
5734 *
5735 * @remarks No-long-jump zone!!!
5736 */
5737static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5738{
5739 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5740
5741 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5742 * stepping. */
5743 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5744 if (pVmxTransient->fIsNestedGuest)
5745 {
5746 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5747 AssertRC(rc);
5748
5749 /* Always intercept Mov DRx accesses for the nested-guest for now. */
5750 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5751 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
5752 AssertRC(rc);
5753 return VINF_SUCCESS;
5754 }
5755
5756#ifdef VBOX_STRICT
5757 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5758 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5759 {
5760 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5761 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5762 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5763 }
5764#endif
5765
5766 bool fSteppingDB = false;
5767 bool fInterceptMovDRx = false;
5768 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5769 if (pVCpu->hm.s.fSingleInstruction)
5770 {
5771 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5772 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5773 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5774 {
5775 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5776 Assert(fSteppingDB == false);
5777 }
5778 else
5779 {
5780 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5781 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5782 pVCpu->hm.s.fClearTrapFlag = true;
5783 fSteppingDB = true;
5784 }
5785 }
5786
5787 uint64_t u64GuestDr7;
5788 if ( fSteppingDB
5789 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5790 {
5791 /*
5792 * Use the combined guest and host DRx values found in the hypervisor register set
5793 * because the hypervisor debugger has breakpoints active or someone is single stepping
5794 * on the host side without a monitor trap flag.
5795 *
5796 * Note! DBGF expects a clean DR6 state before executing guest code.
5797 */
5798 if (!CPUMIsHyperDebugStateActive(pVCpu))
5799 {
5800 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5801 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5802 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5803 }
5804
5805 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
5806 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
5807 pVCpu->hm.s.fUsingHyperDR7 = true;
5808 fInterceptMovDRx = true;
5809 }
5810 else
5811 {
5812 /*
5813 * If the guest has enabled debug registers, we need to load them prior to
5814 * executing guest code so they'll trigger at the right time.
5815 */
5816 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
5817 {
5818 if (!CPUMIsGuestDebugStateActive(pVCpu))
5819 {
5820 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
5821 Assert(CPUMIsGuestDebugStateActive(pVCpu));
5822 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
5823 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
5824 }
5825 Assert(!fInterceptMovDRx);
5826 }
5827 else if (!CPUMIsGuestDebugStateActive(pVCpu))
5828 {
5829 /*
5830 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
5831 * must intercept #DB in order to maintain a correct DR6 guest value, and
5832 * because we need to intercept it to prevent nested #DBs from hanging the
5833 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
5834 */
5835 fInterceptMovDRx = true;
5836 }
5837
5838 /* Update DR7 with the actual guest value. */
5839 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
5840 pVCpu->hm.s.fUsingHyperDR7 = false;
5841 }
5842
5843 if (fInterceptMovDRx)
5844 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5845 else
5846 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
5847
5848 /*
5849 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
5850 * monitor-trap flag and update our cache.
5851 */
5852 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5853 {
5854 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5855 AssertRC(rc);
5856 pVmcsInfo->u32ProcCtls = uProcCtls;
5857 }
5858
5859 /*
5860 * Update guest DR7.
5861 */
5862 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
5863 AssertRC(rc);
5864
5865 /*
5866 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
5867 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
5868 *
5869 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5870 */
5871 if (fSteppingDB)
5872 {
5873 Assert(pVCpu->hm.s.fSingleInstruction);
5874 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
5875
5876 uint32_t fIntrState = 0;
5877 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
5878 AssertRC(rc);
5879
5880 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
5881 {
5882 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
5883 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
5884 AssertRC(rc);
5885 }
5886 }
5887
5888 return VINF_SUCCESS;
5889}
5890
5891
5892#ifdef VBOX_STRICT
5893/**
5894 * Strict function to validate segment registers.
5895 *
5896 * @param pVCpu The cross context virtual CPU structure.
5897 * @param pVmcsInfo The VMCS info. object.
5898 *
5899 * @remarks Will import guest CR0 on strict builds during validation of
5900 * segments.
5901 */
5902static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5903{
5904 /*
5905 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
5906 *
5907 * The reason we check for attribute value 0 in this function and not just the unusable bit is
5908 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
5909 * unusable bit and doesn't change the guest-context value.
5910 */
5911 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5912 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5913 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
5914 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
5915 && ( !CPUMIsGuestInRealModeEx(pCtx)
5916 && !CPUMIsGuestInV86ModeEx(pCtx)))
5917 {
5918 /* Protected mode checks */
5919 /* CS */
5920 Assert(pCtx->cs.Attr.n.u1Present);
5921 Assert(!(pCtx->cs.Attr.u & 0xf00));
5922 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
5923 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
5924 || !(pCtx->cs.Attr.n.u1Granularity));
5925 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
5926 || (pCtx->cs.Attr.n.u1Granularity));
5927 /* CS cannot be loaded with NULL in protected mode. */
5928 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
5929 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
5930 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
5931 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
5932 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
5933 else
5934 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
5935 /* SS */
5936 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5937 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
5938 if ( !(pCtx->cr0 & X86_CR0_PE)
5939 || pCtx->cs.Attr.n.u4Type == 3)
5940 {
5941 Assert(!pCtx->ss.Attr.n.u2Dpl);
5942 }
5943 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
5944 {
5945 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5946 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
5947 Assert(pCtx->ss.Attr.n.u1Present);
5948 Assert(!(pCtx->ss.Attr.u & 0xf00));
5949 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
5950 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
5951 || !(pCtx->ss.Attr.n.u1Granularity));
5952 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
5953 || (pCtx->ss.Attr.n.u1Granularity));
5954 }
5955 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
5956 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
5957 {
5958 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5959 Assert(pCtx->ds.Attr.n.u1Present);
5960 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
5961 Assert(!(pCtx->ds.Attr.u & 0xf00));
5962 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
5963 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
5964 || !(pCtx->ds.Attr.n.u1Granularity));
5965 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
5966 || (pCtx->ds.Attr.n.u1Granularity));
5967 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5968 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
5969 }
5970 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
5971 {
5972 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5973 Assert(pCtx->es.Attr.n.u1Present);
5974 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
5975 Assert(!(pCtx->es.Attr.u & 0xf00));
5976 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
5977 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
5978 || !(pCtx->es.Attr.n.u1Granularity));
5979 Assert( !(pCtx->es.u32Limit & 0xfff00000)
5980 || (pCtx->es.Attr.n.u1Granularity));
5981 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5982 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
5983 }
5984 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
5985 {
5986 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5987 Assert(pCtx->fs.Attr.n.u1Present);
5988 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
5989 Assert(!(pCtx->fs.Attr.u & 0xf00));
5990 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
5991 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
5992 || !(pCtx->fs.Attr.n.u1Granularity));
5993 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
5994 || (pCtx->fs.Attr.n.u1Granularity));
5995 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5996 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
5997 }
5998 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
5999 {
6000 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6001 Assert(pCtx->gs.Attr.n.u1Present);
6002 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6003 Assert(!(pCtx->gs.Attr.u & 0xf00));
6004 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6005 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6006 || !(pCtx->gs.Attr.n.u1Granularity));
6007 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6008 || (pCtx->gs.Attr.n.u1Granularity));
6009 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6010 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6011 }
6012 /* 64-bit capable CPUs. */
6013 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6014 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6015 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6016 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6017 }
6018 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6019 || ( CPUMIsGuestInRealModeEx(pCtx)
6020 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6021 {
6022 /* Real and v86 mode checks. */
6023 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6024 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6025 if (pVmcsInfo->RealMode.fRealOnV86Active)
6026 {
6027 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6028 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6029 }
6030 else
6031 {
6032 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6033 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6034 }
6035
6036 /* CS */
6037 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6038 Assert(pCtx->cs.u32Limit == 0xffff);
6039 Assert(u32CSAttr == 0xf3);
6040 /* SS */
6041 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6042 Assert(pCtx->ss.u32Limit == 0xffff);
6043 Assert(u32SSAttr == 0xf3);
6044 /* DS */
6045 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6046 Assert(pCtx->ds.u32Limit == 0xffff);
6047 Assert(u32DSAttr == 0xf3);
6048 /* ES */
6049 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6050 Assert(pCtx->es.u32Limit == 0xffff);
6051 Assert(u32ESAttr == 0xf3);
6052 /* FS */
6053 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6054 Assert(pCtx->fs.u32Limit == 0xffff);
6055 Assert(u32FSAttr == 0xf3);
6056 /* GS */
6057 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6058 Assert(pCtx->gs.u32Limit == 0xffff);
6059 Assert(u32GSAttr == 0xf3);
6060 /* 64-bit capable CPUs. */
6061 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6062 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6063 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6064 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6065 }
6066}
6067#endif /* VBOX_STRICT */
6068
6069
6070/**
6071 * Exports a guest segment register into the guest-state area in the VMCS.
6072 *
6073 * @returns VBox status code.
6074 * @param pVCpu The cross context virtual CPU structure.
6075 * @param pVmcsInfo The VMCS info. object.
6076 * @param iSegReg The segment register number (X86_SREG_XXX).
6077 * @param pSelReg Pointer to the segment selector.
6078 *
6079 * @remarks No-long-jump zone!!!
6080 */
6081static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6082{
6083 Assert(iSegReg < X86_SREG_COUNT);
6084 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6085 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6086 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6087 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6088
6089 uint32_t u32Access = pSelReg->Attr.u;
6090 if (pVmcsInfo->RealMode.fRealOnV86Active)
6091 {
6092 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6093 u32Access = 0xf3;
6094 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6095 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6096 RT_NOREF_PV(pVCpu);
6097 }
6098 else
6099 {
6100 /*
6101 * The way to differentiate between whether this is really a null selector or was just
6102 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6103 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6104 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6105 * NULL selectors loaded in protected-mode have their attribute as 0.
6106 */
6107 if (!u32Access)
6108 u32Access = X86DESCATTR_UNUSABLE;
6109 }
6110
6111 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6112 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6113 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6114
6115 /*
6116 * Commit it to the VMCS.
6117 */
6118 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc);
6119 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc);
6120 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc);
6121 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc);
6122 return VINF_SUCCESS;
6123}
6124
6125
6126/**
6127 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6128 * area in the VMCS.
6129 *
6130 * @returns VBox status code.
6131 * @param pVCpu The cross context virtual CPU structure.
6132 * @param pVmxTransient The VMX-transient structure.
6133 *
6134 * @remarks Will import guest CR0 on strict builds during validation of
6135 * segments.
6136 * @remarks No-long-jump zone!!!
6137 */
6138static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6139{
6140 int rc = VERR_INTERNAL_ERROR_5;
6141 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6142 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6143 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6144
6145 /*
6146 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6147 */
6148 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6149 {
6150 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6151 {
6152 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6153 if (pVmcsInfo->RealMode.fRealOnV86Active)
6154 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6155 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6156 AssertRC(rc);
6157 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6158 }
6159
6160 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6161 {
6162 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6163 if (pVmcsInfo->RealMode.fRealOnV86Active)
6164 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6165 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6166 AssertRC(rc);
6167 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6168 }
6169
6170 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6171 {
6172 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6173 if (pVmcsInfo->RealMode.fRealOnV86Active)
6174 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6175 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6176 AssertRC(rc);
6177 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6178 }
6179
6180 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6181 {
6182 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6183 if (pVmcsInfo->RealMode.fRealOnV86Active)
6184 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6185 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6186 AssertRC(rc);
6187 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6188 }
6189
6190 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6191 {
6192 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6193 if (pVmcsInfo->RealMode.fRealOnV86Active)
6194 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6195 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6196 AssertRC(rc);
6197 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6198 }
6199
6200 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6201 {
6202 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6203 if (pVmcsInfo->RealMode.fRealOnV86Active)
6204 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6205 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6206 AssertRC(rc);
6207 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6208 }
6209
6210#ifdef VBOX_STRICT
6211 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6212#endif
6213 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6214 pCtx->cs.Attr.u));
6215 }
6216
6217 /*
6218 * Guest TR.
6219 */
6220 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6221 {
6222 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6223
6224 /*
6225 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6226 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6227 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6228 */
6229 uint16_t u16Sel;
6230 uint32_t u32Limit;
6231 uint64_t u64Base;
6232 uint32_t u32AccessRights;
6233 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6234 {
6235 u16Sel = pCtx->tr.Sel;
6236 u32Limit = pCtx->tr.u32Limit;
6237 u64Base = pCtx->tr.u64Base;
6238 u32AccessRights = pCtx->tr.Attr.u;
6239 }
6240 else
6241 {
6242 Assert(!pVmxTransient->fIsNestedGuest);
6243 Assert(pVM->hm.s.vmx.pRealModeTSS);
6244 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6245
6246 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6247 RTGCPHYS GCPhys;
6248 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6249 AssertRCReturn(rc, rc);
6250
6251 X86DESCATTR DescAttr;
6252 DescAttr.u = 0;
6253 DescAttr.n.u1Present = 1;
6254 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6255
6256 u16Sel = 0;
6257 u32Limit = HM_VTX_TSS_SIZE;
6258 u64Base = GCPhys;
6259 u32AccessRights = DescAttr.u;
6260 }
6261
6262 /* Validate. */
6263 Assert(!(u16Sel & RT_BIT(2)));
6264 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6265 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6266 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6267 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6268 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6269 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6270 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6271 Assert( (u32Limit & 0xfff) == 0xfff
6272 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6273 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6274 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6275
6276 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6277 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6278 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6279 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6280
6281 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6282 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6283 }
6284
6285 /*
6286 * Guest GDTR.
6287 */
6288 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6289 {
6290 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6291
6292 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6293 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6294
6295 /* Validate. */
6296 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6297
6298 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6299 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6300 }
6301
6302 /*
6303 * Guest LDTR.
6304 */
6305 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6306 {
6307 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6308
6309 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6310 uint32_t u32Access;
6311 if ( !pVmxTransient->fIsNestedGuest
6312 && !pCtx->ldtr.Attr.u)
6313 u32Access = X86DESCATTR_UNUSABLE;
6314 else
6315 u32Access = pCtx->ldtr.Attr.u;
6316
6317 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6318 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6319 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6320 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6321
6322 /* Validate. */
6323 if (!(u32Access & X86DESCATTR_UNUSABLE))
6324 {
6325 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6326 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6327 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6328 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6329 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6330 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6331 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6332 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6333 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6334 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6335 }
6336
6337 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6338 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6339 }
6340
6341 /*
6342 * Guest IDTR.
6343 */
6344 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6345 {
6346 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6347
6348 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6349 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6350
6351 /* Validate. */
6352 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6353
6354 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6355 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6356 }
6357
6358 return VINF_SUCCESS;
6359}
6360
6361
6362/**
6363 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6364 * areas.
6365 *
6366 * These MSRs will automatically be loaded to the host CPU on every successful
6367 * VM-entry and stored from the host CPU on every successful VM-exit.
6368 *
6369 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6370 * actual host MSR values are not- updated here for performance reasons. See
6371 * hmR0VmxExportHostMsrs().
6372 *
6373 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6374 *
6375 * @returns VBox status code.
6376 * @param pVCpu The cross context virtual CPU structure.
6377 * @param pVmxTransient The VMX-transient structure.
6378 *
6379 * @remarks No-long-jump zone!!!
6380 */
6381static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6382{
6383 AssertPtr(pVCpu);
6384 AssertPtr(pVmxTransient);
6385
6386 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6387 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6388
6389 /*
6390 * MSRs that we use the auto-load/store MSR area in the VMCS.
6391 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6392 * nothing to do here. The host MSR values are updated when it's safe in
6393 * hmR0VmxLazySaveHostMsrs().
6394 *
6395 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6396 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6397 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6398 * for any MSR that are not part of the lazy MSRs so we do not need to place
6399 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6400 */
6401 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6402 {
6403 /* No auto-load/store MSRs currently. */
6404 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6405 }
6406
6407 /*
6408 * Guest Sysenter MSRs.
6409 */
6410 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6411 {
6412 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6413
6414 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6415 {
6416 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6417 AssertRC(rc);
6418 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6419 }
6420
6421 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6422 {
6423 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6424 AssertRC(rc);
6425 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6426 }
6427
6428 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6429 {
6430 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6431 AssertRC(rc);
6432 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6433 }
6434 }
6435
6436 /*
6437 * Guest/host EFER MSR.
6438 */
6439 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6440 {
6441 /* Whether we are using the VMCS to swap the EFER MSR must have been
6442 determined earlier while exporting VM-entry/VM-exit controls. */
6443 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6444 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6445
6446 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6447 {
6448 /*
6449 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6450 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6451 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6452 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6453 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6454 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6455 * during VM-entry.
6456 */
6457 uint64_t uGuestEferMsr = pCtx->msrEFER;
6458 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6459 {
6460 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6461 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6462 else
6463 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6464 }
6465
6466 /*
6467 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6468 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6469 */
6470 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6471 {
6472 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6473 AssertRC(rc);
6474 }
6475 else
6476 {
6477 /*
6478 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6479 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6480 */
6481 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6482 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6483 AssertRCReturn(rc, rc);
6484 }
6485
6486 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6487 }
6488 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6489 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6490
6491 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6492 }
6493
6494 /*
6495 * Other MSRs.
6496 * Speculation Control (R/W).
6497 */
6498 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6499 {
6500 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6501 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6502 {
6503 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6504 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6505 AssertRCReturn(rc, rc);
6506 }
6507 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6508 }
6509
6510 return VINF_SUCCESS;
6511}
6512
6513
6514/**
6515 * Wrapper for running the guest code in VT-x.
6516 *
6517 * @returns VBox status code, no informational status codes.
6518 * @param pVCpu The cross context virtual CPU structure.
6519 * @param pVmxTransient The VMX-transient structure.
6520 *
6521 * @remarks No-long-jump zone!!!
6522 */
6523DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6524{
6525 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6526 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6527 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6528
6529 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6530
6531 /*
6532 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6533 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6534 * callee-saved and thus the need for this XMM wrapper.
6535 *
6536 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6537 */
6538 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6539 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6540 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6541#ifdef VBOX_WITH_KERNEL_USING_XMM
6542 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6543#else
6544 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu);
6545#endif
6546 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6547 return rc;
6548}
6549
6550
6551/**
6552 * Reports world-switch error and dumps some useful debug info.
6553 *
6554 * @param pVCpu The cross context virtual CPU structure.
6555 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6556 * @param pVmxTransient The VMX-transient structure (only
6557 * exitReason updated).
6558 */
6559static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6560{
6561 Assert(pVCpu);
6562 Assert(pVmxTransient);
6563 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6564
6565 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6566 switch (rcVMRun)
6567 {
6568 case VERR_VMX_INVALID_VMXON_PTR:
6569 AssertFailed();
6570 break;
6571 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6572 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6573 {
6574 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6575 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6576 AssertRC(rc);
6577 hmR0VmxReadExitQualVmcs(pVmxTransient);
6578
6579 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6580 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6581 Cannot do it here as we may have been long preempted. */
6582
6583#ifdef VBOX_STRICT
6584 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6585 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6586 pVmxTransient->uExitReason));
6587 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6588 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6589 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6590 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6591 else
6592 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6593 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6594 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6595
6596 static struct
6597 {
6598 /** Name of the field to log. */
6599 const char *pszName;
6600 /** The VMCS field. */
6601 uint32_t uVmcsField;
6602 /** Whether host support of this field needs to be checked. */
6603 bool fCheckSupport;
6604 } const s_aVmcsFields[] =
6605 {
6606 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6607 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6608 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6609 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6610 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6611 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6612 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6613 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6614 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6615 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6616 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6617 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6618 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6619 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6620 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6621 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6622 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6623 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6624 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6625 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6626 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6627 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6628 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6629 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6630 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6631 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6632 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6633 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6634 /* The order of selector fields below are fixed! */
6635 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6636 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6637 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6638 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6639 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6640 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6641 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6642 /* End of ordered selector fields. */
6643 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6644 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6645 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6646 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6647 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6648 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6649 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6650 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6651 };
6652
6653 RTGDTR HostGdtr;
6654 ASMGetGDTR(&HostGdtr);
6655
6656 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6657 for (uint32_t i = 0; i < cVmcsFields; i++)
6658 {
6659 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
6660
6661 bool fSupported;
6662 if (!s_aVmcsFields[i].fCheckSupport)
6663 fSupported = true;
6664 else
6665 {
6666 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6667 switch (uVmcsField)
6668 {
6669 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
6670 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
6671 case VMX_VMCS32_CTRL_PROC_EXEC2:
6672 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
6673 break;
6674 default:
6675 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
6676 }
6677 }
6678
6679 if (fSupported)
6680 {
6681 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
6682 switch (uWidth)
6683 {
6684 case VMX_VMCSFIELD_WIDTH_16BIT:
6685 {
6686 uint16_t u16Val;
6687 rc = VMXReadVmcs16(uVmcsField, &u16Val);
6688 AssertRC(rc);
6689 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
6690
6691 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
6692 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
6693 {
6694 if (u16Val < HostGdtr.cbGdt)
6695 {
6696 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
6697 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
6698 "Host FS", "Host GS", "Host TR" };
6699 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
6700 Assert(idxSel < RT_ELEMENTS(s_apszSel));
6701 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
6702 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
6703 }
6704 else
6705 Log4((" Selector value exceeds GDT limit!\n"));
6706 }
6707 break;
6708 }
6709
6710 case VMX_VMCSFIELD_WIDTH_32BIT:
6711 {
6712 uint32_t u32Val;
6713 rc = VMXReadVmcs32(uVmcsField, &u32Val);
6714 AssertRC(rc);
6715 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
6716 break;
6717 }
6718
6719 case VMX_VMCSFIELD_WIDTH_64BIT:
6720 case VMX_VMCSFIELD_WIDTH_NATURAL:
6721 {
6722 uint64_t u64Val;
6723 rc = VMXReadVmcs64(uVmcsField, &u64Val);
6724 AssertRC(rc);
6725 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
6726 break;
6727 }
6728 }
6729 }
6730 }
6731
6732 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6733 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6734 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6735 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6736 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6737 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6738#endif /* VBOX_STRICT */
6739 break;
6740 }
6741
6742 default:
6743 /* Impossible */
6744 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6745 break;
6746 }
6747}
6748
6749
6750/**
6751 * Sets up the usage of TSC-offsetting and updates the VMCS.
6752 *
6753 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6754 * VMX-preemption timer.
6755 *
6756 * @returns VBox status code.
6757 * @param pVCpu The cross context virtual CPU structure.
6758 * @param pVmxTransient The VMX-transient structure.
6759 *
6760 * @remarks No-long-jump zone!!!
6761 */
6762static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6763{
6764 bool fOffsettedTsc;
6765 bool fParavirtTsc;
6766 uint64_t uTscOffset;
6767 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6768 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6769
6770 if (pVM->hm.s.vmx.fUsePreemptTimer)
6771 {
6772 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
6773
6774 /* Make sure the returned values have sane upper and lower boundaries. */
6775 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
6776 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
6777 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
6778 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
6779
6780 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
6781 * preemption timers here. We probably need to clamp the preemption timer,
6782 * after converting the timer value to the host. */
6783 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
6784 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
6785 AssertRC(rc);
6786 }
6787 else
6788 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
6789
6790 if (fParavirtTsc)
6791 {
6792 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
6793 information before every VM-entry, hence disable it for performance sake. */
6794#if 0
6795 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
6796 AssertRC(rc);
6797#endif
6798 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
6799 }
6800
6801 if ( fOffsettedTsc
6802 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
6803 {
6804 if (pVmxTransient->fIsNestedGuest)
6805 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
6806 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
6807 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6808 }
6809 else
6810 {
6811 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
6812 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6813 }
6814}
6815
6816
6817/**
6818 * Gets the IEM exception flags for the specified vector and IDT vectoring /
6819 * VM-exit interruption info type.
6820 *
6821 * @returns The IEM exception flags.
6822 * @param uVector The event vector.
6823 * @param uVmxEventType The VMX event type.
6824 *
6825 * @remarks This function currently only constructs flags required for
6826 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
6827 * and CR2 aspects of an exception are not included).
6828 */
6829static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
6830{
6831 uint32_t fIemXcptFlags;
6832 switch (uVmxEventType)
6833 {
6834 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
6835 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
6836 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
6837 break;
6838
6839 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
6840 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
6841 break;
6842
6843 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
6844 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
6845 break;
6846
6847 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
6848 {
6849 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6850 if (uVector == X86_XCPT_BP)
6851 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
6852 else if (uVector == X86_XCPT_OF)
6853 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
6854 else
6855 {
6856 fIemXcptFlags = 0;
6857 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
6858 }
6859 break;
6860 }
6861
6862 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
6863 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6864 break;
6865
6866 default:
6867 fIemXcptFlags = 0;
6868 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
6869 break;
6870 }
6871 return fIemXcptFlags;
6872}
6873
6874
6875/**
6876 * Sets an event as a pending event to be injected into the guest.
6877 *
6878 * @param pVCpu The cross context virtual CPU structure.
6879 * @param u32IntInfo The VM-entry interruption-information field.
6880 * @param cbInstr The VM-entry instruction length in bytes (for
6881 * software interrupts, exceptions and privileged
6882 * software exceptions).
6883 * @param u32ErrCode The VM-entry exception error code.
6884 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
6885 * page-fault.
6886 */
6887DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
6888 RTGCUINTPTR GCPtrFaultAddress)
6889{
6890 Assert(!pVCpu->hm.s.Event.fPending);
6891 pVCpu->hm.s.Event.fPending = true;
6892 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
6893 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
6894 pVCpu->hm.s.Event.cbInstr = cbInstr;
6895 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
6896}
6897
6898
6899/**
6900 * Sets an external interrupt as pending-for-injection into the VM.
6901 *
6902 * @param pVCpu The cross context virtual CPU structure.
6903 * @param u8Interrupt The external interrupt vector.
6904 */
6905DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
6906{
6907 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
6908 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
6909 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6910 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6911 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6912}
6913
6914
6915/**
6916 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
6917 *
6918 * @param pVCpu The cross context virtual CPU structure.
6919 */
6920DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
6921{
6922 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
6923 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
6924 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6925 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6926 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6927}
6928
6929
6930/**
6931 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
6932 *
6933 * @param pVCpu The cross context virtual CPU structure.
6934 */
6935DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
6936{
6937 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
6938 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6939 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6940 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6941 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6942}
6943
6944
6945/**
6946 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
6947 *
6948 * @param pVCpu The cross context virtual CPU structure.
6949 */
6950DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
6951{
6952 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
6953 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6954 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6955 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6956 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6957}
6958
6959
6960/**
6961 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
6962 *
6963 * @param pVCpu The cross context virtual CPU structure.
6964 */
6965DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
6966{
6967 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
6968 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6969 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6970 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6971 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6972}
6973
6974
6975#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
6976/**
6977 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
6978 *
6979 * @param pVCpu The cross context virtual CPU structure.
6980 * @param u32ErrCode The error code for the general-protection exception.
6981 */
6982DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
6983{
6984 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
6985 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6986 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6987 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6988 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
6989}
6990
6991
6992/**
6993 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
6994 *
6995 * @param pVCpu The cross context virtual CPU structure.
6996 * @param u32ErrCode The error code for the stack exception.
6997 */
6998DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
6999{
7000 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7001 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7002 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7003 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7004 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7005}
7006#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7007
7008
7009/**
7010 * Fixes up attributes for the specified segment register.
7011 *
7012 * @param pVCpu The cross context virtual CPU structure.
7013 * @param pSelReg The segment register that needs fixing.
7014 * @param idxSel The VMCS field for the corresponding segment register.
7015 */
7016static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7017{
7018 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7019
7020 /*
7021 * If VT-x marks the segment as unusable, most other bits remain undefined:
7022 * - For CS the L, D and G bits have meaning.
7023 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7024 * - For the remaining data segments no bits are defined.
7025 *
7026 * The present bit and the unusable bit has been observed to be set at the
7027 * same time (the selector was supposed to be invalid as we started executing
7028 * a V8086 interrupt in ring-0).
7029 *
7030 * What should be important for the rest of the VBox code, is that the P bit is
7031 * cleared. Some of the other VBox code recognizes the unusable bit, but
7032 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7033 * safe side here, we'll strip off P and other bits we don't care about. If
7034 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7035 *
7036 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7037 */
7038#ifdef VBOX_STRICT
7039 uint32_t const uAttr = pSelReg->Attr.u;
7040#endif
7041
7042 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7043 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7044 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7045
7046#ifdef VBOX_STRICT
7047 VMMRZCallRing3Disable(pVCpu);
7048 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7049# ifdef DEBUG_bird
7050 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7051 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7052 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7053# endif
7054 VMMRZCallRing3Enable(pVCpu);
7055 NOREF(uAttr);
7056#endif
7057 RT_NOREF2(pVCpu, idxSel);
7058}
7059
7060
7061/**
7062 * Imports a guest segment register from the current VMCS into the guest-CPU
7063 * context.
7064 *
7065 * @param pVCpu The cross context virtual CPU structure.
7066 * @param iSegReg The segment register number (X86_SREG_XXX).
7067 *
7068 * @remarks Called with interrupts and/or preemption disabled.
7069 */
7070static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint8_t iSegReg)
7071{
7072 Assert(iSegReg < X86_SREG_COUNT);
7073
7074 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7075 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7076 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7077 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7078
7079 uint16_t u16Sel;
7080 uint64_t u64Base;
7081 uint32_t u32Limit, u32Attr;
7082 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc);
7083 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc);
7084 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc);
7085 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc);
7086
7087 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7088 pSelReg->Sel = u16Sel;
7089 pSelReg->ValidSel = u16Sel;
7090 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7091 pSelReg->u32Limit = u32Limit;
7092 pSelReg->u64Base = u64Base;
7093 pSelReg->Attr.u = u32Attr;
7094 if (u32Attr & X86DESCATTR_UNUSABLE)
7095 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7096}
7097
7098
7099/**
7100 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7101 *
7102 * @param pVCpu The cross context virtual CPU structure.
7103 *
7104 * @remarks Called with interrupts and/or preemption disabled.
7105 */
7106static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7107{
7108 uint16_t u16Sel;
7109 uint64_t u64Base;
7110 uint32_t u32Limit, u32Attr;
7111 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7112 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7113 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7114 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7115
7116 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7117 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7118 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7119 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7120 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7121 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7122 if (u32Attr & X86DESCATTR_UNUSABLE)
7123 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7124}
7125
7126
7127/**
7128 * Imports the guest TR from the current VMCS into the guest-CPU context.
7129 *
7130 * @param pVCpu The cross context virtual CPU structure.
7131 *
7132 * @remarks Called with interrupts and/or preemption disabled.
7133 */
7134static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7135{
7136 uint16_t u16Sel;
7137 uint64_t u64Base;
7138 uint32_t u32Limit, u32Attr;
7139 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7140 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7141 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7142 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7143
7144 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7145 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7146 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7147 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7148 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7149 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7150 /* TR is the only selector that can never be unusable. */
7151 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7152}
7153
7154
7155/**
7156 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7157 *
7158 * @param pVCpu The cross context virtual CPU structure.
7159 *
7160 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7161 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7162 * instead!!!
7163 */
7164static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7165{
7166 uint64_t u64Val;
7167 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7168 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7169 {
7170 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7171 AssertRC(rc);
7172
7173 pCtx->rip = u64Val;
7174 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7175 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7176 }
7177}
7178
7179
7180/**
7181 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7182 *
7183 * @param pVCpu The cross context virtual CPU structure.
7184 * @param pVmcsInfo The VMCS info. object.
7185 *
7186 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7187 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7188 * instead!!!
7189 */
7190static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7191{
7192 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7193 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7194 {
7195 uint64_t u64Val;
7196 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7197 AssertRC(rc);
7198
7199 pCtx->rflags.u64 = u64Val;
7200 if (pVmcsInfo->RealMode.fRealOnV86Active)
7201 {
7202 pCtx->eflags.Bits.u1VM = 0;
7203 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7204 }
7205 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7206 }
7207}
7208
7209
7210/**
7211 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7212 * context.
7213 *
7214 * @param pVCpu The cross context virtual CPU structure.
7215 * @param pVmcsInfo The VMCS info. object.
7216 *
7217 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7218 * do not log!
7219 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7220 * instead!!!
7221 */
7222static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7223{
7224 uint32_t u32Val;
7225 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7226 if (!u32Val)
7227 {
7228 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7229 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7230 CPUMSetGuestNmiBlocking(pVCpu, false);
7231 }
7232 else
7233 {
7234 /*
7235 * We must import RIP here to set our EM interrupt-inhibited state.
7236 * We also import RFLAGS as our code that evaluates pending interrupts
7237 * before VM-entry requires it.
7238 */
7239 hmR0VmxImportGuestRip(pVCpu);
7240 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7241
7242 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7243 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7244 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7245 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7246
7247 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7248 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7249 }
7250}
7251
7252
7253/**
7254 * Worker for VMXR0ImportStateOnDemand.
7255 *
7256 * @returns VBox status code.
7257 * @param pVCpu The cross context virtual CPU structure.
7258 * @param pVmcsInfo The VMCS info. object.
7259 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7260 */
7261static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7262{
7263 int rc = VINF_SUCCESS;
7264 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7265 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7266 uint32_t u32Val;
7267
7268 /*
7269 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7270 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7271 * neither are other host platforms.
7272 *
7273 * Committing this temporarily as it prevents BSOD.
7274 *
7275 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7276 */
7277#ifdef RT_OS_WINDOWS
7278 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7279 return VERR_HM_IPE_1;
7280#endif
7281
7282 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7283
7284 /*
7285 * We disable interrupts to make the updating of the state and in particular
7286 * the fExtrn modification atomic wrt to preemption hooks.
7287 */
7288 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7289
7290 fWhat &= pCtx->fExtrn;
7291 if (fWhat)
7292 {
7293 do
7294 {
7295 if (fWhat & CPUMCTX_EXTRN_RIP)
7296 hmR0VmxImportGuestRip(pVCpu);
7297
7298 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7299 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7300
7301 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7302 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7303
7304 if (fWhat & CPUMCTX_EXTRN_RSP)
7305 {
7306 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7307 AssertRC(rc);
7308 }
7309
7310 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7311 {
7312 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7313 if (fWhat & CPUMCTX_EXTRN_CS)
7314 {
7315 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7316 hmR0VmxImportGuestRip(pVCpu);
7317 if (fRealOnV86Active)
7318 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7319 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7320 }
7321 if (fWhat & CPUMCTX_EXTRN_SS)
7322 {
7323 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7324 if (fRealOnV86Active)
7325 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7326 }
7327 if (fWhat & CPUMCTX_EXTRN_DS)
7328 {
7329 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7330 if (fRealOnV86Active)
7331 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7332 }
7333 if (fWhat & CPUMCTX_EXTRN_ES)
7334 {
7335 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7336 if (fRealOnV86Active)
7337 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7338 }
7339 if (fWhat & CPUMCTX_EXTRN_FS)
7340 {
7341 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7342 if (fRealOnV86Active)
7343 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7344 }
7345 if (fWhat & CPUMCTX_EXTRN_GS)
7346 {
7347 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7348 if (fRealOnV86Active)
7349 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7350 }
7351 }
7352
7353 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7354 {
7355 if (fWhat & CPUMCTX_EXTRN_LDTR)
7356 hmR0VmxImportGuestLdtr(pVCpu);
7357
7358 if (fWhat & CPUMCTX_EXTRN_GDTR)
7359 {
7360 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7361 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7362 pCtx->gdtr.cbGdt = u32Val;
7363 }
7364
7365 /* Guest IDTR. */
7366 if (fWhat & CPUMCTX_EXTRN_IDTR)
7367 {
7368 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7369 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7370 pCtx->idtr.cbIdt = u32Val;
7371 }
7372
7373 /* Guest TR. */
7374 if (fWhat & CPUMCTX_EXTRN_TR)
7375 {
7376 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7377 don't need to import that one. */
7378 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7379 hmR0VmxImportGuestTr(pVCpu);
7380 }
7381 }
7382
7383 if (fWhat & CPUMCTX_EXTRN_DR7)
7384 {
7385 if (!pVCpu->hm.s.fUsingHyperDR7)
7386 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7387 }
7388
7389 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7390 {
7391 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7392 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7393 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7394 pCtx->SysEnter.cs = u32Val;
7395 }
7396
7397 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7398 {
7399 if ( pVM->hm.s.fAllow64BitGuests
7400 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7401 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7402 }
7403
7404 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7405 {
7406 if ( pVM->hm.s.fAllow64BitGuests
7407 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7408 {
7409 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7410 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7411 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7412 }
7413 }
7414
7415 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7416 {
7417 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7418 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7419 Assert(pMsrs);
7420 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7421 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7422 for (uint32_t i = 0; i < cMsrs; i++)
7423 {
7424 uint32_t const idMsr = pMsrs[i].u32Msr;
7425 switch (idMsr)
7426 {
7427 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7428 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7429 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7430 default:
7431 {
7432 pCtx->fExtrn = 0;
7433 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7434 ASMSetFlags(fEFlags);
7435 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7436 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7437 }
7438 }
7439 }
7440 }
7441
7442 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7443 {
7444 if (fWhat & CPUMCTX_EXTRN_CR0)
7445 {
7446 uint64_t u64Cr0;
7447 uint64_t u64Shadow;
7448 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7449 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7450#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7451 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7452 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7453#else
7454 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7455 {
7456 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7457 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7458 }
7459 else
7460 {
7461 /*
7462 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7463 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7464 * re-construct CR0. See @bugref{9180#c95} for details.
7465 */
7466 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7467 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7468 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7469 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7470 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7471 }
7472#endif
7473 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7474 CPUMSetGuestCR0(pVCpu, u64Cr0);
7475 VMMRZCallRing3Enable(pVCpu);
7476 }
7477
7478 if (fWhat & CPUMCTX_EXTRN_CR4)
7479 {
7480 uint64_t u64Cr4;
7481 uint64_t u64Shadow;
7482 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7483 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7484#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7485 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7486 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7487#else
7488 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7489 {
7490 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7491 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7492 }
7493 else
7494 {
7495 /*
7496 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7497 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7498 * re-construct CR4. See @bugref{9180#c95} for details.
7499 */
7500 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7501 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7502 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7503 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7504 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7505 }
7506#endif
7507 pCtx->cr4 = u64Cr4;
7508 }
7509
7510 if (fWhat & CPUMCTX_EXTRN_CR3)
7511 {
7512 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7513 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7514 || ( pVM->hm.s.fNestedPaging
7515 && CPUMIsGuestPagingEnabledEx(pCtx)))
7516 {
7517 uint64_t u64Cr3;
7518 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7519 if (pCtx->cr3 != u64Cr3)
7520 {
7521 pCtx->cr3 = u64Cr3;
7522 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7523 }
7524
7525 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7526 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7527 if (CPUMIsGuestInPAEModeEx(pCtx))
7528 {
7529 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7530 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7531 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7532 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7533 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7534 }
7535 }
7536 }
7537 }
7538
7539#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7540 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7541 {
7542 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7543 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7544 {
7545 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7546 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7547 if (RT_SUCCESS(rc))
7548 { /* likely */ }
7549 else
7550 break;
7551 }
7552 }
7553#endif
7554 } while (0);
7555
7556 if (RT_SUCCESS(rc))
7557 {
7558 /* Update fExtrn. */
7559 pCtx->fExtrn &= ~fWhat;
7560
7561 /* If everything has been imported, clear the HM keeper bit. */
7562 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7563 {
7564 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7565 Assert(!pCtx->fExtrn);
7566 }
7567 }
7568 }
7569 else
7570 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7571
7572 /*
7573 * Restore interrupts.
7574 */
7575 ASMSetFlags(fEFlags);
7576
7577 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7578
7579 if (RT_SUCCESS(rc))
7580 { /* likely */ }
7581 else
7582 return rc;
7583
7584 /*
7585 * Honor any pending CR3 updates.
7586 *
7587 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7588 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7589 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7590 *
7591 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7592 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7593 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7594 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7595 *
7596 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7597 */
7598 if (VMMRZCallRing3IsEnabled(pVCpu))
7599 {
7600 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7601 {
7602 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7603 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7604 }
7605
7606 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7607 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7608
7609 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7610 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7611 }
7612
7613 return VINF_SUCCESS;
7614}
7615
7616
7617/**
7618 * Saves the guest state from the VMCS into the guest-CPU context.
7619 *
7620 * @returns VBox status code.
7621 * @param pVCpu The cross context virtual CPU structure.
7622 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7623 */
7624VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
7625{
7626 AssertPtr(pVCpu);
7627 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7628 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7629}
7630
7631
7632/**
7633 * Check per-VM and per-VCPU force flag actions that require us to go back to
7634 * ring-3 for one reason or another.
7635 *
7636 * @returns Strict VBox status code (i.e. informational status codes too)
7637 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7638 * ring-3.
7639 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7640 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7641 * interrupts)
7642 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7643 * all EMTs to be in ring-3.
7644 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7645 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7646 * to the EM loop.
7647 *
7648 * @param pVCpu The cross context virtual CPU structure.
7649 * @param pVmxTransient The VMX-transient structure.
7650 * @param fStepping Whether we are single-stepping the guest using the
7651 * hypervisor debugger.
7652 *
7653 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
7654 * is no longer in VMX non-root mode.
7655 */
7656static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, bool fStepping)
7657{
7658 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7659
7660 /*
7661 * Update pending interrupts into the APIC's IRR.
7662 */
7663 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7664 APICUpdatePendingInterrupts(pVCpu);
7665
7666 /*
7667 * Anything pending? Should be more likely than not if we're doing a good job.
7668 */
7669 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7670 if ( !fStepping
7671 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7672 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7673 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7674 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7675 return VINF_SUCCESS;
7676
7677 /* Pending PGM C3 sync. */
7678 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7679 {
7680 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7681 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7682 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7683 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7684 if (rcStrict != VINF_SUCCESS)
7685 {
7686 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
7687 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
7688 return rcStrict;
7689 }
7690 }
7691
7692 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7693 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7694 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7695 {
7696 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7697 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7698 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
7699 return rc;
7700 }
7701
7702 /* Pending VM request packets, such as hardware interrupts. */
7703 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7704 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7705 {
7706 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
7707 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7708 return VINF_EM_PENDING_REQUEST;
7709 }
7710
7711 /* Pending PGM pool flushes. */
7712 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7713 {
7714 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
7715 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7716 return VINF_PGM_POOL_FLUSH_PENDING;
7717 }
7718
7719 /* Pending DMA requests. */
7720 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7721 {
7722 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
7723 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7724 return VINF_EM_RAW_TO_R3;
7725 }
7726
7727#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7728 /*
7729 * Pending nested-guest events.
7730 *
7731 * Please note the priority of these events are specified and important.
7732 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
7733 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
7734 */
7735 if (pVmxTransient->fIsNestedGuest)
7736 {
7737 /* Pending nested-guest APIC-write. */
7738 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
7739 {
7740 Log4Func(("Pending nested-guest APIC-write\n"));
7741 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
7742 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7743 return rcStrict;
7744 }
7745
7746 /* Pending nested-guest monitor-trap flag (MTF). */
7747 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
7748 {
7749 Log4Func(("Pending nested-guest MTF\n"));
7750 VBOXSTRICTRC rcStrict = IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */);
7751 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7752 return rcStrict;
7753 }
7754
7755 /* Pending nested-guest VMX-preemption timer expired. */
7756 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
7757 {
7758 Log4Func(("Pending nested-guest MTF\n"));
7759 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitPreemptTimer(pVCpu);
7760 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7761 return rcStrict;
7762 }
7763 }
7764#else
7765 NOREF(pVmxTransient);
7766#endif
7767
7768 return VINF_SUCCESS;
7769}
7770
7771
7772/**
7773 * Converts any TRPM trap into a pending HM event. This is typically used when
7774 * entering from ring-3 (not longjmp returns).
7775 *
7776 * @param pVCpu The cross context virtual CPU structure.
7777 */
7778static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
7779{
7780 Assert(TRPMHasTrap(pVCpu));
7781 Assert(!pVCpu->hm.s.Event.fPending);
7782
7783 uint8_t uVector;
7784 TRPMEVENT enmTrpmEvent;
7785 uint32_t uErrCode;
7786 RTGCUINTPTR GCPtrFaultAddress;
7787 uint8_t cbInstr;
7788 bool fIcebp;
7789
7790 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
7791 AssertRC(rc);
7792
7793 uint32_t u32IntInfo;
7794 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
7795 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
7796
7797 rc = TRPMResetTrap(pVCpu);
7798 AssertRC(rc);
7799 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
7800 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
7801
7802 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
7803}
7804
7805
7806/**
7807 * Converts the pending HM event into a TRPM trap.
7808 *
7809 * @param pVCpu The cross context virtual CPU structure.
7810 */
7811static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
7812{
7813 Assert(pVCpu->hm.s.Event.fPending);
7814
7815 /* If a trap was already pending, we did something wrong! */
7816 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
7817
7818 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
7819 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
7820 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
7821
7822 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
7823
7824 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
7825 AssertRC(rc);
7826
7827 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
7828 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
7829
7830 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
7831 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
7832 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
7833 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
7834
7835 if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
7836 TRPMSetTrapDueToIcebp(pVCpu);
7837
7838 /* We're now done converting the pending event. */
7839 pVCpu->hm.s.Event.fPending = false;
7840}
7841
7842
7843/**
7844 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
7845 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
7846 *
7847 * @param pVCpu The cross context virtual CPU structure.
7848 * @param pVmcsInfo The VMCS info. object.
7849 */
7850static void hmR0VmxSetIntWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7851{
7852 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7853 {
7854 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
7855 {
7856 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
7857 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7858 AssertRC(rc);
7859 }
7860 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
7861}
7862
7863
7864/**
7865 * Clears the interrupt-window exiting control in the VMCS.
7866 *
7867 * @param pVmcsInfo The VMCS info. object.
7868 */
7869DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7870{
7871 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7872 {
7873 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
7874 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7875 AssertRC(rc);
7876 }
7877}
7878
7879
7880/**
7881 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
7882 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
7883 *
7884 * @param pVCpu The cross context virtual CPU structure.
7885 * @param pVmcsInfo The VMCS info. object.
7886 */
7887static void hmR0VmxSetNmiWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7888{
7889 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7890 {
7891 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
7892 {
7893 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7894 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7895 AssertRC(rc);
7896 Log4Func(("Setup NMI-window exiting\n"));
7897 }
7898 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
7899}
7900
7901
7902/**
7903 * Clears the NMI-window exiting control in the VMCS.
7904 *
7905 * @param pVmcsInfo The VMCS info. object.
7906 */
7907DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7908{
7909 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7910 {
7911 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7912 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7913 AssertRC(rc);
7914 }
7915}
7916
7917
7918/**
7919 * Does the necessary state syncing before returning to ring-3 for any reason
7920 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
7921 *
7922 * @returns VBox status code.
7923 * @param pVCpu The cross context virtual CPU structure.
7924 * @param fImportState Whether to import the guest state from the VMCS back
7925 * to the guest-CPU context.
7926 *
7927 * @remarks No-long-jmp zone!!!
7928 */
7929static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
7930{
7931 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
7932 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
7933
7934 RTCPUID const idCpu = RTMpCpuId();
7935 Log4Func(("HostCpuId=%u\n", idCpu));
7936
7937 /*
7938 * !!! IMPORTANT !!!
7939 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
7940 */
7941
7942 /* Save the guest state if necessary. */
7943 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7944 if (fImportState)
7945 {
7946 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
7947 AssertRCReturn(rc, rc);
7948 }
7949
7950 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
7951 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
7952 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
7953
7954 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
7955#ifdef VBOX_STRICT
7956 if (CPUMIsHyperDebugStateActive(pVCpu))
7957 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
7958#endif
7959 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
7960 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
7961 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
7962
7963 /* Restore host-state bits that VT-x only restores partially. */
7964 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
7965 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
7966 {
7967 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
7968 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
7969 }
7970 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
7971
7972 /* Restore the lazy host MSRs as we're leaving VT-x context. */
7973 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
7974 {
7975 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
7976 if (!fImportState)
7977 {
7978 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
7979 AssertRCReturn(rc, rc);
7980 }
7981 hmR0VmxLazyRestoreHostMsrs(pVCpu);
7982 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
7983 }
7984 else
7985 pVCpu->hm.s.vmx.fLazyMsrs = 0;
7986
7987 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
7988 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
7989
7990 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
7991 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
7992 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
7993 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
7994 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
7995 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
7996 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
7997 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
7998 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
7999 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8000
8001 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8002
8003 /** @todo This partially defeats the purpose of having preemption hooks.
8004 * The problem is, deregistering the hooks should be moved to a place that
8005 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8006 * context.
8007 */
8008 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8009 AssertRCReturn(rc, rc);
8010
8011#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8012 /*
8013 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8014 * clear a shadow VMCS before allowing that VMCS to become active on another
8015 * logical processor. We may or may not be importing guest state which clears
8016 * it, so cover for it here.
8017 *
8018 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8019 */
8020 if ( pVmcsInfo->pvShadowVmcs
8021 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8022 {
8023 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8024 AssertRCReturn(rc, rc);
8025 }
8026
8027 /*
8028 * Flag that we need to re-export the host state if we switch to this VMCS before
8029 * executing guest or nested-guest code.
8030 */
8031 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8032#endif
8033
8034 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8035 NOREF(idCpu);
8036 return VINF_SUCCESS;
8037}
8038
8039
8040/**
8041 * Leaves the VT-x session.
8042 *
8043 * @returns VBox status code.
8044 * @param pVCpu The cross context virtual CPU structure.
8045 *
8046 * @remarks No-long-jmp zone!!!
8047 */
8048static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8049{
8050 HM_DISABLE_PREEMPT(pVCpu);
8051 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8052 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8053 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8054
8055 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8056 and done this from the VMXR0ThreadCtxCallback(). */
8057 if (!pVCpu->hm.s.fLeaveDone)
8058 {
8059 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8060 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8061 pVCpu->hm.s.fLeaveDone = true;
8062 }
8063 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8064
8065 /*
8066 * !!! IMPORTANT !!!
8067 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8068 */
8069
8070 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8071 /** @todo Deregistering here means we need to VMCLEAR always
8072 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8073 * for calling VMMR0ThreadCtxHookDisable here! */
8074 VMMR0ThreadCtxHookDisable(pVCpu);
8075
8076 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8077 int rc = HMR0LeaveCpu(pVCpu);
8078 HM_RESTORE_PREEMPT();
8079 return rc;
8080}
8081
8082
8083/**
8084 * Does the necessary state syncing before doing a longjmp to ring-3.
8085 *
8086 * @returns VBox status code.
8087 * @param pVCpu The cross context virtual CPU structure.
8088 *
8089 * @remarks No-long-jmp zone!!!
8090 */
8091DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8092{
8093 return hmR0VmxLeaveSession(pVCpu);
8094}
8095
8096
8097/**
8098 * Take necessary actions before going back to ring-3.
8099 *
8100 * An action requires us to go back to ring-3. This function does the necessary
8101 * steps before we can safely return to ring-3. This is not the same as longjmps
8102 * to ring-3, this is voluntary and prepares the guest so it may continue
8103 * executing outside HM (recompiler/IEM).
8104 *
8105 * @returns VBox status code.
8106 * @param pVCpu The cross context virtual CPU structure.
8107 * @param rcExit The reason for exiting to ring-3. Can be
8108 * VINF_VMM_UNKNOWN_RING3_CALL.
8109 */
8110static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8111{
8112 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8113
8114 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8115 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8116 {
8117 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8118 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8119 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8120 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8121 }
8122
8123 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8124 VMMRZCallRing3Disable(pVCpu);
8125 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8126
8127 /*
8128 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8129 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8130 *
8131 * This is because execution may continue from ring-3 and we would need to inject
8132 * the event from there (hence place it back in TRPM).
8133 */
8134 if (pVCpu->hm.s.Event.fPending)
8135 {
8136 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8137 Assert(!pVCpu->hm.s.Event.fPending);
8138
8139 /* Clear the events from the VMCS. */
8140 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc);
8141 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0); AssertRC(rc);
8142 }
8143#ifdef VBOX_STRICT
8144 else
8145 {
8146 /*
8147 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8148 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8149 * occasionally, see @bugref{9180#c42}.
8150 *
8151 * However, if the VM-entry failed, any VM entry-interruption info. field would
8152 * be left unmodified as the event would not have been injected to the guest. In
8153 * such cases, don't assert, we're not going to continue guest execution anyway.
8154 */
8155 uint32_t uExitReason;
8156 uint32_t uEntryIntInfo;
8157 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8158 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8159 AssertRC(rc);
8160 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8161 }
8162#endif
8163
8164 /*
8165 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8166 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8167 * (e.g. TPR below threshold).
8168 */
8169 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8170 {
8171 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8172 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8173 }
8174
8175 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8176 and if we're injecting an event we should have a TRPM trap pending. */
8177 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8178#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8179 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8180#endif
8181
8182 /* Save guest state and restore host state bits. */
8183 int rc = hmR0VmxLeaveSession(pVCpu);
8184 AssertRCReturn(rc, rc);
8185 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8186
8187 /* Thread-context hooks are unregistered at this point!!! */
8188 /* Ring-3 callback notifications are unregistered at this point!!! */
8189
8190 /* Sync recompiler state. */
8191 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8192 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8193 | CPUM_CHANGED_LDTR
8194 | CPUM_CHANGED_GDTR
8195 | CPUM_CHANGED_IDTR
8196 | CPUM_CHANGED_TR
8197 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8198 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8199 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8200 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8201
8202 Assert(!pVCpu->hm.s.fClearTrapFlag);
8203
8204 /* Update the exit-to-ring 3 reason. */
8205 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8206
8207 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8208 if ( rcExit != VINF_EM_RAW_INTERRUPT
8209 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8210 {
8211 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8212 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8213 }
8214
8215 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8216 VMMRZCallRing3Enable(pVCpu);
8217 return rc;
8218}
8219
8220
8221/**
8222 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8223 * longjump to ring-3 and possibly get preempted.
8224 *
8225 * @returns VBox status code.
8226 * @param pVCpu The cross context virtual CPU structure.
8227 * @param enmOperation The operation causing the ring-3 longjump.
8228 */
8229VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8230{
8231 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8232 {
8233 /*
8234 * !!! IMPORTANT !!!
8235 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8236 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8237 */
8238 VMMRZCallRing3RemoveNotification(pVCpu);
8239 VMMRZCallRing3Disable(pVCpu);
8240 HM_DISABLE_PREEMPT(pVCpu);
8241
8242 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8243 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8244 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8245 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8246
8247 /* Restore host-state bits that VT-x only restores partially. */
8248 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8249 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8250 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8251 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8252
8253 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8254 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8255 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8256
8257 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8258 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8259 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8260
8261 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8262 cleared as part of importing the guest state above. */
8263 hmR0VmxClearVmcs(pVmcsInfo);
8264
8265 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8266 VMMR0ThreadCtxHookDisable(pVCpu);
8267
8268 /* Leave HM context. This takes care of local init (term). */
8269 HMR0LeaveCpu(pVCpu);
8270 HM_RESTORE_PREEMPT();
8271 return VINF_SUCCESS;
8272 }
8273
8274 Assert(pVCpu);
8275 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8276 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8277
8278 VMMRZCallRing3Disable(pVCpu);
8279 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8280
8281 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8282
8283 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8284 AssertRCReturn(rc, rc);
8285
8286 VMMRZCallRing3Enable(pVCpu);
8287 return VINF_SUCCESS;
8288}
8289
8290
8291/**
8292 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8293 * stack.
8294 *
8295 * @returns Strict VBox status code (i.e. informational status codes too).
8296 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8297 * @param pVCpu The cross context virtual CPU structure.
8298 * @param uValue The value to push to the guest stack.
8299 */
8300static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8301{
8302 /*
8303 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8304 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8305 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8306 */
8307 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8308 if (pCtx->sp == 1)
8309 return VINF_EM_RESET;
8310 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8311 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8312 AssertRC(rc);
8313 return rc;
8314}
8315
8316
8317/**
8318 * Injects an event into the guest upon VM-entry by updating the relevant fields
8319 * in the VM-entry area in the VMCS.
8320 *
8321 * @returns Strict VBox status code (i.e. informational status codes too).
8322 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8323 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8324 *
8325 * @param pVCpu The cross context virtual CPU structure.
8326 * @param pVmxTransient The VMX-transient structure.
8327 * @param pEvent The event being injected.
8328 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8329 * will be updated if necessary. This cannot not be NULL.
8330 * @param fStepping Whether we're single-stepping guest execution and should
8331 * return VINF_EM_DBG_STEPPED if the event is injected
8332 * directly (registers modified by us, not by hardware on
8333 * VM-entry).
8334 */
8335static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8336 uint32_t *pfIntrState)
8337{
8338 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8339 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8340 Assert(pfIntrState);
8341
8342 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8343 uint32_t u32IntInfo = pEvent->u64IntInfo;
8344 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8345 uint32_t const cbInstr = pEvent->cbInstr;
8346 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8347 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8348 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8349
8350#ifdef VBOX_STRICT
8351 /*
8352 * Validate the error-code-valid bit for hardware exceptions.
8353 * No error codes for exceptions in real-mode.
8354 *
8355 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8356 */
8357 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8358 && !CPUMIsGuestInRealModeEx(pCtx))
8359 {
8360 switch (uVector)
8361 {
8362 case X86_XCPT_PF:
8363 case X86_XCPT_DF:
8364 case X86_XCPT_TS:
8365 case X86_XCPT_NP:
8366 case X86_XCPT_SS:
8367 case X86_XCPT_GP:
8368 case X86_XCPT_AC:
8369 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8370 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8371 RT_FALL_THRU();
8372 default:
8373 break;
8374 }
8375 }
8376
8377 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8378 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8379 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8380#endif
8381
8382 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8383
8384 /*
8385 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8386 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8387 * interrupt handler in the (real-mode) guest.
8388 *
8389 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8390 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8391 */
8392 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8393 {
8394 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8395 {
8396 /*
8397 * For CPUs with unrestricted guest execution enabled and with the guest
8398 * in real-mode, we must not set the deliver-error-code bit.
8399 *
8400 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8401 */
8402 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8403 }
8404 else
8405 {
8406 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8407 Assert(PDMVmmDevHeapIsEnabled(pVM));
8408 Assert(pVM->hm.s.vmx.pRealModeTSS);
8409 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8410
8411 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8412 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8413 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8414 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8415 AssertRCReturn(rc2, rc2);
8416
8417 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8418 size_t const cbIdtEntry = sizeof(X86IDTR16);
8419 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8420 {
8421 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8422 if (uVector == X86_XCPT_DF)
8423 return VINF_EM_RESET;
8424
8425 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8426 No error codes for exceptions in real-mode. */
8427 if (uVector == X86_XCPT_GP)
8428 {
8429 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8430 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8431 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8432 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8433 HMEVENT EventXcptDf;
8434 RT_ZERO(EventXcptDf);
8435 EventXcptDf.u64IntInfo = uXcptDfInfo;
8436 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8437 }
8438
8439 /*
8440 * If we're injecting an event with no valid IDT entry, inject a #GP.
8441 * No error codes for exceptions in real-mode.
8442 *
8443 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8444 */
8445 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8446 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8447 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8448 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8449 HMEVENT EventXcptGp;
8450 RT_ZERO(EventXcptGp);
8451 EventXcptGp.u64IntInfo = uXcptGpInfo;
8452 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8453 }
8454
8455 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8456 uint16_t uGuestIp = pCtx->ip;
8457 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8458 {
8459 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8460 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8461 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8462 }
8463 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8464 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8465
8466 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8467 X86IDTR16 IdtEntry;
8468 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8469 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8470 AssertRCReturn(rc2, rc2);
8471
8472 /* Construct the stack frame for the interrupt/exception handler. */
8473 VBOXSTRICTRC rcStrict;
8474 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8475 if (rcStrict == VINF_SUCCESS)
8476 {
8477 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8478 if (rcStrict == VINF_SUCCESS)
8479 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8480 }
8481
8482 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8483 if (rcStrict == VINF_SUCCESS)
8484 {
8485 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8486 pCtx->rip = IdtEntry.offSel;
8487 pCtx->cs.Sel = IdtEntry.uSel;
8488 pCtx->cs.ValidSel = IdtEntry.uSel;
8489 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8490 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8491 && uVector == X86_XCPT_PF)
8492 pCtx->cr2 = GCPtrFault;
8493
8494 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8495 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8496 | HM_CHANGED_GUEST_RSP);
8497
8498 /*
8499 * If we delivered a hardware exception (other than an NMI) and if there was
8500 * block-by-STI in effect, we should clear it.
8501 */
8502 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8503 {
8504 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8505 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8506 Log4Func(("Clearing inhibition due to STI\n"));
8507 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8508 }
8509
8510 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8511 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8512
8513 /*
8514 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8515 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8516 */
8517 pVCpu->hm.s.Event.fPending = false;
8518
8519 /*
8520 * If we eventually support nested-guest execution without unrestricted guest execution,
8521 * we should set fInterceptEvents here.
8522 */
8523 Assert(!pVmxTransient->fIsNestedGuest);
8524
8525 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8526 if (fStepping)
8527 rcStrict = VINF_EM_DBG_STEPPED;
8528 }
8529 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8530 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8531 return rcStrict;
8532 }
8533 }
8534
8535 /*
8536 * Validate.
8537 */
8538 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8539 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8540
8541 /*
8542 * Inject the event into the VMCS.
8543 */
8544 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8545 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8546 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8547 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8548 AssertRC(rc);
8549
8550 /*
8551 * Update guest CR2 if this is a page-fault.
8552 */
8553 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8554 pCtx->cr2 = GCPtrFault;
8555
8556 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8557 return VINF_SUCCESS;
8558}
8559
8560
8561/**
8562 * Evaluates the event to be delivered to the guest and sets it as the pending
8563 * event.
8564 *
8565 * @returns Strict VBox status code (i.e. informational status codes too).
8566 * @param pVCpu The cross context virtual CPU structure.
8567 * @param pVmxTransient The VMX-transient structure.
8568 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8569 */
8570static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8571{
8572 Assert(pfIntrState);
8573 Assert(!TRPMHasTrap(pVCpu));
8574
8575 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8576 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8577 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8578
8579 /*
8580 * Get the current interruptibility-state of the guest or nested-guest and
8581 * then figure out what needs to be injected.
8582 */
8583 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
8584 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8585 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8586 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8587
8588 /* We don't support block-by-SMI yet.*/
8589 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
8590
8591 /* Block-by-STI must not be set when interrupts are disabled. */
8592 if (fBlockSti)
8593 {
8594 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
8595 Assert(pCtx->eflags.Bits.u1IF);
8596 }
8597
8598 /* Update interruptibility state to the caller. */
8599 *pfIntrState = fIntrState;
8600
8601 /*
8602 * Toggling of interrupt force-flags here is safe since we update TRPM on
8603 * premature exits to ring-3 before executing guest code, see hmR0VmxExitToRing3().
8604 * We must NOT restore these force-flags.
8605 */
8606
8607 /** @todo SMI. SMIs take priority over NMIs. */
8608
8609 /*
8610 * Check if an NMI is pending and if the guest or nested-guest can receive them.
8611 * NMIs take priority over external interrupts.
8612 */
8613 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8614 {
8615 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
8616 if ( !pVCpu->hm.s.Event.fPending
8617 && !fBlockNmi
8618 && !fBlockSti
8619 && !fBlockMovSS)
8620 {
8621#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8622 if ( fIsNestedGuest
8623 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_NMI_EXIT))
8624 return IEMExecVmxVmexitXcptNmi(pVCpu);
8625#endif
8626 hmR0VmxSetPendingXcptNmi(pVCpu);
8627 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8628 Log4Func(("Pending NMI\n"));
8629 }
8630 else if (!fIsNestedGuest)
8631 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8632 /* else: for nested-guests, NMI-window exiting will be picked up when merging VMCS controls. */
8633 }
8634 /*
8635 * Check if an external interrupt (PIC/APIC) is pending and if the guest or nested-guest
8636 * can receive them. Once PDMGetInterrupt() returns a valid interrupt we -must- deliver
8637 * the interrupt. We can no longer re-request it from the APIC.
8638 */
8639 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8640 && !pVCpu->hm.s.fSingleInstruction)
8641 {
8642 Assert(!DBGFIsStepping(pVCpu));
8643 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8644 AssertRCReturn(rc, rc);
8645
8646 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
8647 if ( !pVCpu->hm.s.Event.fPending
8648 && !fBlockInt
8649 && !fBlockSti
8650 && !fBlockMovSS)
8651 {
8652#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8653 if ( fIsNestedGuest
8654 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8655 && !CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8656 {
8657 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
8658 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8659 return rcStrict;
8660 }
8661#endif
8662 uint8_t u8Interrupt;
8663 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8664 if (RT_SUCCESS(rc))
8665 {
8666#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8667 if ( fIsNestedGuest
8668 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8669 && CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8670 {
8671 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8672 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8673 return rcStrict;
8674 }
8675#endif
8676 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8677 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
8678 }
8679 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8680 {
8681 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8682
8683 if ( !fIsNestedGuest
8684 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8685 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
8686 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
8687
8688 /*
8689 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8690 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8691 * need to re-set this force-flag here.
8692 */
8693 }
8694 else
8695 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8696 }
8697 else if (!fIsNestedGuest)
8698 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8699 /* else: for nested-guests, interrupt-window exiting will be picked up when merging VMCS controls. */
8700 }
8701
8702 return VINF_SUCCESS;
8703}
8704
8705
8706/**
8707 * Injects any pending events into the guest if the guest is in a state to
8708 * receive them.
8709 *
8710 * @returns Strict VBox status code (i.e. informational status codes too).
8711 * @param pVCpu The cross context virtual CPU structure.
8712 * @param pVmxTransient The VMX-transient structure.
8713 * @param fIntrState The VT-x guest-interruptibility state.
8714 * @param fStepping Whether we are single-stepping the guest using the
8715 * hypervisor debugger and should return
8716 * VINF_EM_DBG_STEPPED if the event was dispatched
8717 * directly.
8718 */
8719static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
8720{
8721 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8722 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8723
8724#ifdef VBOX_STRICT
8725 /*
8726 * Verify guest-interruptibility state.
8727 *
8728 * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
8729 * since injecting an event may modify the interruptibility state and we must thus always
8730 * use fIntrState.
8731 */
8732 {
8733 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8734 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8735 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
8736 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
8737 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
8738 Assert(!TRPMHasTrap(pVCpu));
8739 NOREF(fBlockMovSS); NOREF(fBlockSti);
8740 }
8741#endif
8742
8743 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
8744 if (pVCpu->hm.s.Event.fPending)
8745 {
8746 /*
8747 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
8748 * pending even while injecting an event and in this case, we want a VM-exit as soon as
8749 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
8750 *
8751 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
8752 */
8753 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
8754#ifdef VBOX_STRICT
8755 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8756 {
8757 Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
8758 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
8759 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8760 }
8761 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
8762 {
8763 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
8764 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
8765 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8766 }
8767#endif
8768 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
8769 uIntType));
8770
8771 /*
8772 * Inject the event and get any changes to the guest-interruptibility state.
8773 *
8774 * The guest-interruptibility state may need to be updated if we inject the event
8775 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
8776 */
8777 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
8778 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
8779
8780 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8781 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
8782 else
8783 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
8784 }
8785
8786 /*
8787 * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
8788 * is an interrupt shadow (block-by-STI or block-by-MOV SS).
8789 */
8790 if ( (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
8791 && !pVmxTransient->fIsNestedGuest)
8792 {
8793 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
8794
8795 if (!pVCpu->hm.s.fSingleInstruction)
8796 {
8797 /*
8798 * Set or clear the BS bit depending on whether the trap flag is active or not. We need
8799 * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
8800 */
8801 Assert(!DBGFIsStepping(pVCpu));
8802 uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
8803 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
8804 AssertRC(rc);
8805 }
8806 else if (pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF)
8807 {
8808 /*
8809 * We must not deliver a debug exception when single-stepping in the hypervisor debugger
8810 * using EFLAGS.T. Instead, clear interrupt inhibition.
8811 */
8812 Assert(!(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
8813 fIntrState = 0;
8814 }
8815 }
8816 /* else: for nested-guest currently handling while merging controls. */
8817
8818 /*
8819 * Finally, update the guest-interruptibility state.
8820 *
8821 * This is required for the real-on-v86 software interrupt injection, for
8822 * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
8823 */
8824 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
8825 AssertRC(rc);
8826
8827 /*
8828 * There's no need to clear the VM-entry interruption-information field here if we're not
8829 * injecting anything. VT-x clears the valid bit on every VM-exit.
8830 *
8831 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
8832 */
8833
8834 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
8835 return rcStrict;
8836}
8837
8838
8839/**
8840 * Enters the VT-x session.
8841 *
8842 * @returns VBox status code.
8843 * @param pVCpu The cross context virtual CPU structure.
8844 */
8845VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
8846{
8847 AssertPtr(pVCpu);
8848 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
8849 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8850
8851 LogFlowFunc(("pVCpu=%p\n", pVCpu));
8852 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8853 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8854
8855#ifdef VBOX_STRICT
8856 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
8857 RTCCUINTREG uHostCr4 = ASMGetCR4();
8858 if (!(uHostCr4 & X86_CR4_VMXE))
8859 {
8860 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
8861 return VERR_VMX_X86_CR4_VMXE_CLEARED;
8862 }
8863#endif
8864
8865 /*
8866 * Load the appropriate VMCS as the current and active one.
8867 */
8868 PVMXVMCSINFO pVmcsInfo;
8869 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
8870 if (!fInNestedGuestMode)
8871 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
8872 else
8873 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
8874 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
8875 if (RT_SUCCESS(rc))
8876 {
8877 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
8878 pVCpu->hm.s.fLeaveDone = false;
8879 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8880
8881 /*
8882 * Do the EMT scheduled L1D flush here if needed.
8883 */
8884 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8885 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8886 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
8887 hmR0MdsClear();
8888 }
8889 return rc;
8890}
8891
8892
8893/**
8894 * The thread-context callback (only on platforms which support it).
8895 *
8896 * @param enmEvent The thread-context event.
8897 * @param pVCpu The cross context virtual CPU structure.
8898 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
8899 * @thread EMT(pVCpu)
8900 */
8901VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
8902{
8903 AssertPtr(pVCpu);
8904 RT_NOREF1(fGlobalInit);
8905
8906 switch (enmEvent)
8907 {
8908 case RTTHREADCTXEVENT_OUT:
8909 {
8910 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8911 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8912 VMCPU_ASSERT_EMT(pVCpu);
8913
8914 /* No longjmps (logger flushes, locks) in this fragile context. */
8915 VMMRZCallRing3Disable(pVCpu);
8916 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
8917
8918 /* Restore host-state (FPU, debug etc.) */
8919 if (!pVCpu->hm.s.fLeaveDone)
8920 {
8921 /*
8922 * Do -not- import the guest-state here as we might already be in the middle of importing
8923 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
8924 */
8925 hmR0VmxLeave(pVCpu, false /* fImportState */);
8926 pVCpu->hm.s.fLeaveDone = true;
8927 }
8928
8929 /* Leave HM context, takes care of local init (term). */
8930 int rc = HMR0LeaveCpu(pVCpu);
8931 AssertRC(rc);
8932
8933 /* Restore longjmp state. */
8934 VMMRZCallRing3Enable(pVCpu);
8935 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
8936 break;
8937 }
8938
8939 case RTTHREADCTXEVENT_IN:
8940 {
8941 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8942 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8943 VMCPU_ASSERT_EMT(pVCpu);
8944
8945 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
8946 VMMRZCallRing3Disable(pVCpu);
8947 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
8948
8949 /* Initialize the bare minimum state required for HM. This takes care of
8950 initializing VT-x if necessary (onlined CPUs, local init etc.) */
8951 int rc = hmR0EnterCpu(pVCpu);
8952 AssertRC(rc);
8953 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8954 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8955
8956 /* Load the active VMCS as the current one. */
8957 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8958 rc = hmR0VmxLoadVmcs(pVmcsInfo);
8959 AssertRC(rc);
8960 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8961 pVCpu->hm.s.fLeaveDone = false;
8962
8963 /* Do the EMT scheduled L1D flush if needed. */
8964 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8965 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8966
8967 /* Restore longjmp state. */
8968 VMMRZCallRing3Enable(pVCpu);
8969 break;
8970 }
8971
8972 default:
8973 break;
8974 }
8975}
8976
8977
8978/**
8979 * Exports the host state into the VMCS host-state area.
8980 * Sets up the VM-exit MSR-load area.
8981 *
8982 * The CPU state will be loaded from these fields on every successful VM-exit.
8983 *
8984 * @returns VBox status code.
8985 * @param pVCpu The cross context virtual CPU structure.
8986 *
8987 * @remarks No-long-jump zone!!!
8988 */
8989static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
8990{
8991 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8992
8993 int rc = VINF_SUCCESS;
8994 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
8995 {
8996 hmR0VmxExportHostControlRegs();
8997
8998 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
8999 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9000
9001 hmR0VmxExportHostMsrs(pVCpu);
9002
9003 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9004 }
9005 return rc;
9006}
9007
9008
9009/**
9010 * Saves the host state in the VMCS host-state.
9011 *
9012 * @returns VBox status code.
9013 * @param pVCpu The cross context virtual CPU structure.
9014 *
9015 * @remarks No-long-jump zone!!!
9016 */
9017VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
9018{
9019 AssertPtr(pVCpu);
9020 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9021
9022 /*
9023 * Export the host state here while entering HM context.
9024 * When thread-context hooks are used, we might get preempted and have to re-save the host
9025 * state but most of the time we won't be, so do it here before we disable interrupts.
9026 */
9027 return hmR0VmxExportHostState(pVCpu);
9028}
9029
9030
9031/**
9032 * Exports the guest state into the VMCS guest-state area.
9033 *
9034 * The will typically be done before VM-entry when the guest-CPU state and the
9035 * VMCS state may potentially be out of sync.
9036 *
9037 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9038 * VM-entry controls.
9039 * Sets up the appropriate VMX non-root function to execute guest code based on
9040 * the guest CPU mode.
9041 *
9042 * @returns VBox strict status code.
9043 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9044 * without unrestricted guest execution and the VMMDev is not presently
9045 * mapped (e.g. EFI32).
9046 *
9047 * @param pVCpu The cross context virtual CPU structure.
9048 * @param pVmxTransient The VMX-transient structure.
9049 *
9050 * @remarks No-long-jump zone!!!
9051 */
9052static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9053{
9054 AssertPtr(pVCpu);
9055 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9056 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9057
9058 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9059
9060 /*
9061 * Determine real-on-v86 mode.
9062 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9063 */
9064 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9065 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9066 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9067 pVmcsInfo->RealMode.fRealOnV86Active = false;
9068 else
9069 {
9070 Assert(!pVmxTransient->fIsNestedGuest);
9071 pVmcsInfo->RealMode.fRealOnV86Active = true;
9072 }
9073
9074 /*
9075 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9076 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9077 */
9078 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9079 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9080
9081 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9082 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9083
9084 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9085 if (rcStrict == VINF_SUCCESS)
9086 { /* likely */ }
9087 else
9088 {
9089 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9090 return rcStrict;
9091 }
9092
9093 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9094 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9095
9096 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9097 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9098
9099 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9100 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9101 hmR0VmxExportGuestRip(pVCpu);
9102 hmR0VmxExportGuestRsp(pVCpu);
9103 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9104
9105 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9106 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9107
9108 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9109 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9110 | HM_CHANGED_GUEST_CR2
9111 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9112 | HM_CHANGED_GUEST_X87
9113 | HM_CHANGED_GUEST_SSE_AVX
9114 | HM_CHANGED_GUEST_OTHER_XSAVE
9115 | HM_CHANGED_GUEST_XCRx
9116 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9117 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9118 | HM_CHANGED_GUEST_TSC_AUX
9119 | HM_CHANGED_GUEST_OTHER_MSRS
9120 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9121
9122 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9123 return rc;
9124}
9125
9126
9127/**
9128 * Exports the state shared between the host and guest into the VMCS.
9129 *
9130 * @param pVCpu The cross context virtual CPU structure.
9131 * @param pVmxTransient The VMX-transient structure.
9132 *
9133 * @remarks No-long-jump zone!!!
9134 */
9135static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9136{
9137 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9138 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9139
9140 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9141 {
9142 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9143 AssertRC(rc);
9144 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9145
9146 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9147 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9148 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9149 }
9150
9151 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9152 {
9153 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9154 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9155 }
9156
9157 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9158 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9159}
9160
9161
9162/**
9163 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9164 *
9165 * @returns Strict VBox status code (i.e. informational status codes too).
9166 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9167 * without unrestricted guest execution and the VMMDev is not presently
9168 * mapped (e.g. EFI32).
9169 *
9170 * @param pVCpu The cross context virtual CPU structure.
9171 * @param pVmxTransient The VMX-transient structure.
9172 *
9173 * @remarks No-long-jump zone!!!
9174 */
9175static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9176{
9177 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9178 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9179 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9180
9181#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9182 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9183#endif
9184
9185 /*
9186 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9187 * changes. First try to export only these without going through all other changed-flag checks.
9188 */
9189 VBOXSTRICTRC rcStrict;
9190 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9191 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9192 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9193
9194 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9195 if ( (fCtxChanged & fMinimalMask)
9196 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9197 {
9198 hmR0VmxExportGuestRip(pVCpu);
9199 hmR0VmxExportGuestRsp(pVCpu);
9200 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9201 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9202 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9203 }
9204 /* If anything else also changed, go through the full export routine and export as required. */
9205 else if (fCtxChanged & fCtxMask)
9206 {
9207 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9208 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9209 { /* likely */}
9210 else
9211 {
9212 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9213 VBOXSTRICTRC_VAL(rcStrict)));
9214 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9215 return rcStrict;
9216 }
9217 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9218 }
9219 /* Nothing changed, nothing to load here. */
9220 else
9221 rcStrict = VINF_SUCCESS;
9222
9223#ifdef VBOX_STRICT
9224 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9225 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9226 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9227#endif
9228 return rcStrict;
9229}
9230
9231
9232/**
9233 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9234 * and update error record fields accordingly.
9235 *
9236 * @returns VMX_IGS_* error codes.
9237 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9238 * wrong with the guest state.
9239 *
9240 * @param pVCpu The cross context virtual CPU structure.
9241 * @param pVmcsInfo The VMCS info. object.
9242 *
9243 * @remarks This function assumes our cache of the VMCS controls
9244 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9245 */
9246static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9247{
9248#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9249#define HMVMX_CHECK_BREAK(expr, err) do { \
9250 if (!(expr)) { uError = (err); break; } \
9251 } while (0)
9252
9253 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9254 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9255 uint32_t uError = VMX_IGS_ERROR;
9256 uint32_t u32IntrState = 0;
9257 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9258 do
9259 {
9260 int rc;
9261
9262 /*
9263 * Guest-interruptibility state.
9264 *
9265 * Read this first so that any check that fails prior to those that actually
9266 * require the guest-interruptibility state would still reflect the correct
9267 * VMCS value and avoids causing further confusion.
9268 */
9269 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9270 AssertRC(rc);
9271
9272 uint32_t u32Val;
9273 uint64_t u64Val;
9274
9275 /*
9276 * CR0.
9277 */
9278 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9279 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9280 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9281 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9282 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9283 if (fUnrestrictedGuest)
9284 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9285
9286 uint64_t u64GuestCr0;
9287 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9288 AssertRC(rc);
9289 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9290 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9291 if ( !fUnrestrictedGuest
9292 && (u64GuestCr0 & X86_CR0_PG)
9293 && !(u64GuestCr0 & X86_CR0_PE))
9294 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9295
9296 /*
9297 * CR4.
9298 */
9299 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9300 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9301 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9302
9303 uint64_t u64GuestCr4;
9304 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9305 AssertRC(rc);
9306 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9307 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9308
9309 /*
9310 * IA32_DEBUGCTL MSR.
9311 */
9312 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9313 AssertRC(rc);
9314 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9315 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9316 {
9317 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9318 }
9319 uint64_t u64DebugCtlMsr = u64Val;
9320
9321#ifdef VBOX_STRICT
9322 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9323 AssertRC(rc);
9324 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9325#endif
9326 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9327
9328 /*
9329 * RIP and RFLAGS.
9330 */
9331 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9332 AssertRC(rc);
9333 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9334 if ( !fLongModeGuest
9335 || !pCtx->cs.Attr.n.u1Long)
9336 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9337 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9338 * must be identical if the "IA-32e mode guest" VM-entry
9339 * control is 1 and CS.L is 1. No check applies if the
9340 * CPU supports 64 linear-address bits. */
9341
9342 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9343 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9344 AssertRC(rc);
9345 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9346 VMX_IGS_RFLAGS_RESERVED);
9347 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9348 uint32_t const u32Eflags = u64Val;
9349
9350 if ( fLongModeGuest
9351 || ( fUnrestrictedGuest
9352 && !(u64GuestCr0 & X86_CR0_PE)))
9353 {
9354 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9355 }
9356
9357 uint32_t u32EntryInfo;
9358 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9359 AssertRC(rc);
9360 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9361 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9362
9363 /*
9364 * 64-bit checks.
9365 */
9366 if (fLongModeGuest)
9367 {
9368 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9369 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9370 }
9371
9372 if ( !fLongModeGuest
9373 && (u64GuestCr4 & X86_CR4_PCIDE))
9374 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9375
9376 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9377 * 51:32 beyond the processor's physical-address width are 0. */
9378
9379 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9380 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9381 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9382
9383 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9384 AssertRC(rc);
9385 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9386
9387 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9388 AssertRC(rc);
9389 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9390
9391 /*
9392 * PERF_GLOBAL MSR.
9393 */
9394 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9395 {
9396 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9397 AssertRC(rc);
9398 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9399 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9400 }
9401
9402 /*
9403 * PAT MSR.
9404 */
9405 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9406 {
9407 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9408 AssertRC(rc);
9409 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9410 for (unsigned i = 0; i < 8; i++)
9411 {
9412 uint8_t u8Val = (u64Val & 0xff);
9413 if ( u8Val != 0 /* UC */
9414 && u8Val != 1 /* WC */
9415 && u8Val != 4 /* WT */
9416 && u8Val != 5 /* WP */
9417 && u8Val != 6 /* WB */
9418 && u8Val != 7 /* UC- */)
9419 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9420 u64Val >>= 8;
9421 }
9422 }
9423
9424 /*
9425 * EFER MSR.
9426 */
9427 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9428 {
9429 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9430 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9431 AssertRC(rc);
9432 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9433 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9434 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9435 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9436 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9437 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9438 * iemVmxVmentryCheckGuestState(). */
9439 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9440 || !(u64GuestCr0 & X86_CR0_PG)
9441 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9442 VMX_IGS_EFER_LMA_LME_MISMATCH);
9443 }
9444
9445 /*
9446 * Segment registers.
9447 */
9448 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9449 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9450 if (!(u32Eflags & X86_EFL_VM))
9451 {
9452 /* CS */
9453 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9454 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9455 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9456 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9457 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9458 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9459 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9460 /* CS cannot be loaded with NULL in protected mode. */
9461 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9462 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9463 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9464 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9465 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9466 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9467 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9468 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9469 else
9470 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9471
9472 /* SS */
9473 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9474 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9475 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9476 if ( !(pCtx->cr0 & X86_CR0_PE)
9477 || pCtx->cs.Attr.n.u4Type == 3)
9478 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9479
9480 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9481 {
9482 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9483 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9484 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9485 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9486 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9487 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9488 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9489 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9490 }
9491
9492 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9493 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9494 {
9495 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9496 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9497 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9498 || pCtx->ds.Attr.n.u4Type > 11
9499 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9500 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9501 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9502 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9503 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9504 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9505 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9506 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9507 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9508 }
9509 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9510 {
9511 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9512 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9513 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9514 || pCtx->es.Attr.n.u4Type > 11
9515 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9516 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9517 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9518 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9519 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9520 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9521 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9522 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9523 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9524 }
9525 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9526 {
9527 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9528 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9529 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9530 || pCtx->fs.Attr.n.u4Type > 11
9531 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9532 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9533 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9534 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9535 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9536 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9537 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9538 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9539 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9540 }
9541 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9542 {
9543 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9544 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9545 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9546 || pCtx->gs.Attr.n.u4Type > 11
9547 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9548 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9549 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9550 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9551 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9552 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9553 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9554 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9555 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9556 }
9557 /* 64-bit capable CPUs. */
9558 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9559 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9560 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9561 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9562 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9563 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9564 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9565 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9566 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9567 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9568 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9569 }
9570 else
9571 {
9572 /* V86 mode checks. */
9573 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9574 if (pVmcsInfo->RealMode.fRealOnV86Active)
9575 {
9576 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9577 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9578 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9579 }
9580 else
9581 {
9582 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9583 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9584 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9585 }
9586
9587 /* CS */
9588 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9589 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9590 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9591 /* SS */
9592 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9593 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9594 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9595 /* DS */
9596 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9597 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9598 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9599 /* ES */
9600 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9601 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9602 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9603 /* FS */
9604 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9605 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9606 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9607 /* GS */
9608 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9609 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9610 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9611 /* 64-bit capable CPUs. */
9612 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9613 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9614 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9615 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9616 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9617 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9618 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9619 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9620 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9621 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9622 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9623 }
9624
9625 /*
9626 * TR.
9627 */
9628 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9629 /* 64-bit capable CPUs. */
9630 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9631 if (fLongModeGuest)
9632 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9633 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9634 else
9635 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9636 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9637 VMX_IGS_TR_ATTR_TYPE_INVALID);
9638 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9639 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9640 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9641 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9642 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9643 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9644 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9645 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9646
9647 /*
9648 * GDTR and IDTR (64-bit capable checks).
9649 */
9650 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9651 AssertRC(rc);
9652 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9653
9654 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9655 AssertRC(rc);
9656 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9657
9658 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9659 AssertRC(rc);
9660 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9661
9662 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9663 AssertRC(rc);
9664 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9665
9666 /*
9667 * Guest Non-Register State.
9668 */
9669 /* Activity State. */
9670 uint32_t u32ActivityState;
9671 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9672 AssertRC(rc);
9673 HMVMX_CHECK_BREAK( !u32ActivityState
9674 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9675 VMX_IGS_ACTIVITY_STATE_INVALID);
9676 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9677 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9678
9679 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9680 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9681 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9682
9683 /** @todo Activity state and injecting interrupts. Left as a todo since we
9684 * currently don't use activity states but ACTIVE. */
9685
9686 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9687 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9688
9689 /* Guest interruptibility-state. */
9690 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9691 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9692 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9693 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9694 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9695 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9696 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9697 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9698 {
9699 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9700 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9701 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9702 }
9703 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9704 {
9705 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9706 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9707 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9708 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
9709 }
9710 /** @todo Assumes the processor is not in SMM. */
9711 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9712 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
9713 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9714 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9715 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
9716 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
9717 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9718 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
9719
9720 /* Pending debug exceptions. */
9721 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
9722 AssertRC(rc);
9723 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
9724 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
9725 u32Val = u64Val; /* For pending debug exceptions checks below. */
9726
9727 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9728 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
9729 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
9730 {
9731 if ( (u32Eflags & X86_EFL_TF)
9732 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9733 {
9734 /* Bit 14 is PendingDebug.BS. */
9735 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
9736 }
9737 if ( !(u32Eflags & X86_EFL_TF)
9738 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9739 {
9740 /* Bit 14 is PendingDebug.BS. */
9741 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
9742 }
9743 }
9744
9745 /* VMCS link pointer. */
9746 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
9747 AssertRC(rc);
9748 if (u64Val != UINT64_C(0xffffffffffffffff))
9749 {
9750 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
9751 /** @todo Bits beyond the processor's physical-address width MBZ. */
9752 /** @todo SMM checks. */
9753 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
9754 Assert(pVmcsInfo->pvShadowVmcs);
9755 VMXVMCSREVID VmcsRevId;
9756 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
9757 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
9758 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
9759 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
9760 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
9761 }
9762
9763 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
9764 * not using nested paging? */
9765 if ( pVM->hm.s.fNestedPaging
9766 && !fLongModeGuest
9767 && CPUMIsGuestInPAEModeEx(pCtx))
9768 {
9769 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
9770 AssertRC(rc);
9771 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9772
9773 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
9774 AssertRC(rc);
9775 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9776
9777 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
9778 AssertRC(rc);
9779 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9780
9781 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
9782 AssertRC(rc);
9783 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9784 }
9785
9786 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
9787 if (uError == VMX_IGS_ERROR)
9788 uError = VMX_IGS_REASON_NOT_FOUND;
9789 } while (0);
9790
9791 pVCpu->hm.s.u32HMError = uError;
9792 pVCpu->hm.s.vmx.LastError.u32GuestIntrState = u32IntrState;
9793 return uError;
9794
9795#undef HMVMX_ERROR_BREAK
9796#undef HMVMX_CHECK_BREAK
9797}
9798
9799
9800/**
9801 * Map the APIC-access page for virtualizing APIC accesses.
9802 *
9803 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
9804 * this not done as part of exporting guest state, see @bugref{8721}.
9805 *
9806 * @returns VBox status code.
9807 * @param pVCpu The cross context virtual CPU structure.
9808 */
9809static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
9810{
9811 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9812 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
9813
9814 Assert(PDMHasApic(pVM));
9815 Assert(u64MsrApicBase);
9816
9817 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
9818 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
9819
9820 /* Unalias the existing mapping. */
9821 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
9822 AssertRCReturn(rc, rc);
9823
9824 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
9825 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
9826 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
9827 AssertRCReturn(rc, rc);
9828
9829 /* Update the per-VCPU cache of the APIC base MSR. */
9830 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
9831 return VINF_SUCCESS;
9832}
9833
9834
9835/**
9836 * Worker function passed to RTMpOnSpecific() that is to be called on the target
9837 * CPU.
9838 *
9839 * @param idCpu The ID for the CPU the function is called on.
9840 * @param pvUser1 Null, not used.
9841 * @param pvUser2 Null, not used.
9842 */
9843static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
9844{
9845 RT_NOREF3(idCpu, pvUser1, pvUser2);
9846 VMXDispatchHostNmi();
9847}
9848
9849
9850/**
9851 * Dispatching an NMI on the host CPU that received it.
9852 *
9853 * @returns VBox status code.
9854 * @param pVCpu The cross context virtual CPU structure.
9855 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
9856 * executing when receiving the host NMI in VMX non-root
9857 * operation.
9858 */
9859static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9860{
9861 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
9862 Assert(idCpu != NIL_RTCPUID);
9863
9864 /*
9865 * We don't want to delay dispatching the NMI any more than we have to. However,
9866 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
9867 * after executing guest or nested-guest code for the following reasons:
9868 *
9869 * - We would need to perform VMREADs with interrupts disabled and is orders of
9870 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
9871 * supported by the host hypervisor.
9872 *
9873 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
9874 * longer period of time just for handling an edge case like host NMIs which do
9875 * not occur nearly as frequently as other VM-exits.
9876 *
9877 * Let's cover the most likely scenario first. Check if we are on the target CPU
9878 * and dispatch the NMI right away. This should be much faster than calling into
9879 * RTMpOnSpecific() machinery.
9880 */
9881 bool fDispatched = false;
9882 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
9883 if (idCpu == RTMpCpuId())
9884 {
9885 VMXDispatchHostNmi();
9886 fDispatched = true;
9887 }
9888 ASMSetFlags(fEFlags);
9889 if (fDispatched)
9890 {
9891 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
9892 return VINF_SUCCESS;
9893 }
9894
9895 /*
9896 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
9897 * there should be no race or recursion even if we are unlucky enough to be preempted
9898 * (to the target CPU) without dispatching the host NMI above.
9899 */
9900 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
9901 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
9902}
9903
9904
9905#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9906/**
9907 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
9908 * nested-guest using hardware-assisted VMX.
9909 *
9910 * @param pVCpu The cross context virtual CPU structure.
9911 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
9912 * @param pVmcsInfoGst The guest VMCS info. object.
9913 */
9914static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
9915{
9916 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
9917 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
9918 Assert(pu64MsrBitmap);
9919
9920 /*
9921 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
9922 * MSR that is intercepted by the guest is also intercepted while executing the
9923 * nested-guest using hardware-assisted VMX.
9924 *
9925 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
9926 * nested-guest VM-exit even if the outer guest is not intercepting some
9927 * MSRs. We cannot assume the caller has initialized the nested-guest
9928 * MSR bitmap in this case.
9929 *
9930 * The nested hypervisor may also switch whether it uses MSR bitmaps for
9931 * each VM-entry, hence initializing it once per-VM while setting up the
9932 * nested-guest VMCS is not sufficient.
9933 */
9934 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9935 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
9936 {
9937 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
9938 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
9939 Assert(pu64MsrBitmapNstGst);
9940 Assert(pu64MsrBitmapGst);
9941
9942 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
9943 for (uint32_t i = 0; i < cFrags; i++)
9944 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
9945 }
9946 else
9947 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
9948}
9949
9950
9951/**
9952 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
9953 * hardware-assisted VMX execution of the nested-guest.
9954 *
9955 * For a guest, we don't modify these controls once we set up the VMCS and hence
9956 * this function is never called.
9957 *
9958 * For nested-guests since the nested hypervisor provides these controls on every
9959 * nested-guest VM-entry and could potentially change them everytime we need to
9960 * merge them before every nested-guest VM-entry.
9961 *
9962 * @returns VBox status code.
9963 * @param pVCpu The cross context virtual CPU structure.
9964 */
9965static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
9966{
9967 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9968 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
9969 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9970 Assert(pVmcsNstGst);
9971
9972 /*
9973 * Merge the controls with the requirements of the guest VMCS.
9974 *
9975 * We do not need to validate the nested-guest VMX features specified in the nested-guest
9976 * VMCS with the features supported by the physical CPU as it's already done by the
9977 * VMLAUNCH/VMRESUME instruction emulation.
9978 *
9979 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
9980 * derived from the VMX features supported by the physical CPU.
9981 */
9982
9983 /* Pin-based VM-execution controls. */
9984 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
9985
9986 /* Processor-based VM-execution controls. */
9987 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
9988 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
9989 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
9990 | VMX_PROC_CTLS_USE_TPR_SHADOW
9991 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
9992
9993 /* Secondary processor-based VM-execution controls. */
9994 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
9995 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
9996 | VMX_PROC_CTLS2_INVPCID
9997 | VMX_PROC_CTLS2_VMCS_SHADOWING
9998 | VMX_PROC_CTLS2_RDTSCP
9999 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10000 | VMX_PROC_CTLS2_APIC_REG_VIRT
10001 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10002 | VMX_PROC_CTLS2_VMFUNC));
10003
10004 /*
10005 * VM-entry controls:
10006 * These controls contains state that depends on the nested-guest state (primarily
10007 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10008 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
10009 * properly continue executing the nested-guest if the EFER MSR changes but does not
10010 * cause a nested-guest VM-exits.
10011 *
10012 * VM-exit controls:
10013 * These controls specify the host state on return. We cannot use the controls from
10014 * the nested hypervisor state as is as it would contain the guest state rather than
10015 * the host state. Since the host state is subject to change (e.g. preemption, trips
10016 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10017 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10018 *
10019 * VM-entry MSR-load:
10020 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10021 * context by the VMLAUNCH/VMRESUME instruction emulation.
10022 *
10023 * VM-exit MSR-store:
10024 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10025 * back into the VM-exit MSR-store area.
10026 *
10027 * VM-exit MSR-load areas:
10028 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10029 * can entirely ignore what the nested hypervisor wants to load here.
10030 */
10031
10032 /*
10033 * Exception bitmap.
10034 *
10035 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10036 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10037 * code more flexible if intercepting exceptions become more dynamic in the future we do
10038 * it as part of exporting the nested-guest state.
10039 */
10040 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10041
10042 /*
10043 * CR0/CR4 guest/host mask.
10044 *
10045 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10046 * cause VM-exits, so we need to merge them here.
10047 */
10048 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10049 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10050
10051 /*
10052 * Page-fault error-code mask and match.
10053 *
10054 * Although we require unrestricted guest execution (and thereby nested-paging) for
10055 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10056 * normally intercept #PFs, it might intercept them for debugging purposes.
10057 *
10058 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10059 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10060 */
10061 uint32_t u32XcptPFMask;
10062 uint32_t u32XcptPFMatch;
10063 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10064 {
10065 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10066 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10067 }
10068 else
10069 {
10070 u32XcptPFMask = 0;
10071 u32XcptPFMatch = 0;
10072 }
10073
10074 /*
10075 * Pause-Loop exiting.
10076 */
10077 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10078 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10079
10080 /*
10081 * Pending debug exceptions.
10082 * Currently just copy whatever the nested-guest provides us.
10083 */
10084 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10085
10086 /*
10087 * I/O Bitmap.
10088 *
10089 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10090 * intercept all I/O port accesses.
10091 */
10092 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10093 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10094
10095 /*
10096 * VMCS shadowing.
10097 *
10098 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10099 * enabled while executing the nested-guest.
10100 */
10101 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10102
10103 /*
10104 * APIC-access page.
10105 */
10106 RTHCPHYS HCPhysApicAccess;
10107 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10108 {
10109 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10110 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10111
10112 /** @todo NSTVMX: This is not really correct but currently is required to make
10113 * things work. We need to re-enable the page handler when we fallback to
10114 * IEM execution of the nested-guest! */
10115 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10116
10117 void *pvPage;
10118 PGMPAGEMAPLOCK PgLockApicAccess;
10119 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10120 if (RT_SUCCESS(rc))
10121 {
10122 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10123 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10124
10125 /** @todo Handle proper releasing of page-mapping lock later. */
10126 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10127 }
10128 else
10129 return rc;
10130 }
10131 else
10132 HCPhysApicAccess = 0;
10133
10134 /*
10135 * Virtual-APIC page and TPR threshold.
10136 */
10137 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10138 RTHCPHYS HCPhysVirtApic;
10139 uint32_t u32TprThreshold;
10140 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10141 {
10142 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10143 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10144
10145 void *pvPage;
10146 PGMPAGEMAPLOCK PgLockVirtApic;
10147 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10148 if (RT_SUCCESS(rc))
10149 {
10150 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10151 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10152
10153 /** @todo Handle proper releasing of page-mapping lock later. */
10154 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10155 }
10156 else
10157 return rc;
10158
10159 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10160 }
10161 else
10162 {
10163 HCPhysVirtApic = 0;
10164 u32TprThreshold = 0;
10165
10166 /*
10167 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10168 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10169 * be taken care of by EPT/shadow paging.
10170 */
10171 if (pVM->hm.s.fAllow64BitGuests)
10172 {
10173 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10174 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10175 }
10176 }
10177
10178 /*
10179 * Validate basic assumptions.
10180 */
10181 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10182 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10183 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10184
10185 /*
10186 * Commit it to the nested-guest VMCS.
10187 */
10188 int rc = VINF_SUCCESS;
10189 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10190 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10191 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10192 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10193 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10194 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10195 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10196 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10197 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10198 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10199 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10200 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10201 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10202 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10203 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10204 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10205 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10206 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10207 {
10208 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10209 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10210 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10211 }
10212 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10213 {
10214 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10215 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10216 }
10217 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10218 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10219 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10220 AssertRC(rc);
10221
10222 /*
10223 * Update the nested-guest VMCS cache.
10224 */
10225 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10226 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10227 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10228 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10229 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10230 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10231 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10232 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10233 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10234
10235 /*
10236 * We need to flush the TLB if we are switching the APIC-access page address.
10237 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10238 */
10239 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10240 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10241
10242 /*
10243 * MSR bitmap.
10244 *
10245 * The MSR bitmap address has already been initialized while setting up the nested-guest
10246 * VMCS, here we need to merge the MSR bitmaps.
10247 */
10248 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10249 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10250
10251 return VINF_SUCCESS;
10252}
10253#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10254
10255
10256/**
10257 * Does the preparations before executing guest code in VT-x.
10258 *
10259 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10260 * recompiler/IEM. We must be cautious what we do here regarding committing
10261 * guest-state information into the VMCS assuming we assuredly execute the
10262 * guest in VT-x mode.
10263 *
10264 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10265 * the common-state (TRPM/forceflags), we must undo those changes so that the
10266 * recompiler/IEM can (and should) use them when it resumes guest execution.
10267 * Otherwise such operations must be done when we can no longer exit to ring-3.
10268 *
10269 * @returns Strict VBox status code (i.e. informational status codes too).
10270 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10271 * have been disabled.
10272 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10273 * pending events).
10274 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10275 * double-fault into the guest.
10276 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10277 * dispatched directly.
10278 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10279 *
10280 * @param pVCpu The cross context virtual CPU structure.
10281 * @param pVmxTransient The VMX-transient structure.
10282 * @param fStepping Whether we are single-stepping the guest in the
10283 * hypervisor debugger. Makes us ignore some of the reasons
10284 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10285 * if event dispatching took place.
10286 */
10287static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10288{
10289 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10290
10291 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10292
10293#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10294 if (pVmxTransient->fIsNestedGuest)
10295 {
10296 RT_NOREF2(pVCpu, fStepping);
10297 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10298 return VINF_EM_RESCHEDULE_REM;
10299 }
10300#endif
10301
10302#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10303 PGMRZDynMapFlushAutoSet(pVCpu);
10304#endif
10305
10306 /*
10307 * Check and process force flag actions, some of which might require us to go back to ring-3.
10308 */
10309 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, pVmxTransient, fStepping);
10310 if (rcStrict == VINF_SUCCESS)
10311 {
10312 /* FFs don't get set all the time. */
10313#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10314 if ( pVmxTransient->fIsNestedGuest
10315 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10316 {
10317 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10318 return VINF_VMX_VMEXIT;
10319 }
10320#endif
10321 }
10322 else
10323 return rcStrict;
10324
10325 /*
10326 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10327 */
10328 /** @todo Doing this from ring-3 after VM setup phase causes a
10329 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
10330 * idea why atm. */
10331 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10332 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10333 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10334 && PDMHasApic(pVM))
10335 {
10336 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10337 AssertRCReturn(rc, rc);
10338 }
10339
10340#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10341 /*
10342 * Merge guest VMCS controls with the nested-guest VMCS controls.
10343 *
10344 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10345 * saved state), we should be okay with merging controls as we initialize the
10346 * guest VMCS controls as part of VM setup phase.
10347 */
10348 if ( pVmxTransient->fIsNestedGuest
10349 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10350 {
10351 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10352 AssertRCReturn(rc, rc);
10353 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10354 }
10355#endif
10356
10357 /*
10358 * Evaluate events to be injected into the guest.
10359 *
10360 * Events in TRPM can be injected without inspecting the guest state.
10361 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10362 * guest to cause a VM-exit the next time they are ready to receive the event.
10363 *
10364 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10365 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10366 * subject to interecption. Otherwise, we should have checked and injected them
10367 * manually elsewhere (IEM).
10368 */
10369 if (TRPMHasTrap(pVCpu))
10370 {
10371 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10372 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10373 }
10374
10375 uint32_t fIntrState;
10376 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10377
10378#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10379 /*
10380 * While evaluating pending events if something failed (unlikely) or if we were
10381 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10382 */
10383 if (rcStrict != VINF_SUCCESS)
10384 return rcStrict;
10385 if ( pVmxTransient->fIsNestedGuest
10386 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10387 {
10388 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10389 return VINF_VMX_VMEXIT;
10390 }
10391#else
10392 Assert(rcStrict == VINF_SUCCESS);
10393#endif
10394
10395 /*
10396 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10397 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10398 * also result in triple-faulting the VM.
10399 *
10400 * With nested-guests, the above does not apply since unrestricted guest execution is a
10401 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10402 */
10403 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10404 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10405 { /* likely */ }
10406 else
10407 {
10408 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10409 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10410 return rcStrict;
10411 }
10412
10413 /*
10414 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10415 * import CR3 themselves. We will need to update them here, as even as late as the above
10416 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10417 * the below force flags to be set.
10418 */
10419 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10420 {
10421 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10422 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10423 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10424 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10425 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10426 }
10427 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10428 {
10429 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10430 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10431 }
10432
10433#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10434 /* Paranoia. */
10435 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10436#endif
10437
10438 /*
10439 * No longjmps to ring-3 from this point on!!!
10440 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10441 * This also disables flushing of the R0-logger instance (if any).
10442 */
10443 VMMRZCallRing3Disable(pVCpu);
10444
10445 /*
10446 * Export the guest state bits.
10447 *
10448 * We cannot perform longjmps while loading the guest state because we do not preserve the
10449 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10450 * CPU migration.
10451 *
10452 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10453 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10454 */
10455 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10456 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10457 { /* likely */ }
10458 else
10459 {
10460 VMMRZCallRing3Enable(pVCpu);
10461 return rcStrict;
10462 }
10463
10464 /*
10465 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10466 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10467 * preemption disabled for a while. Since this is purely to aid the
10468 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10469 * disable interrupt on NT.
10470 *
10471 * We need to check for force-flags that could've possible been altered since we last
10472 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10473 * see @bugref{6398}).
10474 *
10475 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10476 * to ring-3 before executing guest code.
10477 */
10478 pVmxTransient->fEFlags = ASMIntDisableFlags();
10479
10480 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10481 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10482 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10483 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10484 {
10485 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10486 {
10487#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10488 /*
10489 * If we are executing a nested-guest make sure that we should intercept subsequent
10490 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10491 * the VM-exit instruction emulation happy.
10492 */
10493 if (pVmxTransient->fIsNestedGuest)
10494 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10495#endif
10496
10497 /*
10498 * We've injected any pending events. This is really the point of no return (to ring-3).
10499 *
10500 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10501 * returns from this function, so do -not- enable them here.
10502 */
10503 pVCpu->hm.s.Event.fPending = false;
10504 return VINF_SUCCESS;
10505 }
10506
10507 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10508 rcStrict = VINF_EM_RAW_INTERRUPT;
10509 }
10510 else
10511 {
10512 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10513 rcStrict = VINF_EM_RAW_TO_R3;
10514 }
10515
10516 ASMSetFlags(pVmxTransient->fEFlags);
10517 VMMRZCallRing3Enable(pVCpu);
10518
10519 return rcStrict;
10520}
10521
10522
10523/**
10524 * Final preparations before executing guest code using hardware-assisted VMX.
10525 *
10526 * We can no longer get preempted to a different host CPU and there are no returns
10527 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10528 * failures), this function is not intended to fail sans unrecoverable hardware
10529 * errors.
10530 *
10531 * @param pVCpu The cross context virtual CPU structure.
10532 * @param pVmxTransient The VMX-transient structure.
10533 *
10534 * @remarks Called with preemption disabled.
10535 * @remarks No-long-jump zone!!!
10536 */
10537static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10538{
10539 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10540 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10541 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10542 Assert(!pVCpu->hm.s.Event.fPending);
10543
10544 /*
10545 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10546 */
10547 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10548 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10549
10550 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10551 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10552 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10553 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10554
10555 if (!CPUMIsGuestFPUStateActive(pVCpu))
10556 {
10557 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10558 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10559 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10560 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10561 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10562 }
10563
10564 /*
10565 * Re-export the host state bits as we may've been preempted (only happens when
10566 * thread-context hooks are used or when the VM start function changes) or if
10567 * the host CR0 is modified while loading the guest FPU state above.
10568 *
10569 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10570 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10571 * see @bugref{8432}.
10572 *
10573 * This may also happen when switching to/from a nested-guest VMCS without leaving
10574 * ring-0.
10575 */
10576 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10577 {
10578 hmR0VmxExportHostState(pVCpu);
10579 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10580 }
10581 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10582
10583 /*
10584 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10585 */
10586 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10587 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10588 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10589
10590 /*
10591 * Store status of the shared guest/host debug state at the time of VM-entry.
10592 */
10593 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10594 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10595
10596 /*
10597 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10598 * more than one conditional check. The post-run side of our code shall determine
10599 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10600 */
10601 if (pVmcsInfo->pbVirtApic)
10602 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10603
10604 /*
10605 * Update the host MSRs values in the VM-exit MSR-load area.
10606 */
10607 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10608 {
10609 if (pVmcsInfo->cExitMsrLoad > 0)
10610 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10611 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10612 }
10613
10614 /*
10615 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10616 * VMX-preemption timer based on the next virtual sync clock deadline.
10617 */
10618 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10619 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10620 {
10621 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10622 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10623 }
10624
10625 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
10626 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
10627 if (!fIsRdtscIntercepted)
10628 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
10629 else
10630 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
10631
10632 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10633 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10634 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10635 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
10636 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
10637 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
10638
10639 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10640
10641 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10642 as we're about to start executing the guest. */
10643
10644 /*
10645 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10646 *
10647 * This is done this late as updating the TSC offsetting/preemption timer above
10648 * figures out if we can skip intercepting RDTSCP by calculating the number of
10649 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10650 */
10651 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10652 && !fIsRdtscIntercepted)
10653 {
10654 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10655
10656 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
10657 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
10658 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10659 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10660 AssertRC(rc);
10661 Assert(!pVmxTransient->fRemoveTscAuxMsr);
10662 pVmxTransient->fRemoveTscAuxMsr = true;
10663 }
10664
10665#ifdef VBOX_STRICT
10666 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
10667 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
10668 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10669 AssertRC(hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
10670#endif
10671
10672#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10673 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10674 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
10675 * see @bugref{9180#c54}. */
10676 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10677 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10678 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10679#endif
10680}
10681
10682
10683/**
10684 * First C routine invoked after running guest code using hardware-assisted VMX.
10685 *
10686 * @param pVCpu The cross context virtual CPU structure.
10687 * @param pVmxTransient The VMX-transient structure.
10688 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10689 *
10690 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10691 *
10692 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10693 * unconditionally when it is safe to do so.
10694 */
10695static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10696{
10697 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10698
10699 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10700 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10701 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10702 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10703 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10704 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10705
10706 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10707 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10708 {
10709 uint64_t uGstTsc;
10710 if (!pVmxTransient->fIsNestedGuest)
10711 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10712 else
10713 {
10714 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10715 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
10716 }
10717 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
10718 }
10719
10720 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
10721 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
10722 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10723
10724 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
10725 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
10726#ifdef VBOX_STRICT
10727 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
10728#endif
10729 Assert(!ASMIntAreEnabled());
10730 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
10731 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10732
10733#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
10734 /*
10735 * Clean all the VMCS fields in the transient structure before reading
10736 * anything from the VMCS.
10737 */
10738 pVmxTransient->uExitReason = 0;
10739 pVmxTransient->uExitIntErrorCode = 0;
10740 pVmxTransient->uExitQual = 0;
10741 pVmxTransient->uGuestLinearAddr = 0;
10742 pVmxTransient->uExitIntInfo = 0;
10743 pVmxTransient->cbExitInstr = 0;
10744 pVmxTransient->ExitInstrInfo.u = 0;
10745 pVmxTransient->uEntryIntInfo = 0;
10746 pVmxTransient->uEntryXcptErrorCode = 0;
10747 pVmxTransient->cbEntryInstr = 0;
10748 pVmxTransient->uIdtVectoringInfo = 0;
10749 pVmxTransient->uIdtVectoringErrorCode = 0;
10750#endif
10751
10752 /*
10753 * Save the basic VM-exit reason and check if the VM-entry failed.
10754 * See Intel spec. 24.9.1 "Basic VM-exit Information".
10755 */
10756 uint32_t uExitReason;
10757 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
10758 AssertRC(rc);
10759 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
10760 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
10761
10762 /*
10763 * Log the VM-exit before logging anything else as otherwise it might be a
10764 * tad confusing what happens before and after the world-switch.
10765 */
10766 HMVMX_LOG_EXIT(pVCpu, uExitReason);
10767
10768 /*
10769 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
10770 * bitmap permissions, if it was added before VM-entry.
10771 */
10772 if (pVmxTransient->fRemoveTscAuxMsr)
10773 {
10774 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
10775 pVmxTransient->fRemoveTscAuxMsr = false;
10776 }
10777
10778 /*
10779 * Check if VMLAUNCH/VMRESUME succeeded.
10780 * If this failed, we cause a guru meditation and cease further execution.
10781 *
10782 * However, if we are executing a nested-guest we might fail if we use the
10783 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
10784 */
10785 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
10786 {
10787 /*
10788 * Update the VM-exit history array here even if the VM-entry failed due to:
10789 * - Invalid guest state.
10790 * - MSR loading.
10791 * - Machine-check event.
10792 *
10793 * In any of the above cases we will still have a "valid" VM-exit reason
10794 * despite @a fVMEntryFailed being false.
10795 *
10796 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
10797 *
10798 * Note! We don't have CS or RIP at this point. Will probably address that later
10799 * by amending the history entry added here.
10800 */
10801 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
10802 UINT64_MAX, uHostTsc);
10803
10804 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
10805 {
10806 VMMRZCallRing3Enable(pVCpu);
10807
10808 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10809 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10810
10811#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
10812 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
10813#endif
10814#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
10815 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
10816 AssertRC(rc);
10817#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
10818 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
10819 AssertRC(rc);
10820#else
10821 /*
10822 * Import the guest-interruptibility state always as we need it while evaluating
10823 * injecting events on re-entry.
10824 *
10825 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
10826 * checking for real-mode while exporting the state because all bits that cause
10827 * mode changes wrt CR0 are intercepted.
10828 */
10829 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
10830 AssertRC(rc);
10831#endif
10832
10833 /*
10834 * Sync the TPR shadow with our APIC state.
10835 */
10836 if ( !pVmxTransient->fIsNestedGuest
10837 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
10838 {
10839 Assert(pVmcsInfo->pbVirtApic);
10840 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
10841 {
10842 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
10843 AssertRC(rc);
10844 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
10845 }
10846 }
10847
10848 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10849 return;
10850 }
10851 }
10852#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10853 else if (pVmxTransient->fIsNestedGuest)
10854 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
10855#endif
10856 else
10857 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
10858
10859 VMMRZCallRing3Enable(pVCpu);
10860}
10861
10862
10863/**
10864 * Runs the guest code using hardware-assisted VMX the normal way.
10865 *
10866 * @returns VBox status code.
10867 * @param pVCpu The cross context virtual CPU structure.
10868 * @param pcLoops Pointer to the number of executed loops.
10869 */
10870static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
10871{
10872 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10873 Assert(pcLoops);
10874 Assert(*pcLoops <= cMaxResumeLoops);
10875 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10876
10877#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10878 /*
10879 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
10880 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
10881 * guest VMCS while entering the VMX ring-0 session.
10882 */
10883 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10884 {
10885 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
10886 if (RT_SUCCESS(rc))
10887 { /* likely */ }
10888 else
10889 {
10890 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
10891 return rc;
10892 }
10893 }
10894#endif
10895
10896 VMXTRANSIENT VmxTransient;
10897 RT_ZERO(VmxTransient);
10898 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10899
10900 /* Paranoia. */
10901 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
10902
10903 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10904 for (;;)
10905 {
10906 Assert(!HMR0SuspendPending());
10907 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10908 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10909
10910 /*
10911 * Preparatory work for running nested-guest code, this may force us to
10912 * return to ring-3.
10913 *
10914 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10915 */
10916 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10917 if (rcStrict != VINF_SUCCESS)
10918 break;
10919
10920 /* Interrupts are disabled at this point! */
10921 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10922 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10923 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10924 /* Interrupts are re-enabled at this point! */
10925
10926 /*
10927 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10928 */
10929 if (RT_SUCCESS(rcRun))
10930 { /* very likely */ }
10931 else
10932 {
10933 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10934 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10935 return rcRun;
10936 }
10937
10938 /*
10939 * Profile the VM-exit.
10940 */
10941 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10942 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10943 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10944 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10945 HMVMX_START_EXIT_DISPATCH_PROF();
10946
10947 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10948
10949 /*
10950 * Handle the VM-exit.
10951 */
10952#ifdef HMVMX_USE_FUNCTION_TABLE
10953 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
10954#else
10955 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
10956#endif
10957 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10958 if (rcStrict == VINF_SUCCESS)
10959 {
10960 if (++(*pcLoops) <= cMaxResumeLoops)
10961 continue;
10962 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10963 rcStrict = VINF_EM_RAW_INTERRUPT;
10964 }
10965 break;
10966 }
10967
10968 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10969 return rcStrict;
10970}
10971
10972
10973#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10974/**
10975 * Runs the nested-guest code using hardware-assisted VMX.
10976 *
10977 * @returns VBox status code.
10978 * @param pVCpu The cross context virtual CPU structure.
10979 * @param pcLoops Pointer to the number of executed loops.
10980 *
10981 * @sa hmR0VmxRunGuestCodeNormal.
10982 */
10983static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
10984{
10985 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10986 Assert(pcLoops);
10987 Assert(*pcLoops <= cMaxResumeLoops);
10988 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10989
10990 /*
10991 * Switch to the nested-guest VMCS as we may have transitioned from executing the
10992 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
10993 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
10994 */
10995 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10996 {
10997 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
10998 if (RT_SUCCESS(rc))
10999 { /* likely */ }
11000 else
11001 {
11002 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11003 return rc;
11004 }
11005 }
11006
11007 VMXTRANSIENT VmxTransient;
11008 RT_ZERO(VmxTransient);
11009 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11010 VmxTransient.fIsNestedGuest = true;
11011
11012 /* Paranoia. */
11013 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11014
11015 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11016 for (;;)
11017 {
11018 Assert(!HMR0SuspendPending());
11019 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11020 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11021
11022 /*
11023 * Preparatory work for running guest code, this may force us to
11024 * return to ring-3.
11025 *
11026 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11027 */
11028 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11029 if (rcStrict != VINF_SUCCESS)
11030 break;
11031
11032 /* Interrupts are disabled at this point! */
11033 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11034 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11035 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11036 /* Interrupts are re-enabled at this point! */
11037
11038 /*
11039 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11040 */
11041 if (RT_SUCCESS(rcRun))
11042 { /* very likely */ }
11043 else
11044 {
11045 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11046 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11047 return rcRun;
11048 }
11049
11050 /*
11051 * Profile the VM-exit.
11052 */
11053 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11054 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11055 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11056 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11057 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11058 HMVMX_START_EXIT_DISPATCH_PROF();
11059
11060 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11061
11062 /*
11063 * Handle the VM-exit.
11064 */
11065 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11066 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11067 if (rcStrict == VINF_SUCCESS)
11068 {
11069 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11070 {
11071 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11072 rcStrict = VINF_VMX_VMEXIT;
11073 }
11074 else
11075 {
11076 if (++(*pcLoops) <= cMaxResumeLoops)
11077 continue;
11078 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11079 rcStrict = VINF_EM_RAW_INTERRUPT;
11080 }
11081 }
11082 else
11083 Assert(rcStrict != VINF_VMX_VMEXIT);
11084 break;
11085 }
11086
11087 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11088 return rcStrict;
11089}
11090#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11091
11092
11093/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11094 * probes.
11095 *
11096 * The following few functions and associated structure contains the bloat
11097 * necessary for providing detailed debug events and dtrace probes as well as
11098 * reliable host side single stepping. This works on the principle of
11099 * "subclassing" the normal execution loop and workers. We replace the loop
11100 * method completely and override selected helpers to add necessary adjustments
11101 * to their core operation.
11102 *
11103 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11104 * any performance for debug and analysis features.
11105 *
11106 * @{
11107 */
11108
11109/**
11110 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11111 * the debug run loop.
11112 */
11113typedef struct VMXRUNDBGSTATE
11114{
11115 /** The RIP we started executing at. This is for detecting that we stepped. */
11116 uint64_t uRipStart;
11117 /** The CS we started executing with. */
11118 uint16_t uCsStart;
11119
11120 /** Whether we've actually modified the 1st execution control field. */
11121 bool fModifiedProcCtls : 1;
11122 /** Whether we've actually modified the 2nd execution control field. */
11123 bool fModifiedProcCtls2 : 1;
11124 /** Whether we've actually modified the exception bitmap. */
11125 bool fModifiedXcptBitmap : 1;
11126
11127 /** We desire the modified the CR0 mask to be cleared. */
11128 bool fClearCr0Mask : 1;
11129 /** We desire the modified the CR4 mask to be cleared. */
11130 bool fClearCr4Mask : 1;
11131 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11132 uint32_t fCpe1Extra;
11133 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11134 uint32_t fCpe1Unwanted;
11135 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11136 uint32_t fCpe2Extra;
11137 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11138 uint32_t bmXcptExtra;
11139 /** The sequence number of the Dtrace provider settings the state was
11140 * configured against. */
11141 uint32_t uDtraceSettingsSeqNo;
11142 /** VM-exits to check (one bit per VM-exit). */
11143 uint32_t bmExitsToCheck[3];
11144
11145 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11146 uint32_t fProcCtlsInitial;
11147 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11148 uint32_t fProcCtls2Initial;
11149 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11150 uint32_t bmXcptInitial;
11151} VMXRUNDBGSTATE;
11152AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11153typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11154
11155
11156/**
11157 * Initializes the VMXRUNDBGSTATE structure.
11158 *
11159 * @param pVCpu The cross context virtual CPU structure of the
11160 * calling EMT.
11161 * @param pVmxTransient The VMX-transient structure.
11162 * @param pDbgState The debug state to initialize.
11163 */
11164static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11165{
11166 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11167 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11168
11169 pDbgState->fModifiedProcCtls = false;
11170 pDbgState->fModifiedProcCtls2 = false;
11171 pDbgState->fModifiedXcptBitmap = false;
11172 pDbgState->fClearCr0Mask = false;
11173 pDbgState->fClearCr4Mask = false;
11174 pDbgState->fCpe1Extra = 0;
11175 pDbgState->fCpe1Unwanted = 0;
11176 pDbgState->fCpe2Extra = 0;
11177 pDbgState->bmXcptExtra = 0;
11178 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11179 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11180 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11181}
11182
11183
11184/**
11185 * Updates the VMSC fields with changes requested by @a pDbgState.
11186 *
11187 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11188 * immediately before executing guest code, i.e. when interrupts are disabled.
11189 * We don't check status codes here as we cannot easily assert or return in the
11190 * latter case.
11191 *
11192 * @param pVCpu The cross context virtual CPU structure.
11193 * @param pVmxTransient The VMX-transient structure.
11194 * @param pDbgState The debug state.
11195 */
11196static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11197{
11198 /*
11199 * Ensure desired flags in VMCS control fields are set.
11200 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11201 *
11202 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11203 * there should be no stale data in pCtx at this point.
11204 */
11205 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11206 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11207 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11208 {
11209 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11210 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11211 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11212 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11213 pDbgState->fModifiedProcCtls = true;
11214 }
11215
11216 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11217 {
11218 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11219 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11220 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11221 pDbgState->fModifiedProcCtls2 = true;
11222 }
11223
11224 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11225 {
11226 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11227 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11228 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11229 pDbgState->fModifiedXcptBitmap = true;
11230 }
11231
11232 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11233 {
11234 pVmcsInfo->u64Cr0Mask = 0;
11235 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11236 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11237 }
11238
11239 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11240 {
11241 pVmcsInfo->u64Cr4Mask = 0;
11242 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11243 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11244 }
11245
11246 NOREF(pVCpu);
11247}
11248
11249
11250/**
11251 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11252 * re-entry next time around.
11253 *
11254 * @returns Strict VBox status code (i.e. informational status codes too).
11255 * @param pVCpu The cross context virtual CPU structure.
11256 * @param pVmxTransient The VMX-transient structure.
11257 * @param pDbgState The debug state.
11258 * @param rcStrict The return code from executing the guest using single
11259 * stepping.
11260 */
11261static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11262 VBOXSTRICTRC rcStrict)
11263{
11264 /*
11265 * Restore VM-exit control settings as we may not reenter this function the
11266 * next time around.
11267 */
11268 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11269
11270 /* We reload the initial value, trigger what we can of recalculations the
11271 next time around. From the looks of things, that's all that's required atm. */
11272 if (pDbgState->fModifiedProcCtls)
11273 {
11274 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11275 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11276 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11277 AssertRC(rc2);
11278 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11279 }
11280
11281 /* We're currently the only ones messing with this one, so just restore the
11282 cached value and reload the field. */
11283 if ( pDbgState->fModifiedProcCtls2
11284 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11285 {
11286 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11287 AssertRC(rc2);
11288 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11289 }
11290
11291 /* If we've modified the exception bitmap, we restore it and trigger
11292 reloading and partial recalculation the next time around. */
11293 if (pDbgState->fModifiedXcptBitmap)
11294 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11295
11296 return rcStrict;
11297}
11298
11299
11300/**
11301 * Configures VM-exit controls for current DBGF and DTrace settings.
11302 *
11303 * This updates @a pDbgState and the VMCS execution control fields to reflect
11304 * the necessary VM-exits demanded by DBGF and DTrace.
11305 *
11306 * @param pVCpu The cross context virtual CPU structure.
11307 * @param pVmxTransient The VMX-transient structure. May update
11308 * fUpdatedTscOffsettingAndPreemptTimer.
11309 * @param pDbgState The debug state.
11310 */
11311static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11312{
11313 /*
11314 * Take down the dtrace serial number so we can spot changes.
11315 */
11316 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11317 ASMCompilerBarrier();
11318
11319 /*
11320 * We'll rebuild most of the middle block of data members (holding the
11321 * current settings) as we go along here, so start by clearing it all.
11322 */
11323 pDbgState->bmXcptExtra = 0;
11324 pDbgState->fCpe1Extra = 0;
11325 pDbgState->fCpe1Unwanted = 0;
11326 pDbgState->fCpe2Extra = 0;
11327 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11328 pDbgState->bmExitsToCheck[i] = 0;
11329
11330 /*
11331 * Software interrupts (INT XXh) - no idea how to trigger these...
11332 */
11333 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11334 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11335 || VBOXVMM_INT_SOFTWARE_ENABLED())
11336 {
11337 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11338 }
11339
11340 /*
11341 * INT3 breakpoints - triggered by #BP exceptions.
11342 */
11343 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11344 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11345
11346 /*
11347 * Exception bitmap and XCPT events+probes.
11348 */
11349 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11350 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11351 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11352
11353 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11354 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11355 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11356 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11357 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11358 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11359 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11360 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11361 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11362 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11363 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11364 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11365 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11366 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11367 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11368 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11369 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11370 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11371
11372 if (pDbgState->bmXcptExtra)
11373 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11374
11375 /*
11376 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11377 *
11378 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11379 * So, when adding/changing/removing please don't forget to update it.
11380 *
11381 * Some of the macros are picking up local variables to save horizontal space,
11382 * (being able to see it in a table is the lesser evil here).
11383 */
11384#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11385 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11386 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11387#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11388 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11389 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11390 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11391 } else do { } while (0)
11392#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11393 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11394 { \
11395 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11396 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11397 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11398 } else do { } while (0)
11399#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11400 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11401 { \
11402 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11403 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11404 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11405 } else do { } while (0)
11406#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11407 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11408 { \
11409 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11410 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11411 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11412 } else do { } while (0)
11413
11414 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11415 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11416 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11417 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11418 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11419
11420 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11421 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11422 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11423 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11424 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11425 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11426 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11427 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11428 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11429 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11430 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11431 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11432 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11433 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11434 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11435 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11436 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11437 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11438 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11439 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11440 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11441 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11442 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11443 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11444 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11445 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11446 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11447 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11448 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11449 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11450 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11451 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11452 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11453 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11454 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11455 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11456
11457 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11458 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11459 {
11460 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11461 | CPUMCTX_EXTRN_APIC_TPR);
11462 AssertRC(rc);
11463
11464#if 0 /** @todo fix me */
11465 pDbgState->fClearCr0Mask = true;
11466 pDbgState->fClearCr4Mask = true;
11467#endif
11468 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11469 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11470 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11471 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11472 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11473 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11474 require clearing here and in the loop if we start using it. */
11475 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11476 }
11477 else
11478 {
11479 if (pDbgState->fClearCr0Mask)
11480 {
11481 pDbgState->fClearCr0Mask = false;
11482 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11483 }
11484 if (pDbgState->fClearCr4Mask)
11485 {
11486 pDbgState->fClearCr4Mask = false;
11487 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11488 }
11489 }
11490 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11491 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11492
11493 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11494 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11495 {
11496 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11497 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11498 }
11499 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11500 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11501
11502 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11503 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11504 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11505 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11506 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11507 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11508 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11509 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11510#if 0 /** @todo too slow, fix handler. */
11511 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11512#endif
11513 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11514
11515 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11516 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11517 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11518 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11519 {
11520 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11521 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11522 }
11523 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11524 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11525 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11526 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11527
11528 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11529 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11530 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11531 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11532 {
11533 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11534 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11535 }
11536 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11537 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11538 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11539 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11540
11541 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11542 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11543 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11544 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11545 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11546 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11547 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11548 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11549 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11550 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11551 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11552 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11553 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11554 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11555 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11556 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11557 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11558 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11559 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11560 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11561 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11562 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11563
11564#undef IS_EITHER_ENABLED
11565#undef SET_ONLY_XBM_IF_EITHER_EN
11566#undef SET_CPE1_XBM_IF_EITHER_EN
11567#undef SET_CPEU_XBM_IF_EITHER_EN
11568#undef SET_CPE2_XBM_IF_EITHER_EN
11569
11570 /*
11571 * Sanitize the control stuff.
11572 */
11573 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11574 if (pDbgState->fCpe2Extra)
11575 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11576 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11577 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11578 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11579 {
11580 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11581 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11582 }
11583
11584 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11585 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11586 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11587 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11588}
11589
11590
11591/**
11592 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11593 * appropriate.
11594 *
11595 * The caller has checked the VM-exit against the
11596 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11597 * already, so we don't have to do that either.
11598 *
11599 * @returns Strict VBox status code (i.e. informational status codes too).
11600 * @param pVCpu The cross context virtual CPU structure.
11601 * @param pVmxTransient The VMX-transient structure.
11602 * @param uExitReason The VM-exit reason.
11603 *
11604 * @remarks The name of this function is displayed by dtrace, so keep it short
11605 * and to the point. No longer than 33 chars long, please.
11606 */
11607static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11608{
11609 /*
11610 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11611 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11612 *
11613 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11614 * does. Must add/change/remove both places. Same ordering, please.
11615 *
11616 * Added/removed events must also be reflected in the next section
11617 * where we dispatch dtrace events.
11618 */
11619 bool fDtrace1 = false;
11620 bool fDtrace2 = false;
11621 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11622 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11623 uint32_t uEventArg = 0;
11624#define SET_EXIT(a_EventSubName) \
11625 do { \
11626 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11627 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11628 } while (0)
11629#define SET_BOTH(a_EventSubName) \
11630 do { \
11631 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11632 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11633 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11634 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11635 } while (0)
11636 switch (uExitReason)
11637 {
11638 case VMX_EXIT_MTF:
11639 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11640
11641 case VMX_EXIT_XCPT_OR_NMI:
11642 {
11643 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11644 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11645 {
11646 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11647 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11648 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11649 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11650 {
11651 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11652 {
11653 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11654 uEventArg = pVmxTransient->uExitIntErrorCode;
11655 }
11656 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11657 switch (enmEvent1)
11658 {
11659 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11660 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11661 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11662 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11663 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11664 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11665 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11666 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11667 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11668 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11669 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11670 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11671 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11672 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11673 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11674 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11675 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11676 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11677 default: break;
11678 }
11679 }
11680 else
11681 AssertFailed();
11682 break;
11683
11684 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11685 uEventArg = idxVector;
11686 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11687 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11688 break;
11689 }
11690 break;
11691 }
11692
11693 case VMX_EXIT_TRIPLE_FAULT:
11694 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11695 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11696 break;
11697 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11698 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11699 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11700 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11701 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11702
11703 /* Instruction specific VM-exits: */
11704 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11705 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11706 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11707 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11708 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11709 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11710 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11711 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
11712 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
11713 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
11714 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
11715 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
11716 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
11717 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
11718 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
11719 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
11720 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
11721 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
11722 case VMX_EXIT_MOV_CRX:
11723 hmR0VmxReadExitQualVmcs(pVmxTransient);
11724 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
11725 SET_BOTH(CRX_READ);
11726 else
11727 SET_BOTH(CRX_WRITE);
11728 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
11729 break;
11730 case VMX_EXIT_MOV_DRX:
11731 hmR0VmxReadExitQualVmcs(pVmxTransient);
11732 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
11733 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
11734 SET_BOTH(DRX_READ);
11735 else
11736 SET_BOTH(DRX_WRITE);
11737 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
11738 break;
11739 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
11740 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
11741 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
11742 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
11743 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
11744 case VMX_EXIT_GDTR_IDTR_ACCESS:
11745 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11746 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
11747 {
11748 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
11749 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
11750 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
11751 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
11752 }
11753 break;
11754
11755 case VMX_EXIT_LDTR_TR_ACCESS:
11756 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11757 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
11758 {
11759 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
11760 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
11761 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
11762 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
11763 }
11764 break;
11765
11766 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
11767 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
11768 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
11769 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
11770 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
11771 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
11772 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
11773 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
11774 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
11775 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
11776 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
11777
11778 /* Events that aren't relevant at this point. */
11779 case VMX_EXIT_EXT_INT:
11780 case VMX_EXIT_INT_WINDOW:
11781 case VMX_EXIT_NMI_WINDOW:
11782 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11783 case VMX_EXIT_PREEMPT_TIMER:
11784 case VMX_EXIT_IO_INSTR:
11785 break;
11786
11787 /* Errors and unexpected events. */
11788 case VMX_EXIT_INIT_SIGNAL:
11789 case VMX_EXIT_SIPI:
11790 case VMX_EXIT_IO_SMI:
11791 case VMX_EXIT_SMI:
11792 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11793 case VMX_EXIT_ERR_MSR_LOAD:
11794 case VMX_EXIT_ERR_MACHINE_CHECK:
11795 case VMX_EXIT_PML_FULL:
11796 case VMX_EXIT_VIRTUALIZED_EOI:
11797 break;
11798
11799 default:
11800 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
11801 break;
11802 }
11803#undef SET_BOTH
11804#undef SET_EXIT
11805
11806 /*
11807 * Dtrace tracepoints go first. We do them here at once so we don't
11808 * have to copy the guest state saving and stuff a few dozen times.
11809 * Down side is that we've got to repeat the switch, though this time
11810 * we use enmEvent since the probes are a subset of what DBGF does.
11811 */
11812 if (fDtrace1 || fDtrace2)
11813 {
11814 hmR0VmxReadExitQualVmcs(pVmxTransient);
11815 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11816 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
11817 switch (enmEvent1)
11818 {
11819 /** @todo consider which extra parameters would be helpful for each probe. */
11820 case DBGFEVENT_END: break;
11821 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
11822 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
11823 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
11824 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
11825 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
11826 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
11827 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
11828 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
11829 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
11830 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
11831 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
11832 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
11833 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
11834 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
11835 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
11836 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
11837 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
11838 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
11839 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11840 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11841 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
11842 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
11843 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
11844 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
11845 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
11846 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
11847 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
11848 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11849 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11850 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11851 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11852 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11853 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
11854 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11855 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
11856 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
11857 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
11858 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
11859 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
11860 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
11861 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
11862 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
11863 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
11864 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
11865 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
11866 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
11867 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
11868 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
11869 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
11870 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
11871 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
11872 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
11873 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
11874 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
11875 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
11876 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
11877 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
11878 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
11879 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
11880 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
11881 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
11882 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
11883 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
11884 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
11885 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
11886 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
11887 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
11888 }
11889 switch (enmEvent2)
11890 {
11891 /** @todo consider which extra parameters would be helpful for each probe. */
11892 case DBGFEVENT_END: break;
11893 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
11894 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11895 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
11896 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
11897 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
11898 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
11899 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
11900 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
11901 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
11902 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11903 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11904 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11905 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11906 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11907 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
11908 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11909 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
11910 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
11911 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
11912 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
11913 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
11914 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
11915 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
11916 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
11917 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
11918 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
11919 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
11920 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
11921 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
11922 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
11923 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
11924 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
11925 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
11926 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
11927 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
11928 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
11929 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
11930 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
11931 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
11932 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
11933 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
11934 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
11935 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
11936 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
11937 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
11938 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
11939 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
11940 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
11941 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
11942 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
11943 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
11944 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
11945 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
11946 }
11947 }
11948
11949 /*
11950 * Fire of the DBGF event, if enabled (our check here is just a quick one,
11951 * the DBGF call will do a full check).
11952 *
11953 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
11954 * Note! If we have to events, we prioritize the first, i.e. the instruction
11955 * one, in order to avoid event nesting.
11956 */
11957 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11958 if ( enmEvent1 != DBGFEVENT_END
11959 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
11960 {
11961 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11962 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
11963 if (rcStrict != VINF_SUCCESS)
11964 return rcStrict;
11965 }
11966 else if ( enmEvent2 != DBGFEVENT_END
11967 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
11968 {
11969 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11970 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
11971 if (rcStrict != VINF_SUCCESS)
11972 return rcStrict;
11973 }
11974
11975 return VINF_SUCCESS;
11976}
11977
11978
11979/**
11980 * Single-stepping VM-exit filtering.
11981 *
11982 * This is preprocessing the VM-exits and deciding whether we've gotten far
11983 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
11984 * handling is performed.
11985 *
11986 * @returns Strict VBox status code (i.e. informational status codes too).
11987 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
11988 * @param pVmxTransient The VMX-transient structure.
11989 * @param pDbgState The debug state.
11990 */
11991DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11992{
11993 /*
11994 * Expensive (saves context) generic dtrace VM-exit probe.
11995 */
11996 uint32_t const uExitReason = pVmxTransient->uExitReason;
11997 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
11998 { /* more likely */ }
11999 else
12000 {
12001 hmR0VmxReadExitQualVmcs(pVmxTransient);
12002 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12003 AssertRC(rc);
12004 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12005 }
12006
12007 /*
12008 * Check for host NMI, just to get that out of the way.
12009 */
12010 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12011 { /* normally likely */ }
12012 else
12013 {
12014 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12015 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12016 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12017 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12018 }
12019
12020 /*
12021 * Check for single stepping event if we're stepping.
12022 */
12023 if (pVCpu->hm.s.fSingleInstruction)
12024 {
12025 switch (uExitReason)
12026 {
12027 case VMX_EXIT_MTF:
12028 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12029
12030 /* Various events: */
12031 case VMX_EXIT_XCPT_OR_NMI:
12032 case VMX_EXIT_EXT_INT:
12033 case VMX_EXIT_TRIPLE_FAULT:
12034 case VMX_EXIT_INT_WINDOW:
12035 case VMX_EXIT_NMI_WINDOW:
12036 case VMX_EXIT_TASK_SWITCH:
12037 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12038 case VMX_EXIT_APIC_ACCESS:
12039 case VMX_EXIT_EPT_VIOLATION:
12040 case VMX_EXIT_EPT_MISCONFIG:
12041 case VMX_EXIT_PREEMPT_TIMER:
12042
12043 /* Instruction specific VM-exits: */
12044 case VMX_EXIT_CPUID:
12045 case VMX_EXIT_GETSEC:
12046 case VMX_EXIT_HLT:
12047 case VMX_EXIT_INVD:
12048 case VMX_EXIT_INVLPG:
12049 case VMX_EXIT_RDPMC:
12050 case VMX_EXIT_RDTSC:
12051 case VMX_EXIT_RSM:
12052 case VMX_EXIT_VMCALL:
12053 case VMX_EXIT_VMCLEAR:
12054 case VMX_EXIT_VMLAUNCH:
12055 case VMX_EXIT_VMPTRLD:
12056 case VMX_EXIT_VMPTRST:
12057 case VMX_EXIT_VMREAD:
12058 case VMX_EXIT_VMRESUME:
12059 case VMX_EXIT_VMWRITE:
12060 case VMX_EXIT_VMXOFF:
12061 case VMX_EXIT_VMXON:
12062 case VMX_EXIT_MOV_CRX:
12063 case VMX_EXIT_MOV_DRX:
12064 case VMX_EXIT_IO_INSTR:
12065 case VMX_EXIT_RDMSR:
12066 case VMX_EXIT_WRMSR:
12067 case VMX_EXIT_MWAIT:
12068 case VMX_EXIT_MONITOR:
12069 case VMX_EXIT_PAUSE:
12070 case VMX_EXIT_GDTR_IDTR_ACCESS:
12071 case VMX_EXIT_LDTR_TR_ACCESS:
12072 case VMX_EXIT_INVEPT:
12073 case VMX_EXIT_RDTSCP:
12074 case VMX_EXIT_INVVPID:
12075 case VMX_EXIT_WBINVD:
12076 case VMX_EXIT_XSETBV:
12077 case VMX_EXIT_RDRAND:
12078 case VMX_EXIT_INVPCID:
12079 case VMX_EXIT_VMFUNC:
12080 case VMX_EXIT_RDSEED:
12081 case VMX_EXIT_XSAVES:
12082 case VMX_EXIT_XRSTORS:
12083 {
12084 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12085 AssertRCReturn(rc, rc);
12086 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12087 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12088 return VINF_EM_DBG_STEPPED;
12089 break;
12090 }
12091
12092 /* Errors and unexpected events: */
12093 case VMX_EXIT_INIT_SIGNAL:
12094 case VMX_EXIT_SIPI:
12095 case VMX_EXIT_IO_SMI:
12096 case VMX_EXIT_SMI:
12097 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12098 case VMX_EXIT_ERR_MSR_LOAD:
12099 case VMX_EXIT_ERR_MACHINE_CHECK:
12100 case VMX_EXIT_PML_FULL:
12101 case VMX_EXIT_VIRTUALIZED_EOI:
12102 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12103 break;
12104
12105 default:
12106 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12107 break;
12108 }
12109 }
12110
12111 /*
12112 * Check for debugger event breakpoints and dtrace probes.
12113 */
12114 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12115 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12116 {
12117 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12118 if (rcStrict != VINF_SUCCESS)
12119 return rcStrict;
12120 }
12121
12122 /*
12123 * Normal processing.
12124 */
12125#ifdef HMVMX_USE_FUNCTION_TABLE
12126 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12127#else
12128 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12129#endif
12130}
12131
12132
12133/**
12134 * Single steps guest code using hardware-assisted VMX.
12135 *
12136 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12137 * but single-stepping through the hypervisor debugger.
12138 *
12139 * @returns Strict VBox status code (i.e. informational status codes too).
12140 * @param pVCpu The cross context virtual CPU structure.
12141 * @param pcLoops Pointer to the number of executed loops.
12142 *
12143 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12144 */
12145static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12146{
12147 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12148 Assert(pcLoops);
12149 Assert(*pcLoops <= cMaxResumeLoops);
12150
12151 VMXTRANSIENT VmxTransient;
12152 RT_ZERO(VmxTransient);
12153 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12154
12155 /* Set HMCPU indicators. */
12156 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12157 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12158 pVCpu->hm.s.fDebugWantRdTscExit = false;
12159 pVCpu->hm.s.fUsingDebugLoop = true;
12160
12161 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12162 VMXRUNDBGSTATE DbgState;
12163 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12164 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12165
12166 /*
12167 * The loop.
12168 */
12169 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12170 for (;;)
12171 {
12172 Assert(!HMR0SuspendPending());
12173 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12174 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12175 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12176
12177 /* Set up VM-execution controls the next two can respond to. */
12178 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12179
12180 /*
12181 * Preparatory work for running guest code, this may force us to
12182 * return to ring-3.
12183 *
12184 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12185 */
12186 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12187 if (rcStrict != VINF_SUCCESS)
12188 break;
12189
12190 /* Interrupts are disabled at this point! */
12191 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12192
12193 /* Override any obnoxious code in the above two calls. */
12194 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12195
12196 /*
12197 * Finally execute the guest.
12198 */
12199 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12200
12201 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12202 /* Interrupts are re-enabled at this point! */
12203
12204 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12205 if (RT_SUCCESS(rcRun))
12206 { /* very likely */ }
12207 else
12208 {
12209 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12210 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12211 return rcRun;
12212 }
12213
12214 /* Profile the VM-exit. */
12215 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12216 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12217 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12218 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12219 HMVMX_START_EXIT_DISPATCH_PROF();
12220
12221 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12222
12223 /*
12224 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12225 */
12226 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12227 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12228 if (rcStrict != VINF_SUCCESS)
12229 break;
12230 if (++(*pcLoops) > cMaxResumeLoops)
12231 {
12232 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12233 rcStrict = VINF_EM_RAW_INTERRUPT;
12234 break;
12235 }
12236
12237 /*
12238 * Stepping: Did the RIP change, if so, consider it a single step.
12239 * Otherwise, make sure one of the TFs gets set.
12240 */
12241 if (fStepping)
12242 {
12243 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12244 AssertRC(rc);
12245 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12246 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12247 {
12248 rcStrict = VINF_EM_DBG_STEPPED;
12249 break;
12250 }
12251 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12252 }
12253
12254 /*
12255 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12256 */
12257 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12258 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12259 }
12260
12261 /*
12262 * Clear the X86_EFL_TF if necessary.
12263 */
12264 if (pVCpu->hm.s.fClearTrapFlag)
12265 {
12266 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12267 AssertRC(rc);
12268 pVCpu->hm.s.fClearTrapFlag = false;
12269 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12270 }
12271 /** @todo there seems to be issues with the resume flag when the monitor trap
12272 * flag is pending without being used. Seen early in bios init when
12273 * accessing APIC page in protected mode. */
12274
12275 /*
12276 * Restore VM-exit control settings as we may not re-enter this function the
12277 * next time around.
12278 */
12279 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12280
12281 /* Restore HMCPU indicators. */
12282 pVCpu->hm.s.fUsingDebugLoop = false;
12283 pVCpu->hm.s.fDebugWantRdTscExit = false;
12284 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12285
12286 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12287 return rcStrict;
12288}
12289
12290
12291/** @} */
12292
12293
12294/**
12295 * Checks if any expensive dtrace probes are enabled and we should go to the
12296 * debug loop.
12297 *
12298 * @returns true if we should use debug loop, false if not.
12299 */
12300static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12301{
12302 /* It's probably faster to OR the raw 32-bit counter variables together.
12303 Since the variables are in an array and the probes are next to one
12304 another (more or less), we have good locality. So, better read
12305 eight-nine cache lines ever time and only have one conditional, than
12306 128+ conditionals, right? */
12307 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12308 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12309 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12310 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12311 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12312 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12313 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12314 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12315 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12316 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12317 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12318 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12319 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12320 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12321 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12322 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12323 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12324 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12325 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12326 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12327 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12328 ) != 0
12329 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12330 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12331 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12332 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12333 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12334 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12335 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12336 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12337 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12338 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12339 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12340 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12341 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12342 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12343 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12344 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12345 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12346 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12347 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12348 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12349 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12350 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12351 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12352 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12353 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12354 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12355 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12356 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12357 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12358 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12359 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12360 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12361 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12362 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12363 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12364 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12365 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12366 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12367 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12368 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12369 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12370 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12371 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12372 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12373 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12374 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12375 ) != 0
12376 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12377 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12378 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12379 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12380 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12381 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12382 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12383 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12384 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12385 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12386 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12387 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12388 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12389 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12390 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12391 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12392 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12393 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12394 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12395 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12396 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12397 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12398 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12399 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12400 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12401 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12402 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12403 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12404 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12405 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12406 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12407 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12408 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12409 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12410 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12411 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12412 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12413 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12414 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12415 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12416 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12417 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12418 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12419 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12420 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12421 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12422 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12423 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12424 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12425 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12426 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12427 ) != 0;
12428}
12429
12430
12431/**
12432 * Runs the guest using hardware-assisted VMX.
12433 *
12434 * @returns Strict VBox status code (i.e. informational status codes too).
12435 * @param pVCpu The cross context virtual CPU structure.
12436 */
12437VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12438{
12439 AssertPtr(pVCpu);
12440 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12441 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12442 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12443 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12444
12445 VBOXSTRICTRC rcStrict;
12446 uint32_t cLoops = 0;
12447 for (;;)
12448 {
12449#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12450 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12451#else
12452 NOREF(pCtx);
12453 bool const fInNestedGuestMode = false;
12454#endif
12455 if (!fInNestedGuestMode)
12456 {
12457 if ( !pVCpu->hm.s.fUseDebugLoop
12458 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12459 && !DBGFIsStepping(pVCpu)
12460 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12461 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12462 else
12463 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12464 }
12465#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12466 else
12467 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12468
12469 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12470 {
12471 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12472 continue;
12473 }
12474 if (rcStrict == VINF_VMX_VMEXIT)
12475 {
12476 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12477 continue;
12478 }
12479#endif
12480 break;
12481 }
12482
12483 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12484 switch (rcLoop)
12485 {
12486 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12487 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12488 }
12489
12490 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12491 if (RT_FAILURE(rc2))
12492 {
12493 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12494 rcStrict = rc2;
12495 }
12496 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12497 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12498 return rcStrict;
12499}
12500
12501
12502#ifndef HMVMX_USE_FUNCTION_TABLE
12503/**
12504 * Handles a guest VM-exit from hardware-assisted VMX execution.
12505 *
12506 * @returns Strict VBox status code (i.e. informational status codes too).
12507 * @param pVCpu The cross context virtual CPU structure.
12508 * @param pVmxTransient The VMX-transient structure.
12509 */
12510DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12511{
12512#ifdef DEBUG_ramshankar
12513# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12514 do { \
12515 if (a_fSave != 0) \
12516 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12517 VBOXSTRICTRC rcStrict = a_CallExpr; \
12518 if (a_fSave != 0) \
12519 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12520 return rcStrict; \
12521 } while (0)
12522#else
12523# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12524#endif
12525 uint32_t const uExitReason = pVmxTransient->uExitReason;
12526 switch (uExitReason)
12527 {
12528 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12529 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12530 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12531 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12532 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12533 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12534 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12535 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12536 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12537 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12538 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12539 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12540 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12541 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12542 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12543 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12544 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12545 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12546 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12547 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12548 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12549 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12550 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12551 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12552 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12553 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12554 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12555 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12556 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12557 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12558#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12559 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12560 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12561 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12562 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12563 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12564 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12565 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12566 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12567 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12568 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12569 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12570#else
12571 case VMX_EXIT_VMCLEAR:
12572 case VMX_EXIT_VMLAUNCH:
12573 case VMX_EXIT_VMPTRLD:
12574 case VMX_EXIT_VMPTRST:
12575 case VMX_EXIT_VMREAD:
12576 case VMX_EXIT_VMRESUME:
12577 case VMX_EXIT_VMWRITE:
12578 case VMX_EXIT_VMXOFF:
12579 case VMX_EXIT_VMXON:
12580 case VMX_EXIT_INVVPID:
12581 case VMX_EXIT_INVEPT:
12582 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12583#endif
12584
12585 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12586 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12587 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12588
12589 case VMX_EXIT_INIT_SIGNAL:
12590 case VMX_EXIT_SIPI:
12591 case VMX_EXIT_IO_SMI:
12592 case VMX_EXIT_SMI:
12593 case VMX_EXIT_ERR_MSR_LOAD:
12594 case VMX_EXIT_ERR_MACHINE_CHECK:
12595 case VMX_EXIT_PML_FULL:
12596 case VMX_EXIT_VIRTUALIZED_EOI:
12597 case VMX_EXIT_GDTR_IDTR_ACCESS:
12598 case VMX_EXIT_LDTR_TR_ACCESS:
12599 case VMX_EXIT_APIC_WRITE:
12600 case VMX_EXIT_RDRAND:
12601 case VMX_EXIT_RSM:
12602 case VMX_EXIT_VMFUNC:
12603 case VMX_EXIT_ENCLS:
12604 case VMX_EXIT_RDSEED:
12605 case VMX_EXIT_XSAVES:
12606 case VMX_EXIT_XRSTORS:
12607 case VMX_EXIT_UMWAIT:
12608 case VMX_EXIT_TPAUSE:
12609 default:
12610 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12611 }
12612#undef VMEXIT_CALL_RET
12613}
12614#endif /* !HMVMX_USE_FUNCTION_TABLE */
12615
12616
12617#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12618/**
12619 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12620 *
12621 * @returns Strict VBox status code (i.e. informational status codes too).
12622 * @param pVCpu The cross context virtual CPU structure.
12623 * @param pVmxTransient The VMX-transient structure.
12624 */
12625DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12626{
12627 /** @todo NSTVMX: Remove after debugging page-fault issue. */
12628#ifdef DEBUG_ramshankar
12629 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12630 Log4Func(("cs:rip=%#04x:%#RX64 rsp=%#RX64 eflags=%#RX32 cr3=%#RX64\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
12631 pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.u32, pVCpu->cpum.GstCtx.cr3));
12632#endif
12633
12634 uint32_t const uExitReason = pVmxTransient->uExitReason;
12635 switch (uExitReason)
12636 {
12637 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
12638 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
12639 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
12640 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
12641 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
12642
12643 /*
12644 * We shouldn't direct host physical interrupts to the nested-guest.
12645 */
12646 case VMX_EXIT_EXT_INT:
12647 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
12648
12649 /*
12650 * Instructions that cause VM-exits unconditionally or the condition is
12651 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12652 * happens, it's guaranteed to be a nested-guest VM-exit).
12653 *
12654 * - Provides VM-exit instruction length ONLY.
12655 */
12656 case VMX_EXIT_CPUID: /* Unconditional. */
12657 case VMX_EXIT_VMCALL:
12658 case VMX_EXIT_GETSEC:
12659 case VMX_EXIT_INVD:
12660 case VMX_EXIT_XSETBV:
12661 case VMX_EXIT_VMLAUNCH:
12662 case VMX_EXIT_VMRESUME:
12663 case VMX_EXIT_VMXOFF:
12664 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
12665 case VMX_EXIT_VMFUNC:
12666 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
12667
12668 /*
12669 * Instructions that cause VM-exits unconditionally or the condition is
12670 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12671 * happens, it's guaranteed to be a nested-guest VM-exit).
12672 *
12673 * - Provides VM-exit instruction length.
12674 * - Provides VM-exit information.
12675 * - Optionally provides Exit qualification.
12676 *
12677 * Since Exit qualification is 0 for all VM-exits where it is not
12678 * applicable, reading and passing it to the guest should produce
12679 * defined behavior.
12680 *
12681 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
12682 */
12683 case VMX_EXIT_INVEPT: /* Unconditional. */
12684 case VMX_EXIT_INVVPID:
12685 case VMX_EXIT_VMCLEAR:
12686 case VMX_EXIT_VMPTRLD:
12687 case VMX_EXIT_VMPTRST:
12688 case VMX_EXIT_VMXON:
12689 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
12690 case VMX_EXIT_LDTR_TR_ACCESS:
12691 case VMX_EXIT_RDRAND:
12692 case VMX_EXIT_RDSEED:
12693 case VMX_EXIT_XSAVES:
12694 case VMX_EXIT_XRSTORS:
12695 case VMX_EXIT_UMWAIT:
12696 case VMX_EXIT_TPAUSE:
12697 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
12698
12699 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
12700 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
12701 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
12702 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
12703 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
12704 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
12705 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
12706 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
12707 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
12708 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
12709 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
12710 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
12711 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
12712 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
12713 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
12714 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
12715 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
12716 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
12717 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
12718
12719 case VMX_EXIT_PREEMPT_TIMER:
12720 {
12721 /** @todo NSTVMX: Preempt timer. */
12722 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
12723 }
12724
12725 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
12726 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
12727
12728 case VMX_EXIT_VMREAD:
12729 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
12730
12731 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
12732 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
12733
12734 case VMX_EXIT_INIT_SIGNAL:
12735 case VMX_EXIT_SIPI:
12736 case VMX_EXIT_IO_SMI:
12737 case VMX_EXIT_SMI:
12738 case VMX_EXIT_ERR_MSR_LOAD:
12739 case VMX_EXIT_ERR_MACHINE_CHECK:
12740 case VMX_EXIT_PML_FULL:
12741 case VMX_EXIT_RSM:
12742 default:
12743 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12744 }
12745}
12746#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12747
12748
12749/** @name VM-exit helpers.
12750 * @{
12751 */
12752/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12753/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
12754/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12755
12756/** Macro for VM-exits called unexpectedly. */
12757#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
12758 do { \
12759 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
12760 return VERR_VMX_UNEXPECTED_EXIT; \
12761 } while (0)
12762
12763#ifdef VBOX_STRICT
12764/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
12765# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
12766 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
12767
12768# define HMVMX_ASSERT_PREEMPT_CPUID() \
12769 do { \
12770 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
12771 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
12772 } while (0)
12773
12774# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12775 do { \
12776 AssertPtr((a_pVCpu)); \
12777 AssertPtr((a_pVmxTransient)); \
12778 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
12779 Assert((a_pVmxTransient)->pVmcsInfo); \
12780 Assert(ASMIntAreEnabled()); \
12781 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12782 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
12783 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
12784 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12785 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
12786 HMVMX_ASSERT_PREEMPT_CPUID(); \
12787 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12788 } while (0)
12789
12790# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12791 do { \
12792 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
12793 Assert((a_pVmxTransient)->fIsNestedGuest); \
12794 } while (0)
12795
12796# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12797 do { \
12798 Log4Func(("\n")); \
12799 } while (0)
12800#else
12801# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12802 do { \
12803 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12804 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
12805 } while (0)
12806
12807# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12808 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
12809
12810# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
12811#endif
12812
12813#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12814/** Macro that does the necessary privilege checks and intercepted VM-exits for
12815 * guests that attempted to execute a VMX instruction. */
12816# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
12817 do \
12818 { \
12819 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
12820 if (rcStrictTmp == VINF_SUCCESS) \
12821 { /* likely */ } \
12822 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12823 { \
12824 Assert((a_pVCpu)->hm.s.Event.fPending); \
12825 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
12826 return VINF_SUCCESS; \
12827 } \
12828 else \
12829 { \
12830 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
12831 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
12832 } \
12833 } while (0)
12834
12835/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
12836# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
12837 do \
12838 { \
12839 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
12840 (a_pGCPtrEffAddr)); \
12841 if (rcStrictTmp == VINF_SUCCESS) \
12842 { /* likely */ } \
12843 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12844 { \
12845 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
12846 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
12847 NOREF(uXcptTmp); \
12848 return VINF_SUCCESS; \
12849 } \
12850 else \
12851 { \
12852 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
12853 return rcStrictTmp; \
12854 } \
12855 } while (0)
12856#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12857
12858
12859/**
12860 * Advances the guest RIP by the specified number of bytes.
12861 *
12862 * @param pVCpu The cross context virtual CPU structure.
12863 * @param cbInstr Number of bytes to advance the RIP by.
12864 *
12865 * @remarks No-long-jump zone!!!
12866 */
12867DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
12868{
12869 /* Advance the RIP. */
12870 pVCpu->cpum.GstCtx.rip += cbInstr;
12871 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
12872
12873 /* Update interrupt inhibition. */
12874 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
12875 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
12876 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
12877}
12878
12879
12880/**
12881 * Advances the guest RIP after reading it from the VMCS.
12882 *
12883 * @returns VBox status code, no informational status codes.
12884 * @param pVCpu The cross context virtual CPU structure.
12885 * @param pVmxTransient The VMX-transient structure.
12886 *
12887 * @remarks No-long-jump zone!!!
12888 */
12889static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12890{
12891 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
12892 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
12893 AssertRCReturn(rc, rc);
12894
12895 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
12896 return VINF_SUCCESS;
12897}
12898
12899
12900/**
12901 * Handle a condition that occurred while delivering an event through the guest or
12902 * nested-guest IDT.
12903 *
12904 * @returns Strict VBox status code (i.e. informational status codes too).
12905 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
12906 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
12907 * to continue execution of the guest which will delivery the \#DF.
12908 * @retval VINF_EM_RESET if we detected a triple-fault condition.
12909 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
12910 *
12911 * @param pVCpu The cross context virtual CPU structure.
12912 * @param pVmxTransient The VMX-transient structure.
12913 *
12914 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
12915 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
12916 * is due to an EPT violation, PML full or SPP-related event.
12917 *
12918 * @remarks No-long-jump zone!!!
12919 */
12920static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12921{
12922 Assert(!pVCpu->hm.s.Event.fPending);
12923 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
12924 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
12925 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
12926 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
12927 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
12928
12929 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
12930 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12931 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
12932 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
12933 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
12934 {
12935 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
12936 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
12937
12938 /*
12939 * If the event was a software interrupt (generated with INT n) or a software exception
12940 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
12941 * can handle the VM-exit and continue guest execution which will re-execute the
12942 * instruction rather than re-injecting the exception, as that can cause premature
12943 * trips to ring-3 before injection and involve TRPM which currently has no way of
12944 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
12945 * the problem).
12946 */
12947 IEMXCPTRAISE enmRaise;
12948 IEMXCPTRAISEINFO fRaiseInfo;
12949 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
12950 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
12951 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
12952 {
12953 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
12954 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12955 }
12956 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
12957 {
12958 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
12959 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
12960 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
12961
12962 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
12963 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
12964
12965 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
12966
12967 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
12968 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
12969 {
12970 pVmxTransient->fVectoringPF = true;
12971 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12972 }
12973 }
12974 else
12975 {
12976 /*
12977 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
12978 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
12979 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
12980 */
12981 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
12982 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12983 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
12984 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12985 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12986 }
12987
12988 /*
12989 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
12990 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
12991 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
12992 * subsequent VM-entry would fail, see @bugref{7445}.
12993 *
12994 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
12995 */
12996 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12997 && enmRaise == IEMXCPTRAISE_PREV_EVENT
12998 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
12999 && CPUMIsGuestNmiBlocking(pVCpu))
13000 {
13001 CPUMSetGuestNmiBlocking(pVCpu, false);
13002 }
13003
13004 switch (enmRaise)
13005 {
13006 case IEMXCPTRAISE_CURRENT_XCPT:
13007 {
13008 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13009 Assert(rcStrict == VINF_SUCCESS);
13010 break;
13011 }
13012
13013 case IEMXCPTRAISE_PREV_EVENT:
13014 {
13015 uint32_t u32ErrCode;
13016 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13017 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13018 else
13019 u32ErrCode = 0;
13020
13021 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13022 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13023 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13024 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13025
13026 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13027 pVCpu->hm.s.Event.u32ErrCode));
13028 Assert(rcStrict == VINF_SUCCESS);
13029 break;
13030 }
13031
13032 case IEMXCPTRAISE_REEXEC_INSTR:
13033 Assert(rcStrict == VINF_SUCCESS);
13034 break;
13035
13036 case IEMXCPTRAISE_DOUBLE_FAULT:
13037 {
13038 /*
13039 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13040 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13041 */
13042 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13043 {
13044 pVmxTransient->fVectoringDoublePF = true;
13045 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13046 pVCpu->cpum.GstCtx.cr2));
13047 rcStrict = VINF_SUCCESS;
13048 }
13049 else
13050 {
13051 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13052 hmR0VmxSetPendingXcptDF(pVCpu);
13053 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13054 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13055 rcStrict = VINF_HM_DOUBLE_FAULT;
13056 }
13057 break;
13058 }
13059
13060 case IEMXCPTRAISE_TRIPLE_FAULT:
13061 {
13062 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13063 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13064 rcStrict = VINF_EM_RESET;
13065 break;
13066 }
13067
13068 case IEMXCPTRAISE_CPU_HANG:
13069 {
13070 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13071 rcStrict = VERR_EM_GUEST_CPU_HANG;
13072 break;
13073 }
13074
13075 default:
13076 {
13077 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13078 rcStrict = VERR_VMX_IPE_2;
13079 break;
13080 }
13081 }
13082 }
13083 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13084 && !CPUMIsGuestNmiBlocking(pVCpu))
13085 {
13086 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13087 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13088 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13089 {
13090 /*
13091 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13092 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13093 * that NMIs remain blocked until the IRET execution is completed.
13094 *
13095 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13096 */
13097 CPUMSetGuestNmiBlocking(pVCpu, true);
13098 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13099 }
13100 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13101 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13102 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13103 {
13104 /*
13105 * Execution of IRET caused an EPT violation, page-modification log-full event or
13106 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13107 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13108 * that NMIs remain blocked until the IRET execution is completed.
13109 *
13110 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13111 */
13112 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13113 {
13114 CPUMSetGuestNmiBlocking(pVCpu, true);
13115 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13116 }
13117 }
13118 }
13119
13120 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13121 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13122 return rcStrict;
13123}
13124
13125
13126#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13127/**
13128 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13129 * guest attempting to execute a VMX instruction.
13130 *
13131 * @returns Strict VBox status code (i.e. informational status codes too).
13132 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13133 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13134 *
13135 * @param pVCpu The cross context virtual CPU structure.
13136 * @param uExitReason The VM-exit reason.
13137 *
13138 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13139 * @remarks No-long-jump zone!!!
13140 */
13141static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13142{
13143 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13144 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13145
13146 /*
13147 * The physical CPU would have already checked the CPU mode/code segment.
13148 * We shall just assert here for paranoia.
13149 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13150 */
13151 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13152 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13153 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13154
13155 if (uExitReason == VMX_EXIT_VMXON)
13156 {
13157 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13158
13159 /*
13160 * We check CR4.VMXE because it is required to be always set while in VMX operation
13161 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13162 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13163 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13164 */
13165 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13166 {
13167 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13168 hmR0VmxSetPendingXcptUD(pVCpu);
13169 return VINF_HM_PENDING_XCPT;
13170 }
13171 }
13172 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13173 {
13174 /*
13175 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13176 * (other than VMXON), we need to raise a #UD.
13177 */
13178 Log4Func(("Not in VMX root mode -> #UD\n"));
13179 hmR0VmxSetPendingXcptUD(pVCpu);
13180 return VINF_HM_PENDING_XCPT;
13181 }
13182
13183 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13184 return VINF_SUCCESS;
13185}
13186
13187
13188/**
13189 * Decodes the memory operand of an instruction that caused a VM-exit.
13190 *
13191 * The Exit qualification field provides the displacement field for memory
13192 * operand instructions, if any.
13193 *
13194 * @returns Strict VBox status code (i.e. informational status codes too).
13195 * @retval VINF_SUCCESS if the operand was successfully decoded.
13196 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13197 * operand.
13198 * @param pVCpu The cross context virtual CPU structure.
13199 * @param uExitInstrInfo The VM-exit instruction information field.
13200 * @param enmMemAccess The memory operand's access type (read or write).
13201 * @param GCPtrDisp The instruction displacement field, if any. For
13202 * RIP-relative addressing pass RIP + displacement here.
13203 * @param pGCPtrMem Where to store the effective destination memory address.
13204 *
13205 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13206 * virtual-8086 mode hence skips those checks while verifying if the
13207 * segment is valid.
13208 */
13209static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13210 PRTGCPTR pGCPtrMem)
13211{
13212 Assert(pGCPtrMem);
13213 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13214 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13215 | CPUMCTX_EXTRN_CR0);
13216
13217 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13218 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13219 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13220
13221 VMXEXITINSTRINFO ExitInstrInfo;
13222 ExitInstrInfo.u = uExitInstrInfo;
13223 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13224 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13225 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13226 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13227 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13228 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13229 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13230 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13231 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13232
13233 /*
13234 * Validate instruction information.
13235 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13236 */
13237 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13238 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13239 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13240 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13241 AssertLogRelMsgReturn(fIsMemOperand,
13242 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13243
13244 /*
13245 * Compute the complete effective address.
13246 *
13247 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13248 * See AMD spec. 4.5.2 "Segment Registers".
13249 */
13250 RTGCPTR GCPtrMem = GCPtrDisp;
13251 if (fBaseRegValid)
13252 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13253 if (fIdxRegValid)
13254 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13255
13256 RTGCPTR const GCPtrOff = GCPtrMem;
13257 if ( !fIsLongMode
13258 || iSegReg >= X86_SREG_FS)
13259 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13260 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13261
13262 /*
13263 * Validate effective address.
13264 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13265 */
13266 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13267 Assert(cbAccess > 0);
13268 if (fIsLongMode)
13269 {
13270 if (X86_IS_CANONICAL(GCPtrMem))
13271 {
13272 *pGCPtrMem = GCPtrMem;
13273 return VINF_SUCCESS;
13274 }
13275
13276 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13277 * "Data Limit Checks in 64-bit Mode". */
13278 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13279 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13280 return VINF_HM_PENDING_XCPT;
13281 }
13282
13283 /*
13284 * This is a watered down version of iemMemApplySegment().
13285 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13286 * and segment CPL/DPL checks are skipped.
13287 */
13288 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13289 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13290 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13291
13292 /* Check if the segment is present and usable. */
13293 if ( pSel->Attr.n.u1Present
13294 && !pSel->Attr.n.u1Unusable)
13295 {
13296 Assert(pSel->Attr.n.u1DescType);
13297 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13298 {
13299 /* Check permissions for the data segment. */
13300 if ( enmMemAccess == VMXMEMACCESS_WRITE
13301 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13302 {
13303 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13304 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13305 return VINF_HM_PENDING_XCPT;
13306 }
13307
13308 /* Check limits if it's a normal data segment. */
13309 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13310 {
13311 if ( GCPtrFirst32 > pSel->u32Limit
13312 || GCPtrLast32 > pSel->u32Limit)
13313 {
13314 Log4Func(("Data segment limit exceeded. "
13315 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13316 GCPtrLast32, pSel->u32Limit));
13317 if (iSegReg == X86_SREG_SS)
13318 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13319 else
13320 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13321 return VINF_HM_PENDING_XCPT;
13322 }
13323 }
13324 else
13325 {
13326 /* Check limits if it's an expand-down data segment.
13327 Note! The upper boundary is defined by the B bit, not the G bit! */
13328 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13329 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13330 {
13331 Log4Func(("Expand-down data segment limit exceeded. "
13332 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13333 GCPtrLast32, pSel->u32Limit));
13334 if (iSegReg == X86_SREG_SS)
13335 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13336 else
13337 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13338 return VINF_HM_PENDING_XCPT;
13339 }
13340 }
13341 }
13342 else
13343 {
13344 /* Check permissions for the code segment. */
13345 if ( enmMemAccess == VMXMEMACCESS_WRITE
13346 || ( enmMemAccess == VMXMEMACCESS_READ
13347 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13348 {
13349 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13350 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13351 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13352 return VINF_HM_PENDING_XCPT;
13353 }
13354
13355 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13356 if ( GCPtrFirst32 > pSel->u32Limit
13357 || GCPtrLast32 > pSel->u32Limit)
13358 {
13359 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13360 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13361 if (iSegReg == X86_SREG_SS)
13362 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13363 else
13364 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13365 return VINF_HM_PENDING_XCPT;
13366 }
13367 }
13368 }
13369 else
13370 {
13371 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13372 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13373 return VINF_HM_PENDING_XCPT;
13374 }
13375
13376 *pGCPtrMem = GCPtrMem;
13377 return VINF_SUCCESS;
13378}
13379#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13380
13381
13382/**
13383 * VM-exit helper for LMSW.
13384 */
13385static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13386{
13387 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13388 AssertRCReturn(rc, rc);
13389
13390 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13391 AssertMsg( rcStrict == VINF_SUCCESS
13392 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13393
13394 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13395 if (rcStrict == VINF_IEM_RAISED_XCPT)
13396 {
13397 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13398 rcStrict = VINF_SUCCESS;
13399 }
13400
13401 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13402 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13403 return rcStrict;
13404}
13405
13406
13407/**
13408 * VM-exit helper for CLTS.
13409 */
13410static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13411{
13412 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13413 AssertRCReturn(rc, rc);
13414
13415 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13416 AssertMsg( rcStrict == VINF_SUCCESS
13417 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13418
13419 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13420 if (rcStrict == VINF_IEM_RAISED_XCPT)
13421 {
13422 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13423 rcStrict = VINF_SUCCESS;
13424 }
13425
13426 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13427 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13428 return rcStrict;
13429}
13430
13431
13432/**
13433 * VM-exit helper for MOV from CRx (CRx read).
13434 */
13435static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13436{
13437 Assert(iCrReg < 16);
13438 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13439
13440 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13441 AssertRCReturn(rc, rc);
13442
13443 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13444 AssertMsg( rcStrict == VINF_SUCCESS
13445 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13446
13447 if (iGReg == X86_GREG_xSP)
13448 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13449 else
13450 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13451#ifdef VBOX_WITH_STATISTICS
13452 switch (iCrReg)
13453 {
13454 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13455 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13456 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13457 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13458 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13459 }
13460#endif
13461 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13462 return rcStrict;
13463}
13464
13465
13466/**
13467 * VM-exit helper for MOV to CRx (CRx write).
13468 */
13469static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13470{
13471 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13472 AssertRCReturn(rc, rc);
13473
13474 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13475 AssertMsg( rcStrict == VINF_SUCCESS
13476 || rcStrict == VINF_IEM_RAISED_XCPT
13477 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13478
13479 switch (iCrReg)
13480 {
13481 case 0:
13482 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13483 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13484 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13485 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13486 break;
13487
13488 case 2:
13489 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13490 /* Nothing to do here, CR2 it's not part of the VMCS. */
13491 break;
13492
13493 case 3:
13494 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13495 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13496 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13497 break;
13498
13499 case 4:
13500 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13501 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13502 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13503 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13504 break;
13505
13506 case 8:
13507 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13508 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13509 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13510 break;
13511
13512 default:
13513 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13514 break;
13515 }
13516
13517 if (rcStrict == VINF_IEM_RAISED_XCPT)
13518 {
13519 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13520 rcStrict = VINF_SUCCESS;
13521 }
13522 return rcStrict;
13523}
13524
13525
13526/**
13527 * VM-exit exception handler for \#PF (Page-fault exception).
13528 *
13529 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13530 */
13531static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13532{
13533 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13534 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13535 hmR0VmxReadExitQualVmcs(pVmxTransient);
13536
13537 if (!pVM->hm.s.fNestedPaging)
13538 { /* likely */ }
13539 else
13540 {
13541#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13542 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
13543#endif
13544 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13545 if (!pVmxTransient->fVectoringDoublePF)
13546 {
13547 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13548 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13549 }
13550 else
13551 {
13552 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13553 Assert(!pVmxTransient->fIsNestedGuest);
13554 hmR0VmxSetPendingXcptDF(pVCpu);
13555 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13556 }
13557 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13558 return VINF_SUCCESS;
13559 }
13560
13561 Assert(!pVmxTransient->fIsNestedGuest);
13562
13563 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13564 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13565 if (pVmxTransient->fVectoringPF)
13566 {
13567 Assert(pVCpu->hm.s.Event.fPending);
13568 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13569 }
13570
13571 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13572 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13573 AssertRCReturn(rc, rc);
13574
13575 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13576 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13577
13578 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13579 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13580
13581 Log4Func(("#PF: rc=%Rrc\n", rc));
13582 if (rc == VINF_SUCCESS)
13583 {
13584 /*
13585 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13586 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13587 */
13588 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13589 TRPMResetTrap(pVCpu);
13590 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13591 return rc;
13592 }
13593
13594 if (rc == VINF_EM_RAW_GUEST_TRAP)
13595 {
13596 if (!pVmxTransient->fVectoringDoublePF)
13597 {
13598 /* It's a guest page fault and needs to be reflected to the guest. */
13599 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
13600 TRPMResetTrap(pVCpu);
13601 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13602 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13603 uGstErrorCode, pVmxTransient->uExitQual);
13604 }
13605 else
13606 {
13607 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13608 TRPMResetTrap(pVCpu);
13609 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
13610 hmR0VmxSetPendingXcptDF(pVCpu);
13611 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
13612 }
13613
13614 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13615 return VINF_SUCCESS;
13616 }
13617
13618 TRPMResetTrap(pVCpu);
13619 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
13620 return rc;
13621}
13622
13623
13624/**
13625 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
13626 *
13627 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13628 */
13629static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13630{
13631 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13632 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
13633
13634 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
13635 AssertRCReturn(rc, rc);
13636
13637 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
13638 {
13639 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
13640 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
13641
13642 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
13643 * provides VM-exit instruction length. If this causes problem later,
13644 * disassemble the instruction like it's done on AMD-V. */
13645 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13646 AssertRCReturn(rc2, rc2);
13647 return rc;
13648 }
13649
13650 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
13651 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13652 return VINF_SUCCESS;
13653}
13654
13655
13656/**
13657 * VM-exit exception handler for \#BP (Breakpoint exception).
13658 *
13659 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13660 */
13661static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13662{
13663 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13664 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
13665
13666 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13667 AssertRCReturn(rc, rc);
13668
13669 if (!pVmxTransient->fIsNestedGuest)
13670 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
13671 else
13672 rc = VINF_EM_RAW_GUEST_TRAP;
13673
13674 if (rc == VINF_EM_RAW_GUEST_TRAP)
13675 {
13676 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13677 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13678 rc = VINF_SUCCESS;
13679 }
13680
13681 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
13682 return rc;
13683}
13684
13685
13686/**
13687 * VM-exit exception handler for \#AC (Alignment-check exception).
13688 *
13689 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13690 */
13691static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13692{
13693 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13694 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
13695
13696 /* Re-inject it. We'll detect any nesting before getting here. */
13697 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13698 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13699 return VINF_SUCCESS;
13700}
13701
13702
13703/**
13704 * VM-exit exception handler for \#DB (Debug exception).
13705 *
13706 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13707 */
13708static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13709{
13710 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13711 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
13712
13713 /*
13714 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
13715 */
13716 hmR0VmxReadExitQualVmcs(pVmxTransient);
13717
13718 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
13719 uint64_t const uDR6 = X86_DR6_INIT_VAL
13720 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
13721 | X86_DR6_BD | X86_DR6_BS));
13722
13723 int rc;
13724 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13725 if (!pVmxTransient->fIsNestedGuest)
13726 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
13727 else
13728 rc = VINF_EM_RAW_GUEST_TRAP;
13729 Log6Func(("rc=%Rrc\n", rc));
13730 if (rc == VINF_EM_RAW_GUEST_TRAP)
13731 {
13732 /*
13733 * The exception was for the guest. Update DR6, DR7.GD and
13734 * IA32_DEBUGCTL.LBR before forwarding it.
13735 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
13736 */
13737 VMMRZCallRing3Disable(pVCpu);
13738 HM_DISABLE_PREEMPT(pVCpu);
13739
13740 pCtx->dr[6] &= ~X86_DR6_B_MASK;
13741 pCtx->dr[6] |= uDR6;
13742 if (CPUMIsGuestDebugStateActive(pVCpu))
13743 ASMSetDR6(pCtx->dr[6]);
13744
13745 HM_RESTORE_PREEMPT();
13746 VMMRZCallRing3Enable(pVCpu);
13747
13748 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
13749 AssertRCReturn(rc, rc);
13750
13751 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
13752 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
13753
13754 /* Paranoia. */
13755 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
13756 pCtx->dr[7] |= X86_DR7_RA1_MASK;
13757
13758 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
13759 AssertRC(rc);
13760
13761 /*
13762 * Raise #DB in the guest.
13763 *
13764 * It is important to reflect exactly what the VM-exit gave us (preserving the
13765 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
13766 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
13767 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
13768 *
13769 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
13770 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
13771 */
13772 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13773 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13774 return VINF_SUCCESS;
13775 }
13776
13777 /*
13778 * Not a guest trap, must be a hypervisor related debug event then.
13779 * Update DR6 in case someone is interested in it.
13780 */
13781 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
13782 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
13783 CPUMSetHyperDR6(pVCpu, uDR6);
13784
13785 return rc;
13786}
13787
13788
13789/**
13790 * Hacks its way around the lovely mesa driver's backdoor accesses.
13791 *
13792 * @sa hmR0SvmHandleMesaDrvGp.
13793 */
13794static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13795{
13796 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
13797 RT_NOREF(pCtx);
13798
13799 /* For now we'll just skip the instruction. */
13800 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13801}
13802
13803
13804/**
13805 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
13806 * backdoor logging w/o checking what it is running inside.
13807 *
13808 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
13809 * backdoor port and magic numbers loaded in registers.
13810 *
13811 * @returns true if it is, false if it isn't.
13812 * @sa hmR0SvmIsMesaDrvGp.
13813 */
13814DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13815{
13816 /* 0xed: IN eAX,dx */
13817 uint8_t abInstr[1];
13818 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
13819 return false;
13820
13821 /* Check that it is #GP(0). */
13822 if (pVmxTransient->uExitIntErrorCode != 0)
13823 return false;
13824
13825 /* Check magic and port. */
13826 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
13827 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
13828 if (pCtx->rax != UINT32_C(0x564d5868))
13829 return false;
13830 if (pCtx->dx != UINT32_C(0x5658))
13831 return false;
13832
13833 /* Flat ring-3 CS. */
13834 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
13835 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
13836 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
13837 if (pCtx->cs.Attr.n.u2Dpl != 3)
13838 return false;
13839 if (pCtx->cs.u64Base != 0)
13840 return false;
13841
13842 /* Check opcode. */
13843 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
13844 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
13845 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
13846 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
13847 if (RT_FAILURE(rc))
13848 return false;
13849 if (abInstr[0] != 0xed)
13850 return false;
13851
13852 return true;
13853}
13854
13855
13856/**
13857 * VM-exit exception handler for \#GP (General-protection exception).
13858 *
13859 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13860 */
13861static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13862{
13863 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13864 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
13865
13866 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13867 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13868 if (pVmcsInfo->RealMode.fRealOnV86Active)
13869 { /* likely */ }
13870 else
13871 {
13872#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13873 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
13874#endif
13875 /*
13876 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
13877 * executing a nested-guest, reflect #GP to the guest or nested-guest.
13878 */
13879 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13880 AssertRCReturn(rc, rc);
13881 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
13882 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
13883
13884 if ( pVmxTransient->fIsNestedGuest
13885 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
13886 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
13887 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13888 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13889 else
13890 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
13891 return rc;
13892 }
13893
13894 Assert(CPUMIsGuestInRealModeEx(pCtx));
13895 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
13896 Assert(!pVmxTransient->fIsNestedGuest);
13897
13898 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13899 AssertRCReturn(rc, rc);
13900
13901 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
13902 if (rcStrict == VINF_SUCCESS)
13903 {
13904 if (!CPUMIsGuestInRealModeEx(pCtx))
13905 {
13906 /*
13907 * The guest is no longer in real-mode, check if we can continue executing the
13908 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
13909 */
13910 pVmcsInfo->RealMode.fRealOnV86Active = false;
13911 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
13912 {
13913 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
13914 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13915 }
13916 else
13917 {
13918 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
13919 rcStrict = VINF_EM_RESCHEDULE;
13920 }
13921 }
13922 else
13923 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13924 }
13925 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13926 {
13927 rcStrict = VINF_SUCCESS;
13928 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13929 }
13930 return VBOXSTRICTRC_VAL(rcStrict);
13931}
13932
13933
13934/**
13935 * VM-exit exception handler wrapper for all other exceptions that are not handled
13936 * by a specific handler.
13937 *
13938 * This simply re-injects the exception back into the VM without any special
13939 * processing.
13940 *
13941 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13942 */
13943static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13944{
13945 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13946
13947#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13948 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13949 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
13950 ("uVector=%#x u32XcptBitmap=%#X32\n",
13951 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
13952 NOREF(pVmcsInfo);
13953#endif
13954
13955 /*
13956 * Re-inject the exception into the guest. This cannot be a double-fault condition which
13957 * would have been handled while checking exits due to event delivery.
13958 */
13959 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13960
13961#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13962 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
13963 AssertRCReturn(rc, rc);
13964 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
13965#endif
13966
13967#ifdef VBOX_WITH_STATISTICS
13968 switch (uVector)
13969 {
13970 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
13971 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
13972 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
13973 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13974 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
13975 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
13976 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13977 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
13978 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
13979 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
13980 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
13981 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
13982 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
13983 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
13984 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
13985 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
13986 default:
13987 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
13988 break;
13989 }
13990#endif
13991
13992 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
13993 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
13994 NOREF(uVector);
13995
13996 /* Re-inject the original exception into the guest. */
13997 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13998 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13999 return VINF_SUCCESS;
14000}
14001
14002
14003/**
14004 * VM-exit exception handler for all exceptions (except NMIs!).
14005 *
14006 * @remarks This may be called for both guests and nested-guests. Take care to not
14007 * make assumptions and avoid doing anything that is not relevant when
14008 * executing a nested-guest (e.g., Mesa driver hacks).
14009 */
14010static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14011{
14012 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14013
14014 /*
14015 * If this VM-exit occurred while delivering an event through the guest IDT, take
14016 * action based on the return code and additional hints (e.g. for page-faults)
14017 * that will be updated in the VMX transient structure.
14018 */
14019 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14020 if (rcStrict == VINF_SUCCESS)
14021 {
14022 /*
14023 * If an exception caused a VM-exit due to delivery of an event, the original
14024 * event may have to be re-injected into the guest. We shall reinject it and
14025 * continue guest execution. However, page-fault is a complicated case and
14026 * needs additional processing done in hmR0VmxExitXcptPF().
14027 */
14028 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14029 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14030 if ( !pVCpu->hm.s.Event.fPending
14031 || uVector == X86_XCPT_PF)
14032 {
14033 switch (uVector)
14034 {
14035 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14036 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14037 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14038 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14039 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14040 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14041 default:
14042 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14043 }
14044 }
14045 /* else: inject pending event before resuming guest execution. */
14046 }
14047 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14048 {
14049 Assert(pVCpu->hm.s.Event.fPending);
14050 rcStrict = VINF_SUCCESS;
14051 }
14052
14053 return rcStrict;
14054}
14055/** @} */
14056
14057
14058/** @name VM-exit handlers.
14059 * @{
14060 */
14061/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14062/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14063/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14064
14065/**
14066 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14067 */
14068HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14069{
14070 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14071 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14072 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14073 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14074 return VINF_SUCCESS;
14075 return VINF_EM_RAW_INTERRUPT;
14076}
14077
14078
14079/**
14080 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14081 * VM-exit.
14082 */
14083HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14084{
14085 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14086 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14087
14088 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14089
14090 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14091 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14092 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14093
14094 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14095 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14096 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14097 NOREF(pVmcsInfo);
14098
14099 VBOXSTRICTRC rcStrict;
14100 switch (uExitIntType)
14101 {
14102 /*
14103 * Host physical NMIs:
14104 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14105 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14106 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14107 *
14108 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14109 * See Intel spec. 27.5.5 "Updating Non-Register State".
14110 */
14111 case VMX_EXIT_INT_INFO_TYPE_NMI:
14112 {
14113 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14114 break;
14115 }
14116
14117 /*
14118 * Privileged software exceptions (#DB from ICEBP),
14119 * Software exceptions (#BP and #OF),
14120 * Hardware exceptions:
14121 * Process the required exceptions and resume guest execution if possible.
14122 */
14123 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14124 Assert(uVector == X86_XCPT_DB);
14125 RT_FALL_THRU();
14126 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14127 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14128 RT_FALL_THRU();
14129 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14130 {
14131 NOREF(uVector);
14132 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14133 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14134 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14135 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14136
14137 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14138 break;
14139 }
14140
14141 default:
14142 {
14143 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14144 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14145 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14146 break;
14147 }
14148 }
14149
14150 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14151 return rcStrict;
14152}
14153
14154
14155/**
14156 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14157 */
14158HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14159{
14160 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14161
14162 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14163 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14164 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14165
14166 /* Evaluate and deliver pending events and resume guest execution. */
14167 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14168 return VINF_SUCCESS;
14169}
14170
14171
14172/**
14173 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14174 */
14175HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14176{
14177 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14178
14179 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14180 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14181 {
14182 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14183 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14184 }
14185
14186 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14187
14188 /*
14189 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14190 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14191 */
14192 uint32_t fIntrState;
14193 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14194 AssertRC(rc);
14195 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14196 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14197 {
14198 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14199 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14200
14201 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14202 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14203 AssertRC(rc);
14204 }
14205
14206 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14207 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14208
14209 /* Evaluate and deliver pending events and resume guest execution. */
14210 return VINF_SUCCESS;
14211}
14212
14213
14214/**
14215 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14216 */
14217HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14218{
14219 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14220 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14221}
14222
14223
14224/**
14225 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14226 */
14227HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14228{
14229 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14230 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14231}
14232
14233
14234/**
14235 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14236 */
14237HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14238{
14239 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14240
14241 /*
14242 * Get the state we need and update the exit history entry.
14243 */
14244 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14245 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14246
14247 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14248 AssertRCReturn(rc, rc);
14249
14250 VBOXSTRICTRC rcStrict;
14251 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14252 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14253 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14254 if (!pExitRec)
14255 {
14256 /*
14257 * Regular CPUID instruction execution.
14258 */
14259 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14260 if (rcStrict == VINF_SUCCESS)
14261 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14262 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14263 {
14264 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14265 rcStrict = VINF_SUCCESS;
14266 }
14267 }
14268 else
14269 {
14270 /*
14271 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14272 */
14273 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14274 AssertRCReturn(rc2, rc2);
14275
14276 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14277 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14278
14279 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14280 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14281
14282 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14283 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14284 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14285 }
14286 return rcStrict;
14287}
14288
14289
14290/**
14291 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14292 */
14293HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14294{
14295 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14296
14297 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14298 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14299 AssertRCReturn(rc, rc);
14300
14301 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14302 return VINF_EM_RAW_EMULATE_INSTR;
14303
14304 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14305 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14306}
14307
14308
14309/**
14310 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14311 */
14312HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14313{
14314 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14315
14316 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14317 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14318 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14319 AssertRCReturn(rc, rc);
14320
14321 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14322 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14323 {
14324 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14325 we must reset offsetting on VM-entry. See @bugref{6634}. */
14326 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14327 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14328 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14329 }
14330 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14331 {
14332 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14333 rcStrict = VINF_SUCCESS;
14334 }
14335 return rcStrict;
14336}
14337
14338
14339/**
14340 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14341 */
14342HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14343{
14344 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14345
14346 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14347 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14348 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14349 AssertRCReturn(rc, rc);
14350
14351 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14352 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14353 {
14354 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14355 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14356 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14357 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14358 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14359 }
14360 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14361 {
14362 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14363 rcStrict = VINF_SUCCESS;
14364 }
14365 return rcStrict;
14366}
14367
14368
14369/**
14370 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14371 */
14372HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14373{
14374 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14375
14376 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14377 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14378 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14379 AssertRCReturn(rc, rc);
14380
14381 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14382 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14383 if (RT_LIKELY(rc == VINF_SUCCESS))
14384 {
14385 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14386 Assert(pVmxTransient->cbExitInstr == 2);
14387 }
14388 else
14389 {
14390 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14391 rc = VERR_EM_INTERPRETER;
14392 }
14393 return rc;
14394}
14395
14396
14397/**
14398 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14399 */
14400HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14401{
14402 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14403
14404 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14405 if (EMAreHypercallInstructionsEnabled(pVCpu))
14406 {
14407 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14408 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14409 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14410 AssertRCReturn(rc, rc);
14411
14412 /* Perform the hypercall. */
14413 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14414 if (rcStrict == VINF_SUCCESS)
14415 {
14416 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14417 AssertRCReturn(rc, rc);
14418 }
14419 else
14420 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14421 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14422 || RT_FAILURE(rcStrict));
14423
14424 /* If the hypercall changes anything other than guest's general-purpose registers,
14425 we would need to reload the guest changed bits here before VM-entry. */
14426 }
14427 else
14428 Log4Func(("Hypercalls not enabled\n"));
14429
14430 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14431 if (RT_FAILURE(rcStrict))
14432 {
14433 hmR0VmxSetPendingXcptUD(pVCpu);
14434 rcStrict = VINF_SUCCESS;
14435 }
14436
14437 return rcStrict;
14438}
14439
14440
14441/**
14442 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14443 */
14444HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14445{
14446 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14447 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
14448
14449 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14450 hmR0VmxReadExitQualVmcs(pVmxTransient);
14451 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14452 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14453 AssertRCReturn(rc, rc);
14454
14455 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14456
14457 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14458 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14459 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14460 {
14461 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14462 rcStrict = VINF_SUCCESS;
14463 }
14464 else
14465 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14466 VBOXSTRICTRC_VAL(rcStrict)));
14467 return rcStrict;
14468}
14469
14470
14471/**
14472 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14473 */
14474HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14475{
14476 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14477
14478 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14479 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14480 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14481 AssertRCReturn(rc, rc);
14482
14483 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14484 if (rcStrict == VINF_SUCCESS)
14485 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14486 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14487 {
14488 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14489 rcStrict = VINF_SUCCESS;
14490 }
14491
14492 return rcStrict;
14493}
14494
14495
14496/**
14497 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14498 */
14499HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14500{
14501 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14502
14503 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14504 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14505 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14506 AssertRCReturn(rc, rc);
14507
14508 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14509 if (RT_SUCCESS(rcStrict))
14510 {
14511 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14512 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14513 rcStrict = VINF_SUCCESS;
14514 }
14515
14516 return rcStrict;
14517}
14518
14519
14520/**
14521 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14522 * VM-exit.
14523 */
14524HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14525{
14526 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14527 return VINF_EM_RESET;
14528}
14529
14530
14531/**
14532 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14533 */
14534HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14535{
14536 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14537
14538 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14539 AssertRCReturn(rc, rc);
14540
14541 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14542 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14543 rc = VINF_SUCCESS;
14544 else
14545 rc = VINF_EM_HALT;
14546
14547 if (rc != VINF_SUCCESS)
14548 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14549 return rc;
14550}
14551
14552
14553/**
14554 * VM-exit handler for instructions that result in a \#UD exception delivered to
14555 * the guest.
14556 */
14557HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14558{
14559 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14560 hmR0VmxSetPendingXcptUD(pVCpu);
14561 return VINF_SUCCESS;
14562}
14563
14564
14565/**
14566 * VM-exit handler for expiry of the VMX-preemption timer.
14567 */
14568HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14569{
14570 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14571
14572 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14573 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14574
14575 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14576 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14577 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14578 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14579 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14580}
14581
14582
14583/**
14584 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14585 */
14586HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14587{
14588 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14589
14590 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14591 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14592 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
14593 AssertRCReturn(rc, rc);
14594
14595 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
14596 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14597 : HM_CHANGED_RAISED_XCPT_MASK);
14598
14599 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14600 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
14601
14602 return rcStrict;
14603}
14604
14605
14606/**
14607 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
14608 */
14609HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14610{
14611 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14612
14613#if 1
14614 /** @todo Use VM-exit instruction information. */
14615 return VERR_EM_INTERPRETER;
14616#else
14617 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14618 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
14619 hmR0VmxReadExitQualVmcs(pVmxTransient);
14620 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
14621 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14622 AssertRCReturn(rc, rc);
14623
14624 /* Paranoia. Ensure this has a memory operand. */
14625 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
14626
14627 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
14628 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14629 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
14630 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
14631
14632 RTGCPTR GCPtrDesc;
14633 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
14634
14635 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
14636 GCPtrDesc, uType);
14637 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14638 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14639 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14640 {
14641 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14642 rcStrict = VINF_SUCCESS;
14643 }
14644 return rcStrict;
14645#endif
14646}
14647
14648
14649/**
14650 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
14651 * VM-exit.
14652 */
14653HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14654{
14655 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14656 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14657 AssertRCReturn(rc, rc);
14658
14659 rc = hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
14660 if (RT_FAILURE(rc))
14661 return rc;
14662
14663 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
14664 NOREF(uInvalidReason);
14665
14666#ifdef VBOX_STRICT
14667 uint32_t fIntrState;
14668 uint64_t u64Val;
14669 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
14670 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
14671 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
14672
14673 Log4(("uInvalidReason %u\n", uInvalidReason));
14674 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
14675 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
14676 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
14677
14678 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
14679 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
14680 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
14681 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
14682 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
14683 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
14684 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
14685 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14686 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
14687 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
14688 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
14689 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14690 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
14691 {
14692 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
14693 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
14694 }
14695 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
14696#endif
14697
14698 return VERR_VMX_INVALID_GUEST_STATE;
14699}
14700
14701/**
14702 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
14703 */
14704HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14705{
14706 /*
14707 * Cumulative notes of all recognized but unexpected VM-exits.
14708 *
14709 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
14710 * nested-paging is used.
14711 *
14712 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
14713 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
14714 * this function (and thereby stop VM execution) for handling such instructions.
14715 *
14716 *
14717 * VMX_EXIT_INIT_SIGNAL:
14718 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
14719 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
14720 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
14721 *
14722 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
14723 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
14724 * See Intel spec. "23.8 Restrictions on VMX operation".
14725 *
14726 * VMX_EXIT_SIPI:
14727 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
14728 * activity state is used. We don't make use of it as our guests don't have direct
14729 * access to the host local APIC.
14730 *
14731 * See Intel spec. 25.3 "Other Causes of VM-exits".
14732 *
14733 * VMX_EXIT_IO_SMI:
14734 * VMX_EXIT_SMI:
14735 * This can only happen if we support dual-monitor treatment of SMI, which can be
14736 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
14737 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
14738 * VMX root mode or receive an SMI. If we get here, something funny is going on.
14739 *
14740 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
14741 * See Intel spec. 25.3 "Other Causes of VM-Exits"
14742 *
14743 * VMX_EXIT_ERR_MSR_LOAD:
14744 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
14745 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
14746 * execution.
14747 *
14748 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
14749 *
14750 * VMX_EXIT_ERR_MACHINE_CHECK:
14751 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
14752 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
14753 * #MC exception abort class exception is raised. We thus cannot assume a
14754 * reasonable chance of continuing any sort of execution and we bail.
14755 *
14756 * See Intel spec. 15.1 "Machine-check Architecture".
14757 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
14758 *
14759 * VMX_EXIT_PML_FULL:
14760 * VMX_EXIT_VIRTUALIZED_EOI:
14761 * VMX_EXIT_APIC_WRITE:
14762 * We do not currently support any of these features and thus they are all unexpected
14763 * VM-exits.
14764 *
14765 * VMX_EXIT_GDTR_IDTR_ACCESS:
14766 * VMX_EXIT_LDTR_TR_ACCESS:
14767 * VMX_EXIT_RDRAND:
14768 * VMX_EXIT_RSM:
14769 * VMX_EXIT_VMFUNC:
14770 * VMX_EXIT_ENCLS:
14771 * VMX_EXIT_RDSEED:
14772 * VMX_EXIT_XSAVES:
14773 * VMX_EXIT_XRSTORS:
14774 * VMX_EXIT_UMWAIT:
14775 * VMX_EXIT_TPAUSE:
14776 * These VM-exits are -not- caused unconditionally by execution of the corresponding
14777 * instruction. Any VM-exit for these instructions indicate a hardware problem,
14778 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
14779 *
14780 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
14781 */
14782 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14783 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
14784 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14785}
14786
14787
14788/**
14789 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
14790 */
14791HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14792{
14793 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14794
14795 /** @todo Optimize this: We currently drag in the whole MSR state
14796 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14797 * MSRs required. That would require changes to IEM and possibly CPUM too.
14798 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14799 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14800 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14801 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14802 switch (idMsr)
14803 {
14804 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14805 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14806 }
14807
14808 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14809 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14810 AssertRCReturn(rc, rc);
14811
14812 Log4Func(("ecx=%#RX32\n", idMsr));
14813
14814#ifdef VBOX_STRICT
14815 Assert(!pVmxTransient->fIsNestedGuest);
14816 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
14817 {
14818 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
14819 && idMsr != MSR_K6_EFER)
14820 {
14821 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
14822 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14823 }
14824 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14825 {
14826 Assert(pVmcsInfo->pvMsrBitmap);
14827 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14828 if (fMsrpm & VMXMSRPM_ALLOW_RD)
14829 {
14830 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
14831 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14832 }
14833 }
14834 }
14835#endif
14836
14837 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
14838 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
14839 if (rcStrict == VINF_SUCCESS)
14840 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14841 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14842 {
14843 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14844 rcStrict = VINF_SUCCESS;
14845 }
14846 else
14847 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14848
14849 return rcStrict;
14850}
14851
14852
14853/**
14854 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
14855 */
14856HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14857{
14858 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14859
14860 /** @todo Optimize this: We currently drag in the whole MSR state
14861 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14862 * MSRs required. That would require changes to IEM and possibly CPUM too.
14863 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14864 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14865 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14866
14867 /*
14868 * The FS and GS base MSRs are not part of the above all-MSRs mask.
14869 * Although we don't need to fetch the base as it will be overwritten shortly, while
14870 * loading guest-state we would also load the entire segment register including limit
14871 * and attributes and thus we need to load them here.
14872 */
14873 switch (idMsr)
14874 {
14875 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14876 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14877 }
14878
14879 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14880 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14881 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14882 AssertRCReturn(rc, rc);
14883
14884 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
14885
14886 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
14887 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
14888
14889 if (rcStrict == VINF_SUCCESS)
14890 {
14891 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14892
14893 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
14894 if ( idMsr == MSR_IA32_APICBASE
14895 || ( idMsr >= MSR_IA32_X2APIC_START
14896 && idMsr <= MSR_IA32_X2APIC_END))
14897 {
14898 /*
14899 * We've already saved the APIC related guest-state (TPR) in post-run phase.
14900 * When full APIC register virtualization is implemented we'll have to make
14901 * sure APIC state is saved from the VMCS before IEM changes it.
14902 */
14903 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
14904 }
14905 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
14906 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14907 else if (idMsr == MSR_K6_EFER)
14908 {
14909 /*
14910 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
14911 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
14912 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
14913 */
14914 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
14915 }
14916
14917 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
14918 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
14919 {
14920 switch (idMsr)
14921 {
14922 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
14923 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
14924 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
14925 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
14926 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
14927 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
14928 default:
14929 {
14930 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14931 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
14932 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14933 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
14934 break;
14935 }
14936 }
14937 }
14938#ifdef VBOX_STRICT
14939 else
14940 {
14941 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
14942 switch (idMsr)
14943 {
14944 case MSR_IA32_SYSENTER_CS:
14945 case MSR_IA32_SYSENTER_EIP:
14946 case MSR_IA32_SYSENTER_ESP:
14947 case MSR_K8_FS_BASE:
14948 case MSR_K8_GS_BASE:
14949 {
14950 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
14951 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14952 }
14953
14954 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
14955 default:
14956 {
14957 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14958 {
14959 /* EFER MSR writes are always intercepted. */
14960 if (idMsr != MSR_K6_EFER)
14961 {
14962 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
14963 idMsr));
14964 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14965 }
14966 }
14967
14968 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14969 {
14970 Assert(pVmcsInfo->pvMsrBitmap);
14971 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14972 if (fMsrpm & VMXMSRPM_ALLOW_WR)
14973 {
14974 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
14975 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14976 }
14977 }
14978 break;
14979 }
14980 }
14981 }
14982#endif /* VBOX_STRICT */
14983 }
14984 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14985 {
14986 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14987 rcStrict = VINF_SUCCESS;
14988 }
14989 else
14990 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14991
14992 return rcStrict;
14993}
14994
14995
14996/**
14997 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
14998 */
14999HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15000{
15001 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15002
15003 /** @todo The guest has likely hit a contended spinlock. We might want to
15004 * poke a schedule different guest VCPU. */
15005 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15006 if (RT_SUCCESS(rc))
15007 return VINF_EM_RAW_INTERRUPT;
15008
15009 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15010 return rc;
15011}
15012
15013
15014/**
15015 * VM-exit handler for when the TPR value is lowered below the specified
15016 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15017 */
15018HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15019{
15020 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15021 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15022
15023 /*
15024 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15025 * We'll re-evaluate pending interrupts and inject them before the next VM
15026 * entry so we can just continue execution here.
15027 */
15028 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15029 return VINF_SUCCESS;
15030}
15031
15032
15033/**
15034 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15035 * VM-exit.
15036 *
15037 * @retval VINF_SUCCESS when guest execution can continue.
15038 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15039 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15040 * incompatible guest state for VMX execution (real-on-v86 case).
15041 */
15042HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15043{
15044 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15045 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15046
15047 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15048 hmR0VmxReadExitQualVmcs(pVmxTransient);
15049 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15050
15051 VBOXSTRICTRC rcStrict;
15052 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15053 uint64_t const uExitQual = pVmxTransient->uExitQual;
15054 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15055 switch (uAccessType)
15056 {
15057 /*
15058 * MOV to CRx.
15059 */
15060 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15061 {
15062 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15063 AssertRCReturn(rc, rc);
15064
15065 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15066 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15067 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15068 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15069
15070 /*
15071 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15072 * - When nested paging isn't used.
15073 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15074 * - We are executing in the VM debug loop.
15075 */
15076 Assert( iCrReg != 3
15077 || !pVM->hm.s.fNestedPaging
15078 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15079 || pVCpu->hm.s.fUsingDebugLoop);
15080
15081 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15082 Assert( iCrReg != 8
15083 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15084
15085 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15086 AssertMsg( rcStrict == VINF_SUCCESS
15087 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15088
15089 /*
15090 * This is a kludge for handling switches back to real mode when we try to use
15091 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15092 * deal with special selector values, so we have to return to ring-3 and run
15093 * there till the selector values are V86 mode compatible.
15094 *
15095 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15096 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15097 * this function.
15098 */
15099 if ( iCrReg == 0
15100 && rcStrict == VINF_SUCCESS
15101 && !pVM->hm.s.vmx.fUnrestrictedGuest
15102 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15103 && (uOldCr0 & X86_CR0_PE)
15104 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15105 {
15106 /** @todo Check selectors rather than returning all the time. */
15107 Assert(!pVmxTransient->fIsNestedGuest);
15108 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15109 rcStrict = VINF_EM_RESCHEDULE_REM;
15110 }
15111 break;
15112 }
15113
15114 /*
15115 * MOV from CRx.
15116 */
15117 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15118 {
15119 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15120 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15121
15122 /*
15123 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15124 * - When nested paging isn't used.
15125 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15126 * - We are executing in the VM debug loop.
15127 */
15128 Assert( iCrReg != 3
15129 || !pVM->hm.s.fNestedPaging
15130 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15131 || pVCpu->hm.s.fUsingDebugLoop);
15132
15133 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15134 Assert( iCrReg != 8
15135 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15136
15137 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15138 break;
15139 }
15140
15141 /*
15142 * CLTS (Clear Task-Switch Flag in CR0).
15143 */
15144 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15145 {
15146 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15147 break;
15148 }
15149
15150 /*
15151 * LMSW (Load Machine-Status Word into CR0).
15152 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15153 */
15154 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15155 {
15156 RTGCPTR GCPtrEffDst;
15157 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15158 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15159 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15160 if (fMemOperand)
15161 {
15162 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15163 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15164 }
15165 else
15166 GCPtrEffDst = NIL_RTGCPTR;
15167 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15168 break;
15169 }
15170
15171 default:
15172 {
15173 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15174 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15175 }
15176 }
15177
15178 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15179 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15180 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15181
15182 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15183 NOREF(pVM);
15184 return rcStrict;
15185}
15186
15187
15188/**
15189 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15190 * VM-exit.
15191 */
15192HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15193{
15194 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15195 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15196
15197 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15198 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15199 hmR0VmxReadExitQualVmcs(pVmxTransient);
15200 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15201 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15202 | CPUMCTX_EXTRN_EFER);
15203 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15204 AssertRCReturn(rc, rc);
15205
15206 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15207 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15208 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15209 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15210 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15211 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15212 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15213 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15214
15215 /*
15216 * Update exit history to see if this exit can be optimized.
15217 */
15218 VBOXSTRICTRC rcStrict;
15219 PCEMEXITREC pExitRec = NULL;
15220 if ( !fGstStepping
15221 && !fDbgStepping)
15222 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15223 !fIOString
15224 ? !fIOWrite
15225 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15226 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15227 : !fIOWrite
15228 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15229 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15230 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15231 if (!pExitRec)
15232 {
15233 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15234 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15235
15236 uint32_t const cbValue = s_aIOSizes[uIOSize];
15237 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15238 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15239 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15240 if (fIOString)
15241 {
15242 /*
15243 * INS/OUTS - I/O String instruction.
15244 *
15245 * Use instruction-information if available, otherwise fall back on
15246 * interpreting the instruction.
15247 */
15248 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15249 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15250 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15251 if (fInsOutsInfo)
15252 {
15253 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15254 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15255 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15256 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15257 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15258 if (fIOWrite)
15259 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15260 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15261 else
15262 {
15263 /*
15264 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15265 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15266 * See Intel Instruction spec. for "INS".
15267 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15268 */
15269 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15270 }
15271 }
15272 else
15273 rcStrict = IEMExecOne(pVCpu);
15274
15275 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15276 fUpdateRipAlready = true;
15277 }
15278 else
15279 {
15280 /*
15281 * IN/OUT - I/O instruction.
15282 */
15283 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15284 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15285 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15286 if (fIOWrite)
15287 {
15288 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15289 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15290 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15291 && !pCtx->eflags.Bits.u1TF)
15292 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15293 }
15294 else
15295 {
15296 uint32_t u32Result = 0;
15297 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15298 if (IOM_SUCCESS(rcStrict))
15299 {
15300 /* Save result of I/O IN instr. in AL/AX/EAX. */
15301 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15302 }
15303 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15304 && !pCtx->eflags.Bits.u1TF)
15305 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15306 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15307 }
15308 }
15309
15310 if (IOM_SUCCESS(rcStrict))
15311 {
15312 if (!fUpdateRipAlready)
15313 {
15314 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15315 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15316 }
15317
15318 /*
15319 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15320 * while booting Fedora 17 64-bit guest.
15321 *
15322 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15323 */
15324 if (fIOString)
15325 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15326
15327 /*
15328 * If any I/O breakpoints are armed, we need to check if one triggered
15329 * and take appropriate action.
15330 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15331 */
15332 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15333 AssertRCReturn(rc, rc);
15334
15335 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15336 * execution engines about whether hyper BPs and such are pending. */
15337 uint32_t const uDr7 = pCtx->dr[7];
15338 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15339 && X86_DR7_ANY_RW_IO(uDr7)
15340 && (pCtx->cr4 & X86_CR4_DE))
15341 || DBGFBpIsHwIoArmed(pVM)))
15342 {
15343 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15344
15345 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15346 VMMRZCallRing3Disable(pVCpu);
15347 HM_DISABLE_PREEMPT(pVCpu);
15348
15349 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15350
15351 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15352 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15353 {
15354 /* Raise #DB. */
15355 if (fIsGuestDbgActive)
15356 ASMSetDR6(pCtx->dr[6]);
15357 if (pCtx->dr[7] != uDr7)
15358 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15359
15360 hmR0VmxSetPendingXcptDB(pVCpu);
15361 }
15362 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15363 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15364 else if ( rcStrict2 != VINF_SUCCESS
15365 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15366 rcStrict = rcStrict2;
15367 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15368
15369 HM_RESTORE_PREEMPT();
15370 VMMRZCallRing3Enable(pVCpu);
15371 }
15372 }
15373
15374#ifdef VBOX_STRICT
15375 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15376 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15377 Assert(!fIOWrite);
15378 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15379 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15380 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15381 Assert(fIOWrite);
15382 else
15383 {
15384# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15385 * statuses, that the VMM device and some others may return. See
15386 * IOM_SUCCESS() for guidance. */
15387 AssertMsg( RT_FAILURE(rcStrict)
15388 || rcStrict == VINF_SUCCESS
15389 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15390 || rcStrict == VINF_EM_DBG_BREAKPOINT
15391 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15392 || rcStrict == VINF_EM_RAW_TO_R3
15393 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15394# endif
15395 }
15396#endif
15397 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15398 }
15399 else
15400 {
15401 /*
15402 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15403 */
15404 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15405 AssertRCReturn(rc2, rc2);
15406 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15407 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15408 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15409 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15410 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15411 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15412
15413 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15414 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15415
15416 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15417 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15418 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15419 }
15420 return rcStrict;
15421}
15422
15423
15424/**
15425 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15426 * VM-exit.
15427 */
15428HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15429{
15430 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15431
15432 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15433 hmR0VmxReadExitQualVmcs(pVmxTransient);
15434 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15435 {
15436 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15437 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15438 {
15439 uint32_t uErrCode;
15440 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15441 {
15442 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15443 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15444 }
15445 else
15446 uErrCode = 0;
15447
15448 RTGCUINTPTR GCPtrFaultAddress;
15449 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15450 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15451 else
15452 GCPtrFaultAddress = 0;
15453
15454 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15455
15456 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15457 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15458
15459 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15460 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15461 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15462 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15463 }
15464 }
15465
15466 /* Fall back to the interpreter to emulate the task-switch. */
15467 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15468 return VERR_EM_INTERPRETER;
15469}
15470
15471
15472/**
15473 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15474 */
15475HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15476{
15477 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15478
15479 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15480 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15481 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15482 AssertRC(rc);
15483 return VINF_EM_DBG_STEPPED;
15484}
15485
15486
15487/**
15488 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15489 */
15490HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15491{
15492 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15493 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15494
15495 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15496 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15497 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15498 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15499 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15500
15501 /*
15502 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15503 */
15504 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15505 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15506 {
15507 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15508 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15509 {
15510 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15511 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15512 }
15513 }
15514 else
15515 {
15516 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15517 return rcStrict;
15518 }
15519
15520 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15521 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15522 hmR0VmxReadExitQualVmcs(pVmxTransient);
15523 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15524 AssertRCReturn(rc, rc);
15525
15526 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15527 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15528 switch (uAccessType)
15529 {
15530 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15531 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15532 {
15533 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15534 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15535 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15536
15537 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15538 GCPhys &= PAGE_BASE_GC_MASK;
15539 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15540 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15541 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15542
15543 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
15544 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
15545 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15546 if ( rcStrict == VINF_SUCCESS
15547 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15548 || rcStrict == VERR_PAGE_NOT_PRESENT)
15549 {
15550 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15551 | HM_CHANGED_GUEST_APIC_TPR);
15552 rcStrict = VINF_SUCCESS;
15553 }
15554 break;
15555 }
15556
15557 default:
15558 {
15559 Log4Func(("uAccessType=%#x\n", uAccessType));
15560 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15561 break;
15562 }
15563 }
15564
15565 if (rcStrict != VINF_SUCCESS)
15566 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15567 return rcStrict;
15568}
15569
15570
15571/**
15572 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15573 * VM-exit.
15574 */
15575HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15576{
15577 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15578 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15579
15580 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15581 if (!pVmxTransient->fIsNestedGuest)
15582 {
15583 /* We should -not- get this VM-exit if the guest's debug registers were active. */
15584 if (pVmxTransient->fWasGuestDebugStateActive)
15585 {
15586 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
15587 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15588 }
15589
15590 if ( !pVCpu->hm.s.fSingleInstruction
15591 && !pVmxTransient->fWasHyperDebugStateActive)
15592 {
15593 Assert(!DBGFIsStepping(pVCpu));
15594 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
15595
15596 /* Don't intercept MOV DRx any more. */
15597 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
15598 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15599 AssertRC(rc);
15600
15601 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
15602 VMMRZCallRing3Disable(pVCpu);
15603 HM_DISABLE_PREEMPT(pVCpu);
15604
15605 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
15606 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
15607 Assert(CPUMIsGuestDebugStateActive(pVCpu));
15608
15609 HM_RESTORE_PREEMPT();
15610 VMMRZCallRing3Enable(pVCpu);
15611
15612#ifdef VBOX_WITH_STATISTICS
15613 hmR0VmxReadExitQualVmcs(pVmxTransient);
15614 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15615 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15616 else
15617 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15618#endif
15619 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
15620 return VINF_SUCCESS;
15621 }
15622 }
15623
15624 /*
15625 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
15626 * The EFER MSR is always up-to-date.
15627 * Update the segment registers and DR7 from the CPU.
15628 */
15629 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15630 hmR0VmxReadExitQualVmcs(pVmxTransient);
15631 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
15632 AssertRCReturn(rc, rc);
15633 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
15634
15635 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15636 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15637 {
15638 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15639 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
15640 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
15641 if (RT_SUCCESS(rc))
15642 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
15643 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15644 }
15645 else
15646 {
15647 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15648 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
15649 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
15650 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15651 }
15652
15653 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
15654 if (RT_SUCCESS(rc))
15655 {
15656 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15657 AssertRCReturn(rc2, rc2);
15658 return VINF_SUCCESS;
15659 }
15660 return rc;
15661}
15662
15663
15664/**
15665 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
15666 * Conditional VM-exit.
15667 */
15668HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15669{
15670 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15671 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15672
15673 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15674 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15675 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15676 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15677 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15678
15679 /*
15680 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15681 */
15682 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15683 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15684 {
15685 /*
15686 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
15687 * instruction emulation to inject the original event. Otherwise, injecting the original event
15688 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
15689 */
15690 if (!pVCpu->hm.s.Event.fPending)
15691 { /* likely */ }
15692 else
15693 {
15694 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15695#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15696 /** @todo NSTVMX: Think about how this should be handled. */
15697 if (pVmxTransient->fIsNestedGuest)
15698 return VERR_VMX_IPE_3;
15699#endif
15700 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15701 }
15702 }
15703 else
15704 {
15705 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15706 return rcStrict;
15707 }
15708
15709 /*
15710 * Get sufficient state and update the exit history entry.
15711 */
15712 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15713 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15714 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15715 AssertRCReturn(rc, rc);
15716
15717 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15718 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15719 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
15720 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15721 if (!pExitRec)
15722 {
15723 /*
15724 * If we succeed, resume guest execution.
15725 * If we fail in interpreting the instruction because we couldn't get the guest physical address
15726 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
15727 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
15728 * weird case. See @bugref{6043}.
15729 */
15730 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15731 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15732 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
15733 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
15734 if ( rcStrict == VINF_SUCCESS
15735 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15736 || rcStrict == VERR_PAGE_NOT_PRESENT)
15737 {
15738 /* Successfully handled MMIO operation. */
15739 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15740 | HM_CHANGED_GUEST_APIC_TPR);
15741 rcStrict = VINF_SUCCESS;
15742 }
15743 }
15744 else
15745 {
15746 /*
15747 * Frequent exit or something needing probing. Call EMHistoryExec.
15748 */
15749 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
15750 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
15751
15752 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15753 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15754
15755 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15756 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15757 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15758 }
15759 return rcStrict;
15760}
15761
15762
15763/**
15764 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
15765 * VM-exit.
15766 */
15767HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15768{
15769 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15770 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15771
15772 hmR0VmxReadExitQualVmcs(pVmxTransient);
15773 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15774 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15775 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15776 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15777 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15778
15779 /*
15780 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15781 */
15782 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15783 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15784 {
15785 /*
15786 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
15787 * we shall resolve the nested #PF and re-inject the original event.
15788 */
15789 if (pVCpu->hm.s.Event.fPending)
15790 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
15791 }
15792 else
15793 {
15794 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15795 return rcStrict;
15796 }
15797
15798 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15799 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15800 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15801 AssertRCReturn(rc, rc);
15802
15803 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15804 uint64_t const uExitQual = pVmxTransient->uExitQual;
15805 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
15806
15807 RTGCUINT uErrorCode = 0;
15808 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
15809 uErrorCode |= X86_TRAP_PF_ID;
15810 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
15811 uErrorCode |= X86_TRAP_PF_RW;
15812 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
15813 uErrorCode |= X86_TRAP_PF_P;
15814
15815 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15816 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15817 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
15818
15819 /*
15820 * Handle the pagefault trap for the nested shadow table.
15821 */
15822 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
15823 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
15824 TRPMResetTrap(pVCpu);
15825
15826 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
15827 if ( rcStrict == VINF_SUCCESS
15828 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15829 || rcStrict == VERR_PAGE_NOT_PRESENT)
15830 {
15831 /* Successfully synced our nested page tables. */
15832 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
15833 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
15834 return VINF_SUCCESS;
15835 }
15836
15837 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15838 return rcStrict;
15839}
15840
15841
15842#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15843/**
15844 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
15845 */
15846HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15847{
15848 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15849
15850 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15851 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15852 hmR0VmxReadExitQualVmcs(pVmxTransient);
15853 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15854 | CPUMCTX_EXTRN_HWVIRT
15855 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15856 AssertRCReturn(rc, rc);
15857
15858 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15859
15860 VMXVEXITINFO ExitInfo;
15861 RT_ZERO(ExitInfo);
15862 ExitInfo.uReason = pVmxTransient->uExitReason;
15863 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15864 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15865 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15866 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15867
15868 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
15869 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15870 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15871 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15872 {
15873 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15874 rcStrict = VINF_SUCCESS;
15875 }
15876 return rcStrict;
15877}
15878
15879
15880/**
15881 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
15882 */
15883HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15884{
15885 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15886
15887 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
15888 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15889 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15890 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15891 AssertRCReturn(rc, rc);
15892
15893 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15894
15895 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15896 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
15897 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15898 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15899 {
15900 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15901 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15902 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15903 }
15904 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15905 return rcStrict;
15906}
15907
15908
15909/**
15910 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
15911 */
15912HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15913{
15914 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15915
15916 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15917 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15918 hmR0VmxReadExitQualVmcs(pVmxTransient);
15919 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15920 | CPUMCTX_EXTRN_HWVIRT
15921 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15922 AssertRCReturn(rc, rc);
15923
15924 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15925
15926 VMXVEXITINFO ExitInfo;
15927 RT_ZERO(ExitInfo);
15928 ExitInfo.uReason = pVmxTransient->uExitReason;
15929 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15930 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15931 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15932 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15933
15934 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
15935 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15936 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15937 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15938 {
15939 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15940 rcStrict = VINF_SUCCESS;
15941 }
15942 return rcStrict;
15943}
15944
15945
15946/**
15947 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
15948 */
15949HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15950{
15951 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15952
15953 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15954 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15955 hmR0VmxReadExitQualVmcs(pVmxTransient);
15956 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15957 | CPUMCTX_EXTRN_HWVIRT
15958 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15959 AssertRCReturn(rc, rc);
15960
15961 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15962
15963 VMXVEXITINFO ExitInfo;
15964 RT_ZERO(ExitInfo);
15965 ExitInfo.uReason = pVmxTransient->uExitReason;
15966 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15967 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15968 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15969 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15970
15971 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
15972 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15973 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15974 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15975 {
15976 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15977 rcStrict = VINF_SUCCESS;
15978 }
15979 return rcStrict;
15980}
15981
15982
15983/**
15984 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
15985 */
15986HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15987{
15988 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15989
15990 /*
15991 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
15992 * thus might not need to import the shadow VMCS state, it's safer just in case
15993 * code elsewhere dares look at unsynced VMCS fields.
15994 */
15995 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15996 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15997 hmR0VmxReadExitQualVmcs(pVmxTransient);
15998 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15999 | CPUMCTX_EXTRN_HWVIRT
16000 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16001 AssertRCReturn(rc, rc);
16002
16003 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16004
16005 VMXVEXITINFO ExitInfo;
16006 RT_ZERO(ExitInfo);
16007 ExitInfo.uReason = pVmxTransient->uExitReason;
16008 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16009 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16010 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16011 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16012 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16013
16014 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16015 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16016 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16017 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16018 {
16019 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16020 rcStrict = VINF_SUCCESS;
16021 }
16022 return rcStrict;
16023}
16024
16025
16026/**
16027 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16028 */
16029HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16030{
16031 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16032
16033 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16034 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16035 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16036 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16037 AssertRCReturn(rc, rc);
16038
16039 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16040
16041 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16042 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16043 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16044 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16045 {
16046 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16047 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16048 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16049 }
16050 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16051 return rcStrict;
16052}
16053
16054
16055/**
16056 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16057 */
16058HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16059{
16060 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16061
16062 /*
16063 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16064 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16065 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16066 */
16067 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16068 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16069 hmR0VmxReadExitQualVmcs(pVmxTransient);
16070 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16071 | CPUMCTX_EXTRN_HWVIRT
16072 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16073 AssertRCReturn(rc, rc);
16074
16075 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16076
16077 VMXVEXITINFO ExitInfo;
16078 RT_ZERO(ExitInfo);
16079 ExitInfo.uReason = pVmxTransient->uExitReason;
16080 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16081 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16082 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16083 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16084 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16085
16086 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16087 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16088 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16089 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16090 {
16091 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16092 rcStrict = VINF_SUCCESS;
16093 }
16094 return rcStrict;
16095}
16096
16097
16098/**
16099 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16100 */
16101HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16102{
16103 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16104
16105 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16106 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16107 | CPUMCTX_EXTRN_HWVIRT
16108 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16109 AssertRCReturn(rc, rc);
16110
16111 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16112
16113 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16114 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16115 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16116 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16117 {
16118 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16119 rcStrict = VINF_SUCCESS;
16120 }
16121 return rcStrict;
16122}
16123
16124
16125/**
16126 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16127 */
16128HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16129{
16130 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16131
16132 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16133 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16134 hmR0VmxReadExitQualVmcs(pVmxTransient);
16135 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16136 | CPUMCTX_EXTRN_HWVIRT
16137 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16138 AssertRCReturn(rc, rc);
16139
16140 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16141
16142 VMXVEXITINFO ExitInfo;
16143 RT_ZERO(ExitInfo);
16144 ExitInfo.uReason = pVmxTransient->uExitReason;
16145 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16146 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16147 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16148 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16149
16150 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16151 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16152 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16153 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16154 {
16155 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16156 rcStrict = VINF_SUCCESS;
16157 }
16158 return rcStrict;
16159}
16160
16161
16162/**
16163 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16164 */
16165HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16166{
16167 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16168
16169 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16170 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16171 hmR0VmxReadExitQualVmcs(pVmxTransient);
16172 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16173 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16174 AssertRCReturn(rc, rc);
16175
16176 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16177
16178 VMXVEXITINFO ExitInfo;
16179 RT_ZERO(ExitInfo);
16180 ExitInfo.uReason = pVmxTransient->uExitReason;
16181 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16182 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16183 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16184 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16185
16186 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16187 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16188 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16189 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16190 {
16191 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16192 rcStrict = VINF_SUCCESS;
16193 }
16194 return rcStrict;
16195}
16196#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16197/** @} */
16198
16199
16200#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16201/** @name Nested-guest VM-exit handlers.
16202 * @{
16203 */
16204/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16205/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16206/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16207
16208/**
16209 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16210 * Conditional VM-exit.
16211 */
16212HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16213{
16214 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16215
16216 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16217
16218 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16219 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16220 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16221
16222 switch (uExitIntType)
16223 {
16224 /*
16225 * Physical NMIs:
16226 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16227 */
16228 case VMX_EXIT_INT_INFO_TYPE_NMI:
16229 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16230
16231 /*
16232 * Hardware exceptions,
16233 * Software exceptions,
16234 * Privileged software exceptions:
16235 * Figure out if the exception must be delivered to the guest or the nested-guest.
16236 */
16237 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16238 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16239 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16240 {
16241 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16242 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16243 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16244 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16245
16246 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16247 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16248 pVmxTransient->uExitIntErrorCode);
16249 if (fIntercept)
16250 {
16251 /* Exit qualification is required for debug and page-fault exceptions. */
16252 hmR0VmxReadExitQualVmcs(pVmxTransient);
16253
16254 /*
16255 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16256 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16257 * length. However, if delivery of a software interrupt, software exception or privileged
16258 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16259 */
16260 VMXVEXITINFO ExitInfo;
16261 RT_ZERO(ExitInfo);
16262 ExitInfo.uReason = pVmxTransient->uExitReason;
16263 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16264 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16265
16266 VMXVEXITEVENTINFO ExitEventInfo;
16267 RT_ZERO(ExitEventInfo);
16268 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16269 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16270 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16271 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16272
16273#ifdef DEBUG_ramshankar
16274 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16275 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16276 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16277 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16278 {
16279 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16280 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16281 }
16282#endif
16283 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16284 }
16285
16286 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16287 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16288 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16289 }
16290
16291 /*
16292 * Software interrupts:
16293 * VM-exits cannot be caused by software interrupts.
16294 *
16295 * External interrupts:
16296 * This should only happen when "acknowledge external interrupts on VM-exit"
16297 * control is set. However, we never set this when executing a guest or
16298 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16299 * the guest.
16300 */
16301 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16302 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16303 default:
16304 {
16305 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16306 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16307 }
16308 }
16309}
16310
16311
16312/**
16313 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16314 * Unconditional VM-exit.
16315 */
16316HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16317{
16318 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16319 return IEMExecVmxVmexitTripleFault(pVCpu);
16320}
16321
16322
16323/**
16324 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16325 */
16326HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16327{
16328 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16329
16330 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16331 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16332 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16333}
16334
16335
16336/**
16337 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16338 */
16339HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16340{
16341 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16342
16343 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16344 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16345 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16346}
16347
16348
16349/**
16350 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16351 * Unconditional VM-exit.
16352 */
16353HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16354{
16355 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16356
16357 hmR0VmxReadExitQualVmcs(pVmxTransient);
16358 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16359 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16360 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16361
16362 VMXVEXITINFO ExitInfo;
16363 RT_ZERO(ExitInfo);
16364 ExitInfo.uReason = pVmxTransient->uExitReason;
16365 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16366 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16367
16368 VMXVEXITEVENTINFO ExitEventInfo;
16369 RT_ZERO(ExitEventInfo);
16370 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16371 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16372 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16373}
16374
16375
16376/**
16377 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16378 */
16379HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16380{
16381 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16382
16383 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16384 {
16385 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16386 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16387 }
16388 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16389}
16390
16391
16392/**
16393 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16394 */
16395HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16396{
16397 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16398
16399 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16400 {
16401 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16402 hmR0VmxReadExitQualVmcs(pVmxTransient);
16403
16404 VMXVEXITINFO ExitInfo;
16405 RT_ZERO(ExitInfo);
16406 ExitInfo.uReason = pVmxTransient->uExitReason;
16407 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16408 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16409 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16410 }
16411 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16412}
16413
16414
16415/**
16416 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16417 */
16418HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16419{
16420 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16421
16422 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16423 {
16424 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16425 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16426 }
16427 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16428}
16429
16430
16431/**
16432 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16433 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16434 */
16435HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16436{
16437 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16438
16439 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16440 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16441
16442 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16443
16444 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16445 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16446 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16447
16448 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16449 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16450 u64VmcsField &= UINT64_C(0xffffffff);
16451
16452 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16453 {
16454 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16455 hmR0VmxReadExitQualVmcs(pVmxTransient);
16456
16457 VMXVEXITINFO ExitInfo;
16458 RT_ZERO(ExitInfo);
16459 ExitInfo.uReason = pVmxTransient->uExitReason;
16460 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16461 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16462 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16463 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16464 }
16465
16466 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16467 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16468 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16469}
16470
16471
16472/**
16473 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16474 */
16475HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16476{
16477 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16478
16479 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16480 {
16481 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16482 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16483 }
16484
16485 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16486}
16487
16488
16489/**
16490 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16491 * Conditional VM-exit.
16492 */
16493HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16494{
16495 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16496
16497 hmR0VmxReadExitQualVmcs(pVmxTransient);
16498 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16499
16500 VBOXSTRICTRC rcStrict;
16501 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16502 switch (uAccessType)
16503 {
16504 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16505 {
16506 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16507 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16508 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16509 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16510
16511 bool fIntercept;
16512 switch (iCrReg)
16513 {
16514 case 0:
16515 case 4:
16516 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(&pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16517 break;
16518
16519 case 3:
16520 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16521 break;
16522
16523 case 8:
16524 fIntercept = CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16525 break;
16526
16527 default:
16528 fIntercept = false;
16529 break;
16530 }
16531 if (fIntercept)
16532 {
16533 VMXVEXITINFO ExitInfo;
16534 RT_ZERO(ExitInfo);
16535 ExitInfo.uReason = pVmxTransient->uExitReason;
16536 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16537 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16538 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16539 }
16540 else
16541 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16542 break;
16543 }
16544
16545 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16546 {
16547 /*
16548 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16549 * CR2 reads do not cause a VM-exit.
16550 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16551 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16552 */
16553 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16554 if ( iCrReg == 3
16555 || iCrReg == 8)
16556 {
16557 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16558 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16559 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16560 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uIntercept))
16561 {
16562 VMXVEXITINFO ExitInfo;
16563 RT_ZERO(ExitInfo);
16564 ExitInfo.uReason = pVmxTransient->uExitReason;
16565 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16566 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16567 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16568 }
16569 else
16570 {
16571 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16572 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16573 }
16574 }
16575 else
16576 {
16577 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
16578 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
16579 }
16580 break;
16581 }
16582
16583 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
16584 {
16585 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
16586 Assert(pVmcsNstGst);
16587 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
16588 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
16589 if ( (uGstHostMask & X86_CR0_TS)
16590 && (uReadShadow & X86_CR0_TS))
16591 {
16592 VMXVEXITINFO ExitInfo;
16593 RT_ZERO(ExitInfo);
16594 ExitInfo.uReason = pVmxTransient->uExitReason;
16595 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16596 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16597 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16598 }
16599 else
16600 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
16601 break;
16602 }
16603
16604 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
16605 {
16606 RTGCPTR GCPtrEffDst;
16607 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
16608 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
16609 if (fMemOperand)
16610 {
16611 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16612 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
16613 }
16614 else
16615 GCPtrEffDst = NIL_RTGCPTR;
16616
16617 if (CPUMIsGuestVmxLmswInterceptSet(&pVCpu->cpum.GstCtx, uNewMsw))
16618 {
16619 VMXVEXITINFO ExitInfo;
16620 RT_ZERO(ExitInfo);
16621 ExitInfo.uReason = pVmxTransient->uExitReason;
16622 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16623 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
16624 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16625 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16626 }
16627 else
16628 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
16629 break;
16630 }
16631
16632 default:
16633 {
16634 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
16635 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
16636 }
16637 }
16638
16639 if (rcStrict == VINF_IEM_RAISED_XCPT)
16640 {
16641 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16642 rcStrict = VINF_SUCCESS;
16643 }
16644 return rcStrict;
16645}
16646
16647
16648/**
16649 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
16650 * Conditional VM-exit.
16651 */
16652HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16653{
16654 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16655
16656 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
16657 {
16658 hmR0VmxReadExitQualVmcs(pVmxTransient);
16659 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16660
16661 VMXVEXITINFO ExitInfo;
16662 RT_ZERO(ExitInfo);
16663 ExitInfo.uReason = pVmxTransient->uExitReason;
16664 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16665 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16666 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16667 }
16668 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
16669}
16670
16671
16672/**
16673 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
16674 * Conditional VM-exit.
16675 */
16676HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16677{
16678 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16679
16680 hmR0VmxReadExitQualVmcs(pVmxTransient);
16681
16682 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16683 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16684 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16685
16686 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16687 uint8_t const cbAccess = s_aIOSizes[uIOSize];
16688 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
16689 {
16690 /*
16691 * IN/OUT instruction:
16692 * - Provides VM-exit instruction length.
16693 *
16694 * INS/OUTS instruction:
16695 * - Provides VM-exit instruction length.
16696 * - Provides Guest-linear address.
16697 * - Optionally provides VM-exit instruction info (depends on CPU feature).
16698 */
16699 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16700 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16701
16702 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
16703 pVmxTransient->ExitInstrInfo.u = 0;
16704 pVmxTransient->uGuestLinearAddr = 0;
16705
16706 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
16707 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
16708 if (fIOString)
16709 {
16710 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16711 if (fVmxInsOutsInfo)
16712 {
16713 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
16714 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16715 }
16716 }
16717
16718 VMXVEXITINFO ExitInfo;
16719 RT_ZERO(ExitInfo);
16720 ExitInfo.uReason = pVmxTransient->uExitReason;
16721 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16722 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16723 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16724 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
16725 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16726 }
16727 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
16728}
16729
16730
16731/**
16732 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
16733 */
16734HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16735{
16736 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16737
16738 uint32_t fMsrpm;
16739 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16740 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16741 else
16742 fMsrpm = VMXMSRPM_EXIT_RD;
16743
16744 if (fMsrpm & VMXMSRPM_EXIT_RD)
16745 {
16746 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16747 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16748 }
16749 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
16750}
16751
16752
16753/**
16754 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
16755 */
16756HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16757{
16758 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16759
16760 uint32_t fMsrpm;
16761 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16762 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16763 else
16764 fMsrpm = VMXMSRPM_EXIT_WR;
16765
16766 if (fMsrpm & VMXMSRPM_EXIT_WR)
16767 {
16768 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16769 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16770 }
16771 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
16772}
16773
16774
16775/**
16776 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
16777 */
16778HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16779{
16780 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16781
16782 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
16783 {
16784 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16785 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16786 }
16787 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
16788}
16789
16790
16791/**
16792 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
16793 * VM-exit.
16794 */
16795HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16796{
16797 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16798
16799 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
16800 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
16801 VMXVEXITINFO ExitInfo;
16802 RT_ZERO(ExitInfo);
16803 ExitInfo.uReason = pVmxTransient->uExitReason;
16804 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
16805 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
16806}
16807
16808
16809/**
16810 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
16811 */
16812HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16813{
16814 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16815
16816 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
16817 {
16818 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16819 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16820 }
16821 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
16822}
16823
16824
16825/**
16826 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
16827 */
16828HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16829{
16830 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16831
16832 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
16833 * PAUSE when executing a nested-guest? If it does not, we would not need
16834 * to check for the intercepts here. Just call VM-exit... */
16835
16836 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
16837 if ( CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
16838 || CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
16839 {
16840 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16841 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16842 }
16843 return hmR0VmxExitPause(pVCpu, pVmxTransient);
16844}
16845
16846
16847/**
16848 * Nested-guest VM-exit handler for when the TPR value is lowered below the
16849 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
16850 */
16851HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16852{
16853 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16854
16855 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
16856 {
16857 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
16858 VMXVEXITINFO ExitInfo;
16859 RT_ZERO(ExitInfo);
16860 ExitInfo.uReason = pVmxTransient->uExitReason;
16861 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
16862 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
16863 }
16864 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
16865}
16866
16867
16868/**
16869 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
16870 * VM-exit.
16871 */
16872HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16873{
16874 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16875
16876 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16877 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16878 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16879 hmR0VmxReadExitQualVmcs(pVmxTransient);
16880
16881 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
16882
16883 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
16884 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
16885
16886 VMXVEXITINFO ExitInfo;
16887 RT_ZERO(ExitInfo);
16888 ExitInfo.uReason = pVmxTransient->uExitReason;
16889 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16890 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16891
16892 VMXVEXITEVENTINFO ExitEventInfo;
16893 RT_ZERO(ExitEventInfo);
16894 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16895 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16896 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
16897}
16898
16899
16900/**
16901 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
16902 * Conditional VM-exit.
16903 */
16904HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16905{
16906 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16907
16908 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
16909 hmR0VmxReadExitQualVmcs(pVmxTransient);
16910 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16911}
16912
16913
16914/**
16915 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
16916 * Conditional VM-exit.
16917 */
16918HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16919{
16920 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16921
16922 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
16923 hmR0VmxReadExitQualVmcs(pVmxTransient);
16924 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16925}
16926
16927
16928/**
16929 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
16930 */
16931HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16932{
16933 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16934
16935 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16936 {
16937 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
16938 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16939 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16940 }
16941 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
16942}
16943
16944
16945/**
16946 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
16947 */
16948HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16949{
16950 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16951
16952 if (CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
16953 {
16954 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16955 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16956 }
16957 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
16958}
16959
16960
16961/**
16962 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
16963 */
16964HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16965{
16966 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16967
16968 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16969 {
16970 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
16971 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16972 hmR0VmxReadExitQualVmcs(pVmxTransient);
16973 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16974
16975 VMXVEXITINFO ExitInfo;
16976 RT_ZERO(ExitInfo);
16977 ExitInfo.uReason = pVmxTransient->uExitReason;
16978 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16979 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16980 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16981 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16982 }
16983 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
16984}
16985
16986
16987/**
16988 * Nested-guest VM-exit handler for invalid-guest state
16989 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
16990 */
16991HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16992{
16993 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16994
16995 /*
16996 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
16997 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
16998 * Handle it like it's in an invalid guest state of the outer guest.
16999 *
17000 * When the fast path is implemented, this should be changed to cause the corresponding
17001 * nested-guest VM-exit.
17002 */
17003 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17004}
17005
17006
17007/**
17008 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17009 * and only provide the instruction length.
17010 *
17011 * Unconditional VM-exit.
17012 */
17013HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17014{
17015 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17016
17017#ifdef VBOX_STRICT
17018 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17019 switch (pVmxTransient->uExitReason)
17020 {
17021 case VMX_EXIT_ENCLS:
17022 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17023 break;
17024
17025 case VMX_EXIT_VMFUNC:
17026 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_VMFUNC));
17027 break;
17028 }
17029#endif
17030
17031 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17032 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17033}
17034
17035
17036/**
17037 * Nested-guest VM-exit handler for instructions that provide instruction length as
17038 * well as more information.
17039 *
17040 * Unconditional VM-exit.
17041 */
17042HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17043{
17044 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17045
17046#ifdef VBOX_STRICT
17047 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17048 switch (pVmxTransient->uExitReason)
17049 {
17050 case VMX_EXIT_GDTR_IDTR_ACCESS:
17051 case VMX_EXIT_LDTR_TR_ACCESS:
17052 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17053 break;
17054
17055 case VMX_EXIT_RDRAND:
17056 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17057 break;
17058
17059 case VMX_EXIT_RDSEED:
17060 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17061 break;
17062
17063 case VMX_EXIT_XSAVES:
17064 case VMX_EXIT_XRSTORS:
17065 /** @todo NSTVMX: Verify XSS-bitmap. */
17066 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17067 break;
17068
17069 case VMX_EXIT_UMWAIT:
17070 case VMX_EXIT_TPAUSE:
17071 Assert(CPUMIsGuestVmxProcCtlsSet(pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17072 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17073 break;
17074 }
17075#endif
17076
17077 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17078 hmR0VmxReadExitQualVmcs(pVmxTransient);
17079 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17080
17081 VMXVEXITINFO ExitInfo;
17082 RT_ZERO(ExitInfo);
17083 ExitInfo.uReason = pVmxTransient->uExitReason;
17084 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17085 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17086 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17087 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17088}
17089
17090/** @} */
17091#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17092
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette