VirtualBox

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

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

VMM/HMVMXR0: Don't assert pbVirtApic or HCPhysVirtApic when APIC device isn't present and we don't allocate or fetch these pages.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 706.7 KB
Line 
1/* $Id: HMVMXR0.cpp 81638 2019-11-04 06:03:32Z 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, &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, &pVCpu->cpum.GstCtx,
1867 &pVmcsInfo->HCPhysVirtApic);
1868 Assert(pVmcsInfo->pbVirtApic);
1869 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1870 }
1871 }
1872
1873 return VINF_SUCCESS;
1874}
1875
1876
1877/**
1878 * Free all VT-x structures for the VM.
1879 *
1880 * @returns IPRT status code.
1881 * @param pVM The cross context VM structure.
1882 */
1883static void hmR0VmxStructsFree(PVMCC pVM)
1884{
1885 hmR0VmxPagesFree(pVM->hm.s.vmx.hMemObj);
1886#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1887 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1888 {
1889 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1890 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1891 }
1892#endif
1893
1894 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1895 {
1896 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1897 hmR0VmxVmcsInfoFree(&pVCpu->hm.s.vmx.VmcsInfo);
1898#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1899 if (pVM->cpum.ro.GuestFeatures.fVmx)
1900 hmR0VmxVmcsInfoFree(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1901#endif
1902 }
1903}
1904
1905
1906/**
1907 * Allocate all VT-x structures for the VM.
1908 *
1909 * @returns IPRT status code.
1910 * @param pVM The cross context VM structure.
1911 *
1912 * @remarks This functions will cleanup on memory allocation failures.
1913 */
1914static int hmR0VmxStructsAlloc(PVMCC pVM)
1915{
1916 /*
1917 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1918 * The VMCS size cannot be more than 4096 bytes.
1919 *
1920 * See Intel spec. Appendix A.1 "Basic VMX Information".
1921 */
1922 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1923 if (cbVmcs <= X86_PAGE_4K_SIZE)
1924 { /* likely */ }
1925 else
1926 {
1927 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1928 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1929 }
1930
1931 /*
1932 * Allocate per-VM VT-x structures.
1933 */
1934 bool const fVirtApicAccess = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
1935 bool const fUseVmcsShadowing = pVM->hm.s.vmx.fUseVmcsShadowing;
1936 VMXPAGEALLOCINFO aAllocInfo[] = {
1937 { fVirtApicAccess, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess },
1938 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap },
1939 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap },
1940#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1941 { true, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysScratch, &(PRTR0PTR)pVM->hm.s.vmx.pbScratch },
1942#endif
1943 };
1944
1945 int rc = hmR0VmxPagesAllocZ(pVM->hm.s.vmx.hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1946 if (RT_FAILURE(rc))
1947 goto cleanup;
1948
1949#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1950 /* Allocate the shadow VMCS-fields array. */
1951 if (fUseVmcsShadowing)
1952 {
1953 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
1954 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
1955 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1956 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1957 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
1958 && pVM->hm.s.vmx.paShadowVmcsRoFields))
1959 { /* likely */ }
1960 else
1961 {
1962 rc = VERR_NO_MEMORY;
1963 goto cleanup;
1964 }
1965 }
1966#endif
1967
1968 /*
1969 * Allocate per-VCPU VT-x structures.
1970 */
1971 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1972 {
1973 /* Allocate the guest VMCS structures. */
1974 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1975 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
1976 if (RT_FAILURE(rc))
1977 goto cleanup;
1978
1979#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1980 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
1981 if (pVM->cpum.ro.GuestFeatures.fVmx)
1982 {
1983 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
1984 if (RT_FAILURE(rc))
1985 goto cleanup;
1986 }
1987#endif
1988 }
1989
1990 return VINF_SUCCESS;
1991
1992cleanup:
1993 hmR0VmxStructsFree(pVM);
1994 Assert(rc != VINF_SUCCESS);
1995 return rc;
1996}
1997
1998
1999/**
2000 * Pre-initializes non-zero fields in VMX structures that will be allocated.
2001 *
2002 * @param pVM The cross context VM structure.
2003 */
2004static void hmR0VmxStructsInit(PVMCC pVM)
2005{
2006 /* Paranoia. */
2007 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
2008#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2009 Assert(pVM->hm.s.vmx.pbScratch == NULL);
2010#endif
2011
2012 /*
2013 * Initialize members up-front so we can cleanup en masse on allocation failures.
2014 */
2015#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2016 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
2017#endif
2018 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
2019 pVM->hm.s.vmx.HCPhysVmreadBitmap = NIL_RTHCPHYS;
2020 pVM->hm.s.vmx.HCPhysVmwriteBitmap = NIL_RTHCPHYS;
2021 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2022 {
2023 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2024 hmR0VmxVmcsInfoInit(&pVCpu->hm.s.vmx.VmcsInfo);
2025 hmR0VmxVmcsInfoInit(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
2026 }
2027}
2028
2029#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2030/**
2031 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2032 *
2033 * @returns @c true if the MSR is intercepted, @c false otherwise.
2034 * @param pvMsrBitmap The MSR bitmap.
2035 * @param offMsr The MSR byte offset.
2036 * @param iBit The bit offset from the byte offset.
2037 */
2038DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2039{
2040 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2041 Assert(pbMsrBitmap);
2042 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2043 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2044}
2045#endif
2046
2047/**
2048 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2049 *
2050 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2051 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2052 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2053 * the read/write access of this MSR.
2054 *
2055 * @param pVCpu The cross context virtual CPU structure.
2056 * @param pVmcsInfo The VMCS info. object.
2057 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2058 * @param idMsr The MSR value.
2059 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2060 * include both a read -and- a write permission!
2061 *
2062 * @sa CPUMGetVmxMsrPermission.
2063 * @remarks Can be called with interrupts disabled.
2064 */
2065static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2066{
2067 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2068 Assert(pbMsrBitmap);
2069 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2070
2071 /*
2072 * MSR-bitmap Layout:
2073 * Byte index MSR range Interpreted as
2074 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2075 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2076 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2077 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2078 *
2079 * A bit corresponding to an MSR within the above range causes a VM-exit
2080 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2081 * the MSR range, it always cause a VM-exit.
2082 *
2083 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2084 */
2085 uint16_t const offBitmapRead = 0;
2086 uint16_t const offBitmapWrite = 0x800;
2087 uint16_t offMsr;
2088 int32_t iBit;
2089 if (idMsr <= UINT32_C(0x00001fff))
2090 {
2091 offMsr = 0;
2092 iBit = idMsr;
2093 }
2094 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2095 {
2096 offMsr = 0x400;
2097 iBit = idMsr - UINT32_C(0xc0000000);
2098 }
2099 else
2100 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2101
2102 /*
2103 * Set the MSR read permission.
2104 */
2105 uint16_t const offMsrRead = offBitmapRead + offMsr;
2106 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2107 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2108 {
2109#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2110 bool const fClear = !fIsNstGstVmcs ? true
2111 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2112#else
2113 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2114 bool const fClear = true;
2115#endif
2116 if (fClear)
2117 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2118 }
2119 else
2120 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2121
2122 /*
2123 * Set the MSR write permission.
2124 */
2125 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2126 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2127 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2128 {
2129#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2130 bool const fClear = !fIsNstGstVmcs ? true
2131 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2132#else
2133 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2134 bool const fClear = true;
2135#endif
2136 if (fClear)
2137 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2138 }
2139 else
2140 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2141}
2142
2143
2144/**
2145 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2146 * area.
2147 *
2148 * @returns VBox status code.
2149 * @param pVCpu The cross context virtual CPU structure.
2150 * @param pVmcsInfo The VMCS info. object.
2151 * @param cMsrs The number of MSRs.
2152 */
2153static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2154{
2155 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2156 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2157 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2158 {
2159 /* Commit the MSR counts to the VMCS and update the cache. */
2160 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2161 {
2162 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2163 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2164 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2165 pVmcsInfo->cEntryMsrLoad = cMsrs;
2166 pVmcsInfo->cExitMsrStore = cMsrs;
2167 pVmcsInfo->cExitMsrLoad = cMsrs;
2168 }
2169 return VINF_SUCCESS;
2170 }
2171
2172 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2173 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2174 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2175}
2176
2177
2178/**
2179 * Adds a new (or updates the value of an existing) guest/host MSR
2180 * pair to be swapped during the world-switch as part of the
2181 * auto-load/store MSR area in the VMCS.
2182 *
2183 * @returns VBox status code.
2184 * @param pVCpu The cross context virtual CPU structure.
2185 * @param pVmxTransient The VMX-transient structure.
2186 * @param idMsr The MSR.
2187 * @param uGuestMsrValue Value of the guest MSR.
2188 * @param fSetReadWrite Whether to set the guest read/write access of this
2189 * MSR (thus not causing a VM-exit).
2190 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2191 * necessary.
2192 */
2193static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2194 bool fSetReadWrite, bool fUpdateHostMsr)
2195{
2196 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2197 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2198 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2199 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2200 uint32_t i;
2201
2202 /* Paranoia. */
2203 Assert(pGuestMsrLoad);
2204
2205 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2206
2207 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2208 for (i = 0; i < cMsrs; i++)
2209 {
2210 if (pGuestMsrLoad[i].u32Msr == idMsr)
2211 break;
2212 }
2213
2214 bool fAdded = false;
2215 if (i == cMsrs)
2216 {
2217 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2218 ++cMsrs;
2219 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2220 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2221
2222 /* Set the guest to read/write this MSR without causing VM-exits. */
2223 if ( fSetReadWrite
2224 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2225 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2226
2227 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2228 fAdded = true;
2229 }
2230
2231 /* Update the MSR value for the newly added or already existing MSR. */
2232 pGuestMsrLoad[i].u32Msr = idMsr;
2233 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2234
2235 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2236 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2237 {
2238 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2239 pGuestMsrStore[i].u32Msr = idMsr;
2240 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2241 }
2242
2243 /* Update the corresponding slot in the host MSR area. */
2244 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2245 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2246 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2247 pHostMsr[i].u32Msr = idMsr;
2248
2249 /*
2250 * Only if the caller requests to update the host MSR value AND we've newly added the
2251 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2252 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2253 *
2254 * We do this for performance reasons since reading MSRs may be quite expensive.
2255 */
2256 if (fAdded)
2257 {
2258 if (fUpdateHostMsr)
2259 {
2260 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2261 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2262 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2263 }
2264 else
2265 {
2266 /* Someone else can do the work. */
2267 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2268 }
2269 }
2270 return VINF_SUCCESS;
2271}
2272
2273
2274/**
2275 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2276 * auto-load/store MSR area in the VMCS.
2277 *
2278 * @returns VBox status code.
2279 * @param pVCpu The cross context virtual CPU structure.
2280 * @param pVmxTransient The VMX-transient structure.
2281 * @param idMsr The MSR.
2282 */
2283static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2284{
2285 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2286 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2287 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2288 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2289
2290 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2291
2292 for (uint32_t i = 0; i < cMsrs; i++)
2293 {
2294 /* Find the MSR. */
2295 if (pGuestMsrLoad[i].u32Msr == idMsr)
2296 {
2297 /*
2298 * If it's the last MSR, we only need to reduce the MSR count.
2299 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2300 */
2301 if (i < cMsrs - 1)
2302 {
2303 /* Remove it from the VM-entry MSR-load area. */
2304 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2305 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2306
2307 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2308 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2309 {
2310 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2311 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2312 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2313 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2314 }
2315
2316 /* Remove it from the VM-exit MSR-load area. */
2317 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2318 Assert(pHostMsr[i].u32Msr == idMsr);
2319 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2320 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2321 }
2322
2323 /* Reduce the count to reflect the removed MSR and bail. */
2324 --cMsrs;
2325 break;
2326 }
2327 }
2328
2329 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2330 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2331 {
2332 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2333 AssertRCReturn(rc, rc);
2334
2335 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2336 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2337 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2338
2339 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2340 return VINF_SUCCESS;
2341 }
2342
2343 return VERR_NOT_FOUND;
2344}
2345
2346
2347/**
2348 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2349 *
2350 * @returns @c true if found, @c false otherwise.
2351 * @param pVmcsInfo The VMCS info. object.
2352 * @param idMsr The MSR to find.
2353 */
2354static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2355{
2356 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2357 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2358 Assert(pMsrs);
2359 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2360 for (uint32_t i = 0; i < cMsrs; i++)
2361 {
2362 if (pMsrs[i].u32Msr == idMsr)
2363 return true;
2364 }
2365 return false;
2366}
2367
2368
2369/**
2370 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2371 *
2372 * @param pVCpu The cross context virtual CPU structure.
2373 * @param pVmcsInfo The VMCS info. object.
2374 *
2375 * @remarks No-long-jump zone!!!
2376 */
2377static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2378{
2379 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2380
2381 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2382 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2383 Assert(pHostMsrLoad);
2384 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2385 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2386 for (uint32_t i = 0; i < cMsrs; i++)
2387 {
2388 /*
2389 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2390 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2391 */
2392 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2393 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2394 else
2395 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2396 }
2397}
2398
2399
2400/**
2401 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2402 * perform lazy restoration of the host MSRs while leaving VT-x.
2403 *
2404 * @param pVCpu The cross context virtual CPU structure.
2405 *
2406 * @remarks No-long-jump zone!!!
2407 */
2408static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2409{
2410 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2411
2412 /*
2413 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2414 */
2415 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2416 {
2417 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2418 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2419 {
2420 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2421 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2422 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2423 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2424 }
2425 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2426 }
2427}
2428
2429
2430/**
2431 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2432 * lazily while leaving VT-x.
2433 *
2434 * @returns true if it does, false otherwise.
2435 * @param pVCpu The cross context virtual CPU structure.
2436 * @param idMsr The MSR to check.
2437 */
2438static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2439{
2440 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2441 {
2442 switch (idMsr)
2443 {
2444 case MSR_K8_LSTAR:
2445 case MSR_K6_STAR:
2446 case MSR_K8_SF_MASK:
2447 case MSR_K8_KERNEL_GS_BASE:
2448 return true;
2449 }
2450 }
2451 return false;
2452}
2453
2454
2455/**
2456 * Loads a set of guests MSRs to allow read/passthru to the guest.
2457 *
2458 * The name of this function is slightly confusing. This function does NOT
2459 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2460 * common prefix for functions dealing with "lazy restoration" of the shared
2461 * MSRs.
2462 *
2463 * @param pVCpu The cross context virtual CPU structure.
2464 *
2465 * @remarks No-long-jump zone!!!
2466 */
2467static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2468{
2469 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2470 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2471
2472 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2473 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2474 {
2475 /*
2476 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2477 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2478 * we can skip a few MSR writes.
2479 *
2480 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2481 * guest MSR values in the guest-CPU context might be different to what's currently
2482 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2483 * CPU, see @bugref{8728}.
2484 */
2485 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2486 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2487 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2488 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2489 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2490 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2491 {
2492#ifdef VBOX_STRICT
2493 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2494 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2495 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2496 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2497#endif
2498 }
2499 else
2500 {
2501 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2502 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2503 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2504 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2505 }
2506 }
2507 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2508}
2509
2510
2511/**
2512 * Performs lazy restoration of the set of host MSRs if they were previously
2513 * loaded with guest MSR values.
2514 *
2515 * @param pVCpu The cross context virtual CPU structure.
2516 *
2517 * @remarks No-long-jump zone!!!
2518 * @remarks The guest MSRs should have been saved back into the guest-CPU
2519 * context by hmR0VmxImportGuestState()!!!
2520 */
2521static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2522{
2523 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2524 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2525
2526 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2527 {
2528 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2529 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2530 {
2531 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2532 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2533 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2534 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2535 }
2536 }
2537 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2538}
2539
2540
2541/**
2542 * Verifies that our cached values of the VMCS fields are all consistent with
2543 * what's actually present in the VMCS.
2544 *
2545 * @returns VBox status code.
2546 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2547 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2548 * VMCS content. HMCPU error-field is
2549 * updated, see VMX_VCI_XXX.
2550 * @param pVCpu The cross context virtual CPU structure.
2551 * @param pVmcsInfo The VMCS info. object.
2552 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2553 */
2554static int hmR0VmxCheckVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2555{
2556 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2557
2558 uint32_t u32Val;
2559 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2560 AssertRC(rc);
2561 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2562 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2563 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2564 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2565
2566 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2567 AssertRC(rc);
2568 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2569 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2570 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2571 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2572
2573 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2574 AssertRC(rc);
2575 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2576 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2577 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2578 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2579
2580 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2581 AssertRC(rc);
2582 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2583 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2584 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2585 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2586
2587 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2588 {
2589 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2590 AssertRC(rc);
2591 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2592 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2593 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2594 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2595 }
2596
2597 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2598 AssertRC(rc);
2599 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2600 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2601 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2602 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2603
2604 uint64_t u64Val;
2605 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2606 AssertRC(rc);
2607 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2608 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2609 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2610 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2611
2612 NOREF(pcszVmcs);
2613 return VINF_SUCCESS;
2614}
2615
2616
2617#ifdef VBOX_STRICT
2618/**
2619 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2620 *
2621 * @param pVCpu The cross context virtual CPU structure.
2622 * @param pVmcsInfo The VMCS info. object.
2623 */
2624static void hmR0VmxCheckHostEferMsr(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2625{
2626 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2627
2628 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2629 {
2630 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2631 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2632 uint64_t uVmcsEferMsrVmcs;
2633 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2634 AssertRC(rc);
2635
2636 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2637 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2638 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2639 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2640 }
2641}
2642
2643
2644/**
2645 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2646 * VMCS are correct.
2647 *
2648 * @param pVCpu The cross context virtual CPU structure.
2649 * @param pVmcsInfo The VMCS info. object.
2650 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2651 */
2652static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2653{
2654 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2655
2656 /* Read the various MSR-area counts from the VMCS. */
2657 uint32_t cEntryLoadMsrs;
2658 uint32_t cExitStoreMsrs;
2659 uint32_t cExitLoadMsrs;
2660 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2661 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2662 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2663
2664 /* Verify all the MSR counts are the same. */
2665 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2666 Assert(cExitStoreMsrs == cExitLoadMsrs);
2667 uint32_t const cMsrs = cExitLoadMsrs;
2668
2669 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2670 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2671
2672 /* Verify the MSR counts are within the allocated page size. */
2673 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2674
2675 /* Verify the relevant contents of the MSR areas match. */
2676 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2677 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2678 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2679 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2680 for (uint32_t i = 0; i < cMsrs; i++)
2681 {
2682 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2683 if (fSeparateExitMsrStorePage)
2684 {
2685 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2686 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2687 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2688 }
2689
2690 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2691 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2692 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2693
2694 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2695 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2696 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2697 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2698
2699 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2700 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2701 if (fIsEferMsr)
2702 {
2703 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2704 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2705 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2706 }
2707
2708 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2709 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2710 {
2711 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2712 if (fIsEferMsr)
2713 {
2714 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2715 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2716 }
2717 else
2718 {
2719 if (!fIsNstGstVmcs)
2720 {
2721 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2722 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2723 }
2724 else
2725 {
2726 /*
2727 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2728 * execute a nested-guest with MSR passthrough.
2729 *
2730 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2731 * allow passthrough too.
2732 */
2733 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2734 Assert(pvMsrBitmapNstGst);
2735 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2736 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2737 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2738 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2739 }
2740 }
2741 }
2742
2743 /* Move to the next MSR. */
2744 pHostMsrLoad++;
2745 pGuestMsrLoad++;
2746 pGuestMsrStore++;
2747 }
2748}
2749#endif /* VBOX_STRICT */
2750
2751
2752/**
2753 * Flushes the TLB using EPT.
2754 *
2755 * @returns VBox status code.
2756 * @param pVCpu The cross context virtual CPU structure of the calling
2757 * EMT. Can be NULL depending on @a enmTlbFlush.
2758 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2759 * enmTlbFlush.
2760 * @param enmTlbFlush Type of flush.
2761 *
2762 * @remarks Caller is responsible for making sure this function is called only
2763 * when NestedPaging is supported and providing @a enmTlbFlush that is
2764 * supported by the CPU.
2765 * @remarks Can be called with interrupts disabled.
2766 */
2767static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2768{
2769 uint64_t au64Descriptor[2];
2770 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2771 au64Descriptor[0] = 0;
2772 else
2773 {
2774 Assert(pVCpu);
2775 Assert(pVmcsInfo);
2776 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2777 }
2778 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2779
2780 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2781 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2782
2783 if ( RT_SUCCESS(rc)
2784 && pVCpu)
2785 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2786}
2787
2788
2789/**
2790 * Flushes the TLB using VPID.
2791 *
2792 * @returns VBox status code.
2793 * @param pVCpu The cross context virtual CPU structure of the calling
2794 * EMT. Can be NULL depending on @a enmTlbFlush.
2795 * @param enmTlbFlush Type of flush.
2796 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2797 * on @a enmTlbFlush).
2798 *
2799 * @remarks Can be called with interrupts disabled.
2800 */
2801static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2802{
2803 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2804
2805 uint64_t au64Descriptor[2];
2806 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2807 {
2808 au64Descriptor[0] = 0;
2809 au64Descriptor[1] = 0;
2810 }
2811 else
2812 {
2813 AssertPtr(pVCpu);
2814 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2815 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2816 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2817 au64Descriptor[1] = GCPtr;
2818 }
2819
2820 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2821 AssertMsg(rc == VINF_SUCCESS,
2822 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2823
2824 if ( RT_SUCCESS(rc)
2825 && pVCpu)
2826 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2827 NOREF(rc);
2828}
2829
2830
2831/**
2832 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2833 * otherwise there is nothing really to invalidate.
2834 *
2835 * @returns VBox status code.
2836 * @param pVCpu The cross context virtual CPU structure.
2837 * @param GCVirt Guest virtual address of the page to invalidate.
2838 */
2839VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2840{
2841 AssertPtr(pVCpu);
2842 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2843
2844 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2845 {
2846 /*
2847 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2848 * the EPT case. See @bugref{6043} and @bugref{6177}.
2849 *
2850 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2851 * as this function maybe called in a loop with individual addresses.
2852 */
2853 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2854 if (pVM->hm.s.vmx.fVpid)
2855 {
2856 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2857 if (fVpidFlush)
2858 {
2859 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2860 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2861 }
2862 else
2863 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2864 }
2865 else if (pVM->hm.s.fNestedPaging)
2866 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2867 }
2868
2869 return VINF_SUCCESS;
2870}
2871
2872
2873/**
2874 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2875 * case where neither EPT nor VPID is supported by the CPU.
2876 *
2877 * @param pHostCpu The HM physical-CPU structure.
2878 * @param pVCpu The cross context virtual CPU structure.
2879 *
2880 * @remarks Called with interrupts disabled.
2881 */
2882static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2883{
2884 AssertPtr(pVCpu);
2885 AssertPtr(pHostCpu);
2886
2887 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2888
2889 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2890 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2891 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2892 pVCpu->hm.s.fForceTLBFlush = false;
2893 return;
2894}
2895
2896
2897/**
2898 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2899 *
2900 * @param pHostCpu The HM physical-CPU structure.
2901 * @param pVCpu The cross context virtual CPU structure.
2902 * @param pVmcsInfo The VMCS info. object.
2903 *
2904 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2905 * nomenclature. The reason is, to avoid confusion in compare statements
2906 * since the host-CPU copies are named "ASID".
2907 *
2908 * @remarks Called with interrupts disabled.
2909 */
2910static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2911{
2912#ifdef VBOX_WITH_STATISTICS
2913 bool fTlbFlushed = false;
2914# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2915# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2916 if (!fTlbFlushed) \
2917 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2918 } while (0)
2919#else
2920# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2921# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2922#endif
2923
2924 AssertPtr(pVCpu);
2925 AssertPtr(pHostCpu);
2926 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2927
2928 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2929 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2930 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2931 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2932
2933 /*
2934 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2935 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2936 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2937 * cannot reuse the current ASID anymore.
2938 */
2939 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2940 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2941 {
2942 ++pHostCpu->uCurrentAsid;
2943 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2944 {
2945 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2946 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2947 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2948 }
2949
2950 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2951 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2952 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2953
2954 /*
2955 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2956 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2957 */
2958 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2959 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2960 HMVMX_SET_TAGGED_TLB_FLUSHED();
2961 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2962 }
2963 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2964 {
2965 /*
2966 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2967 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2968 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2969 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2970 * mappings, see @bugref{6568}.
2971 *
2972 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2973 */
2974 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2975 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2976 HMVMX_SET_TAGGED_TLB_FLUSHED();
2977 }
2978 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
2979 {
2980 /*
2981 * The nested-guest specifies its own guest-physical address to use as the APIC-access
2982 * address which requires flushing the TLB of EPT cached structures.
2983 *
2984 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
2985 */
2986 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2987 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
2988 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
2989 HMVMX_SET_TAGGED_TLB_FLUSHED();
2990 }
2991
2992
2993 pVCpu->hm.s.fForceTLBFlush = false;
2994 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
2995
2996 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
2997 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
2998 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2999 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3000 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3001 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3002 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3003 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3004 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3005
3006 /* Update VMCS with the VPID. */
3007 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3008 AssertRC(rc);
3009
3010#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3011}
3012
3013
3014/**
3015 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3016 *
3017 * @param pHostCpu The HM physical-CPU structure.
3018 * @param pVCpu The cross context virtual CPU structure.
3019 * @param pVmcsInfo The VMCS info. object.
3020 *
3021 * @remarks Called with interrupts disabled.
3022 */
3023static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3024{
3025 AssertPtr(pVCpu);
3026 AssertPtr(pHostCpu);
3027 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3028 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3029 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3030
3031 /*
3032 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3033 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3034 */
3035 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3036 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3037 {
3038 pVCpu->hm.s.fForceTLBFlush = true;
3039 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3040 }
3041
3042 /* Check for explicit TLB flushes. */
3043 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3044 {
3045 pVCpu->hm.s.fForceTLBFlush = true;
3046 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3047 }
3048
3049 /* Check for TLB flushes while switching to/from a nested-guest. */
3050 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3051 {
3052 pVCpu->hm.s.fForceTLBFlush = true;
3053 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3054 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3055 }
3056
3057 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3058 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3059
3060 if (pVCpu->hm.s.fForceTLBFlush)
3061 {
3062 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3063 pVCpu->hm.s.fForceTLBFlush = false;
3064 }
3065}
3066
3067
3068/**
3069 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3070 *
3071 * @param pHostCpu The HM physical-CPU structure.
3072 * @param pVCpu The cross context virtual CPU structure.
3073 *
3074 * @remarks Called with interrupts disabled.
3075 */
3076static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3077{
3078 AssertPtr(pVCpu);
3079 AssertPtr(pHostCpu);
3080 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3081 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3082 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3083
3084 /*
3085 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3086 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3087 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3088 * cannot reuse the current ASID anymore.
3089 */
3090 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3091 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3092 {
3093 pVCpu->hm.s.fForceTLBFlush = true;
3094 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3095 }
3096
3097 /* Check for explicit TLB flushes. */
3098 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3099 {
3100 /*
3101 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3102 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3103 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3104 * include fExplicitFlush's too) - an obscure corner case.
3105 */
3106 pVCpu->hm.s.fForceTLBFlush = true;
3107 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3108 }
3109
3110 /* Check for TLB flushes while switching to/from a nested-guest. */
3111 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3112 {
3113 pVCpu->hm.s.fForceTLBFlush = true;
3114 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3115 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3116 }
3117
3118 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3119 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3120 if (pVCpu->hm.s.fForceTLBFlush)
3121 {
3122 ++pHostCpu->uCurrentAsid;
3123 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3124 {
3125 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3126 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3127 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3128 }
3129
3130 pVCpu->hm.s.fForceTLBFlush = false;
3131 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3132 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3133 if (pHostCpu->fFlushAsidBeforeUse)
3134 {
3135 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3136 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3137 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3138 {
3139 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3140 pHostCpu->fFlushAsidBeforeUse = false;
3141 }
3142 else
3143 {
3144 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3145 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3146 }
3147 }
3148 }
3149
3150 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3151 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3152 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3153 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3154 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3155 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3156 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3157
3158 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3159 AssertRC(rc);
3160}
3161
3162
3163/**
3164 * Flushes the guest TLB entry based on CPU capabilities.
3165 *
3166 * @param pHostCpu The HM physical-CPU structure.
3167 * @param pVCpu The cross context virtual CPU structure.
3168 * @param pVmcsInfo The VMCS info. object.
3169 *
3170 * @remarks Called with interrupts disabled.
3171 */
3172static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3173{
3174#ifdef HMVMX_ALWAYS_FLUSH_TLB
3175 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3176#endif
3177 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3178 switch (pVM->hm.s.vmx.enmTlbFlushType)
3179 {
3180 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3181 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3182 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3183 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3184 default:
3185 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3186 break;
3187 }
3188 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3189}
3190
3191
3192/**
3193 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3194 * TLB entries from the host TLB before VM-entry.
3195 *
3196 * @returns VBox status code.
3197 * @param pVM The cross context VM structure.
3198 */
3199static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3200{
3201 /*
3202 * Determine optimal flush type for nested paging.
3203 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3204 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3205 */
3206 if (pVM->hm.s.fNestedPaging)
3207 {
3208 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3209 {
3210 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3211 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3212 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3213 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3214 else
3215 {
3216 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3217 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3218 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3219 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3220 }
3221
3222 /* Make sure the write-back cacheable memory type for EPT is supported. */
3223 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3224 {
3225 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3226 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3227 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3228 }
3229
3230 /* EPT requires a page-walk length of 4. */
3231 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3232 {
3233 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3234 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3235 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3236 }
3237 }
3238 else
3239 {
3240 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3241 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3242 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3243 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3244 }
3245 }
3246
3247 /*
3248 * Determine optimal flush type for VPID.
3249 */
3250 if (pVM->hm.s.vmx.fVpid)
3251 {
3252 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3253 {
3254 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3255 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3256 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3257 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3258 else
3259 {
3260 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3261 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3262 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3263 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3264 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3265 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3266 pVM->hm.s.vmx.fVpid = false;
3267 }
3268 }
3269 else
3270 {
3271 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3272 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3273 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3274 pVM->hm.s.vmx.fVpid = false;
3275 }
3276 }
3277
3278 /*
3279 * Setup the handler for flushing tagged-TLBs.
3280 */
3281 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3282 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3283 else if (pVM->hm.s.fNestedPaging)
3284 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3285 else if (pVM->hm.s.vmx.fVpid)
3286 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3287 else
3288 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3289 return VINF_SUCCESS;
3290}
3291
3292
3293#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3294/**
3295 * Sets up the shadow VMCS fields arrays.
3296 *
3297 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3298 * executing the guest.
3299 *
3300 * @returns VBox status code.
3301 * @param pVM The cross context VM structure.
3302 */
3303static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3304{
3305 /*
3306 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3307 * when the host does not support it.
3308 */
3309 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3310 if ( !fGstVmwriteAll
3311 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3312 { /* likely. */ }
3313 else
3314 {
3315 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3316 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3317 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3318 }
3319
3320 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3321 uint32_t cRwFields = 0;
3322 uint32_t cRoFields = 0;
3323 for (uint32_t i = 0; i < cVmcsFields; i++)
3324 {
3325 VMXVMCSFIELD VmcsField;
3326 VmcsField.u = g_aVmcsFields[i];
3327
3328 /*
3329 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3330 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3331 * in the shadow VMCS fields array as they would be redundant.
3332 *
3333 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3334 * we must not include it in the shadow VMCS fields array. Guests attempting to
3335 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3336 * the required behavior.
3337 */
3338 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3339 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3340 {
3341 /*
3342 * Read-only fields are placed in a separate array so that while syncing shadow
3343 * VMCS fields later (which is more performance critical) we can avoid branches.
3344 *
3345 * However, if the guest can write to all fields (including read-only fields),
3346 * we treat it a as read/write field. Otherwise, writing to these fields would
3347 * cause a VMWRITE instruction error while syncing the shadow VMCS.
3348 */
3349 if ( fGstVmwriteAll
3350 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3351 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3352 else
3353 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3354 }
3355 }
3356
3357 /* Update the counts. */
3358 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3359 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3360 return VINF_SUCCESS;
3361}
3362
3363
3364/**
3365 * Sets up the VMREAD and VMWRITE bitmaps.
3366 *
3367 * @param pVM The cross context VM structure.
3368 */
3369static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3370{
3371 /*
3372 * By default, ensure guest attempts to access any VMCS fields cause VM-exits.
3373 */
3374 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3375 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3376 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3377 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3378 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3379
3380 /*
3381 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3382 * VMREAD and VMWRITE bitmaps.
3383 */
3384 {
3385 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3386 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3387 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3388 {
3389 uint32_t const uVmcsField = paShadowVmcsFields[i];
3390 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3391 Assert(uVmcsField >> 3 < cbBitmap);
3392 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3393 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3394 }
3395 }
3396
3397 /*
3398 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3399 * if the host supports VMWRITE to all supported VMCS fields.
3400 */
3401 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3402 {
3403 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3404 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3405 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3406 {
3407 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3408 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3409 Assert(uVmcsField >> 3 < cbBitmap);
3410 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3411 }
3412 }
3413}
3414#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3415
3416
3417/**
3418 * Sets up the virtual-APIC page address for the VMCS.
3419 *
3420 * @param pVmcsInfo The VMCS info. object.
3421 */
3422DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3423{
3424 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3425 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3426 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3427 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3428 AssertRC(rc);
3429}
3430
3431
3432/**
3433 * Sets up the MSR-bitmap address for the VMCS.
3434 *
3435 * @param pVmcsInfo The VMCS info. object.
3436 */
3437DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3438{
3439 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3440 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3441 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3442 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3443 AssertRC(rc);
3444}
3445
3446
3447/**
3448 * Sets up the APIC-access page address for the VMCS.
3449 *
3450 * @param pVCpu The cross context virtual CPU structure.
3451 */
3452DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3453{
3454 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3455 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3456 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3457 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3458 AssertRC(rc);
3459}
3460
3461
3462#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3463/**
3464 * Sets up the VMREAD bitmap address for the VMCS.
3465 *
3466 * @param pVCpu The cross context virtual CPU structure.
3467 */
3468DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3469{
3470 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3471 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3472 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3473 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3474 AssertRC(rc);
3475}
3476
3477
3478/**
3479 * Sets up the VMWRITE bitmap address for the VMCS.
3480 *
3481 * @param pVCpu The cross context virtual CPU structure.
3482 */
3483DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3484{
3485 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3486 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3487 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3488 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3489 AssertRC(rc);
3490}
3491#endif
3492
3493
3494/**
3495 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3496 * in the VMCS.
3497 *
3498 * @returns VBox status code.
3499 * @param pVmcsInfo The VMCS info. object.
3500 */
3501DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3502{
3503 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3504 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3505 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3506
3507 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3508 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3509 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3510
3511 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3512 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3513 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3514
3515 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3516 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3517 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3518 return VINF_SUCCESS;
3519}
3520
3521
3522/**
3523 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3524 *
3525 * @param pVCpu The cross context virtual CPU structure.
3526 * @param pVmcsInfo The VMCS info. object.
3527 */
3528static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3529{
3530 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3531
3532 /*
3533 * By default, ensure guest attempts to access any MSR cause VM-exits.
3534 * This shall later be relaxed for specific MSRs as necessary.
3535 *
3536 * Note: For nested-guests, the entire bitmap will be merged prior to
3537 * executing the nested-guest using hardware-assisted VMX and hence there
3538 * is no need to perform this operation. See hmR0VmxMergeMsrBitmapNested.
3539 */
3540 Assert(pVmcsInfo->pvMsrBitmap);
3541 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
3542
3543 /*
3544 * The guest can access the following MSRs (read, write) without causing
3545 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3546 */
3547 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3548 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3549 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3550 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3551 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3552 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3553
3554 /*
3555 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3556 * associated with then. We never need to intercept access (writes need to be
3557 * executed without causing a VM-exit, reads will #GP fault anyway).
3558 *
3559 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3560 * read/write them. We swap the the guest/host MSR value using the
3561 * auto-load/store MSR area.
3562 */
3563 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3564 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3565 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3566 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3567 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3568 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3569
3570 /*
3571 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3572 * required for 64-bit guests.
3573 */
3574 if (pVM->hm.s.fAllow64BitGuests)
3575 {
3576 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3577 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3578 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3579 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3580 }
3581
3582 /*
3583 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3584 */
3585#ifdef VBOX_STRICT
3586 Assert(pVmcsInfo->pvMsrBitmap);
3587 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3588 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3589#endif
3590}
3591
3592
3593/**
3594 * Sets up pin-based VM-execution controls in the VMCS.
3595 *
3596 * @returns VBox status code.
3597 * @param pVCpu The cross context virtual CPU structure.
3598 * @param pVmcsInfo The VMCS info. object.
3599 */
3600static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3601{
3602 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3603 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3604 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3605
3606 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3607 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3608
3609 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3610 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3611
3612 /* Enable the VMX-preemption timer. */
3613 if (pVM->hm.s.vmx.fUsePreemptTimer)
3614 {
3615 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3616 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3617 }
3618
3619#if 0
3620 /* Enable posted-interrupt processing. */
3621 if (pVM->hm.s.fPostedIntrs)
3622 {
3623 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3624 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3625 fVal |= VMX_PIN_CTLS_POSTED_INT;
3626 }
3627#endif
3628
3629 if ((fVal & fZap) != fVal)
3630 {
3631 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3632 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3633 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3634 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3635 }
3636
3637 /* Commit it to the VMCS and update our cache. */
3638 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3639 AssertRC(rc);
3640 pVmcsInfo->u32PinCtls = fVal;
3641
3642 return VINF_SUCCESS;
3643}
3644
3645
3646/**
3647 * Sets up secondary processor-based VM-execution controls in the VMCS.
3648 *
3649 * @returns VBox status code.
3650 * @param pVCpu The cross context virtual CPU structure.
3651 * @param pVmcsInfo The VMCS info. object.
3652 */
3653static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3654{
3655 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3656 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3657 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3658
3659 /* WBINVD causes a VM-exit. */
3660 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3661 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3662
3663 /* Enable EPT (aka nested-paging). */
3664 if (pVM->hm.s.fNestedPaging)
3665 fVal |= VMX_PROC_CTLS2_EPT;
3666
3667 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3668 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3669 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3670 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3671 fVal |= VMX_PROC_CTLS2_INVPCID;
3672
3673 /* Enable VPID. */
3674 if (pVM->hm.s.vmx.fVpid)
3675 fVal |= VMX_PROC_CTLS2_VPID;
3676
3677 /* Enable unrestricted guest execution. */
3678 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3679 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3680
3681#if 0
3682 if (pVM->hm.s.fVirtApicRegs)
3683 {
3684 /* Enable APIC-register virtualization. */
3685 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3686 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3687
3688 /* Enable virtual-interrupt delivery. */
3689 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3690 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3691 }
3692#endif
3693
3694 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3695 where the TPR shadow resides. */
3696 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3697 * done dynamically. */
3698 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3699 {
3700 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3701 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3702 }
3703
3704 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3705 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3706 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3707 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3708 fVal |= VMX_PROC_CTLS2_RDTSCP;
3709
3710 /* Enable Pause-Loop exiting. */
3711 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3712 && pVM->hm.s.vmx.cPleGapTicks
3713 && pVM->hm.s.vmx.cPleWindowTicks)
3714 {
3715 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3716
3717 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3718 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3719 }
3720
3721 if ((fVal & fZap) != fVal)
3722 {
3723 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3724 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3725 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3726 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3727 }
3728
3729 /* Commit it to the VMCS and update our cache. */
3730 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3731 AssertRC(rc);
3732 pVmcsInfo->u32ProcCtls2 = fVal;
3733
3734 return VINF_SUCCESS;
3735}
3736
3737
3738/**
3739 * Sets up processor-based VM-execution controls in the VMCS.
3740 *
3741 * @returns VBox status code.
3742 * @param pVCpu The cross context virtual CPU structure.
3743 * @param pVmcsInfo The VMCS info. object.
3744 */
3745static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3746{
3747 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3748
3749 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3750 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3751
3752 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3753 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3754 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3755 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3756 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3757 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3758 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3759
3760 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3761 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3762 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3763 {
3764 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3765 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3766 }
3767
3768 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3769 if (!pVM->hm.s.fNestedPaging)
3770 {
3771 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3772 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3773 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3774 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3775 }
3776
3777 /* Use TPR shadowing if supported by the CPU. */
3778 if ( PDMHasApic(pVM)
3779 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3780 {
3781 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3782 /* CR8 writes cause a VM-exit based on TPR threshold. */
3783 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3784 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3785 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3786 }
3787 else
3788 {
3789 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3790 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3791 if (pVM->hm.s.fAllow64BitGuests)
3792 {
3793 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3794 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3795 }
3796 }
3797
3798 /* Use MSR-bitmaps if supported by the CPU. */
3799 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3800 {
3801 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3802 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3803 }
3804
3805 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3806 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3807 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3808
3809 if ((fVal & fZap) != fVal)
3810 {
3811 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3812 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3813 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3814 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3815 }
3816
3817 /* Commit it to the VMCS and update our cache. */
3818 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3819 AssertRC(rc);
3820 pVmcsInfo->u32ProcCtls = fVal;
3821
3822 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3823 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3824 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3825
3826 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3827 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3828 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3829
3830 /* Sanity check, should not really happen. */
3831 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3832 { /* likely */ }
3833 else
3834 {
3835 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3836 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3837 }
3838
3839 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3840 return VINF_SUCCESS;
3841}
3842
3843
3844/**
3845 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3846 * Processor-based VM-execution) control fields in the VMCS.
3847 *
3848 * @returns VBox status code.
3849 * @param pVCpu The cross context virtual CPU structure.
3850 * @param pVmcsInfo The VMCS info. object.
3851 */
3852static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3853{
3854#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3855 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3856 {
3857 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3858 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3859 }
3860#endif
3861
3862 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3863 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3864 AssertRC(rc);
3865
3866 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3867 if (RT_SUCCESS(rc))
3868 {
3869 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3870 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3871
3872 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
3873 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
3874
3875 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3876 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3877 return VINF_SUCCESS;
3878 }
3879 else
3880 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3881 return rc;
3882}
3883
3884
3885/**
3886 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3887 *
3888 * We shall setup those exception intercepts that don't change during the
3889 * lifetime of the VM here. The rest are done dynamically while loading the
3890 * guest state.
3891 *
3892 * @param pVCpu The cross context virtual CPU structure.
3893 * @param pVmcsInfo The VMCS info. object.
3894 */
3895static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3896{
3897 /*
3898 * The following exceptions are always intercepted:
3899 *
3900 * #AC - To prevent the guest from hanging the CPU.
3901 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3902 * recursive #DBs can cause a CPU hang.
3903 * #PF - To sync our shadow page tables when nested-paging is not used.
3904 */
3905 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3906 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3907 | RT_BIT(X86_XCPT_DB)
3908 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3909
3910 /* Commit it to the VMCS. */
3911 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3912 AssertRC(rc);
3913
3914 /* Update our cache of the exception bitmap. */
3915 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3916}
3917
3918
3919#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3920/**
3921 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3922 *
3923 * @returns VBox status code.
3924 * @param pVCpu The cross context virtual CPU structure.
3925 * @param pVmcsInfo The VMCS info. object.
3926 */
3927static int hmR0VmxSetupVmcsCtlsNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3928{
3929 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3930 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3931 AssertRC(rc);
3932
3933 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3934 if (RT_SUCCESS(rc))
3935 {
3936 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3937 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3938
3939 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
3940 Assert(!pVmcsInfo->u64Cr0Mask);
3941 Assert(!pVmcsInfo->u64Cr4Mask);
3942 return VINF_SUCCESS;
3943 }
3944 else
3945 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3946 return rc;
3947}
3948#endif
3949
3950
3951/**
3952 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
3953 * VMX.
3954 *
3955 * @returns VBox status code.
3956 * @param pVCpu The cross context virtual CPU structure.
3957 * @param pVmcsInfo The VMCS info. object.
3958 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
3959 */
3960static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
3961{
3962 Assert(pVmcsInfo->pvVmcs);
3963 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3964
3965 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
3966 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3967 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3968 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
3969
3970 LogFlowFunc(("\n"));
3971
3972 /*
3973 * Initialize the VMCS using VMCLEAR before loading the VMCS.
3974 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
3975 */
3976 int rc = hmR0VmxClearVmcs(pVmcsInfo);
3977 if (RT_SUCCESS(rc))
3978 {
3979 rc = hmR0VmxLoadVmcs(pVmcsInfo);
3980 if (RT_SUCCESS(rc))
3981 {
3982 if (!fIsNstGstVmcs)
3983 {
3984 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
3985 if (RT_SUCCESS(rc))
3986 {
3987 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
3988 if (RT_SUCCESS(rc))
3989 {
3990 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
3991 if (RT_SUCCESS(rc))
3992 {
3993 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
3994#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3995 /*
3996 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
3997 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
3998 * making it fit for use when VMCS shadowing is later enabled.
3999 */
4000 if (pVmcsInfo->pvShadowVmcs)
4001 {
4002 VMXVMCSREVID VmcsRevId;
4003 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4004 VmcsRevId.n.fIsShadowVmcs = 1;
4005 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4006 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4007 if (RT_SUCCESS(rc))
4008 { /* likely */ }
4009 else
4010 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4011 }
4012#endif
4013 }
4014 else
4015 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4016 }
4017 else
4018 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4019 }
4020 else
4021 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4022 }
4023 else
4024 {
4025#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4026 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4027 if (RT_SUCCESS(rc))
4028 { /* likely */ }
4029 else
4030 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4031#else
4032 AssertFailed();
4033#endif
4034 }
4035 }
4036 else
4037 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4038 }
4039 else
4040 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4041
4042 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4043 if (RT_SUCCESS(rc))
4044 {
4045 rc = hmR0VmxClearVmcs(pVmcsInfo);
4046 if (RT_SUCCESS(rc))
4047 { /* likely */ }
4048 else
4049 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4050 }
4051
4052 /*
4053 * Update the last-error record both for failures and success, so we
4054 * can propagate the status code back to ring-3 for diagnostics.
4055 */
4056 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4057 NOREF(pszVmcs);
4058 return rc;
4059}
4060
4061
4062/**
4063 * Does global VT-x initialization (called during module initialization).
4064 *
4065 * @returns VBox status code.
4066 */
4067VMMR0DECL(int) VMXR0GlobalInit(void)
4068{
4069#ifdef HMVMX_USE_FUNCTION_TABLE
4070 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4071# ifdef VBOX_STRICT
4072 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4073 Assert(g_apfnVMExitHandlers[i]);
4074# endif
4075#endif
4076 return VINF_SUCCESS;
4077}
4078
4079
4080/**
4081 * Does global VT-x termination (called during module termination).
4082 */
4083VMMR0DECL(void) VMXR0GlobalTerm()
4084{
4085 /* Nothing to do currently. */
4086}
4087
4088
4089/**
4090 * Sets up and activates VT-x on the current CPU.
4091 *
4092 * @returns VBox status code.
4093 * @param pHostCpu The HM physical-CPU structure.
4094 * @param pVM The cross context VM structure. Can be
4095 * NULL after a host resume operation.
4096 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4097 * fEnabledByHost is @c true).
4098 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4099 * @a fEnabledByHost is @c true).
4100 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4101 * enable VT-x on the host.
4102 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4103 */
4104VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4105 PCSUPHWVIRTMSRS pHwvirtMsrs)
4106{
4107 AssertPtr(pHostCpu);
4108 AssertPtr(pHwvirtMsrs);
4109 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4110
4111 /* Enable VT-x if it's not already enabled by the host. */
4112 if (!fEnabledByHost)
4113 {
4114 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4115 if (RT_FAILURE(rc))
4116 return rc;
4117 }
4118
4119 /*
4120 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4121 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4122 * invalidated when flushing by VPID.
4123 */
4124 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4125 {
4126 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4127 pHostCpu->fFlushAsidBeforeUse = false;
4128 }
4129 else
4130 pHostCpu->fFlushAsidBeforeUse = true;
4131
4132 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4133 ++pHostCpu->cTlbFlushes;
4134
4135 return VINF_SUCCESS;
4136}
4137
4138
4139/**
4140 * Deactivates VT-x on the current CPU.
4141 *
4142 * @returns VBox status code.
4143 * @param pHostCpu The HM physical-CPU structure.
4144 * @param pvCpuPage Pointer to the VMXON region.
4145 * @param HCPhysCpuPage Physical address of the VMXON region.
4146 *
4147 * @remarks This function should never be called when SUPR0EnableVTx() or
4148 * similar was used to enable VT-x on the host.
4149 */
4150VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4151{
4152 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4153
4154 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4155 return hmR0VmxLeaveRootMode(pHostCpu);
4156}
4157
4158
4159/**
4160 * Does per-VM VT-x initialization.
4161 *
4162 * @returns VBox status code.
4163 * @param pVM The cross context VM structure.
4164 */
4165VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4166{
4167 AssertPtr(pVM);
4168 LogFlowFunc(("pVM=%p\n", pVM));
4169
4170 hmR0VmxStructsInit(pVM);
4171 int rc = hmR0VmxStructsAlloc(pVM);
4172 if (RT_FAILURE(rc))
4173 {
4174 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4175 return rc;
4176 }
4177
4178 /* Setup the crash dump page. */
4179#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4180 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
4181 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
4182#endif
4183 return VINF_SUCCESS;
4184}
4185
4186
4187/**
4188 * Does per-VM VT-x termination.
4189 *
4190 * @returns VBox status code.
4191 * @param pVM The cross context VM structure.
4192 */
4193VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4194{
4195 AssertPtr(pVM);
4196 LogFlowFunc(("pVM=%p\n", pVM));
4197
4198#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4199 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4200 {
4201 Assert(pVM->hm.s.vmx.pvScratch);
4202 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4203 }
4204#endif
4205 hmR0VmxStructsFree(pVM);
4206 return VINF_SUCCESS;
4207}
4208
4209
4210/**
4211 * Sets up the VM for execution using hardware-assisted VMX.
4212 * This function is only called once per-VM during initialization.
4213 *
4214 * @returns VBox status code.
4215 * @param pVM The cross context VM structure.
4216 */
4217VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4218{
4219 AssertPtr(pVM);
4220 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4221
4222 LogFlowFunc(("pVM=%p\n", pVM));
4223
4224 /*
4225 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4226 * without causing a #GP.
4227 */
4228 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4229 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4230 { /* likely */ }
4231 else
4232 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4233
4234 /*
4235 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4236 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4237 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4238 */
4239 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4240 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4241 || !pVM->hm.s.vmx.pRealModeTSS))
4242 {
4243 LogRelFunc(("Invalid real-on-v86 state.\n"));
4244 return VERR_INTERNAL_ERROR;
4245 }
4246
4247 /* Initialize these always, see hmR3InitFinalizeR0().*/
4248 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4249 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4250
4251 /* Setup the tagged-TLB flush handlers. */
4252 int rc = hmR0VmxSetupTaggedTlb(pVM);
4253 if (RT_FAILURE(rc))
4254 {
4255 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4256 return rc;
4257 }
4258
4259#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4260 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4261 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4262 {
4263 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4264 if (RT_SUCCESS(rc))
4265 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4266 else
4267 {
4268 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4269 return rc;
4270 }
4271 }
4272#endif
4273
4274 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4275 {
4276 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4277 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4278
4279 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4280 if (RT_SUCCESS(rc))
4281 {
4282#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4283 if (pVM->cpum.ro.GuestFeatures.fVmx)
4284 {
4285 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4286 if (RT_SUCCESS(rc))
4287 { /* likely */ }
4288 else
4289 {
4290 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4291 return rc;
4292 }
4293 }
4294#endif
4295 }
4296 else
4297 {
4298 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4299 return rc;
4300 }
4301 }
4302
4303 return VINF_SUCCESS;
4304}
4305
4306
4307/**
4308 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4309 * the VMCS.
4310 */
4311static void hmR0VmxExportHostControlRegs(void)
4312{
4313 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4314 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4315 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, ASMGetCR4()); AssertRC(rc);
4316}
4317
4318
4319/**
4320 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4321 * the host-state area in the VMCS.
4322 *
4323 * @returns VBox status code.
4324 * @param pVCpu The cross context virtual CPU structure.
4325 */
4326static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu)
4327{
4328/**
4329 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4330 * requirements. See hmR0VmxExportHostSegmentRegs().
4331 */
4332#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_selValue) \
4333 if ((a_selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4334 { \
4335 bool fValidSelector = true; \
4336 if ((a_selValue) & X86_SEL_LDT) \
4337 { \
4338 uint32_t const uAttr = ASMGetSegAttr(a_selValue); \
4339 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4340 } \
4341 if (fValidSelector) \
4342 { \
4343 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4344 pVCpu->hm.s.vmx.RestoreHost.uHostSel##a_Seg = (a_selValue); \
4345 } \
4346 (a_selValue) = 0; \
4347 }
4348
4349 /*
4350 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4351 * will be messed up. We should -not- save the messed up state without restoring
4352 * the original host-state, see @bugref{7240}.
4353 *
4354 * This apparently can happen (most likely the FPU changes), deal with it rather than
4355 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4356 */
4357 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4358 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4359 {
4360 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4361 pVCpu->idCpu));
4362 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4363 }
4364 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4365
4366 /*
4367 * Host segment registers.
4368 */
4369 RTSEL uSelES = ASMGetES();
4370 RTSEL uSelCS = ASMGetCS();
4371 RTSEL uSelSS = ASMGetSS();
4372 RTSEL uSelDS = ASMGetDS();
4373 RTSEL uSelFS = ASMGetFS();
4374 RTSEL uSelGS = ASMGetGS();
4375 RTSEL uSelTR = ASMGetTR();
4376
4377 /*
4378 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4379 * gain VM-entry and restore them before we get preempted.
4380 *
4381 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4382 */
4383 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4384 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4385 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4386 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4387
4388 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4389 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4390 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4391 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4392 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4393 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4394 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4395 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4396 Assert(uSelCS);
4397 Assert(uSelTR);
4398
4399 /* Write these host selector fields into the host-state area in the VMCS. */
4400 int rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, uSelCS); AssertRC(rc);
4401 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, uSelSS); AssertRC(rc);
4402 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4403 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4404 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4405 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4406 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, uSelTR); AssertRC(rc);
4407
4408 /*
4409 * Host GDTR and IDTR.
4410 */
4411 RTGDTR Gdtr;
4412 RTIDTR Idtr;
4413 RT_ZERO(Gdtr);
4414 RT_ZERO(Idtr);
4415 ASMGetGDTR(&Gdtr);
4416 ASMGetIDTR(&Idtr);
4417 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt); AssertRC(rc);
4418 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt); AssertRC(rc);
4419
4420 /*
4421 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4422 * them to the maximum limit (0xffff) on every VM-exit.
4423 */
4424 if (Gdtr.cbGdt != 0xffff)
4425 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4426
4427 /*
4428 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4429 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4430 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4431 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4432 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4433 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4434 * at 0xffff on hosts where we are sure it won't cause trouble.
4435 */
4436#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4437 if (Idtr.cbIdt < 0x0fff)
4438#else
4439 if (Idtr.cbIdt != 0xffff)
4440#endif
4441 {
4442 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4443 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4444 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4445 }
4446
4447 /*
4448 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4449 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4450 * RPL should be too in most cases.
4451 */
4452 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4453 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4454
4455 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4456 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4457
4458 /*
4459 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4460 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4461 * restoration if the host has something else. Task switching is not supported in 64-bit
4462 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4463 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4464 *
4465 * [1] See Intel spec. 3.5 "System Descriptor Types".
4466 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4467 */
4468 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4469 Assert(pDesc->System.u4Type == 11);
4470 if ( pDesc->System.u16LimitLow != 0x67
4471 || pDesc->System.u4LimitHigh)
4472 {
4473 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4474 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4475 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4476 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4477 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4478 }
4479
4480 /*
4481 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4482 */
4483 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4484 {
4485 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4486 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4487 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4488 {
4489 /* The GDT is read-only but the writable GDT is available. */
4490 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4491 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4492 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4493 AssertRCReturn(rc, rc);
4494 }
4495 }
4496
4497 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase);
4498 AssertRC(rc);
4499
4500 /*
4501 * Host FS base and GS base.
4502 */
4503 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4504 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4505 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, u64FSBase); AssertRC(rc);
4506 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, u64GSBase); AssertRC(rc);
4507
4508 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4509 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4510 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4511 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4512 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4513
4514 return VINF_SUCCESS;
4515#undef VMXLOCAL_ADJUST_HOST_SEG
4516}
4517
4518
4519/**
4520 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4521 * host-state area of the VMCS.
4522 *
4523 * These MSRs will be automatically restored on the host after every successful
4524 * VM-exit.
4525 *
4526 * @param pVCpu The cross context virtual CPU structure.
4527 *
4528 * @remarks No-long-jump zone!!!
4529 */
4530static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4531{
4532 AssertPtr(pVCpu);
4533
4534 /*
4535 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4536 * rather than swapping them on every VM-entry.
4537 */
4538 hmR0VmxLazySaveHostMsrs(pVCpu);
4539
4540 /*
4541 * Host Sysenter MSRs.
4542 */
4543 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4544 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4545 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4546
4547 /*
4548 * Host EFER MSR.
4549 *
4550 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4551 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4552 */
4553 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4554 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4555 {
4556 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4557 AssertRC(rc);
4558 }
4559
4560 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4561 * hmR0VmxExportGuestEntryExitCtls(). */
4562}
4563
4564
4565/**
4566 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4567 *
4568 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4569 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4570 *
4571 * @returns true if we need to load guest EFER, false otherwise.
4572 * @param pVCpu The cross context virtual CPU structure.
4573 * @param pVmxTransient The VMX-transient structure.
4574 *
4575 * @remarks Requires EFER, CR4.
4576 * @remarks No-long-jump zone!!!
4577 */
4578static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4579{
4580#ifdef HMVMX_ALWAYS_SWAP_EFER
4581 RT_NOREF2(pVCpu, pVmxTransient);
4582 return true;
4583#else
4584 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4585 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4586 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4587 uint64_t const u64GuestEfer = pCtx->msrEFER;
4588
4589# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4590 /*
4591 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4592 * the nested-guest.
4593 */
4594 if ( pVmxTransient->fIsNestedGuest
4595 && ( CPUMIsGuestVmxEntryCtlsSet(pVCpu, pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4596 || CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4597 || CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4598 return true;
4599# else
4600 RT_NOREF(pVmxTransient);
4601#endif
4602
4603 /*
4604 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4605 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4606 */
4607 if ( CPUMIsGuestInLongModeEx(pCtx)
4608 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4609 return true;
4610
4611 /*
4612 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4613 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4614 *
4615 * See Intel spec. 4.5 "IA-32e Paging".
4616 * See Intel spec. 4.1.1 "Three Paging Modes".
4617 *
4618 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4619 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4620 */
4621 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4622 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4623 if ( (pCtx->cr4 & X86_CR4_PAE)
4624 && (pCtx->cr0 & X86_CR0_PG))
4625 {
4626 /*
4627 * If nested paging is not used, verify that the guest paging mode matches the
4628 * shadow paging mode which is/will be placed in the VMCS (which is what will
4629 * actually be used while executing the guest and not the CR4 shadow value).
4630 */
4631 AssertMsg(pVM->hm.s.fNestedPaging || ( pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4632 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4633 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4634 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX),
4635 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4636 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4637 {
4638 /* Verify that the host is NX capable. */
4639 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4640 return true;
4641 }
4642 }
4643
4644 return false;
4645#endif
4646}
4647
4648
4649/**
4650 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4651 * VMCS.
4652 *
4653 * This is typically required when the guest changes paging mode.
4654 *
4655 * @returns VBox status code.
4656 * @param pVCpu The cross context virtual CPU structure.
4657 * @param pVmxTransient The VMX-transient structure.
4658 *
4659 * @remarks Requires EFER.
4660 * @remarks No-long-jump zone!!!
4661 */
4662static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4663{
4664 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4665 {
4666 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4667 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4668 bool const fGstInLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
4669
4670 /*
4671 * VMRUN function.
4672 * If the guest is in long mode, use the 64-bit guest handler, else the 32-bit guest handler.
4673 * The host is always 64-bit since we no longer support 32-bit hosts.
4674 */
4675 if (fGstInLongMode)
4676 {
4677#ifndef VBOX_WITH_64_BITS_GUESTS
4678 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
4679#else
4680 Assert(pVM->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
4681 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
4682#endif
4683 }
4684 else
4685 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
4686
4687 /*
4688 * VM-entry controls.
4689 */
4690 {
4691 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4692 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4693
4694 /*
4695 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4696 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4697 *
4698 * For nested-guests, this is a mandatory VM-entry control. It's also
4699 * required because we do not want to leak host bits to the nested-guest.
4700 */
4701 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4702
4703 /*
4704 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4705 *
4706 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4707 * required to get the nested-guest working with hardware-assisted VMX execution.
4708 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
4709 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4710 * here rather than while merging the guest VMCS controls.
4711 */
4712 if (fGstInLongMode)
4713 {
4714 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
4715 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4716 }
4717 else
4718 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4719
4720 /*
4721 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4722 *
4723 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4724 * regardless of whether the nested-guest VMCS specifies it because we are free to
4725 * load whatever MSRs we require and we do not need to modify the guest visible copy
4726 * of the VM-entry MSR load area.
4727 */
4728 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4729 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4730 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4731 else
4732 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4733
4734 /*
4735 * The following should -not- be set (since we're not in SMM mode):
4736 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4737 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4738 */
4739
4740 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4741 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4742
4743 if ((fVal & fZap) == fVal)
4744 { /* likely */ }
4745 else
4746 {
4747 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4748 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4749 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4750 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4751 }
4752
4753 /* Commit it to the VMCS. */
4754 if (pVmcsInfo->u32EntryCtls != fVal)
4755 {
4756 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4757 AssertRC(rc);
4758 pVmcsInfo->u32EntryCtls = fVal;
4759 }
4760 }
4761
4762 /*
4763 * VM-exit controls.
4764 */
4765 {
4766 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4767 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4768
4769 /*
4770 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4771 * supported the 1-setting of this bit.
4772 *
4773 * For nested-guests, we set the "save debug controls" as the converse
4774 * "load debug controls" is mandatory for nested-guests anyway.
4775 */
4776 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4777
4778 /*
4779 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4780 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4781 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4782 * hmR0VmxExportHostMsrs().
4783 *
4784 * For nested-guests, we always set this bit as we do not support 32-bit
4785 * hosts.
4786 */
4787 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4788
4789 /*
4790 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4791 *
4792 * For nested-guests, we should use the "save IA32_EFER" control if we also
4793 * used the "load IA32_EFER" control while exporting VM-entry controls.
4794 */
4795 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4796 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4797 {
4798 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4799 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4800 }
4801
4802 /*
4803 * Enable saving of the VMX-preemption timer value on VM-exit.
4804 * For nested-guests, currently not exposed/used.
4805 */
4806 if ( pVM->hm.s.vmx.fUsePreemptTimer
4807 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4808 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4809
4810 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4811 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4812
4813 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
4814 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
4815 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
4816
4817 if ((fVal & fZap) == fVal)
4818 { /* likely */ }
4819 else
4820 {
4821 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
4822 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
4823 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
4824 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4825 }
4826
4827 /* Commit it to the VMCS. */
4828 if (pVmcsInfo->u32ExitCtls != fVal)
4829 {
4830 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
4831 AssertRC(rc);
4832 pVmcsInfo->u32ExitCtls = fVal;
4833 }
4834 }
4835
4836 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
4837 }
4838 return VINF_SUCCESS;
4839}
4840
4841
4842/**
4843 * Sets the TPR threshold in the VMCS.
4844 *
4845 * @param pVmcsInfo The VMCS info. object.
4846 * @param u32TprThreshold The TPR threshold (task-priority class only).
4847 */
4848DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
4849{
4850 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
4851 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
4852 RT_NOREF(pVmcsInfo);
4853 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
4854 AssertRC(rc);
4855}
4856
4857
4858/**
4859 * Exports the guest APIC TPR state into the VMCS.
4860 *
4861 * @param pVCpu The cross context virtual CPU structure.
4862 * @param pVmxTransient The VMX-transient structure.
4863 *
4864 * @remarks No-long-jump zone!!!
4865 */
4866static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4867{
4868 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
4869 {
4870 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
4871
4872 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4873 if (!pVmxTransient->fIsNestedGuest)
4874 {
4875 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
4876 && APICIsEnabled(pVCpu))
4877 {
4878 /*
4879 * Setup TPR shadowing.
4880 */
4881 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
4882 {
4883 bool fPendingIntr = false;
4884 uint8_t u8Tpr = 0;
4885 uint8_t u8PendingIntr = 0;
4886 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
4887 AssertRC(rc);
4888
4889 /*
4890 * If there are interrupts pending but masked by the TPR, instruct VT-x to
4891 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
4892 * priority of the pending interrupt so we can deliver the interrupt. If there
4893 * are no interrupts pending, set threshold to 0 to not cause any
4894 * TPR-below-threshold VM-exits.
4895 */
4896 uint32_t u32TprThreshold = 0;
4897 if (fPendingIntr)
4898 {
4899 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
4900 (which is the Task-Priority Class). */
4901 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
4902 const uint8_t u8TprPriority = u8Tpr >> 4;
4903 if (u8PendingPriority <= u8TprPriority)
4904 u32TprThreshold = u8PendingPriority;
4905 }
4906
4907 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
4908 }
4909 }
4910 }
4911 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
4912 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
4913 }
4914}
4915
4916
4917/**
4918 * Gets the guest interruptibility-state.
4919 *
4920 * @returns Guest's interruptibility-state.
4921 * @param pVCpu The cross context virtual CPU structure.
4922 * @param pVmxTransient The VMX-transient structure.
4923 *
4924 * @remarks No-long-jump zone!!!
4925 */
4926static uint32_t hmR0VmxGetGuestIntrState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4927{
4928 /*
4929 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
4930 */
4931 uint32_t fIntrState = 0;
4932 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4933 {
4934 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
4935 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
4936
4937 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4938 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
4939 {
4940 if (pCtx->eflags.Bits.u1IF)
4941 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
4942 else
4943 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
4944 }
4945 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4946 {
4947 /*
4948 * We can clear the inhibit force flag as even if we go back to the recompiler
4949 * without executing guest code in VT-x, the flag's condition to be cleared is
4950 * met and thus the cleared state is correct.
4951 */
4952 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
4953 }
4954 }
4955
4956 /*
4957 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
4958 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
4959 * setting this would block host-NMIs and IRET will not clear the blocking.
4960 *
4961 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
4962 *
4963 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
4964 */
4965 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4966 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
4967 && CPUMIsGuestNmiBlocking(pVCpu))
4968 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
4969
4970 return fIntrState;
4971}
4972
4973
4974/**
4975 * Exports the exception intercepts required for guest execution in the VMCS.
4976 *
4977 * @param pVCpu The cross context virtual CPU structure.
4978 * @param pVmxTransient The VMX-transient structure.
4979 *
4980 * @remarks No-long-jump zone!!!
4981 */
4982static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4983{
4984 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
4985 {
4986 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
4987 if ( !pVmxTransient->fIsNestedGuest
4988 && pVCpu->hm.s.fGIMTrapXcptUD)
4989 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
4990 else
4991 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
4992
4993 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
4994 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
4995 }
4996}
4997
4998
4999/**
5000 * Exports the guest's RIP into the guest-state area in the VMCS.
5001 *
5002 * @param pVCpu The cross context virtual CPU structure.
5003 *
5004 * @remarks No-long-jump zone!!!
5005 */
5006static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5007{
5008 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5009 {
5010 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5011
5012 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5013 AssertRC(rc);
5014
5015 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5016 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5017 }
5018}
5019
5020
5021/**
5022 * Exports the guest's RSP into the guest-state area in the VMCS.
5023 *
5024 * @param pVCpu The cross context virtual CPU structure.
5025 *
5026 * @remarks No-long-jump zone!!!
5027 */
5028static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5029{
5030 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5031 {
5032 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5033
5034 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5035 AssertRC(rc);
5036
5037 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5038 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5039 }
5040}
5041
5042
5043/**
5044 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5045 *
5046 * @param pVCpu The cross context virtual CPU structure.
5047 * @param pVmxTransient The VMX-transient structure.
5048 *
5049 * @remarks No-long-jump zone!!!
5050 */
5051static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5052{
5053 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5054 {
5055 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5056
5057 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5058 Let us assert it as such and use 32-bit VMWRITE. */
5059 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5060 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5061 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5062 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5063
5064 /*
5065 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5066 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5067 * can run the real-mode guest code under Virtual 8086 mode.
5068 */
5069 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5070 if (pVmcsInfo->RealMode.fRealOnV86Active)
5071 {
5072 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5073 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5074 Assert(!pVmxTransient->fIsNestedGuest);
5075 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5076 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5077 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5078 }
5079
5080 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5081 AssertRC(rc);
5082
5083 /*
5084 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
5085 *
5086 * We must avoid setting any automatic debug exceptions delivery when single-stepping
5087 * through the hypervisor debugger using EFLAGS.TF.
5088 */
5089 if ( !pVmxTransient->fIsNestedGuest
5090 && !pVCpu->hm.s.fSingleInstruction
5091 && fEFlags.Bits.u1TF)
5092 {
5093 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
5094 * premature trips to ring-3 esp since IEM does not yet handle it. */
5095 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
5096 AssertRC(rc);
5097 }
5098 /* else: for nested-guest currently handling while merging controls. */
5099
5100 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5101 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5102 }
5103}
5104
5105
5106#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5107/**
5108 * Copies the nested-guest VMCS to the shadow VMCS.
5109 *
5110 * @returns VBox status code.
5111 * @param pVCpu The cross context virtual CPU structure.
5112 * @param pVmcsInfo The VMCS info. object.
5113 *
5114 * @remarks No-long-jump zone!!!
5115 */
5116static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5117{
5118 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5119 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5120
5121 /*
5122 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5123 * current VMCS, as we may try saving guest lazy MSRs.
5124 *
5125 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5126 * calling the import VMCS code which is currently performing the guest MSR reads
5127 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5128 * and the rest of the VMX leave session machinery.
5129 */
5130 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5131
5132 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5133 if (RT_SUCCESS(rc))
5134 {
5135 /*
5136 * Copy all guest read/write VMCS fields.
5137 *
5138 * We don't check for VMWRITE failures here for performance reasons and
5139 * because they are not expected to fail, barring irrecoverable conditions
5140 * like hardware errors.
5141 */
5142 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5143 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5144 {
5145 uint64_t u64Val;
5146 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5147 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5148 VMXWriteVmcs64(uVmcsField, u64Val);
5149 }
5150
5151 /*
5152 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5153 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5154 */
5155 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5156 {
5157 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5158 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5159 {
5160 uint64_t u64Val;
5161 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5162 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5163 VMXWriteVmcs64(uVmcsField, u64Val);
5164 }
5165 }
5166
5167 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5168 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5169 }
5170
5171 ASMSetFlags(fEFlags);
5172 return rc;
5173}
5174
5175
5176/**
5177 * Copies the shadow VMCS to the nested-guest VMCS.
5178 *
5179 * @returns VBox status code.
5180 * @param pVCpu The cross context virtual CPU structure.
5181 * @param pVmcsInfo The VMCS info. object.
5182 *
5183 * @remarks Called with interrupts disabled.
5184 */
5185static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5186{
5187 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5188 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5189 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5190
5191 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5192 if (RT_SUCCESS(rc))
5193 {
5194 /*
5195 * Copy guest read/write fields from the shadow VMCS.
5196 * Guest read-only fields cannot be modified, so no need to copy them.
5197 *
5198 * We don't check for VMREAD failures here for performance reasons and
5199 * because they are not expected to fail, barring irrecoverable conditions
5200 * like hardware errors.
5201 */
5202 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5203 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5204 {
5205 uint64_t u64Val;
5206 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5207 VMXReadVmcs64(uVmcsField, &u64Val);
5208 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5209 }
5210
5211 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5212 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5213 }
5214 return rc;
5215}
5216
5217
5218/**
5219 * Enables VMCS shadowing for the given VMCS info. object.
5220 *
5221 * @param pVmcsInfo The VMCS info. object.
5222 *
5223 * @remarks No-long-jump zone!!!
5224 */
5225static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5226{
5227 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5228 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5229 {
5230 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5231 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5232 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5233 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5234 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5235 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5236 Log4Func(("Enabled\n"));
5237 }
5238}
5239
5240
5241/**
5242 * Disables VMCS shadowing for the given VMCS info. object.
5243 *
5244 * @param pVmcsInfo The VMCS info. object.
5245 *
5246 * @remarks No-long-jump zone!!!
5247 */
5248static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5249{
5250 /*
5251 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5252 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5253 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5254 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5255 *
5256 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5257 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5258 */
5259 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5260 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5261 {
5262 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5263 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5264 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5265 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5266 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5267 Log4Func(("Disabled\n"));
5268 }
5269}
5270#endif
5271
5272
5273/**
5274 * Exports the guest hardware-virtualization state.
5275 *
5276 * @returns VBox status code.
5277 * @param pVCpu The cross context virtual CPU structure.
5278 * @param pVmxTransient The VMX-transient structure.
5279 *
5280 * @remarks No-long-jump zone!!!
5281 */
5282static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5283{
5284 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5285 {
5286#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5287 /*
5288 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5289 * VMCS shadowing.
5290 */
5291 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5292 {
5293 /*
5294 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5295 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5296 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5297 *
5298 * We check for VMX root mode here in case the guest executes VMXOFF without
5299 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5300 * not clear the current VMCS pointer.
5301 */
5302 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5303 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5304 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5305 && CPUMIsGuestVmxCurrentVmcsValid(pVCpu, &pVCpu->cpum.GstCtx))
5306 {
5307 /* Paranoia. */
5308 Assert(!pVmxTransient->fIsNestedGuest);
5309
5310 /*
5311 * For performance reasons, also check if the nested hypervisor's current VMCS
5312 * was newly loaded or modified before copying it to the shadow VMCS.
5313 */
5314 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5315 {
5316 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5317 AssertRCReturn(rc, rc);
5318 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5319 }
5320 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5321 }
5322 else
5323 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5324 }
5325#else
5326 NOREF(pVmxTransient);
5327#endif
5328 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5329 }
5330 return VINF_SUCCESS;
5331}
5332
5333
5334/**
5335 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5336 *
5337 * The guest FPU state is always pre-loaded hence we don't need to bother about
5338 * sharing FPU related CR0 bits between the guest and host.
5339 *
5340 * @returns VBox status code.
5341 * @param pVCpu The cross context virtual CPU structure.
5342 * @param pVmxTransient The VMX-transient structure.
5343 *
5344 * @remarks No-long-jump zone!!!
5345 */
5346static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5347{
5348 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5349 {
5350 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5351 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5352
5353 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
5354 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5355 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5356 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5357 else
5358 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5359
5360 if (!pVmxTransient->fIsNestedGuest)
5361 {
5362 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5363 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5364 uint64_t const u64ShadowCr0 = u64GuestCr0;
5365 Assert(!RT_HI_U32(u64GuestCr0));
5366
5367 /*
5368 * Setup VT-x's view of the guest CR0.
5369 */
5370 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5371 if (pVM->hm.s.fNestedPaging)
5372 {
5373 if (CPUMIsGuestPagingEnabled(pVCpu))
5374 {
5375 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5376 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5377 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5378 }
5379 else
5380 {
5381 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5382 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5383 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5384 }
5385
5386 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5387 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5388 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5389 }
5390 else
5391 {
5392 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5393 u64GuestCr0 |= X86_CR0_WP;
5394 }
5395
5396 /*
5397 * Guest FPU bits.
5398 *
5399 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5400 * using CR0.TS.
5401 *
5402 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5403 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5404 */
5405 u64GuestCr0 |= X86_CR0_NE;
5406
5407 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5408 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5409
5410 /*
5411 * Update exception intercepts.
5412 */
5413 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5414 if (pVmcsInfo->RealMode.fRealOnV86Active)
5415 {
5416 Assert(PDMVmmDevHeapIsEnabled(pVM));
5417 Assert(pVM->hm.s.vmx.pRealModeTSS);
5418 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5419 }
5420 else
5421 {
5422 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5423 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5424 if (fInterceptMF)
5425 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5426 }
5427
5428 /* Additional intercepts for debugging, define these yourself explicitly. */
5429#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5430 uXcptBitmap |= 0
5431 | RT_BIT(X86_XCPT_BP)
5432 | RT_BIT(X86_XCPT_DE)
5433 | RT_BIT(X86_XCPT_NM)
5434 | RT_BIT(X86_XCPT_TS)
5435 | RT_BIT(X86_XCPT_UD)
5436 | RT_BIT(X86_XCPT_NP)
5437 | RT_BIT(X86_XCPT_SS)
5438 | RT_BIT(X86_XCPT_GP)
5439 | RT_BIT(X86_XCPT_PF)
5440 | RT_BIT(X86_XCPT_MF)
5441 ;
5442#elif defined(HMVMX_ALWAYS_TRAP_PF)
5443 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5444#endif
5445 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5446 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5447 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5448
5449 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5450 u64GuestCr0 |= fSetCr0;
5451 u64GuestCr0 &= fZapCr0;
5452 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5453
5454 /* Commit the CR0 and related fields to the guest VMCS. */
5455 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5456 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5457 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5458 {
5459 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5460 AssertRC(rc);
5461 }
5462 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5463 {
5464 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5465 AssertRC(rc);
5466 }
5467
5468 /* Update our caches. */
5469 pVmcsInfo->u32ProcCtls = uProcCtls;
5470 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5471
5472 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5473 }
5474 else
5475 {
5476 /*
5477 * With nested-guests, we may have extended the guest/host mask here since we
5478 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5479 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5480 * originally supplied. We must copy those bits from the nested-guest CR0 into
5481 * the nested-guest CR0 read-shadow.
5482 */
5483 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5484 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5485 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(pVCpu, &pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5486 Assert(!RT_HI_U32(u64GuestCr0));
5487 Assert(u64GuestCr0 & X86_CR0_NE);
5488
5489 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5490 u64GuestCr0 |= fSetCr0;
5491 u64GuestCr0 &= fZapCr0;
5492 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5493
5494 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5495 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5496 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5497
5498 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5499 }
5500
5501 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5502 }
5503
5504 return VINF_SUCCESS;
5505}
5506
5507
5508/**
5509 * Exports the guest control registers (CR3, CR4) into the guest-state area
5510 * in the VMCS.
5511 *
5512 * @returns VBox strict status code.
5513 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5514 * without unrestricted guest access and the VMMDev is not presently
5515 * mapped (e.g. EFI32).
5516 *
5517 * @param pVCpu The cross context virtual CPU structure.
5518 * @param pVmxTransient The VMX-transient structure.
5519 *
5520 * @remarks No-long-jump zone!!!
5521 */
5522static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5523{
5524 int rc = VINF_SUCCESS;
5525 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5526
5527 /*
5528 * Guest CR2.
5529 * It's always loaded in the assembler code. Nothing to do here.
5530 */
5531
5532 /*
5533 * Guest CR3.
5534 */
5535 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5536 {
5537 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5538
5539 if (pVM->hm.s.fNestedPaging)
5540 {
5541 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5542 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5543
5544 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5545 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5546 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5547 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5548
5549 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5550 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5551 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5552
5553 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5554 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5555 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5556 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5557 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5558 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5559 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5560
5561 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5562 AssertRC(rc);
5563
5564 uint64_t u64GuestCr3;
5565 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5566 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5567 || CPUMIsGuestPagingEnabledEx(pCtx))
5568 {
5569 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5570 if (CPUMIsGuestInPAEModeEx(pCtx))
5571 {
5572 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5573 AssertRC(rc);
5574 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5575 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5576 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5577 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5578 }
5579
5580 /*
5581 * The guest's view of its CR3 is unblemished with nested paging when the
5582 * guest is using paging or we have unrestricted guest execution to handle
5583 * the guest when it's not using paging.
5584 */
5585 u64GuestCr3 = pCtx->cr3;
5586 }
5587 else
5588 {
5589 /*
5590 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5591 * thinks it accesses physical memory directly, we use our identity-mapped
5592 * page table to map guest-linear to guest-physical addresses. EPT takes care
5593 * of translating it to host-physical addresses.
5594 */
5595 RTGCPHYS GCPhys;
5596 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5597
5598 /* We obtain it here every time as the guest could have relocated this PCI region. */
5599 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5600 if (RT_SUCCESS(rc))
5601 { /* likely */ }
5602 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5603 {
5604 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5605 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5606 }
5607 else
5608 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5609
5610 u64GuestCr3 = GCPhys;
5611 }
5612
5613 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5614 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5615 AssertRC(rc);
5616 }
5617 else
5618 {
5619 Assert(!pVmxTransient->fIsNestedGuest);
5620 /* Non-nested paging case, just use the hypervisor's CR3. */
5621 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5622
5623 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5624 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5625 AssertRC(rc);
5626 }
5627
5628 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5629 }
5630
5631 /*
5632 * Guest CR4.
5633 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5634 */
5635 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5636 {
5637 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5638 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5639
5640 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
5641 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5642
5643 /*
5644 * With nested-guests, we may have extended the guest/host mask here (since we
5645 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5646 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5647 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5648 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5649 */
5650 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5651 uint64_t u64GuestCr4 = pCtx->cr4;
5652 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5653 ? pCtx->cr4
5654 : CPUMGetGuestVmxMaskedCr4(pVCpu, pCtx, pVmcsInfo->u64Cr4Mask);
5655 Assert(!RT_HI_U32(u64GuestCr4));
5656
5657 /*
5658 * Setup VT-x's view of the guest CR4.
5659 *
5660 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5661 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5662 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5663 *
5664 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5665 */
5666 if (pVmcsInfo->RealMode.fRealOnV86Active)
5667 {
5668 Assert(pVM->hm.s.vmx.pRealModeTSS);
5669 Assert(PDMVmmDevHeapIsEnabled(pVM));
5670 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5671 }
5672
5673 if (pVM->hm.s.fNestedPaging)
5674 {
5675 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5676 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5677 {
5678 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5679 u64GuestCr4 |= X86_CR4_PSE;
5680 /* Our identity mapping is a 32-bit page directory. */
5681 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5682 }
5683 /* else use guest CR4.*/
5684 }
5685 else
5686 {
5687 Assert(!pVmxTransient->fIsNestedGuest);
5688
5689 /*
5690 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5691 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5692 */
5693 switch (pVCpu->hm.s.enmShadowMode)
5694 {
5695 case PGMMODE_REAL: /* Real-mode. */
5696 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5697 case PGMMODE_32_BIT: /* 32-bit paging. */
5698 {
5699 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5700 break;
5701 }
5702
5703 case PGMMODE_PAE: /* PAE paging. */
5704 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5705 {
5706 u64GuestCr4 |= X86_CR4_PAE;
5707 break;
5708 }
5709
5710 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5711 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5712 {
5713#ifdef VBOX_WITH_64_BITS_GUESTS
5714 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
5715 Assert(u64GuestCr4 & X86_CR4_PAE);
5716 break;
5717#endif
5718 }
5719 default:
5720 AssertFailed();
5721 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5722 }
5723 }
5724
5725 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
5726 u64GuestCr4 |= fSetCr4;
5727 u64GuestCr4 &= fZapCr4;
5728
5729 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
5730 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
5731 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
5732
5733 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5734 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5735
5736 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5737
5738 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5739 }
5740 return rc;
5741}
5742
5743
5744/**
5745 * Exports the guest debug registers into the guest-state area in the VMCS.
5746 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5747 *
5748 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5749 *
5750 * @returns VBox status code.
5751 * @param pVCpu The cross context virtual CPU structure.
5752 * @param pVmxTransient The VMX-transient structure.
5753 *
5754 * @remarks No-long-jump zone!!!
5755 */
5756static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5757{
5758 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5759
5760 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5761 * stepping. */
5762 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5763 if (pVmxTransient->fIsNestedGuest)
5764 {
5765 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5766 AssertRC(rc);
5767
5768 /* Always intercept Mov DRx accesses for the nested-guest for now. */
5769 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5770 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
5771 AssertRC(rc);
5772 return VINF_SUCCESS;
5773 }
5774
5775#ifdef VBOX_STRICT
5776 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5777 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5778 {
5779 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5780 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5781 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5782 }
5783#endif
5784
5785 bool fSteppingDB = false;
5786 bool fInterceptMovDRx = false;
5787 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5788 if (pVCpu->hm.s.fSingleInstruction)
5789 {
5790 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5791 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5792 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5793 {
5794 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5795 Assert(fSteppingDB == false);
5796 }
5797 else
5798 {
5799 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5800 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5801 pVCpu->hm.s.fClearTrapFlag = true;
5802 fSteppingDB = true;
5803 }
5804 }
5805
5806 uint64_t u64GuestDr7;
5807 if ( fSteppingDB
5808 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5809 {
5810 /*
5811 * Use the combined guest and host DRx values found in the hypervisor register set
5812 * because the hypervisor debugger has breakpoints active or someone is single stepping
5813 * on the host side without a monitor trap flag.
5814 *
5815 * Note! DBGF expects a clean DR6 state before executing guest code.
5816 */
5817 if (!CPUMIsHyperDebugStateActive(pVCpu))
5818 {
5819 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5820 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5821 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5822 }
5823
5824 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
5825 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
5826 pVCpu->hm.s.fUsingHyperDR7 = true;
5827 fInterceptMovDRx = true;
5828 }
5829 else
5830 {
5831 /*
5832 * If the guest has enabled debug registers, we need to load them prior to
5833 * executing guest code so they'll trigger at the right time.
5834 */
5835 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
5836 {
5837 if (!CPUMIsGuestDebugStateActive(pVCpu))
5838 {
5839 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
5840 Assert(CPUMIsGuestDebugStateActive(pVCpu));
5841 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
5842 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
5843 }
5844 Assert(!fInterceptMovDRx);
5845 }
5846 else if (!CPUMIsGuestDebugStateActive(pVCpu))
5847 {
5848 /*
5849 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
5850 * must intercept #DB in order to maintain a correct DR6 guest value, and
5851 * because we need to intercept it to prevent nested #DBs from hanging the
5852 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
5853 */
5854 fInterceptMovDRx = true;
5855 }
5856
5857 /* Update DR7 with the actual guest value. */
5858 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
5859 pVCpu->hm.s.fUsingHyperDR7 = false;
5860 }
5861
5862 if (fInterceptMovDRx)
5863 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5864 else
5865 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
5866
5867 /*
5868 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
5869 * monitor-trap flag and update our cache.
5870 */
5871 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5872 {
5873 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5874 AssertRC(rc);
5875 pVmcsInfo->u32ProcCtls = uProcCtls;
5876 }
5877
5878 /*
5879 * Update guest DR7.
5880 */
5881 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
5882 AssertRC(rc);
5883
5884 /*
5885 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
5886 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
5887 *
5888 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5889 */
5890 if (fSteppingDB)
5891 {
5892 Assert(pVCpu->hm.s.fSingleInstruction);
5893 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
5894
5895 uint32_t fIntrState = 0;
5896 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
5897 AssertRC(rc);
5898
5899 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
5900 {
5901 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
5902 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
5903 AssertRC(rc);
5904 }
5905 }
5906
5907 return VINF_SUCCESS;
5908}
5909
5910
5911#ifdef VBOX_STRICT
5912/**
5913 * Strict function to validate segment registers.
5914 *
5915 * @param pVCpu The cross context virtual CPU structure.
5916 * @param pVmcsInfo The VMCS info. object.
5917 *
5918 * @remarks Will import guest CR0 on strict builds during validation of
5919 * segments.
5920 */
5921static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5922{
5923 /*
5924 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
5925 *
5926 * The reason we check for attribute value 0 in this function and not just the unusable bit is
5927 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
5928 * unusable bit and doesn't change the guest-context value.
5929 */
5930 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5931 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5932 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
5933 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
5934 && ( !CPUMIsGuestInRealModeEx(pCtx)
5935 && !CPUMIsGuestInV86ModeEx(pCtx)))
5936 {
5937 /* Protected mode checks */
5938 /* CS */
5939 Assert(pCtx->cs.Attr.n.u1Present);
5940 Assert(!(pCtx->cs.Attr.u & 0xf00));
5941 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
5942 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
5943 || !(pCtx->cs.Attr.n.u1Granularity));
5944 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
5945 || (pCtx->cs.Attr.n.u1Granularity));
5946 /* CS cannot be loaded with NULL in protected mode. */
5947 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
5948 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
5949 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
5950 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
5951 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
5952 else
5953 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
5954 /* SS */
5955 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5956 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
5957 if ( !(pCtx->cr0 & X86_CR0_PE)
5958 || pCtx->cs.Attr.n.u4Type == 3)
5959 {
5960 Assert(!pCtx->ss.Attr.n.u2Dpl);
5961 }
5962 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
5963 {
5964 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5965 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
5966 Assert(pCtx->ss.Attr.n.u1Present);
5967 Assert(!(pCtx->ss.Attr.u & 0xf00));
5968 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
5969 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
5970 || !(pCtx->ss.Attr.n.u1Granularity));
5971 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
5972 || (pCtx->ss.Attr.n.u1Granularity));
5973 }
5974 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
5975 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
5976 {
5977 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5978 Assert(pCtx->ds.Attr.n.u1Present);
5979 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
5980 Assert(!(pCtx->ds.Attr.u & 0xf00));
5981 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
5982 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
5983 || !(pCtx->ds.Attr.n.u1Granularity));
5984 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
5985 || (pCtx->ds.Attr.n.u1Granularity));
5986 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5987 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
5988 }
5989 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
5990 {
5991 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5992 Assert(pCtx->es.Attr.n.u1Present);
5993 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
5994 Assert(!(pCtx->es.Attr.u & 0xf00));
5995 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
5996 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
5997 || !(pCtx->es.Attr.n.u1Granularity));
5998 Assert( !(pCtx->es.u32Limit & 0xfff00000)
5999 || (pCtx->es.Attr.n.u1Granularity));
6000 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6001 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6002 }
6003 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6004 {
6005 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6006 Assert(pCtx->fs.Attr.n.u1Present);
6007 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6008 Assert(!(pCtx->fs.Attr.u & 0xf00));
6009 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6010 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6011 || !(pCtx->fs.Attr.n.u1Granularity));
6012 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6013 || (pCtx->fs.Attr.n.u1Granularity));
6014 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6015 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6016 }
6017 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6018 {
6019 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6020 Assert(pCtx->gs.Attr.n.u1Present);
6021 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6022 Assert(!(pCtx->gs.Attr.u & 0xf00));
6023 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6024 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6025 || !(pCtx->gs.Attr.n.u1Granularity));
6026 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6027 || (pCtx->gs.Attr.n.u1Granularity));
6028 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6029 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6030 }
6031 /* 64-bit capable CPUs. */
6032 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6033 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6034 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6035 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6036 }
6037 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6038 || ( CPUMIsGuestInRealModeEx(pCtx)
6039 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6040 {
6041 /* Real and v86 mode checks. */
6042 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6043 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6044 if (pVmcsInfo->RealMode.fRealOnV86Active)
6045 {
6046 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6047 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6048 }
6049 else
6050 {
6051 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6052 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6053 }
6054
6055 /* CS */
6056 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6057 Assert(pCtx->cs.u32Limit == 0xffff);
6058 Assert(u32CSAttr == 0xf3);
6059 /* SS */
6060 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6061 Assert(pCtx->ss.u32Limit == 0xffff);
6062 Assert(u32SSAttr == 0xf3);
6063 /* DS */
6064 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6065 Assert(pCtx->ds.u32Limit == 0xffff);
6066 Assert(u32DSAttr == 0xf3);
6067 /* ES */
6068 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6069 Assert(pCtx->es.u32Limit == 0xffff);
6070 Assert(u32ESAttr == 0xf3);
6071 /* FS */
6072 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6073 Assert(pCtx->fs.u32Limit == 0xffff);
6074 Assert(u32FSAttr == 0xf3);
6075 /* GS */
6076 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6077 Assert(pCtx->gs.u32Limit == 0xffff);
6078 Assert(u32GSAttr == 0xf3);
6079 /* 64-bit capable CPUs. */
6080 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6081 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6082 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6083 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6084 }
6085}
6086#endif /* VBOX_STRICT */
6087
6088
6089/**
6090 * Exports a guest segment register into the guest-state area in the VMCS.
6091 *
6092 * @returns VBox status code.
6093 * @param pVCpu The cross context virtual CPU structure.
6094 * @param pVmcsInfo The VMCS info. object.
6095 * @param iSegReg The segment register number (X86_SREG_XXX).
6096 * @param pSelReg Pointer to the segment selector.
6097 *
6098 * @remarks No-long-jump zone!!!
6099 */
6100static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6101{
6102 Assert(iSegReg < X86_SREG_COUNT);
6103 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6104 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6105 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6106 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6107
6108 uint32_t u32Access = pSelReg->Attr.u;
6109 if (pVmcsInfo->RealMode.fRealOnV86Active)
6110 {
6111 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6112 u32Access = 0xf3;
6113 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6114 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6115 RT_NOREF_PV(pVCpu);
6116 }
6117 else
6118 {
6119 /*
6120 * The way to differentiate between whether this is really a null selector or was just
6121 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6122 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6123 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6124 * NULL selectors loaded in protected-mode have their attribute as 0.
6125 */
6126 if (!u32Access)
6127 u32Access = X86DESCATTR_UNUSABLE;
6128 }
6129
6130 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6131 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6132 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6133
6134 /*
6135 * Commit it to the VMCS.
6136 */
6137 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc);
6138 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc);
6139 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc);
6140 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc);
6141 return VINF_SUCCESS;
6142}
6143
6144
6145/**
6146 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6147 * area in the VMCS.
6148 *
6149 * @returns VBox status code.
6150 * @param pVCpu The cross context virtual CPU structure.
6151 * @param pVmxTransient The VMX-transient structure.
6152 *
6153 * @remarks Will import guest CR0 on strict builds during validation of
6154 * segments.
6155 * @remarks No-long-jump zone!!!
6156 */
6157static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6158{
6159 int rc = VERR_INTERNAL_ERROR_5;
6160 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6161 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6162 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6163
6164 /*
6165 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6166 */
6167 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6168 {
6169 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6170 {
6171 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6172 if (pVmcsInfo->RealMode.fRealOnV86Active)
6173 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6174 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6175 AssertRC(rc);
6176 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6177 }
6178
6179 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6180 {
6181 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6182 if (pVmcsInfo->RealMode.fRealOnV86Active)
6183 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6184 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6185 AssertRC(rc);
6186 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6187 }
6188
6189 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6190 {
6191 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6192 if (pVmcsInfo->RealMode.fRealOnV86Active)
6193 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6194 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6195 AssertRC(rc);
6196 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6197 }
6198
6199 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6200 {
6201 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6202 if (pVmcsInfo->RealMode.fRealOnV86Active)
6203 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6204 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6205 AssertRC(rc);
6206 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6207 }
6208
6209 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6210 {
6211 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6212 if (pVmcsInfo->RealMode.fRealOnV86Active)
6213 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6214 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6215 AssertRC(rc);
6216 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6217 }
6218
6219 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6220 {
6221 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6222 if (pVmcsInfo->RealMode.fRealOnV86Active)
6223 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6224 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6225 AssertRC(rc);
6226 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6227 }
6228
6229#ifdef VBOX_STRICT
6230 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6231#endif
6232 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6233 pCtx->cs.Attr.u));
6234 }
6235
6236 /*
6237 * Guest TR.
6238 */
6239 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6240 {
6241 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6242
6243 /*
6244 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6245 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6246 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6247 */
6248 uint16_t u16Sel;
6249 uint32_t u32Limit;
6250 uint64_t u64Base;
6251 uint32_t u32AccessRights;
6252 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6253 {
6254 u16Sel = pCtx->tr.Sel;
6255 u32Limit = pCtx->tr.u32Limit;
6256 u64Base = pCtx->tr.u64Base;
6257 u32AccessRights = pCtx->tr.Attr.u;
6258 }
6259 else
6260 {
6261 Assert(!pVmxTransient->fIsNestedGuest);
6262 Assert(pVM->hm.s.vmx.pRealModeTSS);
6263 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6264
6265 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6266 RTGCPHYS GCPhys;
6267 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6268 AssertRCReturn(rc, rc);
6269
6270 X86DESCATTR DescAttr;
6271 DescAttr.u = 0;
6272 DescAttr.n.u1Present = 1;
6273 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6274
6275 u16Sel = 0;
6276 u32Limit = HM_VTX_TSS_SIZE;
6277 u64Base = GCPhys;
6278 u32AccessRights = DescAttr.u;
6279 }
6280
6281 /* Validate. */
6282 Assert(!(u16Sel & RT_BIT(2)));
6283 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6284 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6285 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6286 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6287 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6288 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6289 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6290 Assert( (u32Limit & 0xfff) == 0xfff
6291 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6292 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6293 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6294
6295 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6296 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6297 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6298 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6299
6300 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6301 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6302 }
6303
6304 /*
6305 * Guest GDTR.
6306 */
6307 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6308 {
6309 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6310
6311 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6312 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6313
6314 /* Validate. */
6315 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6316
6317 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6318 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6319 }
6320
6321 /*
6322 * Guest LDTR.
6323 */
6324 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6325 {
6326 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6327
6328 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6329 uint32_t u32Access;
6330 if ( !pVmxTransient->fIsNestedGuest
6331 && !pCtx->ldtr.Attr.u)
6332 u32Access = X86DESCATTR_UNUSABLE;
6333 else
6334 u32Access = pCtx->ldtr.Attr.u;
6335
6336 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6337 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6338 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6339 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6340
6341 /* Validate. */
6342 if (!(u32Access & X86DESCATTR_UNUSABLE))
6343 {
6344 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6345 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6346 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6347 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6348 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6349 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6350 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6351 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6352 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6353 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6354 }
6355
6356 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6357 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6358 }
6359
6360 /*
6361 * Guest IDTR.
6362 */
6363 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6364 {
6365 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6366
6367 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6368 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6369
6370 /* Validate. */
6371 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6372
6373 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6374 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6375 }
6376
6377 return VINF_SUCCESS;
6378}
6379
6380
6381/**
6382 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6383 * areas.
6384 *
6385 * These MSRs will automatically be loaded to the host CPU on every successful
6386 * VM-entry and stored from the host CPU on every successful VM-exit.
6387 *
6388 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6389 * actual host MSR values are not- updated here for performance reasons. See
6390 * hmR0VmxExportHostMsrs().
6391 *
6392 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6393 *
6394 * @returns VBox status code.
6395 * @param pVCpu The cross context virtual CPU structure.
6396 * @param pVmxTransient The VMX-transient structure.
6397 *
6398 * @remarks No-long-jump zone!!!
6399 */
6400static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6401{
6402 AssertPtr(pVCpu);
6403 AssertPtr(pVmxTransient);
6404
6405 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6406 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6407
6408 /*
6409 * MSRs that we use the auto-load/store MSR area in the VMCS.
6410 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6411 * nothing to do here. The host MSR values are updated when it's safe in
6412 * hmR0VmxLazySaveHostMsrs().
6413 *
6414 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6415 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6416 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6417 * for any MSR that are not part of the lazy MSRs so we do not need to place
6418 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6419 */
6420 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6421 {
6422 /* No auto-load/store MSRs currently. */
6423 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6424 }
6425
6426 /*
6427 * Guest Sysenter MSRs.
6428 */
6429 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6430 {
6431 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6432
6433 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6434 {
6435 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6436 AssertRC(rc);
6437 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6438 }
6439
6440 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6441 {
6442 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6443 AssertRC(rc);
6444 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6445 }
6446
6447 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6448 {
6449 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6450 AssertRC(rc);
6451 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6452 }
6453 }
6454
6455 /*
6456 * Guest/host EFER MSR.
6457 */
6458 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6459 {
6460 /* Whether we are using the VMCS to swap the EFER MSR must have been
6461 determined earlier while exporting VM-entry/VM-exit controls. */
6462 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6463 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6464
6465 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6466 {
6467 /*
6468 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6469 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6470 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6471 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6472 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6473 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6474 * during VM-entry.
6475 */
6476 uint64_t uGuestEferMsr = pCtx->msrEFER;
6477 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6478 {
6479 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6480 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6481 else
6482 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6483 }
6484
6485 /*
6486 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6487 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6488 */
6489 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6490 {
6491 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6492 AssertRC(rc);
6493 }
6494 else
6495 {
6496 /*
6497 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6498 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6499 */
6500 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6501 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6502 AssertRCReturn(rc, rc);
6503 }
6504
6505 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6506 }
6507 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6508 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6509
6510 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6511 }
6512
6513 /*
6514 * Other MSRs.
6515 * Speculation Control (R/W).
6516 */
6517 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6518 {
6519 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6520 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6521 {
6522 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6523 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6524 AssertRCReturn(rc, rc);
6525 }
6526 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6527 }
6528
6529 return VINF_SUCCESS;
6530}
6531
6532
6533/**
6534 * Wrapper for running the guest code in VT-x.
6535 *
6536 * @returns VBox status code, no informational status codes.
6537 * @param pVCpu The cross context virtual CPU structure.
6538 * @param pVmxTransient The VMX-transient structure.
6539 *
6540 * @remarks No-long-jump zone!!!
6541 */
6542DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6543{
6544 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6545 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6546 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6547
6548 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6549
6550 /*
6551 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6552 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6553 * callee-saved and thus the need for this XMM wrapper.
6554 *
6555 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6556 */
6557 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6558 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6559 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6560#ifdef VBOX_WITH_KERNEL_USING_XMM
6561 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6562#else
6563 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu);
6564#endif
6565 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6566 return rc;
6567}
6568
6569
6570/**
6571 * Reports world-switch error and dumps some useful debug info.
6572 *
6573 * @param pVCpu The cross context virtual CPU structure.
6574 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6575 * @param pVmxTransient The VMX-transient structure (only
6576 * exitReason updated).
6577 */
6578static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6579{
6580 Assert(pVCpu);
6581 Assert(pVmxTransient);
6582 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6583
6584 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6585 switch (rcVMRun)
6586 {
6587 case VERR_VMX_INVALID_VMXON_PTR:
6588 AssertFailed();
6589 break;
6590 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6591 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6592 {
6593 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6594 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6595 AssertRC(rc);
6596 hmR0VmxReadExitQualVmcs(pVmxTransient);
6597
6598 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6599 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6600 Cannot do it here as we may have been long preempted. */
6601
6602#ifdef VBOX_STRICT
6603 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6604 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6605 pVmxTransient->uExitReason));
6606 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6607 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6608 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6609 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6610 else
6611 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6612 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6613 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6614
6615 static struct
6616 {
6617 /** Name of the field to log. */
6618 const char *pszName;
6619 /** The VMCS field. */
6620 uint32_t uVmcsField;
6621 /** Whether host support of this field needs to be checked. */
6622 bool fCheckSupport;
6623 } const s_aVmcsFields[] =
6624 {
6625 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6626 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6627 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6628 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6629 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6630 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6631 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6632 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6633 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6634 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6635 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6636 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6637 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6638 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6639 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6640 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6641 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6642 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6643 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6644 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6645 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6646 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6647 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6648 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6649 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6650 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6651 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6652 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6653 /* The order of selector fields below are fixed! */
6654 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6655 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6656 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6657 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6658 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6659 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6660 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6661 /* End of ordered selector fields. */
6662 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6663 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6664 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6665 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6666 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6667 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6668 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6669 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6670 };
6671
6672 RTGDTR HostGdtr;
6673 ASMGetGDTR(&HostGdtr);
6674
6675 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6676 for (uint32_t i = 0; i < cVmcsFields; i++)
6677 {
6678 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
6679
6680 bool fSupported;
6681 if (!s_aVmcsFields[i].fCheckSupport)
6682 fSupported = true;
6683 else
6684 {
6685 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6686 switch (uVmcsField)
6687 {
6688 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
6689 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
6690 case VMX_VMCS32_CTRL_PROC_EXEC2:
6691 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
6692 break;
6693 default:
6694 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
6695 }
6696 }
6697
6698 if (fSupported)
6699 {
6700 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
6701 switch (uWidth)
6702 {
6703 case VMX_VMCSFIELD_WIDTH_16BIT:
6704 {
6705 uint16_t u16Val;
6706 rc = VMXReadVmcs16(uVmcsField, &u16Val);
6707 AssertRC(rc);
6708 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
6709
6710 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
6711 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
6712 {
6713 if (u16Val < HostGdtr.cbGdt)
6714 {
6715 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
6716 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
6717 "Host FS", "Host GS", "Host TR" };
6718 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
6719 Assert(idxSel < RT_ELEMENTS(s_apszSel));
6720 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
6721 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
6722 }
6723 else
6724 Log4((" Selector value exceeds GDT limit!\n"));
6725 }
6726 break;
6727 }
6728
6729 case VMX_VMCSFIELD_WIDTH_32BIT:
6730 {
6731 uint32_t u32Val;
6732 rc = VMXReadVmcs32(uVmcsField, &u32Val);
6733 AssertRC(rc);
6734 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
6735 break;
6736 }
6737
6738 case VMX_VMCSFIELD_WIDTH_64BIT:
6739 case VMX_VMCSFIELD_WIDTH_NATURAL:
6740 {
6741 uint64_t u64Val;
6742 rc = VMXReadVmcs64(uVmcsField, &u64Val);
6743 AssertRC(rc);
6744 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
6745 break;
6746 }
6747 }
6748 }
6749 }
6750
6751 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6752 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6753 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6754 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6755 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6756 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6757#endif /* VBOX_STRICT */
6758 break;
6759 }
6760
6761 default:
6762 /* Impossible */
6763 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6764 break;
6765 }
6766}
6767
6768
6769/**
6770 * Sets up the usage of TSC-offsetting and updates the VMCS.
6771 *
6772 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6773 * VMX-preemption timer.
6774 *
6775 * @returns VBox status code.
6776 * @param pVCpu The cross context virtual CPU structure.
6777 * @param pVmxTransient The VMX-transient structure.
6778 *
6779 * @remarks No-long-jump zone!!!
6780 */
6781static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6782{
6783 bool fOffsettedTsc;
6784 bool fParavirtTsc;
6785 uint64_t uTscOffset;
6786 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6787 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6788
6789 if (pVM->hm.s.vmx.fUsePreemptTimer)
6790 {
6791 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
6792
6793 /* Make sure the returned values have sane upper and lower boundaries. */
6794 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
6795 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
6796 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
6797 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
6798
6799 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
6800 * preemption timers here. We probably need to clamp the preemption timer,
6801 * after converting the timer value to the host. */
6802 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
6803 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
6804 AssertRC(rc);
6805 }
6806 else
6807 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
6808
6809 if (fParavirtTsc)
6810 {
6811 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
6812 information before every VM-entry, hence disable it for performance sake. */
6813#if 0
6814 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
6815 AssertRC(rc);
6816#endif
6817 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
6818 }
6819
6820 if ( fOffsettedTsc
6821 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
6822 {
6823 if (pVmxTransient->fIsNestedGuest)
6824 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
6825 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
6826 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6827 }
6828 else
6829 {
6830 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
6831 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6832 }
6833}
6834
6835
6836/**
6837 * Gets the IEM exception flags for the specified vector and IDT vectoring /
6838 * VM-exit interruption info type.
6839 *
6840 * @returns The IEM exception flags.
6841 * @param uVector The event vector.
6842 * @param uVmxEventType The VMX event type.
6843 *
6844 * @remarks This function currently only constructs flags required for
6845 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
6846 * and CR2 aspects of an exception are not included).
6847 */
6848static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
6849{
6850 uint32_t fIemXcptFlags;
6851 switch (uVmxEventType)
6852 {
6853 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
6854 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
6855 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
6856 break;
6857
6858 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
6859 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
6860 break;
6861
6862 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
6863 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
6864 break;
6865
6866 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
6867 {
6868 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6869 if (uVector == X86_XCPT_BP)
6870 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
6871 else if (uVector == X86_XCPT_OF)
6872 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
6873 else
6874 {
6875 fIemXcptFlags = 0;
6876 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
6877 }
6878 break;
6879 }
6880
6881 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
6882 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6883 break;
6884
6885 default:
6886 fIemXcptFlags = 0;
6887 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
6888 break;
6889 }
6890 return fIemXcptFlags;
6891}
6892
6893
6894/**
6895 * Sets an event as a pending event to be injected into the guest.
6896 *
6897 * @param pVCpu The cross context virtual CPU structure.
6898 * @param u32IntInfo The VM-entry interruption-information field.
6899 * @param cbInstr The VM-entry instruction length in bytes (for
6900 * software interrupts, exceptions and privileged
6901 * software exceptions).
6902 * @param u32ErrCode The VM-entry exception error code.
6903 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
6904 * page-fault.
6905 */
6906DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
6907 RTGCUINTPTR GCPtrFaultAddress)
6908{
6909 Assert(!pVCpu->hm.s.Event.fPending);
6910 pVCpu->hm.s.Event.fPending = true;
6911 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
6912 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
6913 pVCpu->hm.s.Event.cbInstr = cbInstr;
6914 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
6915}
6916
6917
6918/**
6919 * Sets an external interrupt as pending-for-injection into the VM.
6920 *
6921 * @param pVCpu The cross context virtual CPU structure.
6922 * @param u8Interrupt The external interrupt vector.
6923 */
6924DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
6925{
6926 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
6927 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
6928 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6929 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6930 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6931}
6932
6933
6934/**
6935 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
6936 *
6937 * @param pVCpu The cross context virtual CPU structure.
6938 */
6939DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
6940{
6941 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
6942 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
6943 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6944 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6945 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6946}
6947
6948
6949/**
6950 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
6951 *
6952 * @param pVCpu The cross context virtual CPU structure.
6953 */
6954DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
6955{
6956 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
6957 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6958 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6959 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6960 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6961}
6962
6963
6964/**
6965 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
6966 *
6967 * @param pVCpu The cross context virtual CPU structure.
6968 */
6969DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
6970{
6971 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
6972 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6973 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6974 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6975 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6976}
6977
6978
6979/**
6980 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
6981 *
6982 * @param pVCpu The cross context virtual CPU structure.
6983 */
6984DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
6985{
6986 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
6987 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6988 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6989 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6990 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6991}
6992
6993
6994#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
6995/**
6996 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
6997 *
6998 * @param pVCpu The cross context virtual CPU structure.
6999 * @param u32ErrCode The error code for the general-protection exception.
7000 */
7001DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7002{
7003 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7004 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7005 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7006 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7007 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7008}
7009
7010
7011/**
7012 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7013 *
7014 * @param pVCpu The cross context virtual CPU structure.
7015 * @param u32ErrCode The error code for the stack exception.
7016 */
7017DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7018{
7019 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7020 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7021 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7022 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7023 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7024}
7025#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7026
7027
7028/**
7029 * Fixes up attributes for the specified segment register.
7030 *
7031 * @param pVCpu The cross context virtual CPU structure.
7032 * @param pSelReg The segment register that needs fixing.
7033 * @param idxSel The VMCS field for the corresponding segment register.
7034 */
7035static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7036{
7037 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7038
7039 /*
7040 * If VT-x marks the segment as unusable, most other bits remain undefined:
7041 * - For CS the L, D and G bits have meaning.
7042 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7043 * - For the remaining data segments no bits are defined.
7044 *
7045 * The present bit and the unusable bit has been observed to be set at the
7046 * same time (the selector was supposed to be invalid as we started executing
7047 * a V8086 interrupt in ring-0).
7048 *
7049 * What should be important for the rest of the VBox code, is that the P bit is
7050 * cleared. Some of the other VBox code recognizes the unusable bit, but
7051 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7052 * safe side here, we'll strip off P and other bits we don't care about. If
7053 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7054 *
7055 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7056 */
7057#ifdef VBOX_STRICT
7058 uint32_t const uAttr = pSelReg->Attr.u;
7059#endif
7060
7061 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7062 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7063 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7064
7065#ifdef VBOX_STRICT
7066 VMMRZCallRing3Disable(pVCpu);
7067 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7068# ifdef DEBUG_bird
7069 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7070 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7071 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7072# endif
7073 VMMRZCallRing3Enable(pVCpu);
7074 NOREF(uAttr);
7075#endif
7076 RT_NOREF2(pVCpu, idxSel);
7077}
7078
7079
7080/**
7081 * Imports a guest segment register from the current VMCS into the guest-CPU
7082 * context.
7083 *
7084 * @param pVCpu The cross context virtual CPU structure.
7085 * @param iSegReg The segment register number (X86_SREG_XXX).
7086 *
7087 * @remarks Called with interrupts and/or preemption disabled.
7088 */
7089static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint8_t iSegReg)
7090{
7091 Assert(iSegReg < X86_SREG_COUNT);
7092
7093 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7094 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7095 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7096 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7097
7098 uint16_t u16Sel;
7099 uint64_t u64Base;
7100 uint32_t u32Limit, u32Attr;
7101 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc);
7102 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc);
7103 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc);
7104 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc);
7105
7106 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7107 pSelReg->Sel = u16Sel;
7108 pSelReg->ValidSel = u16Sel;
7109 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7110 pSelReg->u32Limit = u32Limit;
7111 pSelReg->u64Base = u64Base;
7112 pSelReg->Attr.u = u32Attr;
7113 if (u32Attr & X86DESCATTR_UNUSABLE)
7114 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7115}
7116
7117
7118/**
7119 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7120 *
7121 * @param pVCpu The cross context virtual CPU structure.
7122 *
7123 * @remarks Called with interrupts and/or preemption disabled.
7124 */
7125static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7126{
7127 uint16_t u16Sel;
7128 uint64_t u64Base;
7129 uint32_t u32Limit, u32Attr;
7130 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7131 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7132 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7133 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7134
7135 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7136 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7137 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7138 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7139 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7140 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7141 if (u32Attr & X86DESCATTR_UNUSABLE)
7142 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7143}
7144
7145
7146/**
7147 * Imports the guest TR from the current VMCS into the guest-CPU context.
7148 *
7149 * @param pVCpu The cross context virtual CPU structure.
7150 *
7151 * @remarks Called with interrupts and/or preemption disabled.
7152 */
7153static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7154{
7155 uint16_t u16Sel;
7156 uint64_t u64Base;
7157 uint32_t u32Limit, u32Attr;
7158 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7159 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7160 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7161 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7162
7163 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7164 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7165 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7166 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7167 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7168 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7169 /* TR is the only selector that can never be unusable. */
7170 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7171}
7172
7173
7174/**
7175 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7176 *
7177 * @param pVCpu The cross context virtual CPU structure.
7178 *
7179 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7180 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7181 * instead!!!
7182 */
7183static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7184{
7185 uint64_t u64Val;
7186 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7187 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7188 {
7189 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7190 AssertRC(rc);
7191
7192 pCtx->rip = u64Val;
7193 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7194 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7195 }
7196}
7197
7198
7199/**
7200 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7201 *
7202 * @param pVCpu The cross context virtual CPU structure.
7203 * @param pVmcsInfo The VMCS info. object.
7204 *
7205 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7206 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7207 * instead!!!
7208 */
7209static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7210{
7211 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7212 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7213 {
7214 uint64_t u64Val;
7215 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7216 AssertRC(rc);
7217
7218 pCtx->rflags.u64 = u64Val;
7219 if (pVmcsInfo->RealMode.fRealOnV86Active)
7220 {
7221 pCtx->eflags.Bits.u1VM = 0;
7222 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7223 }
7224 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7225 }
7226}
7227
7228
7229/**
7230 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7231 * context.
7232 *
7233 * @param pVCpu The cross context virtual CPU structure.
7234 * @param pVmcsInfo The VMCS info. object.
7235 *
7236 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7237 * do not log!
7238 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7239 * instead!!!
7240 */
7241static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7242{
7243 uint32_t u32Val;
7244 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7245 if (!u32Val)
7246 {
7247 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7248 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7249 CPUMSetGuestNmiBlocking(pVCpu, false);
7250 }
7251 else
7252 {
7253 /*
7254 * We must import RIP here to set our EM interrupt-inhibited state.
7255 * We also import RFLAGS as our code that evaluates pending interrupts
7256 * before VM-entry requires it.
7257 */
7258 hmR0VmxImportGuestRip(pVCpu);
7259 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7260
7261 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7262 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7263 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7264 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7265
7266 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7267 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7268 }
7269}
7270
7271
7272/**
7273 * Worker for VMXR0ImportStateOnDemand.
7274 *
7275 * @returns VBox status code.
7276 * @param pVCpu The cross context virtual CPU structure.
7277 * @param pVmcsInfo The VMCS info. object.
7278 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7279 */
7280static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7281{
7282 int rc = VINF_SUCCESS;
7283 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7284 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7285 uint32_t u32Val;
7286
7287 /*
7288 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7289 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7290 * neither are other host platforms.
7291 *
7292 * Committing this temporarily as it prevents BSOD.
7293 *
7294 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7295 */
7296#ifdef RT_OS_WINDOWS
7297 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7298 return VERR_HM_IPE_1;
7299#endif
7300
7301 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7302
7303 /*
7304 * We disable interrupts to make the updating of the state and in particular
7305 * the fExtrn modification atomic wrt to preemption hooks.
7306 */
7307 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7308
7309 fWhat &= pCtx->fExtrn;
7310 if (fWhat)
7311 {
7312 do
7313 {
7314 if (fWhat & CPUMCTX_EXTRN_RIP)
7315 hmR0VmxImportGuestRip(pVCpu);
7316
7317 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7318 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7319
7320 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7321 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7322
7323 if (fWhat & CPUMCTX_EXTRN_RSP)
7324 {
7325 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7326 AssertRC(rc);
7327 }
7328
7329 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7330 {
7331 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7332 if (fWhat & CPUMCTX_EXTRN_CS)
7333 {
7334 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7335 hmR0VmxImportGuestRip(pVCpu);
7336 if (fRealOnV86Active)
7337 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7338 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7339 }
7340 if (fWhat & CPUMCTX_EXTRN_SS)
7341 {
7342 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7343 if (fRealOnV86Active)
7344 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7345 }
7346 if (fWhat & CPUMCTX_EXTRN_DS)
7347 {
7348 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7349 if (fRealOnV86Active)
7350 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7351 }
7352 if (fWhat & CPUMCTX_EXTRN_ES)
7353 {
7354 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7355 if (fRealOnV86Active)
7356 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7357 }
7358 if (fWhat & CPUMCTX_EXTRN_FS)
7359 {
7360 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7361 if (fRealOnV86Active)
7362 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7363 }
7364 if (fWhat & CPUMCTX_EXTRN_GS)
7365 {
7366 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7367 if (fRealOnV86Active)
7368 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7369 }
7370 }
7371
7372 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7373 {
7374 if (fWhat & CPUMCTX_EXTRN_LDTR)
7375 hmR0VmxImportGuestLdtr(pVCpu);
7376
7377 if (fWhat & CPUMCTX_EXTRN_GDTR)
7378 {
7379 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7380 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7381 pCtx->gdtr.cbGdt = u32Val;
7382 }
7383
7384 /* Guest IDTR. */
7385 if (fWhat & CPUMCTX_EXTRN_IDTR)
7386 {
7387 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7388 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7389 pCtx->idtr.cbIdt = u32Val;
7390 }
7391
7392 /* Guest TR. */
7393 if (fWhat & CPUMCTX_EXTRN_TR)
7394 {
7395 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7396 don't need to import that one. */
7397 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7398 hmR0VmxImportGuestTr(pVCpu);
7399 }
7400 }
7401
7402 if (fWhat & CPUMCTX_EXTRN_DR7)
7403 {
7404 if (!pVCpu->hm.s.fUsingHyperDR7)
7405 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7406 }
7407
7408 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7409 {
7410 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7411 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7412 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7413 pCtx->SysEnter.cs = u32Val;
7414 }
7415
7416 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7417 {
7418 if ( pVM->hm.s.fAllow64BitGuests
7419 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7420 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7421 }
7422
7423 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7424 {
7425 if ( pVM->hm.s.fAllow64BitGuests
7426 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7427 {
7428 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7429 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7430 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7431 }
7432 }
7433
7434 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7435 {
7436 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7437 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7438 Assert(pMsrs);
7439 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7440 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7441 for (uint32_t i = 0; i < cMsrs; i++)
7442 {
7443 uint32_t const idMsr = pMsrs[i].u32Msr;
7444 switch (idMsr)
7445 {
7446 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7447 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7448 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7449 default:
7450 {
7451 pCtx->fExtrn = 0;
7452 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7453 ASMSetFlags(fEFlags);
7454 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7455 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7456 }
7457 }
7458 }
7459 }
7460
7461 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7462 {
7463 if (fWhat & CPUMCTX_EXTRN_CR0)
7464 {
7465 uint64_t u64Cr0;
7466 uint64_t u64Shadow;
7467 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7468 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7469#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7470 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7471 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7472#else
7473 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7474 {
7475 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7476 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7477 }
7478 else
7479 {
7480 /*
7481 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7482 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7483 * re-construct CR0. See @bugref{9180#c95} for details.
7484 */
7485 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7486 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7487 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7488 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7489 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7490 }
7491#endif
7492 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7493 CPUMSetGuestCR0(pVCpu, u64Cr0);
7494 VMMRZCallRing3Enable(pVCpu);
7495 }
7496
7497 if (fWhat & CPUMCTX_EXTRN_CR4)
7498 {
7499 uint64_t u64Cr4;
7500 uint64_t u64Shadow;
7501 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7502 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7503#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7504 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7505 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7506#else
7507 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7508 {
7509 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7510 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7511 }
7512 else
7513 {
7514 /*
7515 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7516 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7517 * re-construct CR4. See @bugref{9180#c95} for details.
7518 */
7519 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7520 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7521 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7522 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7523 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7524 }
7525#endif
7526 pCtx->cr4 = u64Cr4;
7527 }
7528
7529 if (fWhat & CPUMCTX_EXTRN_CR3)
7530 {
7531 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7532 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7533 || ( pVM->hm.s.fNestedPaging
7534 && CPUMIsGuestPagingEnabledEx(pCtx)))
7535 {
7536 uint64_t u64Cr3;
7537 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7538 if (pCtx->cr3 != u64Cr3)
7539 {
7540 pCtx->cr3 = u64Cr3;
7541 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7542 }
7543
7544 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7545 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7546 if (CPUMIsGuestInPAEModeEx(pCtx))
7547 {
7548 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7549 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7550 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7551 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7552 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7553 }
7554 }
7555 }
7556 }
7557
7558#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7559 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7560 {
7561 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7562 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7563 {
7564 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7565 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7566 if (RT_SUCCESS(rc))
7567 { /* likely */ }
7568 else
7569 break;
7570 }
7571 }
7572#endif
7573 } while (0);
7574
7575 if (RT_SUCCESS(rc))
7576 {
7577 /* Update fExtrn. */
7578 pCtx->fExtrn &= ~fWhat;
7579
7580 /* If everything has been imported, clear the HM keeper bit. */
7581 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7582 {
7583 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7584 Assert(!pCtx->fExtrn);
7585 }
7586 }
7587 }
7588 else
7589 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7590
7591 /*
7592 * Restore interrupts.
7593 */
7594 ASMSetFlags(fEFlags);
7595
7596 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7597
7598 if (RT_SUCCESS(rc))
7599 { /* likely */ }
7600 else
7601 return rc;
7602
7603 /*
7604 * Honor any pending CR3 updates.
7605 *
7606 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7607 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7608 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7609 *
7610 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7611 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7612 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7613 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7614 *
7615 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7616 */
7617 if (VMMRZCallRing3IsEnabled(pVCpu))
7618 {
7619 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7620 {
7621 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7622 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7623 }
7624
7625 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7626 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7627
7628 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7629 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7630 }
7631
7632 return VINF_SUCCESS;
7633}
7634
7635
7636/**
7637 * Saves the guest state from the VMCS into the guest-CPU context.
7638 *
7639 * @returns VBox status code.
7640 * @param pVCpu The cross context virtual CPU structure.
7641 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7642 */
7643VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
7644{
7645 AssertPtr(pVCpu);
7646 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7647 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7648}
7649
7650
7651/**
7652 * Check per-VM and per-VCPU force flag actions that require us to go back to
7653 * ring-3 for one reason or another.
7654 *
7655 * @returns Strict VBox status code (i.e. informational status codes too)
7656 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7657 * ring-3.
7658 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7659 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7660 * interrupts)
7661 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7662 * all EMTs to be in ring-3.
7663 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7664 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7665 * to the EM loop.
7666 *
7667 * @param pVCpu The cross context virtual CPU structure.
7668 * @param fStepping Whether we are single-stepping the guest using the
7669 * hypervisor debugger.
7670 *
7671 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
7672 * is no longer in VMX non-root mode.
7673 */
7674static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, bool fStepping)
7675{
7676 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7677
7678 /*
7679 * Update pending interrupts into the APIC's IRR.
7680 */
7681 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7682 APICUpdatePendingInterrupts(pVCpu);
7683
7684 /*
7685 * Anything pending? Should be more likely than not if we're doing a good job.
7686 */
7687 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7688 if ( !fStepping
7689 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7690 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7691 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7692 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7693 return VINF_SUCCESS;
7694
7695 /* Pending PGM C3 sync. */
7696 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7697 {
7698 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7699 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7700 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7701 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7702 if (rcStrict != VINF_SUCCESS)
7703 {
7704 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
7705 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
7706 return rcStrict;
7707 }
7708 }
7709
7710 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7711 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7712 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7713 {
7714 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7715 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7716 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
7717 return rc;
7718 }
7719
7720 /* Pending VM request packets, such as hardware interrupts. */
7721 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7722 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7723 {
7724 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
7725 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7726 return VINF_EM_PENDING_REQUEST;
7727 }
7728
7729 /* Pending PGM pool flushes. */
7730 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7731 {
7732 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
7733 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7734 return VINF_PGM_POOL_FLUSH_PENDING;
7735 }
7736
7737 /* Pending DMA requests. */
7738 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7739 {
7740 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
7741 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7742 return VINF_EM_RAW_TO_R3;
7743 }
7744
7745#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7746 /* Pending nested-guest APIC-write (has highest priority among nested-guest FFs). */
7747 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
7748 {
7749 Log4Func(("Pending nested-guest APIC-write\n"));
7750 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
7751 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7752 return rcStrict;
7753 }
7754 /** @todo VMCPU_FF_VMX_MTF, VMCPU_FF_VMX_PREEMPT_TIMER */
7755#endif
7756
7757 return VINF_SUCCESS;
7758}
7759
7760
7761/**
7762 * Converts any TRPM trap into a pending HM event. This is typically used when
7763 * entering from ring-3 (not longjmp returns).
7764 *
7765 * @param pVCpu The cross context virtual CPU structure.
7766 */
7767static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
7768{
7769 Assert(TRPMHasTrap(pVCpu));
7770 Assert(!pVCpu->hm.s.Event.fPending);
7771
7772 uint8_t uVector;
7773 TRPMEVENT enmTrpmEvent;
7774 uint32_t uErrCode;
7775 RTGCUINTPTR GCPtrFaultAddress;
7776 uint8_t cbInstr;
7777 bool fIcebp;
7778
7779 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
7780 AssertRC(rc);
7781
7782 uint32_t u32IntInfo;
7783 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
7784 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
7785
7786 rc = TRPMResetTrap(pVCpu);
7787 AssertRC(rc);
7788 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
7789 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
7790
7791 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
7792}
7793
7794
7795/**
7796 * Converts the pending HM event into a TRPM trap.
7797 *
7798 * @param pVCpu The cross context virtual CPU structure.
7799 */
7800static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
7801{
7802 Assert(pVCpu->hm.s.Event.fPending);
7803
7804 /* If a trap was already pending, we did something wrong! */
7805 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
7806
7807 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
7808 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
7809 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
7810
7811 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
7812
7813 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
7814 AssertRC(rc);
7815
7816 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
7817 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
7818
7819 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
7820 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
7821 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
7822 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
7823
7824 if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
7825 TRPMSetTrapDueToIcebp(pVCpu);
7826
7827 /* We're now done converting the pending event. */
7828 pVCpu->hm.s.Event.fPending = false;
7829}
7830
7831
7832/**
7833 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
7834 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
7835 *
7836 * @param pVCpu The cross context virtual CPU structure.
7837 * @param pVmcsInfo The VMCS info. object.
7838 */
7839static void hmR0VmxSetIntWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7840{
7841 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7842 {
7843 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
7844 {
7845 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
7846 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7847 AssertRC(rc);
7848 }
7849 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
7850}
7851
7852
7853/**
7854 * Clears the interrupt-window exiting control in the VMCS.
7855 *
7856 * @param pVmcsInfo The VMCS info. object.
7857 */
7858DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7859{
7860 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7861 {
7862 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
7863 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7864 AssertRC(rc);
7865 }
7866}
7867
7868
7869/**
7870 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
7871 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
7872 *
7873 * @param pVCpu The cross context virtual CPU structure.
7874 * @param pVmcsInfo The VMCS info. object.
7875 */
7876static void hmR0VmxSetNmiWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7877{
7878 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7879 {
7880 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
7881 {
7882 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7883 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7884 AssertRC(rc);
7885 Log4Func(("Setup NMI-window exiting\n"));
7886 }
7887 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
7888}
7889
7890
7891/**
7892 * Clears the NMI-window exiting control in the VMCS.
7893 *
7894 * @param pVmcsInfo The VMCS info. object.
7895 */
7896DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7897{
7898 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7899 {
7900 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7901 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7902 AssertRC(rc);
7903 }
7904}
7905
7906
7907/**
7908 * Does the necessary state syncing before returning to ring-3 for any reason
7909 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
7910 *
7911 * @returns VBox status code.
7912 * @param pVCpu The cross context virtual CPU structure.
7913 * @param fImportState Whether to import the guest state from the VMCS back
7914 * to the guest-CPU context.
7915 *
7916 * @remarks No-long-jmp zone!!!
7917 */
7918static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
7919{
7920 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
7921 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
7922
7923 RTCPUID const idCpu = RTMpCpuId();
7924 Log4Func(("HostCpuId=%u\n", idCpu));
7925
7926 /*
7927 * !!! IMPORTANT !!!
7928 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
7929 */
7930
7931 /* Save the guest state if necessary. */
7932 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7933 if (fImportState)
7934 {
7935 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
7936 AssertRCReturn(rc, rc);
7937 }
7938
7939 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
7940 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
7941 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
7942
7943 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
7944#ifdef VBOX_STRICT
7945 if (CPUMIsHyperDebugStateActive(pVCpu))
7946 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
7947#endif
7948 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
7949 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
7950 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
7951
7952 /* Restore host-state bits that VT-x only restores partially. */
7953 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
7954 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
7955 {
7956 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
7957 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
7958 }
7959 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
7960
7961 /* Restore the lazy host MSRs as we're leaving VT-x context. */
7962 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
7963 {
7964 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
7965 if (!fImportState)
7966 {
7967 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
7968 AssertRCReturn(rc, rc);
7969 }
7970 hmR0VmxLazyRestoreHostMsrs(pVCpu);
7971 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
7972 }
7973 else
7974 pVCpu->hm.s.vmx.fLazyMsrs = 0;
7975
7976 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
7977 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
7978
7979 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
7980 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
7981 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
7982 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
7983 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
7984 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
7985 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
7986 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
7987 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
7988 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
7989
7990 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
7991
7992 /** @todo This partially defeats the purpose of having preemption hooks.
7993 * The problem is, deregistering the hooks should be moved to a place that
7994 * lasts until the EMT is about to be destroyed not everytime while leaving HM
7995 * context.
7996 */
7997 int rc = hmR0VmxClearVmcs(pVmcsInfo);
7998 AssertRCReturn(rc, rc);
7999
8000#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8001 /*
8002 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8003 * clear a shadow VMCS before allowing that VMCS to become active on another
8004 * logical processor. We may or may not be importing guest state which clears
8005 * it, so cover for it here.
8006 *
8007 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8008 */
8009 if ( pVmcsInfo->pvShadowVmcs
8010 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8011 {
8012 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8013 AssertRCReturn(rc, rc);
8014 }
8015
8016 /*
8017 * Flag that we need to re-export the host state if we switch to this VMCS before
8018 * executing guest or nested-guest code.
8019 */
8020 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8021#endif
8022
8023 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8024 NOREF(idCpu);
8025 return VINF_SUCCESS;
8026}
8027
8028
8029/**
8030 * Leaves the VT-x session.
8031 *
8032 * @returns VBox status code.
8033 * @param pVCpu The cross context virtual CPU structure.
8034 *
8035 * @remarks No-long-jmp zone!!!
8036 */
8037static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8038{
8039 HM_DISABLE_PREEMPT(pVCpu);
8040 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8041 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8042 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8043
8044 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8045 and done this from the VMXR0ThreadCtxCallback(). */
8046 if (!pVCpu->hm.s.fLeaveDone)
8047 {
8048 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8049 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8050 pVCpu->hm.s.fLeaveDone = true;
8051 }
8052 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8053
8054 /*
8055 * !!! IMPORTANT !!!
8056 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8057 */
8058
8059 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8060 /** @todo Deregistering here means we need to VMCLEAR always
8061 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8062 * for calling VMMR0ThreadCtxHookDisable here! */
8063 VMMR0ThreadCtxHookDisable(pVCpu);
8064
8065 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8066 int rc = HMR0LeaveCpu(pVCpu);
8067 HM_RESTORE_PREEMPT();
8068 return rc;
8069}
8070
8071
8072/**
8073 * Does the necessary state syncing before doing a longjmp to ring-3.
8074 *
8075 * @returns VBox status code.
8076 * @param pVCpu The cross context virtual CPU structure.
8077 *
8078 * @remarks No-long-jmp zone!!!
8079 */
8080DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8081{
8082 return hmR0VmxLeaveSession(pVCpu);
8083}
8084
8085
8086/**
8087 * Take necessary actions before going back to ring-3.
8088 *
8089 * An action requires us to go back to ring-3. This function does the necessary
8090 * steps before we can safely return to ring-3. This is not the same as longjmps
8091 * to ring-3, this is voluntary and prepares the guest so it may continue
8092 * executing outside HM (recompiler/IEM).
8093 *
8094 * @returns VBox status code.
8095 * @param pVCpu The cross context virtual CPU structure.
8096 * @param rcExit The reason for exiting to ring-3. Can be
8097 * VINF_VMM_UNKNOWN_RING3_CALL.
8098 */
8099static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8100{
8101 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8102
8103 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8104 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8105 {
8106 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8107 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8108 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8109 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8110 }
8111
8112 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8113 VMMRZCallRing3Disable(pVCpu);
8114 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8115
8116 /*
8117 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8118 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8119 *
8120 * This is because execution may continue from ring-3 and we would need to inject
8121 * the event from there (hence place it back in TRPM).
8122 */
8123 if (pVCpu->hm.s.Event.fPending)
8124 {
8125 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8126 Assert(!pVCpu->hm.s.Event.fPending);
8127
8128 /* Clear the events from the VMCS. */
8129 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8130 AssertRC(rc);
8131 }
8132#ifdef VBOX_STRICT
8133 else
8134 {
8135 /*
8136 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8137 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8138 * occasionally, see @bugref{9180#c42}.
8139 *
8140 * However, if the VM-entry failed, any VM entry-interruption info. field would
8141 * be left unmodified as the event would not have been injected to the guest. In
8142 * such cases, don't assert, we're not going to continue guest execution anyway.
8143 */
8144 uint32_t uExitReason;
8145 uint32_t uEntryIntInfo;
8146 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8147 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8148 AssertRC(rc);
8149 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8150 }
8151#endif
8152
8153 /*
8154 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8155 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8156 * (e.g. TPR below threshold).
8157 */
8158 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8159 {
8160 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8161 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8162 }
8163
8164 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8165 and if we're injecting an event we should have a TRPM trap pending. */
8166 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8167#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8168 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8169#endif
8170
8171 /* Save guest state and restore host state bits. */
8172 int rc = hmR0VmxLeaveSession(pVCpu);
8173 AssertRCReturn(rc, rc);
8174 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8175
8176 /* Thread-context hooks are unregistered at this point!!! */
8177 /* Ring-3 callback notifications are unregistered at this point!!! */
8178
8179 /* Sync recompiler state. */
8180 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8181 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8182 | CPUM_CHANGED_LDTR
8183 | CPUM_CHANGED_GDTR
8184 | CPUM_CHANGED_IDTR
8185 | CPUM_CHANGED_TR
8186 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8187 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8188 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8189 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8190
8191 Assert(!pVCpu->hm.s.fClearTrapFlag);
8192
8193 /* Update the exit-to-ring 3 reason. */
8194 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8195
8196 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8197 if ( rcExit != VINF_EM_RAW_INTERRUPT
8198 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8199 {
8200 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8201 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8202 }
8203
8204 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8205 VMMRZCallRing3Enable(pVCpu);
8206 return rc;
8207}
8208
8209
8210/**
8211 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8212 * longjump to ring-3 and possibly get preempted.
8213 *
8214 * @returns VBox status code.
8215 * @param pVCpu The cross context virtual CPU structure.
8216 * @param enmOperation The operation causing the ring-3 longjump.
8217 */
8218VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8219{
8220 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8221 {
8222 /*
8223 * !!! IMPORTANT !!!
8224 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8225 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8226 */
8227 VMMRZCallRing3RemoveNotification(pVCpu);
8228 VMMRZCallRing3Disable(pVCpu);
8229 HM_DISABLE_PREEMPT(pVCpu);
8230
8231 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8232 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8233 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8234 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8235
8236 /* Restore host-state bits that VT-x only restores partially. */
8237 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8238 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8239 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8240 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8241
8242 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8243 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8244 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8245
8246 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8247 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8248 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8249
8250 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8251 cleared as part of importing the guest state above. */
8252 hmR0VmxClearVmcs(pVmcsInfo);
8253
8254 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8255 VMMR0ThreadCtxHookDisable(pVCpu);
8256
8257 /* Leave HM context. This takes care of local init (term). */
8258 HMR0LeaveCpu(pVCpu);
8259 HM_RESTORE_PREEMPT();
8260 return VINF_SUCCESS;
8261 }
8262
8263 Assert(pVCpu);
8264 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8265 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8266
8267 VMMRZCallRing3Disable(pVCpu);
8268 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8269
8270 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8271
8272 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8273 AssertRCReturn(rc, rc);
8274
8275 VMMRZCallRing3Enable(pVCpu);
8276 return VINF_SUCCESS;
8277}
8278
8279
8280/**
8281 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8282 * stack.
8283 *
8284 * @returns Strict VBox status code (i.e. informational status codes too).
8285 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8286 * @param pVCpu The cross context virtual CPU structure.
8287 * @param uValue The value to push to the guest stack.
8288 */
8289static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8290{
8291 /*
8292 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8293 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8294 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8295 */
8296 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8297 if (pCtx->sp == 1)
8298 return VINF_EM_RESET;
8299 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8300 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8301 AssertRC(rc);
8302 return rc;
8303}
8304
8305
8306/**
8307 * Injects an event into the guest upon VM-entry by updating the relevant fields
8308 * in the VM-entry area in the VMCS.
8309 *
8310 * @returns Strict VBox status code (i.e. informational status codes too).
8311 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8312 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8313 *
8314 * @param pVCpu The cross context virtual CPU structure.
8315 * @param pVmxTransient The VMX-transient structure.
8316 * @param pEvent The event being injected.
8317 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8318 * will be updated if necessary. This cannot not be NULL.
8319 * @param fStepping Whether we're single-stepping guest execution and should
8320 * return VINF_EM_DBG_STEPPED if the event is injected
8321 * directly (registers modified by us, not by hardware on
8322 * VM-entry).
8323 */
8324static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8325 uint32_t *pfIntrState)
8326{
8327 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8328 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8329 Assert(pfIntrState);
8330
8331 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8332 uint32_t u32IntInfo = pEvent->u64IntInfo;
8333 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8334 uint32_t const cbInstr = pEvent->cbInstr;
8335 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8336 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8337 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8338
8339#ifdef VBOX_STRICT
8340 /*
8341 * Validate the error-code-valid bit for hardware exceptions.
8342 * No error codes for exceptions in real-mode.
8343 *
8344 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8345 */
8346 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8347 && !CPUMIsGuestInRealModeEx(pCtx))
8348 {
8349 switch (uVector)
8350 {
8351 case X86_XCPT_PF:
8352 case X86_XCPT_DF:
8353 case X86_XCPT_TS:
8354 case X86_XCPT_NP:
8355 case X86_XCPT_SS:
8356 case X86_XCPT_GP:
8357 case X86_XCPT_AC:
8358 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8359 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8360 RT_FALL_THRU();
8361 default:
8362 break;
8363 }
8364 }
8365
8366 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8367 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8368 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8369#endif
8370
8371 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8372
8373 /*
8374 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8375 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8376 * interrupt handler in the (real-mode) guest.
8377 *
8378 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8379 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8380 */
8381 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8382 {
8383 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8384 {
8385 /*
8386 * For CPUs with unrestricted guest execution enabled and with the guest
8387 * in real-mode, we must not set the deliver-error-code bit.
8388 *
8389 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8390 */
8391 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8392 }
8393 else
8394 {
8395 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8396 Assert(PDMVmmDevHeapIsEnabled(pVM));
8397 Assert(pVM->hm.s.vmx.pRealModeTSS);
8398 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8399
8400 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8401 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8402 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8403 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8404 AssertRCReturn(rc2, rc2);
8405
8406 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8407 size_t const cbIdtEntry = sizeof(X86IDTR16);
8408 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8409 {
8410 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8411 if (uVector == X86_XCPT_DF)
8412 return VINF_EM_RESET;
8413
8414 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8415 No error codes for exceptions in real-mode. */
8416 if (uVector == X86_XCPT_GP)
8417 {
8418 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8419 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8420 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8421 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8422 HMEVENT EventXcptDf;
8423 RT_ZERO(EventXcptDf);
8424 EventXcptDf.u64IntInfo = uXcptDfInfo;
8425 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8426 }
8427
8428 /*
8429 * If we're injecting an event with no valid IDT entry, inject a #GP.
8430 * No error codes for exceptions in real-mode.
8431 *
8432 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8433 */
8434 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8435 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8436 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8437 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8438 HMEVENT EventXcptGp;
8439 RT_ZERO(EventXcptGp);
8440 EventXcptGp.u64IntInfo = uXcptGpInfo;
8441 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8442 }
8443
8444 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8445 uint16_t uGuestIp = pCtx->ip;
8446 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8447 {
8448 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8449 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8450 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8451 }
8452 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8453 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8454
8455 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8456 X86IDTR16 IdtEntry;
8457 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8458 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8459 AssertRCReturn(rc2, rc2);
8460
8461 /* Construct the stack frame for the interrupt/exception handler. */
8462 VBOXSTRICTRC rcStrict;
8463 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8464 if (rcStrict == VINF_SUCCESS)
8465 {
8466 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8467 if (rcStrict == VINF_SUCCESS)
8468 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8469 }
8470
8471 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8472 if (rcStrict == VINF_SUCCESS)
8473 {
8474 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8475 pCtx->rip = IdtEntry.offSel;
8476 pCtx->cs.Sel = IdtEntry.uSel;
8477 pCtx->cs.ValidSel = IdtEntry.uSel;
8478 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8479 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8480 && uVector == X86_XCPT_PF)
8481 pCtx->cr2 = GCPtrFault;
8482
8483 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8484 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8485 | HM_CHANGED_GUEST_RSP);
8486
8487 /*
8488 * If we delivered a hardware exception (other than an NMI) and if there was
8489 * block-by-STI in effect, we should clear it.
8490 */
8491 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8492 {
8493 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8494 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8495 Log4Func(("Clearing inhibition due to STI\n"));
8496 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8497 }
8498
8499 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8500 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8501
8502 /*
8503 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8504 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8505 */
8506 pVCpu->hm.s.Event.fPending = false;
8507
8508 /*
8509 * If we eventually support nested-guest execution without unrestricted guest execution,
8510 * we should set fInterceptEvents here.
8511 */
8512 Assert(!pVmxTransient->fIsNestedGuest);
8513
8514 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8515 if (fStepping)
8516 rcStrict = VINF_EM_DBG_STEPPED;
8517 }
8518 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8519 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8520 return rcStrict;
8521 }
8522 }
8523
8524 /*
8525 * Validate.
8526 */
8527 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8528 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8529
8530 /*
8531 * Inject the event into the VMCS.
8532 */
8533 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8534 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8535 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8536 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8537 AssertRC(rc);
8538
8539 /*
8540 * Update guest CR2 if this is a page-fault.
8541 */
8542 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8543 pCtx->cr2 = GCPtrFault;
8544
8545 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8546 return VINF_SUCCESS;
8547}
8548
8549
8550/**
8551 * Evaluates the event to be delivered to the guest and sets it as the pending
8552 * event.
8553 *
8554 * @returns Strict VBox status code (i.e. informational status codes too).
8555 * @param pVCpu The cross context virtual CPU structure.
8556 * @param pVmxTransient The VMX-transient structure.
8557 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8558 */
8559static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8560{
8561 Assert(pfIntrState);
8562 Assert(!TRPMHasTrap(pVCpu));
8563
8564 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8565 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8566 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8567
8568 /*
8569 * Get the current interruptibility-state of the guest or nested-guest and
8570 * then figure out what needs to be injected.
8571 */
8572 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
8573 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8574 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8575 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8576
8577 /* We don't support block-by-SMI yet.*/
8578 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
8579
8580 /* Block-by-STI must not be set when interrupts are disabled. */
8581 if (fBlockSti)
8582 {
8583 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
8584 Assert(pCtx->eflags.Bits.u1IF);
8585 }
8586
8587 /* Update interruptibility state to the caller. */
8588 *pfIntrState = fIntrState;
8589
8590 /*
8591 * Toggling of interrupt force-flags here is safe since we update TRPM on
8592 * premature exits to ring-3 before executing guest code, see hmR0VmxExitToRing3().
8593 * We must NOT restore these force-flags.
8594 */
8595
8596 /** @todo SMI. SMIs take priority over NMIs. */
8597
8598 /*
8599 * Check if an NMI is pending and if the guest or nested-guest can receive them.
8600 * NMIs take priority over external interrupts.
8601 */
8602 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8603 {
8604 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
8605 if ( !pVCpu->hm.s.Event.fPending
8606 && !fBlockNmi
8607 && !fBlockSti
8608 && !fBlockMovSS)
8609 {
8610#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8611 if ( fIsNestedGuest
8612 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
8613 return IEMExecVmxVmexitXcptNmi(pVCpu);
8614#endif
8615 hmR0VmxSetPendingXcptNmi(pVCpu);
8616 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8617 Log4Func(("Pending NMI\n"));
8618 }
8619 else if (!fIsNestedGuest)
8620 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8621 /* else: for nested-guests, NMI-window exiting will be picked up when merging VMCS controls. */
8622 }
8623 /*
8624 * Check if an external interrupt (PIC/APIC) is pending and if the guest or nested-guest
8625 * can receive them. Once PDMGetInterrupt() returns a valid interrupt we -must- deliver
8626 * the interrupt. We can no longer re-request it from the APIC.
8627 */
8628 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8629 && !pVCpu->hm.s.fSingleInstruction)
8630 {
8631 Assert(!DBGFIsStepping(pVCpu));
8632 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8633 AssertRCReturn(rc, rc);
8634
8635 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
8636 if ( !pVCpu->hm.s.Event.fPending
8637 && !fBlockInt
8638 && !fBlockSti
8639 && !fBlockMovSS)
8640 {
8641#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8642 if ( fIsNestedGuest
8643 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8644 && !CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8645 {
8646 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
8647 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8648 return rcStrict;
8649 }
8650#endif
8651 uint8_t u8Interrupt;
8652 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8653 if (RT_SUCCESS(rc))
8654 {
8655#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8656 if ( fIsNestedGuest
8657 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8658 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8659 {
8660 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8661 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8662 return rcStrict;
8663 }
8664#endif
8665 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8666 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
8667 }
8668 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8669 {
8670 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8671
8672 if ( !fIsNestedGuest
8673 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8674 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
8675 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
8676
8677 /*
8678 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8679 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8680 * need to re-set this force-flag here.
8681 */
8682 }
8683 else
8684 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8685 }
8686 else if (!fIsNestedGuest)
8687 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8688 /* else: for nested-guests, interrupt-window exiting will be picked up when merging VMCS controls. */
8689 }
8690
8691 return VINF_SUCCESS;
8692}
8693
8694
8695/**
8696 * Injects any pending events into the guest if the guest is in a state to
8697 * receive them.
8698 *
8699 * @returns Strict VBox status code (i.e. informational status codes too).
8700 * @param pVCpu The cross context virtual CPU structure.
8701 * @param pVmxTransient The VMX-transient structure.
8702 * @param fIntrState The VT-x guest-interruptibility state.
8703 * @param fStepping Whether we are single-stepping the guest using the
8704 * hypervisor debugger and should return
8705 * VINF_EM_DBG_STEPPED if the event was dispatched
8706 * directly.
8707 */
8708static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
8709{
8710 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8711 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8712
8713 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8714 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8715
8716 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
8717 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
8718 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
8719 Assert(!TRPMHasTrap(pVCpu));
8720
8721 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
8722 if (pVCpu->hm.s.Event.fPending)
8723 {
8724 /*
8725 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
8726 * pending even while injecting an event and in this case, we want a VM-exit as soon as
8727 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
8728 *
8729 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
8730 */
8731 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
8732#ifdef VBOX_STRICT
8733 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8734 {
8735 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
8736 Assert(!fBlockInt);
8737 Assert(!fBlockSti);
8738 Assert(!fBlockMovSS);
8739 }
8740 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
8741 {
8742 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8743 Assert(!fBlockSti);
8744 Assert(!fBlockMovSS);
8745 Assert(!fBlockNmi);
8746 }
8747#endif
8748 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
8749 uIntType));
8750
8751 /*
8752 * Inject the event and get any changes to the guest-interruptibility state.
8753 *
8754 * The guest-interruptibility state may need to be updated if we inject the event
8755 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
8756 */
8757 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
8758 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
8759
8760 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8761 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
8762 else
8763 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
8764 }
8765
8766 /*
8767 * Update the guest-interruptibility state.
8768 *
8769 * This is required for the real-on-v86 software interrupt injection case above, as well as
8770 * updates to the guest state from ring-3 or IEM/REM.
8771 */
8772 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
8773 AssertRC(rc);
8774
8775 /*
8776 * There's no need to clear the VM-entry interruption-information field here if we're not
8777 * injecting anything. VT-x clears the valid bit on every VM-exit.
8778 *
8779 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
8780 */
8781
8782 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
8783 NOREF(fBlockMovSS); NOREF(fBlockSti);
8784 return rcStrict;
8785}
8786
8787
8788/**
8789 * Enters the VT-x session.
8790 *
8791 * @returns VBox status code.
8792 * @param pVCpu The cross context virtual CPU structure.
8793 */
8794VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
8795{
8796 AssertPtr(pVCpu);
8797 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
8798 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8799
8800 LogFlowFunc(("pVCpu=%p\n", pVCpu));
8801 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8802 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8803
8804#ifdef VBOX_STRICT
8805 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
8806 RTCCUINTREG uHostCr4 = ASMGetCR4();
8807 if (!(uHostCr4 & X86_CR4_VMXE))
8808 {
8809 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
8810 return VERR_VMX_X86_CR4_VMXE_CLEARED;
8811 }
8812#endif
8813
8814 /*
8815 * Load the appropriate VMCS as the current and active one.
8816 */
8817 PVMXVMCSINFO pVmcsInfo;
8818 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
8819 if (!fInNestedGuestMode)
8820 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
8821 else
8822 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
8823 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
8824 if (RT_SUCCESS(rc))
8825 {
8826 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
8827 pVCpu->hm.s.fLeaveDone = false;
8828 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8829
8830 /*
8831 * Do the EMT scheduled L1D flush here if needed.
8832 */
8833 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8834 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8835 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
8836 hmR0MdsClear();
8837 }
8838 return rc;
8839}
8840
8841
8842/**
8843 * The thread-context callback (only on platforms which support it).
8844 *
8845 * @param enmEvent The thread-context event.
8846 * @param pVCpu The cross context virtual CPU structure.
8847 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
8848 * @thread EMT(pVCpu)
8849 */
8850VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
8851{
8852 AssertPtr(pVCpu);
8853 RT_NOREF1(fGlobalInit);
8854
8855 switch (enmEvent)
8856 {
8857 case RTTHREADCTXEVENT_OUT:
8858 {
8859 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8860 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8861 VMCPU_ASSERT_EMT(pVCpu);
8862
8863 /* No longjmps (logger flushes, locks) in this fragile context. */
8864 VMMRZCallRing3Disable(pVCpu);
8865 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
8866
8867 /* Restore host-state (FPU, debug etc.) */
8868 if (!pVCpu->hm.s.fLeaveDone)
8869 {
8870 /*
8871 * Do -not- import the guest-state here as we might already be in the middle of importing
8872 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
8873 */
8874 hmR0VmxLeave(pVCpu, false /* fImportState */);
8875 pVCpu->hm.s.fLeaveDone = true;
8876 }
8877
8878 /* Leave HM context, takes care of local init (term). */
8879 int rc = HMR0LeaveCpu(pVCpu);
8880 AssertRC(rc);
8881
8882 /* Restore longjmp state. */
8883 VMMRZCallRing3Enable(pVCpu);
8884 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
8885 break;
8886 }
8887
8888 case RTTHREADCTXEVENT_IN:
8889 {
8890 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8891 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8892 VMCPU_ASSERT_EMT(pVCpu);
8893
8894 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
8895 VMMRZCallRing3Disable(pVCpu);
8896 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
8897
8898 /* Initialize the bare minimum state required for HM. This takes care of
8899 initializing VT-x if necessary (onlined CPUs, local init etc.) */
8900 int rc = hmR0EnterCpu(pVCpu);
8901 AssertRC(rc);
8902 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8903 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8904
8905 /* Load the active VMCS as the current one. */
8906 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8907 rc = hmR0VmxLoadVmcs(pVmcsInfo);
8908 AssertRC(rc);
8909 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8910 pVCpu->hm.s.fLeaveDone = false;
8911
8912 /* Do the EMT scheduled L1D flush if needed. */
8913 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8914 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8915
8916 /* Restore longjmp state. */
8917 VMMRZCallRing3Enable(pVCpu);
8918 break;
8919 }
8920
8921 default:
8922 break;
8923 }
8924}
8925
8926
8927/**
8928 * Exports the host state into the VMCS host-state area.
8929 * Sets up the VM-exit MSR-load area.
8930 *
8931 * The CPU state will be loaded from these fields on every successful VM-exit.
8932 *
8933 * @returns VBox status code.
8934 * @param pVCpu The cross context virtual CPU structure.
8935 *
8936 * @remarks No-long-jump zone!!!
8937 */
8938static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
8939{
8940 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8941
8942 int rc = VINF_SUCCESS;
8943 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
8944 {
8945 hmR0VmxExportHostControlRegs();
8946
8947 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
8948 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8949
8950 hmR0VmxExportHostMsrs(pVCpu);
8951
8952 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
8953 }
8954 return rc;
8955}
8956
8957
8958/**
8959 * Saves the host state in the VMCS host-state.
8960 *
8961 * @returns VBox status code.
8962 * @param pVCpu The cross context virtual CPU structure.
8963 *
8964 * @remarks No-long-jump zone!!!
8965 */
8966VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
8967{
8968 AssertPtr(pVCpu);
8969 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8970
8971 /*
8972 * Export the host state here while entering HM context.
8973 * When thread-context hooks are used, we might get preempted and have to re-save the host
8974 * state but most of the time we won't be, so do it here before we disable interrupts.
8975 */
8976 return hmR0VmxExportHostState(pVCpu);
8977}
8978
8979
8980/**
8981 * Exports the guest state into the VMCS guest-state area.
8982 *
8983 * The will typically be done before VM-entry when the guest-CPU state and the
8984 * VMCS state may potentially be out of sync.
8985 *
8986 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
8987 * VM-entry controls.
8988 * Sets up the appropriate VMX non-root function to execute guest code based on
8989 * the guest CPU mode.
8990 *
8991 * @returns VBox strict status code.
8992 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
8993 * without unrestricted guest execution and the VMMDev is not presently
8994 * mapped (e.g. EFI32).
8995 *
8996 * @param pVCpu The cross context virtual CPU structure.
8997 * @param pVmxTransient The VMX-transient structure.
8998 *
8999 * @remarks No-long-jump zone!!!
9000 */
9001static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9002{
9003 AssertPtr(pVCpu);
9004 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9005 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9006
9007 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9008
9009 /*
9010 * Determine real-on-v86 mode.
9011 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9012 */
9013 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9014 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9015 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9016 pVmcsInfo->RealMode.fRealOnV86Active = false;
9017 else
9018 {
9019 Assert(!pVmxTransient->fIsNestedGuest);
9020 pVmcsInfo->RealMode.fRealOnV86Active = true;
9021 }
9022
9023 /*
9024 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9025 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9026 */
9027 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9028 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9029
9030 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9031 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9032
9033 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9034 if (rcStrict == VINF_SUCCESS)
9035 { /* likely */ }
9036 else
9037 {
9038 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9039 return rcStrict;
9040 }
9041
9042 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9043 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9044
9045 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9046 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9047
9048 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9049 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9050 hmR0VmxExportGuestRip(pVCpu);
9051 hmR0VmxExportGuestRsp(pVCpu);
9052 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9053
9054 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9055 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9056
9057 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9058 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9059 | HM_CHANGED_GUEST_CR2
9060 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9061 | HM_CHANGED_GUEST_X87
9062 | HM_CHANGED_GUEST_SSE_AVX
9063 | HM_CHANGED_GUEST_OTHER_XSAVE
9064 | HM_CHANGED_GUEST_XCRx
9065 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9066 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9067 | HM_CHANGED_GUEST_TSC_AUX
9068 | HM_CHANGED_GUEST_OTHER_MSRS
9069 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9070
9071 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9072 return rc;
9073}
9074
9075
9076/**
9077 * Exports the state shared between the host and guest into the VMCS.
9078 *
9079 * @param pVCpu The cross context virtual CPU structure.
9080 * @param pVmxTransient The VMX-transient structure.
9081 *
9082 * @remarks No-long-jump zone!!!
9083 */
9084static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9085{
9086 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9087 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9088
9089 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9090 {
9091 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9092 AssertRC(rc);
9093 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9094
9095 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9096 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9097 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9098 }
9099
9100 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9101 {
9102 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9103 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9104 }
9105
9106 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9107 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9108}
9109
9110
9111/**
9112 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9113 *
9114 * @returns Strict VBox status code (i.e. informational status codes too).
9115 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9116 * without unrestricted guest execution and the VMMDev is not presently
9117 * mapped (e.g. EFI32).
9118 *
9119 * @param pVCpu The cross context virtual CPU structure.
9120 * @param pVmxTransient The VMX-transient structure.
9121 *
9122 * @remarks No-long-jump zone!!!
9123 */
9124static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9125{
9126 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9127 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9128 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9129
9130#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9131 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9132#endif
9133
9134 /*
9135 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9136 * changes. First try to export only these without going through all other changed-flag checks.
9137 */
9138 VBOXSTRICTRC rcStrict;
9139 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9140 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9141 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9142
9143 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9144 if ( (fCtxChanged & fMinimalMask)
9145 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9146 {
9147 hmR0VmxExportGuestRip(pVCpu);
9148 hmR0VmxExportGuestRsp(pVCpu);
9149 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9150 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9151 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9152 }
9153 /* If anything else also changed, go through the full export routine and export as required. */
9154 else if (fCtxChanged & fCtxMask)
9155 {
9156 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9157 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9158 { /* likely */}
9159 else
9160 {
9161 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9162 VBOXSTRICTRC_VAL(rcStrict)));
9163 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9164 return rcStrict;
9165 }
9166 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9167 }
9168 /* Nothing changed, nothing to load here. */
9169 else
9170 rcStrict = VINF_SUCCESS;
9171
9172#ifdef VBOX_STRICT
9173 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9174 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9175 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9176#endif
9177 return rcStrict;
9178}
9179
9180
9181/**
9182 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9183 * and update error record fields accordingly.
9184 *
9185 * @returns VMX_IGS_* error codes.
9186 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9187 * wrong with the guest state.
9188 *
9189 * @param pVCpu The cross context virtual CPU structure.
9190 * @param pVmcsInfo The VMCS info. object.
9191 *
9192 * @remarks This function assumes our cache of the VMCS controls
9193 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9194 */
9195static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9196{
9197#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9198#define HMVMX_CHECK_BREAK(expr, err) do { \
9199 if (!(expr)) { uError = (err); break; } \
9200 } while (0)
9201
9202 int rc;
9203 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9204 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9205 uint32_t uError = VMX_IGS_ERROR;
9206 uint32_t u32Val;
9207 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9208
9209 do
9210 {
9211 /*
9212 * CR0.
9213 */
9214 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9215 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9216 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9217 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9218 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9219 if (fUnrestrictedGuest)
9220 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9221
9222 uint64_t u64GuestCr0;
9223 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9224 AssertRC(rc);
9225 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9226 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9227 if ( !fUnrestrictedGuest
9228 && (u64GuestCr0 & X86_CR0_PG)
9229 && !(u64GuestCr0 & X86_CR0_PE))
9230 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9231
9232 /*
9233 * CR4.
9234 */
9235 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9236 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9237 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9238
9239 uint64_t u64GuestCr4;
9240 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9241 AssertRC(rc);
9242 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9243 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9244
9245 /*
9246 * IA32_DEBUGCTL MSR.
9247 */
9248 uint64_t u64Val;
9249 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9250 AssertRC(rc);
9251 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9252 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9253 {
9254 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9255 }
9256 uint64_t u64DebugCtlMsr = u64Val;
9257
9258#ifdef VBOX_STRICT
9259 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9260 AssertRC(rc);
9261 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9262#endif
9263 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9264
9265 /*
9266 * RIP and RFLAGS.
9267 */
9268 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9269 AssertRC(rc);
9270 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9271 if ( !fLongModeGuest
9272 || !pCtx->cs.Attr.n.u1Long)
9273 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9274 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9275 * must be identical if the "IA-32e mode guest" VM-entry
9276 * control is 1 and CS.L is 1. No check applies if the
9277 * CPU supports 64 linear-address bits. */
9278
9279 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9280 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9281 AssertRC(rc);
9282 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9283 VMX_IGS_RFLAGS_RESERVED);
9284 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9285 uint32_t const u32Eflags = u64Val;
9286
9287 if ( fLongModeGuest
9288 || ( fUnrestrictedGuest
9289 && !(u64GuestCr0 & X86_CR0_PE)))
9290 {
9291 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9292 }
9293
9294 uint32_t u32EntryInfo;
9295 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9296 AssertRC(rc);
9297 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9298 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9299
9300 /*
9301 * 64-bit checks.
9302 */
9303 if (fLongModeGuest)
9304 {
9305 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9306 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9307 }
9308
9309 if ( !fLongModeGuest
9310 && (u64GuestCr4 & X86_CR4_PCIDE))
9311 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9312
9313 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9314 * 51:32 beyond the processor's physical-address width are 0. */
9315
9316 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9317 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9318 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9319
9320 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9321 AssertRC(rc);
9322 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9323
9324 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9325 AssertRC(rc);
9326 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9327
9328 /*
9329 * PERF_GLOBAL MSR.
9330 */
9331 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9332 {
9333 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9334 AssertRC(rc);
9335 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9336 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9337 }
9338
9339 /*
9340 * PAT MSR.
9341 */
9342 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9343 {
9344 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9345 AssertRC(rc);
9346 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9347 for (unsigned i = 0; i < 8; i++)
9348 {
9349 uint8_t u8Val = (u64Val & 0xff);
9350 if ( u8Val != 0 /* UC */
9351 && u8Val != 1 /* WC */
9352 && u8Val != 4 /* WT */
9353 && u8Val != 5 /* WP */
9354 && u8Val != 6 /* WB */
9355 && u8Val != 7 /* UC- */)
9356 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9357 u64Val >>= 8;
9358 }
9359 }
9360
9361 /*
9362 * EFER MSR.
9363 */
9364 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9365 {
9366 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9367 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9368 AssertRC(rc);
9369 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9370 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9371 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9372 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9373 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9374 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9375 * iemVmxVmentryCheckGuestState(). */
9376 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9377 || !(u64GuestCr0 & X86_CR0_PG)
9378 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9379 VMX_IGS_EFER_LMA_LME_MISMATCH);
9380 }
9381
9382 /*
9383 * Segment registers.
9384 */
9385 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9386 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9387 if (!(u32Eflags & X86_EFL_VM))
9388 {
9389 /* CS */
9390 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9391 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9392 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9393 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9394 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9395 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9396 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9397 /* CS cannot be loaded with NULL in protected mode. */
9398 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9399 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9400 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9401 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9402 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9403 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9404 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9405 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9406 else
9407 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9408
9409 /* SS */
9410 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9411 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9412 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9413 if ( !(pCtx->cr0 & X86_CR0_PE)
9414 || pCtx->cs.Attr.n.u4Type == 3)
9415 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9416
9417 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9418 {
9419 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9420 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9421 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9422 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9423 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9424 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9425 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9426 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9427 }
9428
9429 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9430 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9431 {
9432 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9433 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9434 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9435 || pCtx->ds.Attr.n.u4Type > 11
9436 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9437 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9438 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9439 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9440 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9441 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9442 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9443 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9444 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9445 }
9446 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9447 {
9448 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9449 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9450 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9451 || pCtx->es.Attr.n.u4Type > 11
9452 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9453 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9454 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9455 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9456 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9457 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9458 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9459 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9460 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9461 }
9462 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9463 {
9464 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9465 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9466 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9467 || pCtx->fs.Attr.n.u4Type > 11
9468 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9469 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9470 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9471 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9472 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9473 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9474 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9475 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9476 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9477 }
9478 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9479 {
9480 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9481 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9482 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9483 || pCtx->gs.Attr.n.u4Type > 11
9484 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9485 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9486 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9487 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9488 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9489 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9490 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9491 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9492 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9493 }
9494 /* 64-bit capable CPUs. */
9495 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9496 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9497 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9498 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9499 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9500 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9501 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9502 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9503 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9504 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9505 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9506 }
9507 else
9508 {
9509 /* V86 mode checks. */
9510 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9511 if (pVmcsInfo->RealMode.fRealOnV86Active)
9512 {
9513 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9514 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9515 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9516 }
9517 else
9518 {
9519 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9520 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9521 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9522 }
9523
9524 /* CS */
9525 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9526 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9527 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9528 /* SS */
9529 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9530 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9531 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9532 /* DS */
9533 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9534 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9535 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9536 /* ES */
9537 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9538 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9539 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9540 /* FS */
9541 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9542 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9543 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9544 /* GS */
9545 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9546 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9547 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9548 /* 64-bit capable CPUs. */
9549 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9550 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9551 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9552 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9553 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9554 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9555 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9556 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9557 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9558 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9559 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9560 }
9561
9562 /*
9563 * TR.
9564 */
9565 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9566 /* 64-bit capable CPUs. */
9567 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9568 if (fLongModeGuest)
9569 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9570 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9571 else
9572 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9573 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9574 VMX_IGS_TR_ATTR_TYPE_INVALID);
9575 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9576 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9577 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9578 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9579 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9580 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9581 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9582 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9583
9584 /*
9585 * GDTR and IDTR (64-bit capable checks).
9586 */
9587 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9588 AssertRC(rc);
9589 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9590
9591 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9592 AssertRC(rc);
9593 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9594
9595 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9596 AssertRC(rc);
9597 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9598
9599 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9600 AssertRC(rc);
9601 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9602
9603 /*
9604 * Guest Non-Register State.
9605 */
9606 /* Activity State. */
9607 uint32_t u32ActivityState;
9608 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9609 AssertRC(rc);
9610 HMVMX_CHECK_BREAK( !u32ActivityState
9611 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9612 VMX_IGS_ACTIVITY_STATE_INVALID);
9613 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9614 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9615 uint32_t u32IntrState;
9616 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9617 AssertRC(rc);
9618 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9619 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9620 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9621
9622 /** @todo Activity state and injecting interrupts. Left as a todo since we
9623 * currently don't use activity states but ACTIVE. */
9624
9625 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9626 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9627
9628 /* Guest interruptibility-state. */
9629 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9630 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9631 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9632 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9633 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9634 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9635 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9636 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9637 {
9638 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9639 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9640 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9641 }
9642 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9643 {
9644 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9645 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9646 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9647 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
9648 }
9649 /** @todo Assumes the processor is not in SMM. */
9650 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9651 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
9652 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9653 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9654 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
9655 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
9656 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9657 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
9658
9659 /* Pending debug exceptions. */
9660 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
9661 AssertRC(rc);
9662 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
9663 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
9664 u32Val = u64Val; /* For pending debug exceptions checks below. */
9665
9666 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9667 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
9668 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
9669 {
9670 if ( (u32Eflags & X86_EFL_TF)
9671 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9672 {
9673 /* Bit 14 is PendingDebug.BS. */
9674 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
9675 }
9676 if ( !(u32Eflags & X86_EFL_TF)
9677 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9678 {
9679 /* Bit 14 is PendingDebug.BS. */
9680 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
9681 }
9682 }
9683
9684 /* VMCS link pointer. */
9685 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
9686 AssertRC(rc);
9687 if (u64Val != UINT64_C(0xffffffffffffffff))
9688 {
9689 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
9690 /** @todo Bits beyond the processor's physical-address width MBZ. */
9691 /** @todo SMM checks. */
9692 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
9693 Assert(pVmcsInfo->pvShadowVmcs);
9694 VMXVMCSREVID VmcsRevId;
9695 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
9696 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
9697 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
9698 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
9699 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
9700 }
9701
9702 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
9703 * not using nested paging? */
9704 if ( pVM->hm.s.fNestedPaging
9705 && !fLongModeGuest
9706 && CPUMIsGuestInPAEModeEx(pCtx))
9707 {
9708 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
9709 AssertRC(rc);
9710 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9711
9712 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
9713 AssertRC(rc);
9714 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9715
9716 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
9717 AssertRC(rc);
9718 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9719
9720 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
9721 AssertRC(rc);
9722 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9723 }
9724
9725 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
9726 if (uError == VMX_IGS_ERROR)
9727 uError = VMX_IGS_REASON_NOT_FOUND;
9728 } while (0);
9729
9730 pVCpu->hm.s.u32HMError = uError;
9731 return uError;
9732
9733#undef HMVMX_ERROR_BREAK
9734#undef HMVMX_CHECK_BREAK
9735}
9736
9737
9738/**
9739 * Map the APIC-access page for virtualizing APIC accesses.
9740 *
9741 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
9742 * this not done as part of exporting guest state, see @bugref{8721}.
9743 *
9744 * @returns VBox status code.
9745 * @param pVCpu The cross context virtual CPU structure.
9746 */
9747static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
9748{
9749 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9750 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
9751
9752 Assert(PDMHasApic(pVM));
9753 Assert(u64MsrApicBase);
9754
9755 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
9756 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
9757
9758 /* Unalias the existing mapping. */
9759 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
9760 AssertRCReturn(rc, rc);
9761
9762 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
9763 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
9764 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
9765 AssertRCReturn(rc, rc);
9766
9767 /* Update the per-VCPU cache of the APIC base MSR. */
9768 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
9769 return VINF_SUCCESS;
9770}
9771
9772
9773/**
9774 * Worker function passed to RTMpOnSpecific() that is to be called on the target
9775 * CPU.
9776 *
9777 * @param idCpu The ID for the CPU the function is called on.
9778 * @param pvUser1 Null, not used.
9779 * @param pvUser2 Null, not used.
9780 */
9781static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
9782{
9783 RT_NOREF3(idCpu, pvUser1, pvUser2);
9784 VMXDispatchHostNmi();
9785}
9786
9787
9788/**
9789 * Dispatching an NMI on the host CPU that received it.
9790 *
9791 * @returns VBox status code.
9792 * @param pVCpu The cross context virtual CPU structure.
9793 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
9794 * executing when receiving the host NMI in VMX non-root
9795 * operation.
9796 */
9797static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9798{
9799 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
9800 Assert(idCpu != NIL_RTCPUID);
9801
9802 /*
9803 * We don't want to delay dispatching the NMI any more than we have to. However,
9804 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
9805 * after executing guest or nested-guest code for the following reasons:
9806 *
9807 * - We would need to perform VMREADs with interrupts disabled and is orders of
9808 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
9809 * supported by the host hypervisor.
9810 *
9811 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
9812 * longer period of time just for handling an edge case like host NMIs which do
9813 * not occur nearly as frequently as other VM-exits.
9814 *
9815 * Let's cover the most likely scenario first. Check if we are on the target CPU
9816 * and dispatch the NMI right away. This should be much faster than calling into
9817 * RTMpOnSpecific() machinery.
9818 */
9819 bool fDispatched = false;
9820 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
9821 if (idCpu == RTMpCpuId())
9822 {
9823 VMXDispatchHostNmi();
9824 fDispatched = true;
9825 }
9826 ASMSetFlags(fEFlags);
9827 if (fDispatched)
9828 {
9829 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
9830 return VINF_SUCCESS;
9831 }
9832
9833 /*
9834 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
9835 * there should be no race or recursion even if we are unlucky enough to be preempted
9836 * (to the target CPU) without dispatching the host NMI above.
9837 */
9838 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
9839 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
9840}
9841
9842
9843#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9844/**
9845 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
9846 * nested-guest using hardware-assisted VMX.
9847 *
9848 * @param pVCpu The cross context virtual CPU structure.
9849 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
9850 * @param pVmcsInfoGst The guest VMCS info. object.
9851 */
9852static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
9853{
9854 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
9855 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
9856 Assert(pu64MsrBitmap);
9857
9858 /*
9859 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
9860 * MSR that is intercepted by the guest is also intercepted while executing the
9861 * nested-guest using hardware-assisted VMX.
9862 *
9863 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
9864 * nested-guest VM-exit even if the outer guest is not intercepting some
9865 * MSRs. We cannot assume the caller has initialized the nested-guest
9866 * MSR bitmap in this case.
9867 *
9868 * The nested hypervisor may also switch whether it uses MSR bitmaps for
9869 * each VM-entry, hence initializing it once per-VM while setting up the
9870 * nested-guest VMCS is not sufficient.
9871 */
9872 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9873 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
9874 {
9875 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
9876 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
9877 Assert(pu64MsrBitmapNstGst);
9878 Assert(pu64MsrBitmapGst);
9879
9880 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
9881 for (uint32_t i = 0; i < cFrags; i++)
9882 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
9883 }
9884 else
9885 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
9886}
9887
9888
9889/**
9890 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
9891 * hardware-assisted VMX execution of the nested-guest.
9892 *
9893 * For a guest, we don't modify these controls once we set up the VMCS and hence
9894 * this function is never called.
9895 *
9896 * For nested-guests since the nested hypervisor provides these controls on every
9897 * nested-guest VM-entry and could potentially change them everytime we need to
9898 * merge them before every nested-guest VM-entry.
9899 *
9900 * @returns VBox status code.
9901 * @param pVCpu The cross context virtual CPU structure.
9902 */
9903static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
9904{
9905 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9906 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
9907 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9908 Assert(pVmcsNstGst);
9909
9910 /*
9911 * Merge the controls with the requirements of the guest VMCS.
9912 *
9913 * We do not need to validate the nested-guest VMX features specified in the nested-guest
9914 * VMCS with the features supported by the physical CPU as it's already done by the
9915 * VMLAUNCH/VMRESUME instruction emulation.
9916 *
9917 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
9918 * derived from the VMX features supported by the physical CPU.
9919 */
9920
9921 /* Pin-based VM-execution controls. */
9922 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
9923
9924 /* Processor-based VM-execution controls. */
9925 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
9926 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
9927 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
9928 | VMX_PROC_CTLS_USE_TPR_SHADOW
9929 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
9930
9931 /* Secondary processor-based VM-execution controls. */
9932 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
9933 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
9934 | VMX_PROC_CTLS2_INVPCID
9935 | VMX_PROC_CTLS2_VMCS_SHADOWING
9936 | VMX_PROC_CTLS2_RDTSCP
9937 | VMX_PROC_CTLS2_XSAVES_XRSTORS
9938 | VMX_PROC_CTLS2_APIC_REG_VIRT
9939 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
9940 | VMX_PROC_CTLS2_VMFUNC));
9941
9942 /*
9943 * VM-entry controls:
9944 * These controls contains state that depends on the nested-guest state (primarily
9945 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
9946 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
9947 * properly continue executing the nested-guest if the EFER MSR changes but does not
9948 * cause a nested-guest VM-exits.
9949 *
9950 * VM-exit controls:
9951 * These controls specify the host state on return. We cannot use the controls from
9952 * the nested hypervisor state as is as it would contain the guest state rather than
9953 * the host state. Since the host state is subject to change (e.g. preemption, trips
9954 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
9955 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
9956 *
9957 * VM-entry MSR-load:
9958 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
9959 * context by the VMLAUNCH/VMRESUME instruction emulation.
9960 *
9961 * VM-exit MSR-store:
9962 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
9963 * back into the VM-exit MSR-store area.
9964 *
9965 * VM-exit MSR-load areas:
9966 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
9967 * can entirely ignore what the nested hypervisor wants to load here.
9968 */
9969
9970 /*
9971 * Exception bitmap.
9972 *
9973 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
9974 * here (and avoid doing anything while exporting nested-guest state), but to keep the
9975 * code more flexible if intercepting exceptions become more dynamic in the future we do
9976 * it as part of exporting the nested-guest state.
9977 */
9978 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
9979
9980 /*
9981 * CR0/CR4 guest/host mask.
9982 *
9983 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
9984 * cause VM-exits, so we need to merge them here.
9985 */
9986 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
9987 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
9988
9989 /*
9990 * Page-fault error-code mask and match.
9991 *
9992 * Although we require unrestricted guest execution (and thereby nested-paging) for
9993 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
9994 * normally intercept #PFs, it might intercept them for debugging purposes.
9995 *
9996 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
9997 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
9998 */
9999 uint32_t u32XcptPFMask;
10000 uint32_t u32XcptPFMatch;
10001 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10002 {
10003 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10004 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10005 }
10006 else
10007 {
10008 u32XcptPFMask = 0;
10009 u32XcptPFMatch = 0;
10010 }
10011
10012 /*
10013 * Pause-Loop exiting.
10014 */
10015 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10016 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10017
10018 /*
10019 * Pending debug exceptions.
10020 * Currently just copy whatever the nested-guest provides us.
10021 */
10022 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10023
10024 /*
10025 * I/O Bitmap.
10026 *
10027 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10028 * intercept all I/O port accesses.
10029 */
10030 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10031 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10032
10033 /*
10034 * VMCS shadowing.
10035 *
10036 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10037 * enabled while executing the nested-guest.
10038 */
10039 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10040
10041 /*
10042 * APIC-access page.
10043 */
10044 RTHCPHYS HCPhysApicAccess;
10045 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10046 {
10047 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10048 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10049
10050 /** @todo NSTVMX: This is not really correct but currently is required to make
10051 * things work. We need to re-enable the page handler when we fallback to
10052 * IEM execution of the nested-guest! */
10053 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10054
10055 void *pvPage;
10056 PGMPAGEMAPLOCK PgLockApicAccess;
10057 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10058 if (RT_SUCCESS(rc))
10059 {
10060 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10061 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10062
10063 /** @todo Handle proper releasing of page-mapping lock later. */
10064 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10065 }
10066 else
10067 return rc;
10068 }
10069 else
10070 HCPhysApicAccess = 0;
10071
10072 /*
10073 * Virtual-APIC page and TPR threshold.
10074 */
10075 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10076 RTHCPHYS HCPhysVirtApic;
10077 uint32_t u32TprThreshold;
10078 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10079 {
10080 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10081 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10082
10083 void *pvPage;
10084 PGMPAGEMAPLOCK PgLockVirtApic;
10085 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10086 if (RT_SUCCESS(rc))
10087 {
10088 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10089 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10090
10091 /** @todo Handle proper releasing of page-mapping lock later. */
10092 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10093 }
10094 else
10095 return rc;
10096
10097 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10098 }
10099 else
10100 {
10101 HCPhysVirtApic = 0;
10102 u32TprThreshold = 0;
10103
10104 /*
10105 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10106 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10107 * be taken care of by EPT/shadow paging.
10108 */
10109 if (pVM->hm.s.fAllow64BitGuests)
10110 {
10111 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10112 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10113 }
10114 }
10115
10116 /*
10117 * Validate basic assumptions.
10118 */
10119 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10120 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10121 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10122
10123 /*
10124 * Commit it to the nested-guest VMCS.
10125 */
10126 int rc = VINF_SUCCESS;
10127 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10128 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10129 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10130 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10131 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10132 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10133 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10134 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10135 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10136 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10137 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10138 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10139 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10140 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10141 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10142 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10143 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10144 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10145 {
10146 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10147 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10148 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10149 }
10150 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10151 {
10152 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10153 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10154 }
10155 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10156 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10157 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10158 AssertRC(rc);
10159
10160 /*
10161 * Update the nested-guest VMCS cache.
10162 */
10163 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10164 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10165 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10166 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10167 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10168 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10169 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10170 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10171 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10172
10173 /*
10174 * We need to flush the TLB if we are switching the APIC-access page address.
10175 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10176 */
10177 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10178 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10179
10180 /*
10181 * MSR bitmap.
10182 *
10183 * The MSR bitmap address has already been initialized while setting up the nested-guest
10184 * VMCS, here we need to merge the MSR bitmaps.
10185 */
10186 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10187 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10188
10189 return VINF_SUCCESS;
10190}
10191#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10192
10193
10194/**
10195 * Does the preparations before executing guest code in VT-x.
10196 *
10197 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10198 * recompiler/IEM. We must be cautious what we do here regarding committing
10199 * guest-state information into the VMCS assuming we assuredly execute the
10200 * guest in VT-x mode.
10201 *
10202 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10203 * the common-state (TRPM/forceflags), we must undo those changes so that the
10204 * recompiler/IEM can (and should) use them when it resumes guest execution.
10205 * Otherwise such operations must be done when we can no longer exit to ring-3.
10206 *
10207 * @returns Strict VBox status code (i.e. informational status codes too).
10208 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10209 * have been disabled.
10210 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10211 * pending events).
10212 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10213 * double-fault into the guest.
10214 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10215 * dispatched directly.
10216 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10217 *
10218 * @param pVCpu The cross context virtual CPU structure.
10219 * @param pVmxTransient The VMX-transient structure.
10220 * @param fStepping Whether we are single-stepping the guest in the
10221 * hypervisor debugger. Makes us ignore some of the reasons
10222 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10223 * if event dispatching took place.
10224 */
10225static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10226{
10227 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10228
10229 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10230
10231#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10232 if (pVmxTransient->fIsNestedGuest)
10233 {
10234 RT_NOREF2(pVCpu, fStepping);
10235 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10236 return VINF_EM_RESCHEDULE_REM;
10237 }
10238#endif
10239
10240#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10241 PGMRZDynMapFlushAutoSet(pVCpu);
10242#endif
10243
10244 /*
10245 * Check and process force flag actions, some of which might require us to go back to ring-3.
10246 */
10247 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
10248 if (rcStrict == VINF_SUCCESS)
10249 {
10250 /* FFs don't get set all the time. */
10251#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10252 if ( pVmxTransient->fIsNestedGuest
10253 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10254 {
10255 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10256 return VINF_VMX_VMEXIT;
10257 }
10258#endif
10259 }
10260 else
10261 return rcStrict;
10262
10263 /*
10264 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10265 */
10266 /** @todo Doing this from ring-3 after VM setup phase causes a
10267 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
10268 * idea why atm. */
10269 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10270 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10271 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10272 && PDMHasApic(pVM))
10273 {
10274 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10275 AssertRCReturn(rc, rc);
10276 }
10277
10278#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10279 /*
10280 * Merge guest VMCS controls with the nested-guest VMCS controls.
10281 *
10282 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10283 * saved state), we should be okay with merging controls as we initialize the
10284 * guest VMCS controls as part of VM setup phase.
10285 */
10286 if ( pVmxTransient->fIsNestedGuest
10287 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10288 {
10289 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10290 AssertRCReturn(rc, rc);
10291 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10292 }
10293#endif
10294
10295 /*
10296 * Evaluate events to be injected into the guest.
10297 *
10298 * Events in TRPM can be injected without inspecting the guest state.
10299 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10300 * guest to cause a VM-exit the next time they are ready to receive the event.
10301 *
10302 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10303 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10304 * subject to interecption. Otherwise, we should have checked and injected them
10305 * manually elsewhere (IEM).
10306 */
10307 if (TRPMHasTrap(pVCpu))
10308 {
10309 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10310 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10311 }
10312
10313 uint32_t fIntrState;
10314 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10315
10316#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10317 /*
10318 * While evaluating pending events if something failed (unlikely) or if we were
10319 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10320 */
10321 if (rcStrict != VINF_SUCCESS)
10322 return rcStrict;
10323 if ( pVmxTransient->fIsNestedGuest
10324 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10325 {
10326 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10327 return VINF_VMX_VMEXIT;
10328 }
10329#else
10330 Assert(rcStrict == VINF_SUCCESS);
10331#endif
10332
10333 /*
10334 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10335 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10336 * also result in triple-faulting the VM.
10337 *
10338 * With nested-guests, the above does not apply since unrestricted guest execution is a
10339 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10340 */
10341 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10342 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10343 { /* likely */ }
10344 else
10345 {
10346 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10347 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10348 return rcStrict;
10349 }
10350
10351 /*
10352 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10353 * import CR3 themselves. We will need to update them here, as even as late as the above
10354 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10355 * the below force flags to be set.
10356 */
10357 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10358 {
10359 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10360 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10361 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10362 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10363 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10364 }
10365 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10366 {
10367 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10368 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10369 }
10370
10371#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10372 /* Paranoia. */
10373 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10374#endif
10375
10376 /*
10377 * No longjmps to ring-3 from this point on!!!
10378 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10379 * This also disables flushing of the R0-logger instance (if any).
10380 */
10381 VMMRZCallRing3Disable(pVCpu);
10382
10383 /*
10384 * Export the guest state bits.
10385 *
10386 * We cannot perform longjmps while loading the guest state because we do not preserve the
10387 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10388 * CPU migration.
10389 *
10390 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10391 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10392 */
10393 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10394 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10395 { /* likely */ }
10396 else
10397 {
10398 VMMRZCallRing3Enable(pVCpu);
10399 return rcStrict;
10400 }
10401
10402 /*
10403 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10404 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10405 * preemption disabled for a while. Since this is purely to aid the
10406 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10407 * disable interrupt on NT.
10408 *
10409 * We need to check for force-flags that could've possible been altered since we last
10410 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10411 * see @bugref{6398}).
10412 *
10413 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10414 * to ring-3 before executing guest code.
10415 */
10416 pVmxTransient->fEFlags = ASMIntDisableFlags();
10417
10418 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10419 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10420 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10421 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10422 {
10423 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10424 {
10425#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10426 /*
10427 * If we are executing a nested-guest make sure that we should intercept subsequent
10428 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10429 * the VM-exit instruction emulation happy.
10430 */
10431 if (pVmxTransient->fIsNestedGuest)
10432 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10433#endif
10434
10435 /*
10436 * We've injected any pending events. This is really the point of no return (to ring-3).
10437 *
10438 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10439 * returns from this function, so do -not- enable them here.
10440 */
10441 pVCpu->hm.s.Event.fPending = false;
10442 return VINF_SUCCESS;
10443 }
10444
10445 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10446 rcStrict = VINF_EM_RAW_INTERRUPT;
10447 }
10448 else
10449 {
10450 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10451 rcStrict = VINF_EM_RAW_TO_R3;
10452 }
10453
10454 ASMSetFlags(pVmxTransient->fEFlags);
10455 VMMRZCallRing3Enable(pVCpu);
10456
10457 return rcStrict;
10458}
10459
10460
10461/**
10462 * Final preparations before executing guest code using hardware-assisted VMX.
10463 *
10464 * We can no longer get preempted to a different host CPU and there are no returns
10465 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10466 * failures), this function is not intended to fail sans unrecoverable hardware
10467 * errors.
10468 *
10469 * @param pVCpu The cross context virtual CPU structure.
10470 * @param pVmxTransient The VMX-transient structure.
10471 *
10472 * @remarks Called with preemption disabled.
10473 * @remarks No-long-jump zone!!!
10474 */
10475static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10476{
10477 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10478 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10479 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10480 Assert(!pVCpu->hm.s.Event.fPending);
10481
10482 /*
10483 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10484 */
10485 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10486 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10487
10488 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10489 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10490 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10491 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10492
10493 if (!CPUMIsGuestFPUStateActive(pVCpu))
10494 {
10495 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10496 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10497 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10498 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10499 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10500 }
10501
10502 /*
10503 * Re-export the host state bits as we may've been preempted (only happens when
10504 * thread-context hooks are used or when the VM start function changes) or if
10505 * the host CR0 is modified while loading the guest FPU state above.
10506 *
10507 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10508 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10509 * see @bugref{8432}.
10510 *
10511 * This may also happen when switching to/from a nested-guest VMCS without leaving
10512 * ring-0.
10513 */
10514 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10515 {
10516 hmR0VmxExportHostState(pVCpu);
10517 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10518 }
10519 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10520
10521 /*
10522 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10523 */
10524 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10525 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10526 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10527
10528 /*
10529 * Store status of the shared guest/host debug state at the time of VM-entry.
10530 */
10531 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10532 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10533
10534 /*
10535 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10536 * more than one conditional check. The post-run side of our code shall determine
10537 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10538 */
10539 if (pVmcsInfo->pbVirtApic)
10540 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10541
10542 /*
10543 * Update the host MSRs values in the VM-exit MSR-load area.
10544 */
10545 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10546 {
10547 if (pVmcsInfo->cExitMsrLoad > 0)
10548 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10549 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10550 }
10551
10552 /*
10553 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10554 * VMX-preemption timer based on the next virtual sync clock deadline.
10555 */
10556 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10557 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10558 {
10559 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10560 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10561 }
10562
10563 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
10564 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
10565 if (!fIsRdtscIntercepted)
10566 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
10567 else
10568 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
10569
10570 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10571 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10572 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10573 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
10574 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
10575 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
10576
10577 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10578
10579 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10580 as we're about to start executing the guest. */
10581
10582 /*
10583 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10584 *
10585 * This is done this late as updating the TSC offsetting/preemption timer above
10586 * figures out if we can skip intercepting RDTSCP by calculating the number of
10587 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10588 */
10589 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10590 && !fIsRdtscIntercepted)
10591 {
10592 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10593
10594 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
10595 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
10596 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10597 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10598 AssertRC(rc);
10599 Assert(!pVmxTransient->fRemoveTscAuxMsr);
10600 pVmxTransient->fRemoveTscAuxMsr = true;
10601 }
10602
10603#ifdef VBOX_STRICT
10604 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
10605 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
10606 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10607 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
10608#endif
10609
10610#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10611 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10612 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
10613 * see @bugref{9180#c54}. */
10614 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10615 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10616 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10617#endif
10618}
10619
10620
10621/**
10622 * First C routine invoked after running guest code using hardware-assisted VMX.
10623 *
10624 * @param pVCpu The cross context virtual CPU structure.
10625 * @param pVmxTransient The VMX-transient structure.
10626 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10627 *
10628 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10629 *
10630 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10631 * unconditionally when it is safe to do so.
10632 */
10633static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10634{
10635 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10636
10637 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10638 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10639 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10640 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10641 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10642 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10643
10644 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10645 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10646 {
10647 uint64_t uGstTsc;
10648 if (!pVmxTransient->fIsNestedGuest)
10649 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10650 else
10651 {
10652 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10653 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
10654 }
10655 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
10656 }
10657
10658 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
10659 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
10660 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10661
10662 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
10663 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
10664#ifdef VBOX_STRICT
10665 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
10666#endif
10667 Assert(!ASMIntAreEnabled());
10668 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
10669 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10670
10671#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
10672 /*
10673 * Clean all the VMCS fields in the transient structure before reading
10674 * anything from the VMCS.
10675 */
10676 pVmxTransient->uExitReason = 0;
10677 pVmxTransient->uExitIntErrorCode = 0;
10678 pVmxTransient->uExitQual = 0;
10679 pVmxTransient->uGuestLinearAddr = 0;
10680 pVmxTransient->uExitIntInfo = 0;
10681 pVmxTransient->cbExitInstr = 0;
10682 pVmxTransient->ExitInstrInfo.u = 0;
10683 pVmxTransient->uEntryIntInfo = 0;
10684 pVmxTransient->uEntryXcptErrorCode = 0;
10685 pVmxTransient->cbEntryInstr = 0;
10686 pVmxTransient->uIdtVectoringInfo = 0;
10687 pVmxTransient->uIdtVectoringErrorCode = 0;
10688#endif
10689
10690 /*
10691 * Save the basic VM-exit reason and check if the VM-entry failed.
10692 * See Intel spec. 24.9.1 "Basic VM-exit Information".
10693 */
10694 uint32_t uExitReason;
10695 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
10696 AssertRC(rc);
10697 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
10698 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
10699
10700 /*
10701 * Log the VM-exit before logging anything else as otherwise it might be a
10702 * tad confusing what happens before and after the world-switch.
10703 */
10704 HMVMX_LOG_EXIT(pVCpu, uExitReason);
10705
10706 /*
10707 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
10708 * bitmap permissions, if it was added before VM-entry.
10709 */
10710 if (pVmxTransient->fRemoveTscAuxMsr)
10711 {
10712 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
10713 pVmxTransient->fRemoveTscAuxMsr = false;
10714 }
10715
10716 /*
10717 * Check if VMLAUNCH/VMRESUME succeeded.
10718 * If this failed, we cause a guru meditation and cease further execution.
10719 *
10720 * However, if we are executing a nested-guest we might fail if we use the
10721 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
10722 */
10723 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
10724 {
10725 /*
10726 * Update the VM-exit history array here even if the VM-entry failed due to:
10727 * - Invalid guest state.
10728 * - MSR loading.
10729 * - Machine-check event.
10730 *
10731 * In any of the above cases we will still have a "valid" VM-exit reason
10732 * despite @a fVMEntryFailed being false.
10733 *
10734 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
10735 *
10736 * Note! We don't have CS or RIP at this point. Will probably address that later
10737 * by amending the history entry added here.
10738 */
10739 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
10740 UINT64_MAX, uHostTsc);
10741
10742 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
10743 {
10744 VMMRZCallRing3Enable(pVCpu);
10745
10746 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10747 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10748
10749#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
10750 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
10751#endif
10752#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
10753 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
10754 AssertRC(rc);
10755#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
10756 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
10757 AssertRC(rc);
10758#else
10759 /*
10760 * Import the guest-interruptibility state always as we need it while evaluating
10761 * injecting events on re-entry.
10762 *
10763 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
10764 * checking for real-mode while exporting the state because all bits that cause
10765 * mode changes wrt CR0 are intercepted.
10766 */
10767 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
10768 AssertRC(rc);
10769#endif
10770
10771 /*
10772 * Sync the TPR shadow with our APIC state.
10773 */
10774 if ( !pVmxTransient->fIsNestedGuest
10775 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
10776 {
10777 Assert(pVmcsInfo->pbVirtApic);
10778 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
10779 {
10780 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
10781 AssertRC(rc);
10782 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
10783 }
10784 }
10785
10786 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10787 return;
10788 }
10789 }
10790#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10791 else if (pVmxTransient->fIsNestedGuest)
10792 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
10793#endif
10794 else
10795 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
10796
10797 VMMRZCallRing3Enable(pVCpu);
10798}
10799
10800
10801/**
10802 * Runs the guest code using hardware-assisted VMX the normal way.
10803 *
10804 * @returns VBox status code.
10805 * @param pVCpu The cross context virtual CPU structure.
10806 * @param pcLoops Pointer to the number of executed loops.
10807 */
10808static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
10809{
10810 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10811 Assert(pcLoops);
10812 Assert(*pcLoops <= cMaxResumeLoops);
10813 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10814
10815#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10816 /*
10817 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
10818 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
10819 * guest VMCS while entering the VMX ring-0 session.
10820 */
10821 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10822 {
10823 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
10824 if (RT_SUCCESS(rc))
10825 { /* likely */ }
10826 else
10827 {
10828 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
10829 return rc;
10830 }
10831 }
10832#endif
10833
10834 VMXTRANSIENT VmxTransient;
10835 RT_ZERO(VmxTransient);
10836 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10837
10838 /* Paranoia. */
10839 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
10840
10841 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10842 for (;;)
10843 {
10844 Assert(!HMR0SuspendPending());
10845 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10846 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10847
10848 /*
10849 * Preparatory work for running nested-guest code, this may force us to
10850 * return to ring-3.
10851 *
10852 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10853 */
10854 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10855 if (rcStrict != VINF_SUCCESS)
10856 break;
10857
10858 /* Interrupts are disabled at this point! */
10859 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10860 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10861 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10862 /* Interrupts are re-enabled at this point! */
10863
10864 /*
10865 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10866 */
10867 if (RT_SUCCESS(rcRun))
10868 { /* very likely */ }
10869 else
10870 {
10871 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10872 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10873 return rcRun;
10874 }
10875
10876 /*
10877 * Profile the VM-exit.
10878 */
10879 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10880 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10881 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10882 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10883 HMVMX_START_EXIT_DISPATCH_PROF();
10884
10885 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10886
10887 /*
10888 * Handle the VM-exit.
10889 */
10890#ifdef HMVMX_USE_FUNCTION_TABLE
10891 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
10892#else
10893 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
10894#endif
10895 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10896 if (rcStrict == VINF_SUCCESS)
10897 {
10898 if (++(*pcLoops) <= cMaxResumeLoops)
10899 continue;
10900 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10901 rcStrict = VINF_EM_RAW_INTERRUPT;
10902 }
10903 break;
10904 }
10905
10906 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10907 return rcStrict;
10908}
10909
10910
10911#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10912/**
10913 * Runs the nested-guest code using hardware-assisted VMX.
10914 *
10915 * @returns VBox status code.
10916 * @param pVCpu The cross context virtual CPU structure.
10917 * @param pcLoops Pointer to the number of executed loops.
10918 *
10919 * @sa hmR0VmxRunGuestCodeNormal.
10920 */
10921static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
10922{
10923 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10924 Assert(pcLoops);
10925 Assert(*pcLoops <= cMaxResumeLoops);
10926 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10927
10928 /*
10929 * Switch to the nested-guest VMCS as we may have transitioned from executing the
10930 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
10931 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
10932 */
10933 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10934 {
10935 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
10936 if (RT_SUCCESS(rc))
10937 { /* likely */ }
10938 else
10939 {
10940 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
10941 return rc;
10942 }
10943 }
10944
10945 VMXTRANSIENT VmxTransient;
10946 RT_ZERO(VmxTransient);
10947 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10948 VmxTransient.fIsNestedGuest = true;
10949
10950 /* Paranoia. */
10951 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
10952
10953 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10954 for (;;)
10955 {
10956 Assert(!HMR0SuspendPending());
10957 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10958 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10959
10960 /*
10961 * Preparatory work for running guest code, this may force us to
10962 * return to ring-3.
10963 *
10964 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10965 */
10966 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10967 if (rcStrict != VINF_SUCCESS)
10968 break;
10969
10970 /* Interrupts are disabled at this point! */
10971 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10972 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10973 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10974 /* Interrupts are re-enabled at this point! */
10975
10976 /*
10977 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10978 */
10979 if (RT_SUCCESS(rcRun))
10980 { /* very likely */ }
10981 else
10982 {
10983 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10984 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10985 return rcRun;
10986 }
10987
10988 /*
10989 * Profile the VM-exit.
10990 */
10991 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10992 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10993 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
10994 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10995 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10996 HMVMX_START_EXIT_DISPATCH_PROF();
10997
10998 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10999
11000 /*
11001 * Handle the VM-exit.
11002 */
11003 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11004 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11005 if (rcStrict == VINF_SUCCESS)
11006 {
11007 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11008 {
11009 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11010 rcStrict = VINF_VMX_VMEXIT;
11011 }
11012 else
11013 {
11014 if (++(*pcLoops) <= cMaxResumeLoops)
11015 continue;
11016 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11017 rcStrict = VINF_EM_RAW_INTERRUPT;
11018 }
11019 }
11020 else
11021 Assert(rcStrict != VINF_VMX_VMEXIT);
11022 break;
11023 }
11024
11025 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11026 return rcStrict;
11027}
11028#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11029
11030
11031/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11032 * probes.
11033 *
11034 * The following few functions and associated structure contains the bloat
11035 * necessary for providing detailed debug events and dtrace probes as well as
11036 * reliable host side single stepping. This works on the principle of
11037 * "subclassing" the normal execution loop and workers. We replace the loop
11038 * method completely and override selected helpers to add necessary adjustments
11039 * to their core operation.
11040 *
11041 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11042 * any performance for debug and analysis features.
11043 *
11044 * @{
11045 */
11046
11047/**
11048 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11049 * the debug run loop.
11050 */
11051typedef struct VMXRUNDBGSTATE
11052{
11053 /** The RIP we started executing at. This is for detecting that we stepped. */
11054 uint64_t uRipStart;
11055 /** The CS we started executing with. */
11056 uint16_t uCsStart;
11057
11058 /** Whether we've actually modified the 1st execution control field. */
11059 bool fModifiedProcCtls : 1;
11060 /** Whether we've actually modified the 2nd execution control field. */
11061 bool fModifiedProcCtls2 : 1;
11062 /** Whether we've actually modified the exception bitmap. */
11063 bool fModifiedXcptBitmap : 1;
11064
11065 /** We desire the modified the CR0 mask to be cleared. */
11066 bool fClearCr0Mask : 1;
11067 /** We desire the modified the CR4 mask to be cleared. */
11068 bool fClearCr4Mask : 1;
11069 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11070 uint32_t fCpe1Extra;
11071 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11072 uint32_t fCpe1Unwanted;
11073 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11074 uint32_t fCpe2Extra;
11075 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11076 uint32_t bmXcptExtra;
11077 /** The sequence number of the Dtrace provider settings the state was
11078 * configured against. */
11079 uint32_t uDtraceSettingsSeqNo;
11080 /** VM-exits to check (one bit per VM-exit). */
11081 uint32_t bmExitsToCheck[3];
11082
11083 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11084 uint32_t fProcCtlsInitial;
11085 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11086 uint32_t fProcCtls2Initial;
11087 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11088 uint32_t bmXcptInitial;
11089} VMXRUNDBGSTATE;
11090AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11091typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11092
11093
11094/**
11095 * Initializes the VMXRUNDBGSTATE structure.
11096 *
11097 * @param pVCpu The cross context virtual CPU structure of the
11098 * calling EMT.
11099 * @param pVmxTransient The VMX-transient structure.
11100 * @param pDbgState The debug state to initialize.
11101 */
11102static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11103{
11104 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11105 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11106
11107 pDbgState->fModifiedProcCtls = false;
11108 pDbgState->fModifiedProcCtls2 = false;
11109 pDbgState->fModifiedXcptBitmap = false;
11110 pDbgState->fClearCr0Mask = false;
11111 pDbgState->fClearCr4Mask = false;
11112 pDbgState->fCpe1Extra = 0;
11113 pDbgState->fCpe1Unwanted = 0;
11114 pDbgState->fCpe2Extra = 0;
11115 pDbgState->bmXcptExtra = 0;
11116 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11117 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11118 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11119}
11120
11121
11122/**
11123 * Updates the VMSC fields with changes requested by @a pDbgState.
11124 *
11125 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11126 * immediately before executing guest code, i.e. when interrupts are disabled.
11127 * We don't check status codes here as we cannot easily assert or return in the
11128 * latter case.
11129 *
11130 * @param pVCpu The cross context virtual CPU structure.
11131 * @param pVmxTransient The VMX-transient structure.
11132 * @param pDbgState The debug state.
11133 */
11134static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11135{
11136 /*
11137 * Ensure desired flags in VMCS control fields are set.
11138 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11139 *
11140 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11141 * there should be no stale data in pCtx at this point.
11142 */
11143 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11144 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11145 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11146 {
11147 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11148 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11149 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11150 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11151 pDbgState->fModifiedProcCtls = true;
11152 }
11153
11154 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11155 {
11156 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11157 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11158 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11159 pDbgState->fModifiedProcCtls2 = true;
11160 }
11161
11162 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11163 {
11164 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11165 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11166 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11167 pDbgState->fModifiedXcptBitmap = true;
11168 }
11169
11170 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11171 {
11172 pVmcsInfo->u64Cr0Mask = 0;
11173 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11174 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11175 }
11176
11177 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11178 {
11179 pVmcsInfo->u64Cr4Mask = 0;
11180 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11181 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11182 }
11183
11184 NOREF(pVCpu);
11185}
11186
11187
11188/**
11189 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11190 * re-entry next time around.
11191 *
11192 * @returns Strict VBox status code (i.e. informational status codes too).
11193 * @param pVCpu The cross context virtual CPU structure.
11194 * @param pVmxTransient The VMX-transient structure.
11195 * @param pDbgState The debug state.
11196 * @param rcStrict The return code from executing the guest using single
11197 * stepping.
11198 */
11199static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11200 VBOXSTRICTRC rcStrict)
11201{
11202 /*
11203 * Restore VM-exit control settings as we may not reenter this function the
11204 * next time around.
11205 */
11206 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11207
11208 /* We reload the initial value, trigger what we can of recalculations the
11209 next time around. From the looks of things, that's all that's required atm. */
11210 if (pDbgState->fModifiedProcCtls)
11211 {
11212 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11213 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11214 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11215 AssertRC(rc2);
11216 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11217 }
11218
11219 /* We're currently the only ones messing with this one, so just restore the
11220 cached value and reload the field. */
11221 if ( pDbgState->fModifiedProcCtls2
11222 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11223 {
11224 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11225 AssertRC(rc2);
11226 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11227 }
11228
11229 /* If we've modified the exception bitmap, we restore it and trigger
11230 reloading and partial recalculation the next time around. */
11231 if (pDbgState->fModifiedXcptBitmap)
11232 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11233
11234 return rcStrict;
11235}
11236
11237
11238/**
11239 * Configures VM-exit controls for current DBGF and DTrace settings.
11240 *
11241 * This updates @a pDbgState and the VMCS execution control fields to reflect
11242 * the necessary VM-exits demanded by DBGF and DTrace.
11243 *
11244 * @param pVCpu The cross context virtual CPU structure.
11245 * @param pVmxTransient The VMX-transient structure. May update
11246 * fUpdatedTscOffsettingAndPreemptTimer.
11247 * @param pDbgState The debug state.
11248 */
11249static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11250{
11251 /*
11252 * Take down the dtrace serial number so we can spot changes.
11253 */
11254 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11255 ASMCompilerBarrier();
11256
11257 /*
11258 * We'll rebuild most of the middle block of data members (holding the
11259 * current settings) as we go along here, so start by clearing it all.
11260 */
11261 pDbgState->bmXcptExtra = 0;
11262 pDbgState->fCpe1Extra = 0;
11263 pDbgState->fCpe1Unwanted = 0;
11264 pDbgState->fCpe2Extra = 0;
11265 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11266 pDbgState->bmExitsToCheck[i] = 0;
11267
11268 /*
11269 * Software interrupts (INT XXh) - no idea how to trigger these...
11270 */
11271 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11272 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11273 || VBOXVMM_INT_SOFTWARE_ENABLED())
11274 {
11275 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11276 }
11277
11278 /*
11279 * INT3 breakpoints - triggered by #BP exceptions.
11280 */
11281 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11282 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11283
11284 /*
11285 * Exception bitmap and XCPT events+probes.
11286 */
11287 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11288 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11289 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11290
11291 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11292 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11293 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11294 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11295 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11296 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11297 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11298 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11299 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11300 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11301 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11302 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11303 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11304 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11305 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11306 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11307 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11308 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11309
11310 if (pDbgState->bmXcptExtra)
11311 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11312
11313 /*
11314 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11315 *
11316 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11317 * So, when adding/changing/removing please don't forget to update it.
11318 *
11319 * Some of the macros are picking up local variables to save horizontal space,
11320 * (being able to see it in a table is the lesser evil here).
11321 */
11322#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11323 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11324 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11325#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11326 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11327 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11328 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11329 } else do { } while (0)
11330#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11331 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11332 { \
11333 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11334 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11335 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11336 } else do { } while (0)
11337#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11338 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11339 { \
11340 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11341 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11342 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11343 } else do { } while (0)
11344#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11345 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11346 { \
11347 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11348 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11349 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11350 } else do { } while (0)
11351
11352 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11353 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11354 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11355 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11356 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11357
11358 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11359 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11360 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11361 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11362 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11363 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11364 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11365 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11366 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11367 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11368 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11369 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11370 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11371 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11372 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11373 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11374 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11375 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11376 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11377 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11378 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11379 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11380 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11381 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11382 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11383 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11384 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11385 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11386 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11387 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11388 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11389 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11390 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11391 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11392 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11393 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11394
11395 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11396 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11397 {
11398 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11399 | CPUMCTX_EXTRN_APIC_TPR);
11400 AssertRC(rc);
11401
11402#if 0 /** @todo fix me */
11403 pDbgState->fClearCr0Mask = true;
11404 pDbgState->fClearCr4Mask = true;
11405#endif
11406 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11407 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11408 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11409 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11410 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11411 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11412 require clearing here and in the loop if we start using it. */
11413 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11414 }
11415 else
11416 {
11417 if (pDbgState->fClearCr0Mask)
11418 {
11419 pDbgState->fClearCr0Mask = false;
11420 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11421 }
11422 if (pDbgState->fClearCr4Mask)
11423 {
11424 pDbgState->fClearCr4Mask = false;
11425 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11426 }
11427 }
11428 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11429 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11430
11431 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11432 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11433 {
11434 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11435 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11436 }
11437 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11438 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11439
11440 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11441 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11442 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11443 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11444 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11445 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11446 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11447 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11448#if 0 /** @todo too slow, fix handler. */
11449 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11450#endif
11451 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11452
11453 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11454 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11455 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11456 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11457 {
11458 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11459 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11460 }
11461 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11462 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11463 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11464 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11465
11466 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11467 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11468 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11469 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11470 {
11471 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11472 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11473 }
11474 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11475 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11476 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11477 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11478
11479 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11480 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11481 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11482 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11483 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11484 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11485 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11486 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11487 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11488 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11489 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11490 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11491 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11492 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11493 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11494 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11495 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11496 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11497 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11498 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11499 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11500 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11501
11502#undef IS_EITHER_ENABLED
11503#undef SET_ONLY_XBM_IF_EITHER_EN
11504#undef SET_CPE1_XBM_IF_EITHER_EN
11505#undef SET_CPEU_XBM_IF_EITHER_EN
11506#undef SET_CPE2_XBM_IF_EITHER_EN
11507
11508 /*
11509 * Sanitize the control stuff.
11510 */
11511 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11512 if (pDbgState->fCpe2Extra)
11513 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11514 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11515 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11516 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11517 {
11518 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11519 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11520 }
11521
11522 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11523 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11524 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11525 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11526}
11527
11528
11529/**
11530 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11531 * appropriate.
11532 *
11533 * The caller has checked the VM-exit against the
11534 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11535 * already, so we don't have to do that either.
11536 *
11537 * @returns Strict VBox status code (i.e. informational status codes too).
11538 * @param pVCpu The cross context virtual CPU structure.
11539 * @param pVmxTransient The VMX-transient structure.
11540 * @param uExitReason The VM-exit reason.
11541 *
11542 * @remarks The name of this function is displayed by dtrace, so keep it short
11543 * and to the point. No longer than 33 chars long, please.
11544 */
11545static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11546{
11547 /*
11548 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11549 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11550 *
11551 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11552 * does. Must add/change/remove both places. Same ordering, please.
11553 *
11554 * Added/removed events must also be reflected in the next section
11555 * where we dispatch dtrace events.
11556 */
11557 bool fDtrace1 = false;
11558 bool fDtrace2 = false;
11559 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11560 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11561 uint32_t uEventArg = 0;
11562#define SET_EXIT(a_EventSubName) \
11563 do { \
11564 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11565 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11566 } while (0)
11567#define SET_BOTH(a_EventSubName) \
11568 do { \
11569 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11570 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11571 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11572 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11573 } while (0)
11574 switch (uExitReason)
11575 {
11576 case VMX_EXIT_MTF:
11577 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11578
11579 case VMX_EXIT_XCPT_OR_NMI:
11580 {
11581 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11582 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11583 {
11584 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11585 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11586 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11587 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11588 {
11589 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11590 {
11591 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11592 uEventArg = pVmxTransient->uExitIntErrorCode;
11593 }
11594 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11595 switch (enmEvent1)
11596 {
11597 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11598 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11599 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11600 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11601 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11602 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11603 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11604 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11605 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11606 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11607 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11608 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11609 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11610 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11611 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11612 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11613 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11614 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11615 default: break;
11616 }
11617 }
11618 else
11619 AssertFailed();
11620 break;
11621
11622 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11623 uEventArg = idxVector;
11624 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11625 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11626 break;
11627 }
11628 break;
11629 }
11630
11631 case VMX_EXIT_TRIPLE_FAULT:
11632 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11633 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11634 break;
11635 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11636 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11637 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11638 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11639 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11640
11641 /* Instruction specific VM-exits: */
11642 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11643 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11644 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11645 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11646 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11647 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11648 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11649 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
11650 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
11651 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
11652 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
11653 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
11654 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
11655 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
11656 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
11657 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
11658 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
11659 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
11660 case VMX_EXIT_MOV_CRX:
11661 hmR0VmxReadExitQualVmcs(pVmxTransient);
11662 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
11663 SET_BOTH(CRX_READ);
11664 else
11665 SET_BOTH(CRX_WRITE);
11666 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
11667 break;
11668 case VMX_EXIT_MOV_DRX:
11669 hmR0VmxReadExitQualVmcs(pVmxTransient);
11670 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
11671 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
11672 SET_BOTH(DRX_READ);
11673 else
11674 SET_BOTH(DRX_WRITE);
11675 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
11676 break;
11677 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
11678 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
11679 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
11680 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
11681 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
11682 case VMX_EXIT_GDTR_IDTR_ACCESS:
11683 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11684 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
11685 {
11686 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
11687 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
11688 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
11689 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
11690 }
11691 break;
11692
11693 case VMX_EXIT_LDTR_TR_ACCESS:
11694 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11695 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
11696 {
11697 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
11698 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
11699 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
11700 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
11701 }
11702 break;
11703
11704 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
11705 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
11706 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
11707 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
11708 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
11709 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
11710 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
11711 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
11712 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
11713 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
11714 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
11715
11716 /* Events that aren't relevant at this point. */
11717 case VMX_EXIT_EXT_INT:
11718 case VMX_EXIT_INT_WINDOW:
11719 case VMX_EXIT_NMI_WINDOW:
11720 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11721 case VMX_EXIT_PREEMPT_TIMER:
11722 case VMX_EXIT_IO_INSTR:
11723 break;
11724
11725 /* Errors and unexpected events. */
11726 case VMX_EXIT_INIT_SIGNAL:
11727 case VMX_EXIT_SIPI:
11728 case VMX_EXIT_IO_SMI:
11729 case VMX_EXIT_SMI:
11730 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11731 case VMX_EXIT_ERR_MSR_LOAD:
11732 case VMX_EXIT_ERR_MACHINE_CHECK:
11733 case VMX_EXIT_PML_FULL:
11734 case VMX_EXIT_VIRTUALIZED_EOI:
11735 break;
11736
11737 default:
11738 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
11739 break;
11740 }
11741#undef SET_BOTH
11742#undef SET_EXIT
11743
11744 /*
11745 * Dtrace tracepoints go first. We do them here at once so we don't
11746 * have to copy the guest state saving and stuff a few dozen times.
11747 * Down side is that we've got to repeat the switch, though this time
11748 * we use enmEvent since the probes are a subset of what DBGF does.
11749 */
11750 if (fDtrace1 || fDtrace2)
11751 {
11752 hmR0VmxReadExitQualVmcs(pVmxTransient);
11753 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11754 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
11755 switch (enmEvent1)
11756 {
11757 /** @todo consider which extra parameters would be helpful for each probe. */
11758 case DBGFEVENT_END: break;
11759 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
11760 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
11761 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
11762 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
11763 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
11764 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
11765 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
11766 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
11767 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
11768 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
11769 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
11770 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
11771 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
11772 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
11773 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
11774 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
11775 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
11776 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
11777 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11778 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11779 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
11780 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
11781 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
11782 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
11783 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
11784 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
11785 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
11786 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11787 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11788 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11789 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11790 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11791 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
11792 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11793 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
11794 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
11795 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
11796 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
11797 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
11798 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
11799 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
11800 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
11801 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
11802 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
11803 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
11804 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
11805 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
11806 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
11807 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
11808 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
11809 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
11810 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
11811 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
11812 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
11813 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
11814 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
11815 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
11816 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
11817 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
11818 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
11819 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
11820 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
11821 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
11822 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
11823 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
11824 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
11825 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
11826 }
11827 switch (enmEvent2)
11828 {
11829 /** @todo consider which extra parameters would be helpful for each probe. */
11830 case DBGFEVENT_END: break;
11831 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
11832 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11833 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
11834 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
11835 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
11836 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
11837 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
11838 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
11839 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
11840 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11841 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11842 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11843 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11844 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11845 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
11846 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11847 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
11848 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
11849 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
11850 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
11851 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
11852 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
11853 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
11854 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
11855 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
11856 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
11857 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
11858 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
11859 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
11860 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
11861 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
11862 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
11863 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
11864 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
11865 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
11866 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
11867 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
11868 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
11869 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
11870 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
11871 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
11872 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
11873 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
11874 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
11875 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
11876 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
11877 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
11878 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
11879 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
11880 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
11881 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
11882 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
11883 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
11884 }
11885 }
11886
11887 /*
11888 * Fire of the DBGF event, if enabled (our check here is just a quick one,
11889 * the DBGF call will do a full check).
11890 *
11891 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
11892 * Note! If we have to events, we prioritize the first, i.e. the instruction
11893 * one, in order to avoid event nesting.
11894 */
11895 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11896 if ( enmEvent1 != DBGFEVENT_END
11897 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
11898 {
11899 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11900 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
11901 if (rcStrict != VINF_SUCCESS)
11902 return rcStrict;
11903 }
11904 else if ( enmEvent2 != DBGFEVENT_END
11905 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
11906 {
11907 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11908 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
11909 if (rcStrict != VINF_SUCCESS)
11910 return rcStrict;
11911 }
11912
11913 return VINF_SUCCESS;
11914}
11915
11916
11917/**
11918 * Single-stepping VM-exit filtering.
11919 *
11920 * This is preprocessing the VM-exits and deciding whether we've gotten far
11921 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
11922 * handling is performed.
11923 *
11924 * @returns Strict VBox status code (i.e. informational status codes too).
11925 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
11926 * @param pVmxTransient The VMX-transient structure.
11927 * @param pDbgState The debug state.
11928 */
11929DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11930{
11931 /*
11932 * Expensive (saves context) generic dtrace VM-exit probe.
11933 */
11934 uint32_t const uExitReason = pVmxTransient->uExitReason;
11935 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
11936 { /* more likely */ }
11937 else
11938 {
11939 hmR0VmxReadExitQualVmcs(pVmxTransient);
11940 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11941 AssertRC(rc);
11942 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
11943 }
11944
11945 /*
11946 * Check for host NMI, just to get that out of the way.
11947 */
11948 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
11949 { /* normally likely */ }
11950 else
11951 {
11952 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
11953 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
11954 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
11955 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
11956 }
11957
11958 /*
11959 * Check for single stepping event if we're stepping.
11960 */
11961 if (pVCpu->hm.s.fSingleInstruction)
11962 {
11963 switch (uExitReason)
11964 {
11965 case VMX_EXIT_MTF:
11966 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11967
11968 /* Various events: */
11969 case VMX_EXIT_XCPT_OR_NMI:
11970 case VMX_EXIT_EXT_INT:
11971 case VMX_EXIT_TRIPLE_FAULT:
11972 case VMX_EXIT_INT_WINDOW:
11973 case VMX_EXIT_NMI_WINDOW:
11974 case VMX_EXIT_TASK_SWITCH:
11975 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11976 case VMX_EXIT_APIC_ACCESS:
11977 case VMX_EXIT_EPT_VIOLATION:
11978 case VMX_EXIT_EPT_MISCONFIG:
11979 case VMX_EXIT_PREEMPT_TIMER:
11980
11981 /* Instruction specific VM-exits: */
11982 case VMX_EXIT_CPUID:
11983 case VMX_EXIT_GETSEC:
11984 case VMX_EXIT_HLT:
11985 case VMX_EXIT_INVD:
11986 case VMX_EXIT_INVLPG:
11987 case VMX_EXIT_RDPMC:
11988 case VMX_EXIT_RDTSC:
11989 case VMX_EXIT_RSM:
11990 case VMX_EXIT_VMCALL:
11991 case VMX_EXIT_VMCLEAR:
11992 case VMX_EXIT_VMLAUNCH:
11993 case VMX_EXIT_VMPTRLD:
11994 case VMX_EXIT_VMPTRST:
11995 case VMX_EXIT_VMREAD:
11996 case VMX_EXIT_VMRESUME:
11997 case VMX_EXIT_VMWRITE:
11998 case VMX_EXIT_VMXOFF:
11999 case VMX_EXIT_VMXON:
12000 case VMX_EXIT_MOV_CRX:
12001 case VMX_EXIT_MOV_DRX:
12002 case VMX_EXIT_IO_INSTR:
12003 case VMX_EXIT_RDMSR:
12004 case VMX_EXIT_WRMSR:
12005 case VMX_EXIT_MWAIT:
12006 case VMX_EXIT_MONITOR:
12007 case VMX_EXIT_PAUSE:
12008 case VMX_EXIT_GDTR_IDTR_ACCESS:
12009 case VMX_EXIT_LDTR_TR_ACCESS:
12010 case VMX_EXIT_INVEPT:
12011 case VMX_EXIT_RDTSCP:
12012 case VMX_EXIT_INVVPID:
12013 case VMX_EXIT_WBINVD:
12014 case VMX_EXIT_XSETBV:
12015 case VMX_EXIT_RDRAND:
12016 case VMX_EXIT_INVPCID:
12017 case VMX_EXIT_VMFUNC:
12018 case VMX_EXIT_RDSEED:
12019 case VMX_EXIT_XSAVES:
12020 case VMX_EXIT_XRSTORS:
12021 {
12022 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12023 AssertRCReturn(rc, rc);
12024 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12025 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12026 return VINF_EM_DBG_STEPPED;
12027 break;
12028 }
12029
12030 /* Errors and unexpected events: */
12031 case VMX_EXIT_INIT_SIGNAL:
12032 case VMX_EXIT_SIPI:
12033 case VMX_EXIT_IO_SMI:
12034 case VMX_EXIT_SMI:
12035 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12036 case VMX_EXIT_ERR_MSR_LOAD:
12037 case VMX_EXIT_ERR_MACHINE_CHECK:
12038 case VMX_EXIT_PML_FULL:
12039 case VMX_EXIT_VIRTUALIZED_EOI:
12040 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12041 break;
12042
12043 default:
12044 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12045 break;
12046 }
12047 }
12048
12049 /*
12050 * Check for debugger event breakpoints and dtrace probes.
12051 */
12052 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12053 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12054 {
12055 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12056 if (rcStrict != VINF_SUCCESS)
12057 return rcStrict;
12058 }
12059
12060 /*
12061 * Normal processing.
12062 */
12063#ifdef HMVMX_USE_FUNCTION_TABLE
12064 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12065#else
12066 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12067#endif
12068}
12069
12070
12071/**
12072 * Single steps guest code using hardware-assisted VMX.
12073 *
12074 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12075 * but single-stepping through the hypervisor debugger.
12076 *
12077 * @returns Strict VBox status code (i.e. informational status codes too).
12078 * @param pVCpu The cross context virtual CPU structure.
12079 * @param pcLoops Pointer to the number of executed loops.
12080 *
12081 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12082 */
12083static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12084{
12085 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12086 Assert(pcLoops);
12087 Assert(*pcLoops <= cMaxResumeLoops);
12088
12089 VMXTRANSIENT VmxTransient;
12090 RT_ZERO(VmxTransient);
12091 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12092
12093 /* Set HMCPU indicators. */
12094 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12095 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12096 pVCpu->hm.s.fDebugWantRdTscExit = false;
12097 pVCpu->hm.s.fUsingDebugLoop = true;
12098
12099 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12100 VMXRUNDBGSTATE DbgState;
12101 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12102 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12103
12104 /*
12105 * The loop.
12106 */
12107 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12108 for (;;)
12109 {
12110 Assert(!HMR0SuspendPending());
12111 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12112 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12113 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12114
12115 /* Set up VM-execution controls the next two can respond to. */
12116 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12117
12118 /*
12119 * Preparatory work for running guest code, this may force us to
12120 * return to ring-3.
12121 *
12122 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12123 */
12124 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12125 if (rcStrict != VINF_SUCCESS)
12126 break;
12127
12128 /* Interrupts are disabled at this point! */
12129 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12130
12131 /* Override any obnoxious code in the above two calls. */
12132 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12133
12134 /*
12135 * Finally execute the guest.
12136 */
12137 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12138
12139 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12140 /* Interrupts are re-enabled at this point! */
12141
12142 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12143 if (RT_SUCCESS(rcRun))
12144 { /* very likely */ }
12145 else
12146 {
12147 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12148 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12149 return rcRun;
12150 }
12151
12152 /* Profile the VM-exit. */
12153 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12154 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12155 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12156 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12157 HMVMX_START_EXIT_DISPATCH_PROF();
12158
12159 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12160
12161 /*
12162 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12163 */
12164 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12165 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12166 if (rcStrict != VINF_SUCCESS)
12167 break;
12168 if (++(*pcLoops) > cMaxResumeLoops)
12169 {
12170 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12171 rcStrict = VINF_EM_RAW_INTERRUPT;
12172 break;
12173 }
12174
12175 /*
12176 * Stepping: Did the RIP change, if so, consider it a single step.
12177 * Otherwise, make sure one of the TFs gets set.
12178 */
12179 if (fStepping)
12180 {
12181 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12182 AssertRC(rc);
12183 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12184 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12185 {
12186 rcStrict = VINF_EM_DBG_STEPPED;
12187 break;
12188 }
12189 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12190 }
12191
12192 /*
12193 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12194 */
12195 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12196 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12197 }
12198
12199 /*
12200 * Clear the X86_EFL_TF if necessary.
12201 */
12202 if (pVCpu->hm.s.fClearTrapFlag)
12203 {
12204 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12205 AssertRC(rc);
12206 pVCpu->hm.s.fClearTrapFlag = false;
12207 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12208 }
12209 /** @todo there seems to be issues with the resume flag when the monitor trap
12210 * flag is pending without being used. Seen early in bios init when
12211 * accessing APIC page in protected mode. */
12212
12213 /*
12214 * Restore VM-exit control settings as we may not re-enter this function the
12215 * next time around.
12216 */
12217 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12218
12219 /* Restore HMCPU indicators. */
12220 pVCpu->hm.s.fUsingDebugLoop = false;
12221 pVCpu->hm.s.fDebugWantRdTscExit = false;
12222 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12223
12224 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12225 return rcStrict;
12226}
12227
12228
12229/** @} */
12230
12231
12232/**
12233 * Checks if any expensive dtrace probes are enabled and we should go to the
12234 * debug loop.
12235 *
12236 * @returns true if we should use debug loop, false if not.
12237 */
12238static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12239{
12240 /* It's probably faster to OR the raw 32-bit counter variables together.
12241 Since the variables are in an array and the probes are next to one
12242 another (more or less), we have good locality. So, better read
12243 eight-nine cache lines ever time and only have one conditional, than
12244 128+ conditionals, right? */
12245 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12246 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12247 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12248 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12249 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12250 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12251 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12252 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12253 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12254 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12255 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12256 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12257 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12258 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12259 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12260 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12261 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12262 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12263 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12264 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12265 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12266 ) != 0
12267 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12268 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12269 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12270 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12271 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12272 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12273 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12274 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12275 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12276 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12277 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12278 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12279 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12280 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12281 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12282 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12283 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12284 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12285 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12286 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12287 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12288 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12289 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12290 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12291 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12292 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12293 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12294 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12295 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12296 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12297 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12298 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12299 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12300 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12301 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12302 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12303 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12304 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12305 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12306 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12307 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12308 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12309 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12310 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12311 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12312 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12313 ) != 0
12314 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12315 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12316 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12317 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12318 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12319 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12320 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12321 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12322 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12323 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12324 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12325 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12326 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12327 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12328 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12329 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12330 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12331 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12332 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12333 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12334 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12335 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12336 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12337 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12338 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12339 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12340 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12341 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12342 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12343 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12344 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12345 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12346 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12347 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12348 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12349 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12350 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12351 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12352 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12353 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12354 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12355 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12356 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12357 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12358 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12359 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12360 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12361 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12362 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12363 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12364 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12365 ) != 0;
12366}
12367
12368
12369/**
12370 * Runs the guest using hardware-assisted VMX.
12371 *
12372 * @returns Strict VBox status code (i.e. informational status codes too).
12373 * @param pVCpu The cross context virtual CPU structure.
12374 */
12375VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12376{
12377 AssertPtr(pVCpu);
12378 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12379 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12380 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12381 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12382
12383 VBOXSTRICTRC rcStrict;
12384 uint32_t cLoops = 0;
12385 for (;;)
12386 {
12387#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12388 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12389#else
12390 NOREF(pCtx);
12391 bool const fInNestedGuestMode = false;
12392#endif
12393 if (!fInNestedGuestMode)
12394 {
12395 if ( !pVCpu->hm.s.fUseDebugLoop
12396 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12397 && !DBGFIsStepping(pVCpu)
12398 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12399 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12400 else
12401 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12402 }
12403#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12404 else
12405 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12406
12407 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12408 {
12409 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12410 continue;
12411 }
12412 if (rcStrict == VINF_VMX_VMEXIT)
12413 {
12414 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12415 continue;
12416 }
12417#endif
12418 break;
12419 }
12420
12421 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12422 switch (rcLoop)
12423 {
12424 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12425 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12426 }
12427
12428 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12429 if (RT_FAILURE(rc2))
12430 {
12431 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12432 rcStrict = rc2;
12433 }
12434 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12435 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12436 return rcStrict;
12437}
12438
12439
12440#ifndef HMVMX_USE_FUNCTION_TABLE
12441/**
12442 * Handles a guest VM-exit from hardware-assisted VMX execution.
12443 *
12444 * @returns Strict VBox status code (i.e. informational status codes too).
12445 * @param pVCpu The cross context virtual CPU structure.
12446 * @param pVmxTransient The VMX-transient structure.
12447 */
12448DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12449{
12450#ifdef DEBUG_ramshankar
12451# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12452 do { \
12453 if (a_fSave != 0) \
12454 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12455 VBOXSTRICTRC rcStrict = a_CallExpr; \
12456 if (a_fSave != 0) \
12457 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12458 return rcStrict; \
12459 } while (0)
12460#else
12461# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12462#endif
12463 uint32_t const uExitReason = pVmxTransient->uExitReason;
12464 switch (uExitReason)
12465 {
12466 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12467 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12468 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12469 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12470 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12471 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12472 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12473 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12474 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12475 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12476 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12477 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12478 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12479 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12480 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12481 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12482 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12483 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12484 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12485 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12486 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12487 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12488 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12489 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12490 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12491 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12492 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12493 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12494 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12495 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12496#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12497 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12498 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12499 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12500 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12501 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12502 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12503 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12504 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12505 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12506 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12507 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12508#else
12509 case VMX_EXIT_VMCLEAR:
12510 case VMX_EXIT_VMLAUNCH:
12511 case VMX_EXIT_VMPTRLD:
12512 case VMX_EXIT_VMPTRST:
12513 case VMX_EXIT_VMREAD:
12514 case VMX_EXIT_VMRESUME:
12515 case VMX_EXIT_VMWRITE:
12516 case VMX_EXIT_VMXOFF:
12517 case VMX_EXIT_VMXON:
12518 case VMX_EXIT_INVVPID:
12519 case VMX_EXIT_INVEPT:
12520 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12521#endif
12522
12523 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12524 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12525 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12526
12527 case VMX_EXIT_INIT_SIGNAL:
12528 case VMX_EXIT_SIPI:
12529 case VMX_EXIT_IO_SMI:
12530 case VMX_EXIT_SMI:
12531 case VMX_EXIT_ERR_MSR_LOAD:
12532 case VMX_EXIT_ERR_MACHINE_CHECK:
12533 case VMX_EXIT_PML_FULL:
12534 case VMX_EXIT_VIRTUALIZED_EOI:
12535 case VMX_EXIT_GDTR_IDTR_ACCESS:
12536 case VMX_EXIT_LDTR_TR_ACCESS:
12537 case VMX_EXIT_APIC_WRITE:
12538 case VMX_EXIT_RDRAND:
12539 case VMX_EXIT_RSM:
12540 case VMX_EXIT_VMFUNC:
12541 case VMX_EXIT_ENCLS:
12542 case VMX_EXIT_RDSEED:
12543 case VMX_EXIT_XSAVES:
12544 case VMX_EXIT_XRSTORS:
12545 case VMX_EXIT_UMWAIT:
12546 case VMX_EXIT_TPAUSE:
12547 default:
12548 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12549 }
12550#undef VMEXIT_CALL_RET
12551}
12552#endif /* !HMVMX_USE_FUNCTION_TABLE */
12553
12554
12555#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12556/**
12557 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12558 *
12559 * @returns Strict VBox status code (i.e. informational status codes too).
12560 * @param pVCpu The cross context virtual CPU structure.
12561 * @param pVmxTransient The VMX-transient structure.
12562 */
12563DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12564{
12565 /** @todo NSTVMX: Remove after debugging page-fault issue. */
12566#ifdef DEBUG_ramshankar
12567 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12568 Log4Func(("cs:rip=%#04x:%#RX64 rsp=%#RX64 eflags=%#RX32 cr3=%#RX64\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
12569 pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.u32, pVCpu->cpum.GstCtx.cr3));
12570#endif
12571
12572 uint32_t const uExitReason = pVmxTransient->uExitReason;
12573 switch (uExitReason)
12574 {
12575 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
12576 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
12577 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
12578 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
12579 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
12580
12581 /*
12582 * We shouldn't direct host physical interrupts to the nested-guest.
12583 */
12584 case VMX_EXIT_EXT_INT:
12585 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
12586
12587 /*
12588 * Instructions that cause VM-exits unconditionally or the condition is
12589 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12590 * happens, it's guaranteed to be a nested-guest VM-exit).
12591 *
12592 * - Provides VM-exit instruction length ONLY.
12593 */
12594 case VMX_EXIT_CPUID: /* Unconditional. */
12595 case VMX_EXIT_VMCALL:
12596 case VMX_EXIT_GETSEC:
12597 case VMX_EXIT_INVD:
12598 case VMX_EXIT_XSETBV:
12599 case VMX_EXIT_VMLAUNCH:
12600 case VMX_EXIT_VMRESUME:
12601 case VMX_EXIT_VMXOFF:
12602 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
12603 case VMX_EXIT_VMFUNC:
12604 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
12605
12606 /*
12607 * Instructions that cause VM-exits unconditionally or the condition is
12608 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12609 * happens, it's guaranteed to be a nested-guest VM-exit).
12610 *
12611 * - Provides VM-exit instruction length.
12612 * - Provides VM-exit information.
12613 * - Optionally provides Exit qualification.
12614 *
12615 * Since Exit qualification is 0 for all VM-exits where it is not
12616 * applicable, reading and passing it to the guest should produce
12617 * defined behavior.
12618 *
12619 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
12620 */
12621 case VMX_EXIT_INVEPT: /* Unconditional. */
12622 case VMX_EXIT_INVVPID:
12623 case VMX_EXIT_VMCLEAR:
12624 case VMX_EXIT_VMPTRLD:
12625 case VMX_EXIT_VMPTRST:
12626 case VMX_EXIT_VMXON:
12627 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
12628 case VMX_EXIT_LDTR_TR_ACCESS:
12629 case VMX_EXIT_RDRAND:
12630 case VMX_EXIT_RDSEED:
12631 case VMX_EXIT_XSAVES:
12632 case VMX_EXIT_XRSTORS:
12633 case VMX_EXIT_UMWAIT:
12634 case VMX_EXIT_TPAUSE:
12635 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
12636
12637 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
12638 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
12639 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
12640 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
12641 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
12642 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
12643 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
12644 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
12645 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
12646 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
12647 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
12648 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
12649 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
12650 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
12651 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
12652 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
12653 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
12654 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
12655 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
12656
12657 case VMX_EXIT_PREEMPT_TIMER:
12658 {
12659 /** @todo NSTVMX: Preempt timer. */
12660 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
12661 }
12662
12663 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
12664 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
12665
12666 case VMX_EXIT_VMREAD:
12667 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
12668
12669 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
12670 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
12671
12672 case VMX_EXIT_INIT_SIGNAL:
12673 case VMX_EXIT_SIPI:
12674 case VMX_EXIT_IO_SMI:
12675 case VMX_EXIT_SMI:
12676 case VMX_EXIT_ERR_MSR_LOAD:
12677 case VMX_EXIT_ERR_MACHINE_CHECK:
12678 case VMX_EXIT_PML_FULL:
12679 case VMX_EXIT_RSM:
12680 default:
12681 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12682 }
12683}
12684#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12685
12686
12687/** @name VM-exit helpers.
12688 * @{
12689 */
12690/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12691/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
12692/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12693
12694/** Macro for VM-exits called unexpectedly. */
12695#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
12696 do { \
12697 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
12698 return VERR_VMX_UNEXPECTED_EXIT; \
12699 } while (0)
12700
12701#ifdef VBOX_STRICT
12702/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
12703# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
12704 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
12705
12706# define HMVMX_ASSERT_PREEMPT_CPUID() \
12707 do { \
12708 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
12709 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
12710 } while (0)
12711
12712# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12713 do { \
12714 AssertPtr((a_pVCpu)); \
12715 AssertPtr((a_pVmxTransient)); \
12716 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
12717 Assert((a_pVmxTransient)->pVmcsInfo); \
12718 Assert(ASMIntAreEnabled()); \
12719 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12720 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
12721 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
12722 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12723 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
12724 HMVMX_ASSERT_PREEMPT_CPUID(); \
12725 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12726 } while (0)
12727
12728# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12729 do { \
12730 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
12731 Assert((a_pVmxTransient)->fIsNestedGuest); \
12732 } while (0)
12733
12734# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12735 do { \
12736 Log4Func(("\n")); \
12737 } while (0)
12738#else
12739# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12740 do { \
12741 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12742 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
12743 } while (0)
12744
12745# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12746 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
12747
12748# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
12749#endif
12750
12751#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12752/** Macro that does the necessary privilege checks and intercepted VM-exits for
12753 * guests that attempted to execute a VMX instruction. */
12754# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
12755 do \
12756 { \
12757 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
12758 if (rcStrictTmp == VINF_SUCCESS) \
12759 { /* likely */ } \
12760 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12761 { \
12762 Assert((a_pVCpu)->hm.s.Event.fPending); \
12763 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
12764 return VINF_SUCCESS; \
12765 } \
12766 else \
12767 { \
12768 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
12769 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
12770 } \
12771 } while (0)
12772
12773/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
12774# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
12775 do \
12776 { \
12777 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
12778 (a_pGCPtrEffAddr)); \
12779 if (rcStrictTmp == VINF_SUCCESS) \
12780 { /* likely */ } \
12781 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12782 { \
12783 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
12784 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
12785 NOREF(uXcptTmp); \
12786 return VINF_SUCCESS; \
12787 } \
12788 else \
12789 { \
12790 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
12791 return rcStrictTmp; \
12792 } \
12793 } while (0)
12794#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12795
12796
12797/**
12798 * Advances the guest RIP by the specified number of bytes.
12799 *
12800 * @param pVCpu The cross context virtual CPU structure.
12801 * @param cbInstr Number of bytes to advance the RIP by.
12802 *
12803 * @remarks No-long-jump zone!!!
12804 */
12805DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
12806{
12807 /* Advance the RIP. */
12808 pVCpu->cpum.GstCtx.rip += cbInstr;
12809 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
12810
12811 /* Update interrupt inhibition. */
12812 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
12813 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
12814 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
12815}
12816
12817
12818/**
12819 * Advances the guest RIP after reading it from the VMCS.
12820 *
12821 * @returns VBox status code, no informational status codes.
12822 * @param pVCpu The cross context virtual CPU structure.
12823 * @param pVmxTransient The VMX-transient structure.
12824 *
12825 * @remarks No-long-jump zone!!!
12826 */
12827static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12828{
12829 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
12830 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
12831 AssertRCReturn(rc, rc);
12832
12833 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
12834 return VINF_SUCCESS;
12835}
12836
12837
12838/**
12839 * Handle a condition that occurred while delivering an event through the guest or
12840 * nested-guest IDT.
12841 *
12842 * @returns Strict VBox status code (i.e. informational status codes too).
12843 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
12844 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
12845 * to continue execution of the guest which will delivery the \#DF.
12846 * @retval VINF_EM_RESET if we detected a triple-fault condition.
12847 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
12848 *
12849 * @param pVCpu The cross context virtual CPU structure.
12850 * @param pVmxTransient The VMX-transient structure.
12851 *
12852 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
12853 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
12854 * is due to an EPT violation, PML full or SPP-related event.
12855 *
12856 * @remarks No-long-jump zone!!!
12857 */
12858static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12859{
12860 Assert(!pVCpu->hm.s.Event.fPending);
12861 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
12862 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
12863 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
12864 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
12865 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
12866
12867 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
12868 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12869 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
12870 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
12871 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
12872 {
12873 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
12874 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
12875
12876 /*
12877 * If the event was a software interrupt (generated with INT n) or a software exception
12878 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
12879 * can handle the VM-exit and continue guest execution which will re-execute the
12880 * instruction rather than re-injecting the exception, as that can cause premature
12881 * trips to ring-3 before injection and involve TRPM which currently has no way of
12882 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
12883 * the problem).
12884 */
12885 IEMXCPTRAISE enmRaise;
12886 IEMXCPTRAISEINFO fRaiseInfo;
12887 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
12888 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
12889 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
12890 {
12891 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
12892 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12893 }
12894 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
12895 {
12896 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
12897 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
12898 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
12899
12900 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
12901 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
12902
12903 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
12904
12905 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
12906 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
12907 {
12908 pVmxTransient->fVectoringPF = true;
12909 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12910 }
12911 }
12912 else
12913 {
12914 /*
12915 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
12916 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
12917 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
12918 */
12919 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
12920 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12921 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
12922 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12923 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12924 }
12925
12926 /*
12927 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
12928 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
12929 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
12930 * subsequent VM-entry would fail, see @bugref{7445}.
12931 *
12932 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
12933 */
12934 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12935 && enmRaise == IEMXCPTRAISE_PREV_EVENT
12936 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
12937 && CPUMIsGuestNmiBlocking(pVCpu))
12938 {
12939 CPUMSetGuestNmiBlocking(pVCpu, false);
12940 }
12941
12942 switch (enmRaise)
12943 {
12944 case IEMXCPTRAISE_CURRENT_XCPT:
12945 {
12946 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
12947 Assert(rcStrict == VINF_SUCCESS);
12948 break;
12949 }
12950
12951 case IEMXCPTRAISE_PREV_EVENT:
12952 {
12953 uint32_t u32ErrCode;
12954 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
12955 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
12956 else
12957 u32ErrCode = 0;
12958
12959 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
12960 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
12961 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
12962 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
12963
12964 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
12965 pVCpu->hm.s.Event.u32ErrCode));
12966 Assert(rcStrict == VINF_SUCCESS);
12967 break;
12968 }
12969
12970 case IEMXCPTRAISE_REEXEC_INSTR:
12971 Assert(rcStrict == VINF_SUCCESS);
12972 break;
12973
12974 case IEMXCPTRAISE_DOUBLE_FAULT:
12975 {
12976 /*
12977 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
12978 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
12979 */
12980 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
12981 {
12982 pVmxTransient->fVectoringDoublePF = true;
12983 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
12984 pVCpu->cpum.GstCtx.cr2));
12985 rcStrict = VINF_SUCCESS;
12986 }
12987 else
12988 {
12989 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
12990 hmR0VmxSetPendingXcptDF(pVCpu);
12991 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
12992 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
12993 rcStrict = VINF_HM_DOUBLE_FAULT;
12994 }
12995 break;
12996 }
12997
12998 case IEMXCPTRAISE_TRIPLE_FAULT:
12999 {
13000 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13001 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13002 rcStrict = VINF_EM_RESET;
13003 break;
13004 }
13005
13006 case IEMXCPTRAISE_CPU_HANG:
13007 {
13008 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13009 rcStrict = VERR_EM_GUEST_CPU_HANG;
13010 break;
13011 }
13012
13013 default:
13014 {
13015 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13016 rcStrict = VERR_VMX_IPE_2;
13017 break;
13018 }
13019 }
13020 }
13021 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13022 && !CPUMIsGuestNmiBlocking(pVCpu))
13023 {
13024 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13025 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13026 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13027 {
13028 /*
13029 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13030 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13031 * that NMIs remain blocked until the IRET execution is completed.
13032 *
13033 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13034 */
13035 CPUMSetGuestNmiBlocking(pVCpu, true);
13036 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13037 }
13038 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13039 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13040 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13041 {
13042 /*
13043 * Execution of IRET caused an EPT violation, page-modification log-full event or
13044 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13045 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13046 * that NMIs remain blocked until the IRET execution is completed.
13047 *
13048 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13049 */
13050 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13051 {
13052 CPUMSetGuestNmiBlocking(pVCpu, true);
13053 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13054 }
13055 }
13056 }
13057
13058 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13059 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13060 return rcStrict;
13061}
13062
13063
13064#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13065/**
13066 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13067 * guest attempting to execute a VMX instruction.
13068 *
13069 * @returns Strict VBox status code (i.e. informational status codes too).
13070 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13071 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13072 *
13073 * @param pVCpu The cross context virtual CPU structure.
13074 * @param uExitReason The VM-exit reason.
13075 *
13076 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13077 * @remarks No-long-jump zone!!!
13078 */
13079static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13080{
13081 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13082 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13083
13084 /*
13085 * The physical CPU would have already checked the CPU mode/code segment.
13086 * We shall just assert here for paranoia.
13087 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13088 */
13089 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13090 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13091 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13092
13093 if (uExitReason == VMX_EXIT_VMXON)
13094 {
13095 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13096
13097 /*
13098 * We check CR4.VMXE because it is required to be always set while in VMX operation
13099 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13100 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13101 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13102 */
13103 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13104 {
13105 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13106 hmR0VmxSetPendingXcptUD(pVCpu);
13107 return VINF_HM_PENDING_XCPT;
13108 }
13109 }
13110 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13111 {
13112 /*
13113 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13114 * (other than VMXON), we need to raise a #UD.
13115 */
13116 Log4Func(("Not in VMX root mode -> #UD\n"));
13117 hmR0VmxSetPendingXcptUD(pVCpu);
13118 return VINF_HM_PENDING_XCPT;
13119 }
13120
13121 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13122 return VINF_SUCCESS;
13123}
13124
13125
13126/**
13127 * Decodes the memory operand of an instruction that caused a VM-exit.
13128 *
13129 * The Exit qualification field provides the displacement field for memory
13130 * operand instructions, if any.
13131 *
13132 * @returns Strict VBox status code (i.e. informational status codes too).
13133 * @retval VINF_SUCCESS if the operand was successfully decoded.
13134 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13135 * operand.
13136 * @param pVCpu The cross context virtual CPU structure.
13137 * @param uExitInstrInfo The VM-exit instruction information field.
13138 * @param enmMemAccess The memory operand's access type (read or write).
13139 * @param GCPtrDisp The instruction displacement field, if any. For
13140 * RIP-relative addressing pass RIP + displacement here.
13141 * @param pGCPtrMem Where to store the effective destination memory address.
13142 *
13143 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13144 * virtual-8086 mode hence skips those checks while verifying if the
13145 * segment is valid.
13146 */
13147static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13148 PRTGCPTR pGCPtrMem)
13149{
13150 Assert(pGCPtrMem);
13151 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13152 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13153 | CPUMCTX_EXTRN_CR0);
13154
13155 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13156 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13157 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13158
13159 VMXEXITINSTRINFO ExitInstrInfo;
13160 ExitInstrInfo.u = uExitInstrInfo;
13161 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13162 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13163 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13164 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13165 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13166 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13167 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13168 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13169 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13170
13171 /*
13172 * Validate instruction information.
13173 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13174 */
13175 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13176 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13177 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13178 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13179 AssertLogRelMsgReturn(fIsMemOperand,
13180 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13181
13182 /*
13183 * Compute the complete effective address.
13184 *
13185 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13186 * See AMD spec. 4.5.2 "Segment Registers".
13187 */
13188 RTGCPTR GCPtrMem = GCPtrDisp;
13189 if (fBaseRegValid)
13190 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13191 if (fIdxRegValid)
13192 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13193
13194 RTGCPTR const GCPtrOff = GCPtrMem;
13195 if ( !fIsLongMode
13196 || iSegReg >= X86_SREG_FS)
13197 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13198 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13199
13200 /*
13201 * Validate effective address.
13202 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13203 */
13204 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13205 Assert(cbAccess > 0);
13206 if (fIsLongMode)
13207 {
13208 if (X86_IS_CANONICAL(GCPtrMem))
13209 {
13210 *pGCPtrMem = GCPtrMem;
13211 return VINF_SUCCESS;
13212 }
13213
13214 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13215 * "Data Limit Checks in 64-bit Mode". */
13216 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13217 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13218 return VINF_HM_PENDING_XCPT;
13219 }
13220
13221 /*
13222 * This is a watered down version of iemMemApplySegment().
13223 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13224 * and segment CPL/DPL checks are skipped.
13225 */
13226 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13227 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13228 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13229
13230 /* Check if the segment is present and usable. */
13231 if ( pSel->Attr.n.u1Present
13232 && !pSel->Attr.n.u1Unusable)
13233 {
13234 Assert(pSel->Attr.n.u1DescType);
13235 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13236 {
13237 /* Check permissions for the data segment. */
13238 if ( enmMemAccess == VMXMEMACCESS_WRITE
13239 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13240 {
13241 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13242 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13243 return VINF_HM_PENDING_XCPT;
13244 }
13245
13246 /* Check limits if it's a normal data segment. */
13247 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13248 {
13249 if ( GCPtrFirst32 > pSel->u32Limit
13250 || GCPtrLast32 > pSel->u32Limit)
13251 {
13252 Log4Func(("Data segment limit exceeded. "
13253 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13254 GCPtrLast32, pSel->u32Limit));
13255 if (iSegReg == X86_SREG_SS)
13256 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13257 else
13258 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13259 return VINF_HM_PENDING_XCPT;
13260 }
13261 }
13262 else
13263 {
13264 /* Check limits if it's an expand-down data segment.
13265 Note! The upper boundary is defined by the B bit, not the G bit! */
13266 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13267 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13268 {
13269 Log4Func(("Expand-down data segment limit exceeded. "
13270 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13271 GCPtrLast32, pSel->u32Limit));
13272 if (iSegReg == X86_SREG_SS)
13273 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13274 else
13275 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13276 return VINF_HM_PENDING_XCPT;
13277 }
13278 }
13279 }
13280 else
13281 {
13282 /* Check permissions for the code segment. */
13283 if ( enmMemAccess == VMXMEMACCESS_WRITE
13284 || ( enmMemAccess == VMXMEMACCESS_READ
13285 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13286 {
13287 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13288 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13289 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13290 return VINF_HM_PENDING_XCPT;
13291 }
13292
13293 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13294 if ( GCPtrFirst32 > pSel->u32Limit
13295 || GCPtrLast32 > pSel->u32Limit)
13296 {
13297 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13298 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13299 if (iSegReg == X86_SREG_SS)
13300 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13301 else
13302 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13303 return VINF_HM_PENDING_XCPT;
13304 }
13305 }
13306 }
13307 else
13308 {
13309 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13310 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13311 return VINF_HM_PENDING_XCPT;
13312 }
13313
13314 *pGCPtrMem = GCPtrMem;
13315 return VINF_SUCCESS;
13316}
13317#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13318
13319
13320/**
13321 * VM-exit helper for LMSW.
13322 */
13323static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13324{
13325 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13326 AssertRCReturn(rc, rc);
13327
13328 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13329 AssertMsg( rcStrict == VINF_SUCCESS
13330 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13331
13332 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13333 if (rcStrict == VINF_IEM_RAISED_XCPT)
13334 {
13335 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13336 rcStrict = VINF_SUCCESS;
13337 }
13338
13339 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13340 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13341 return rcStrict;
13342}
13343
13344
13345/**
13346 * VM-exit helper for CLTS.
13347 */
13348static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13349{
13350 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13351 AssertRCReturn(rc, rc);
13352
13353 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13354 AssertMsg( rcStrict == VINF_SUCCESS
13355 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13356
13357 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13358 if (rcStrict == VINF_IEM_RAISED_XCPT)
13359 {
13360 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13361 rcStrict = VINF_SUCCESS;
13362 }
13363
13364 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13365 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13366 return rcStrict;
13367}
13368
13369
13370/**
13371 * VM-exit helper for MOV from CRx (CRx read).
13372 */
13373static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13374{
13375 Assert(iCrReg < 16);
13376 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13377
13378 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13379 AssertRCReturn(rc, rc);
13380
13381 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13382 AssertMsg( rcStrict == VINF_SUCCESS
13383 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13384
13385 if (iGReg == X86_GREG_xSP)
13386 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13387 else
13388 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13389#ifdef VBOX_WITH_STATISTICS
13390 switch (iCrReg)
13391 {
13392 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13393 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13394 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13395 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13396 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13397 }
13398#endif
13399 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13400 return rcStrict;
13401}
13402
13403
13404/**
13405 * VM-exit helper for MOV to CRx (CRx write).
13406 */
13407static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13408{
13409 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13410 AssertRCReturn(rc, rc);
13411
13412 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13413 AssertMsg( rcStrict == VINF_SUCCESS
13414 || rcStrict == VINF_IEM_RAISED_XCPT
13415 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13416
13417 switch (iCrReg)
13418 {
13419 case 0:
13420 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13421 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13422 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13423 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13424 break;
13425
13426 case 2:
13427 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13428 /* Nothing to do here, CR2 it's not part of the VMCS. */
13429 break;
13430
13431 case 3:
13432 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13433 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13434 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13435 break;
13436
13437 case 4:
13438 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13439 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13440 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13441 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13442 break;
13443
13444 case 8:
13445 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13446 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13447 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13448 break;
13449
13450 default:
13451 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13452 break;
13453 }
13454
13455 if (rcStrict == VINF_IEM_RAISED_XCPT)
13456 {
13457 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13458 rcStrict = VINF_SUCCESS;
13459 }
13460 return rcStrict;
13461}
13462
13463
13464/**
13465 * VM-exit exception handler for \#PF (Page-fault exception).
13466 *
13467 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13468 */
13469static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13470{
13471 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13472 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13473 hmR0VmxReadExitQualVmcs(pVmxTransient);
13474
13475 if (!pVM->hm.s.fNestedPaging)
13476 { /* likely */ }
13477 else
13478 {
13479#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13480 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
13481#endif
13482 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13483 if (!pVmxTransient->fVectoringDoublePF)
13484 {
13485 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13486 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13487 }
13488 else
13489 {
13490 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13491 Assert(!pVmxTransient->fIsNestedGuest);
13492 hmR0VmxSetPendingXcptDF(pVCpu);
13493 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13494 }
13495 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13496 return VINF_SUCCESS;
13497 }
13498
13499 Assert(!pVmxTransient->fIsNestedGuest);
13500
13501 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13502 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13503 if (pVmxTransient->fVectoringPF)
13504 {
13505 Assert(pVCpu->hm.s.Event.fPending);
13506 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13507 }
13508
13509 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13510 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13511 AssertRCReturn(rc, rc);
13512
13513 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13514 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13515
13516 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13517 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13518
13519 Log4Func(("#PF: rc=%Rrc\n", rc));
13520 if (rc == VINF_SUCCESS)
13521 {
13522 /*
13523 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13524 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13525 */
13526 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13527 TRPMResetTrap(pVCpu);
13528 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13529 return rc;
13530 }
13531
13532 if (rc == VINF_EM_RAW_GUEST_TRAP)
13533 {
13534 if (!pVmxTransient->fVectoringDoublePF)
13535 {
13536 /* It's a guest page fault and needs to be reflected to the guest. */
13537 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
13538 TRPMResetTrap(pVCpu);
13539 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13540 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13541 uGstErrorCode, pVmxTransient->uExitQual);
13542 }
13543 else
13544 {
13545 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13546 TRPMResetTrap(pVCpu);
13547 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
13548 hmR0VmxSetPendingXcptDF(pVCpu);
13549 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
13550 }
13551
13552 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13553 return VINF_SUCCESS;
13554 }
13555
13556 TRPMResetTrap(pVCpu);
13557 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
13558 return rc;
13559}
13560
13561
13562/**
13563 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
13564 *
13565 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13566 */
13567static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13568{
13569 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13570 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
13571
13572 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
13573 AssertRCReturn(rc, rc);
13574
13575 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
13576 {
13577 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
13578 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
13579
13580 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
13581 * provides VM-exit instruction length. If this causes problem later,
13582 * disassemble the instruction like it's done on AMD-V. */
13583 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13584 AssertRCReturn(rc2, rc2);
13585 return rc;
13586 }
13587
13588 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
13589 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13590 return VINF_SUCCESS;
13591}
13592
13593
13594/**
13595 * VM-exit exception handler for \#BP (Breakpoint exception).
13596 *
13597 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13598 */
13599static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13600{
13601 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13602 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
13603
13604 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13605 AssertRCReturn(rc, rc);
13606
13607 if (!pVmxTransient->fIsNestedGuest)
13608 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
13609 else
13610 rc = VINF_EM_RAW_GUEST_TRAP;
13611
13612 if (rc == VINF_EM_RAW_GUEST_TRAP)
13613 {
13614 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13615 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13616 rc = VINF_SUCCESS;
13617 }
13618
13619 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
13620 return rc;
13621}
13622
13623
13624/**
13625 * VM-exit exception handler for \#AC (Alignment-check exception).
13626 *
13627 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13628 */
13629static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13630{
13631 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13632 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
13633
13634 /* Re-inject it. We'll detect any nesting before getting here. */
13635 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13636 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13637 return VINF_SUCCESS;
13638}
13639
13640
13641/**
13642 * VM-exit exception handler for \#DB (Debug exception).
13643 *
13644 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13645 */
13646static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13647{
13648 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13649 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
13650
13651 /*
13652 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
13653 */
13654 hmR0VmxReadExitQualVmcs(pVmxTransient);
13655
13656 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
13657 uint64_t const uDR6 = X86_DR6_INIT_VAL
13658 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
13659 | X86_DR6_BD | X86_DR6_BS));
13660
13661 int rc;
13662 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13663 if (!pVmxTransient->fIsNestedGuest)
13664 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
13665 else
13666 rc = VINF_EM_RAW_GUEST_TRAP;
13667 Log6Func(("rc=%Rrc\n", rc));
13668 if (rc == VINF_EM_RAW_GUEST_TRAP)
13669 {
13670 /*
13671 * The exception was for the guest. Update DR6, DR7.GD and
13672 * IA32_DEBUGCTL.LBR before forwarding it.
13673 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
13674 */
13675 VMMRZCallRing3Disable(pVCpu);
13676 HM_DISABLE_PREEMPT(pVCpu);
13677
13678 pCtx->dr[6] &= ~X86_DR6_B_MASK;
13679 pCtx->dr[6] |= uDR6;
13680 if (CPUMIsGuestDebugStateActive(pVCpu))
13681 ASMSetDR6(pCtx->dr[6]);
13682
13683 HM_RESTORE_PREEMPT();
13684 VMMRZCallRing3Enable(pVCpu);
13685
13686 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
13687 AssertRCReturn(rc, rc);
13688
13689 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
13690 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
13691
13692 /* Paranoia. */
13693 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
13694 pCtx->dr[7] |= X86_DR7_RA1_MASK;
13695
13696 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
13697 AssertRC(rc);
13698
13699 /*
13700 * Raise #DB in the guest.
13701 *
13702 * It is important to reflect exactly what the VM-exit gave us (preserving the
13703 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
13704 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
13705 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
13706 *
13707 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
13708 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
13709 */
13710 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13711 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13712 return VINF_SUCCESS;
13713 }
13714
13715 /*
13716 * Not a guest trap, must be a hypervisor related debug event then.
13717 * Update DR6 in case someone is interested in it.
13718 */
13719 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
13720 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
13721 CPUMSetHyperDR6(pVCpu, uDR6);
13722
13723 return rc;
13724}
13725
13726
13727/**
13728 * Hacks its way around the lovely mesa driver's backdoor accesses.
13729 *
13730 * @sa hmR0SvmHandleMesaDrvGp.
13731 */
13732static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13733{
13734 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
13735 RT_NOREF(pCtx);
13736
13737 /* For now we'll just skip the instruction. */
13738 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13739}
13740
13741
13742/**
13743 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
13744 * backdoor logging w/o checking what it is running inside.
13745 *
13746 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
13747 * backdoor port and magic numbers loaded in registers.
13748 *
13749 * @returns true if it is, false if it isn't.
13750 * @sa hmR0SvmIsMesaDrvGp.
13751 */
13752DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13753{
13754 /* 0xed: IN eAX,dx */
13755 uint8_t abInstr[1];
13756 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
13757 return false;
13758
13759 /* Check that it is #GP(0). */
13760 if (pVmxTransient->uExitIntErrorCode != 0)
13761 return false;
13762
13763 /* Check magic and port. */
13764 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
13765 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
13766 if (pCtx->rax != UINT32_C(0x564d5868))
13767 return false;
13768 if (pCtx->dx != UINT32_C(0x5658))
13769 return false;
13770
13771 /* Flat ring-3 CS. */
13772 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
13773 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
13774 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
13775 if (pCtx->cs.Attr.n.u2Dpl != 3)
13776 return false;
13777 if (pCtx->cs.u64Base != 0)
13778 return false;
13779
13780 /* Check opcode. */
13781 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
13782 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
13783 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
13784 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
13785 if (RT_FAILURE(rc))
13786 return false;
13787 if (abInstr[0] != 0xed)
13788 return false;
13789
13790 return true;
13791}
13792
13793
13794/**
13795 * VM-exit exception handler for \#GP (General-protection exception).
13796 *
13797 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13798 */
13799static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13800{
13801 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13802 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
13803
13804 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13805 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13806 if (pVmcsInfo->RealMode.fRealOnV86Active)
13807 { /* likely */ }
13808 else
13809 {
13810#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13811 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
13812#endif
13813 /*
13814 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
13815 * executing a nested-guest, reflect #GP to the guest or nested-guest.
13816 */
13817 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13818 AssertRCReturn(rc, rc);
13819 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
13820 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
13821
13822 if ( pVmxTransient->fIsNestedGuest
13823 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
13824 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
13825 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13826 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13827 else
13828 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
13829 return rc;
13830 }
13831
13832 Assert(CPUMIsGuestInRealModeEx(pCtx));
13833 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
13834 Assert(!pVmxTransient->fIsNestedGuest);
13835
13836 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13837 AssertRCReturn(rc, rc);
13838
13839 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
13840 if (rcStrict == VINF_SUCCESS)
13841 {
13842 if (!CPUMIsGuestInRealModeEx(pCtx))
13843 {
13844 /*
13845 * The guest is no longer in real-mode, check if we can continue executing the
13846 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
13847 */
13848 pVmcsInfo->RealMode.fRealOnV86Active = false;
13849 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
13850 {
13851 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
13852 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13853 }
13854 else
13855 {
13856 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
13857 rcStrict = VINF_EM_RESCHEDULE;
13858 }
13859 }
13860 else
13861 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13862 }
13863 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13864 {
13865 rcStrict = VINF_SUCCESS;
13866 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13867 }
13868 return VBOXSTRICTRC_VAL(rcStrict);
13869}
13870
13871
13872/**
13873 * VM-exit exception handler wrapper for all other exceptions that are not handled
13874 * by a specific handler.
13875 *
13876 * This simply re-injects the exception back into the VM without any special
13877 * processing.
13878 *
13879 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13880 */
13881static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13882{
13883 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13884
13885#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13886 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13887 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
13888 ("uVector=%#x u32XcptBitmap=%#X32\n",
13889 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
13890 NOREF(pVmcsInfo);
13891#endif
13892
13893 /*
13894 * Re-inject the exception into the guest. This cannot be a double-fault condition which
13895 * would have been handled while checking exits due to event delivery.
13896 */
13897 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13898
13899#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13900 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
13901 AssertRCReturn(rc, rc);
13902 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
13903#endif
13904
13905#ifdef VBOX_WITH_STATISTICS
13906 switch (uVector)
13907 {
13908 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
13909 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
13910 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
13911 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13912 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
13913 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
13914 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13915 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
13916 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
13917 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
13918 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
13919 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
13920 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
13921 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
13922 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
13923 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
13924 default:
13925 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
13926 break;
13927 }
13928#endif
13929
13930 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
13931 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
13932 NOREF(uVector);
13933
13934 /* Re-inject the original exception into the guest. */
13935 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13936 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13937 return VINF_SUCCESS;
13938}
13939
13940
13941/**
13942 * VM-exit exception handler for all exceptions (except NMIs!).
13943 *
13944 * @remarks This may be called for both guests and nested-guests. Take care to not
13945 * make assumptions and avoid doing anything that is not relevant when
13946 * executing a nested-guest (e.g., Mesa driver hacks).
13947 */
13948static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13949{
13950 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13951
13952 /*
13953 * If this VM-exit occurred while delivering an event through the guest IDT, take
13954 * action based on the return code and additional hints (e.g. for page-faults)
13955 * that will be updated in the VMX transient structure.
13956 */
13957 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
13958 if (rcStrict == VINF_SUCCESS)
13959 {
13960 /*
13961 * If an exception caused a VM-exit due to delivery of an event, the original
13962 * event may have to be re-injected into the guest. We shall reinject it and
13963 * continue guest execution. However, page-fault is a complicated case and
13964 * needs additional processing done in hmR0VmxExitXcptPF().
13965 */
13966 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
13967 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13968 if ( !pVCpu->hm.s.Event.fPending
13969 || uVector == X86_XCPT_PF)
13970 {
13971 switch (uVector)
13972 {
13973 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
13974 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
13975 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
13976 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
13977 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
13978 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
13979 default:
13980 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
13981 }
13982 }
13983 /* else: inject pending event before resuming guest execution. */
13984 }
13985 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
13986 {
13987 Assert(pVCpu->hm.s.Event.fPending);
13988 rcStrict = VINF_SUCCESS;
13989 }
13990
13991 return rcStrict;
13992}
13993/** @} */
13994
13995
13996/** @name VM-exit handlers.
13997 * @{
13998 */
13999/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14000/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14001/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14002
14003/**
14004 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14005 */
14006HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14007{
14008 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14009 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14010 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14011 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14012 return VINF_SUCCESS;
14013 return VINF_EM_RAW_INTERRUPT;
14014}
14015
14016
14017/**
14018 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14019 * VM-exit.
14020 */
14021HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14022{
14023 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14024 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14025
14026 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14027
14028 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14029 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14030 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14031
14032 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14033 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14034 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14035 NOREF(pVmcsInfo);
14036
14037 VBOXSTRICTRC rcStrict;
14038 switch (uExitIntType)
14039 {
14040 /*
14041 * Host physical NMIs:
14042 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14043 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14044 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14045 *
14046 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14047 * See Intel spec. 27.5.5 "Updating Non-Register State".
14048 */
14049 case VMX_EXIT_INT_INFO_TYPE_NMI:
14050 {
14051 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14052 break;
14053 }
14054
14055 /*
14056 * Privileged software exceptions (#DB from ICEBP),
14057 * Software exceptions (#BP and #OF),
14058 * Hardware exceptions:
14059 * Process the required exceptions and resume guest execution if possible.
14060 */
14061 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14062 Assert(uVector == X86_XCPT_DB);
14063 RT_FALL_THRU();
14064 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14065 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14066 RT_FALL_THRU();
14067 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14068 {
14069 NOREF(uVector);
14070 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14071 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14072 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14073 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14074
14075 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14076 break;
14077 }
14078
14079 default:
14080 {
14081 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14082 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14083 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14084 break;
14085 }
14086 }
14087
14088 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14089 return rcStrict;
14090}
14091
14092
14093/**
14094 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14095 */
14096HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14097{
14098 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14099
14100 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14101 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14102 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14103
14104 /* Evaluate and deliver pending events and resume guest execution. */
14105 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14106 return VINF_SUCCESS;
14107}
14108
14109
14110/**
14111 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14112 */
14113HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14114{
14115 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14116
14117 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14118 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14119 {
14120 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14121 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14122 }
14123
14124 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14125
14126 /*
14127 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14128 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14129 */
14130 uint32_t fIntrState;
14131 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14132 AssertRC(rc);
14133 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14134 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14135 {
14136 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14137 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14138
14139 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14140 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14141 AssertRC(rc);
14142 }
14143
14144 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14145 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14146
14147 /* Evaluate and deliver pending events and resume guest execution. */
14148 return VINF_SUCCESS;
14149}
14150
14151
14152/**
14153 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14154 */
14155HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14156{
14157 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14158 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14159}
14160
14161
14162/**
14163 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14164 */
14165HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14166{
14167 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14168 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14169}
14170
14171
14172/**
14173 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14174 */
14175HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14176{
14177 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14178
14179 /*
14180 * Get the state we need and update the exit history entry.
14181 */
14182 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14183 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14184
14185 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14186 AssertRCReturn(rc, rc);
14187
14188 VBOXSTRICTRC rcStrict;
14189 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14190 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14191 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14192 if (!pExitRec)
14193 {
14194 /*
14195 * Regular CPUID instruction execution.
14196 */
14197 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14198 if (rcStrict == VINF_SUCCESS)
14199 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14200 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14201 {
14202 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14203 rcStrict = VINF_SUCCESS;
14204 }
14205 }
14206 else
14207 {
14208 /*
14209 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14210 */
14211 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14212 AssertRCReturn(rc2, rc2);
14213
14214 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14215 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14216
14217 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14218 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14219
14220 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14221 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14222 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14223 }
14224 return rcStrict;
14225}
14226
14227
14228/**
14229 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14230 */
14231HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14232{
14233 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14234
14235 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14236 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14237 AssertRCReturn(rc, rc);
14238
14239 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14240 return VINF_EM_RAW_EMULATE_INSTR;
14241
14242 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14243 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14244}
14245
14246
14247/**
14248 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14249 */
14250HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14251{
14252 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14253
14254 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14255 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14256 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14257 AssertRCReturn(rc, rc);
14258
14259 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14260 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14261 {
14262 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14263 we must reset offsetting on VM-entry. See @bugref{6634}. */
14264 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14265 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14266 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14267 }
14268 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14269 {
14270 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14271 rcStrict = VINF_SUCCESS;
14272 }
14273 return rcStrict;
14274}
14275
14276
14277/**
14278 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14279 */
14280HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14281{
14282 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14283
14284 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14285 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14286 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14287 AssertRCReturn(rc, rc);
14288
14289 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14290 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14291 {
14292 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14293 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14294 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14295 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14296 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14297 }
14298 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14299 {
14300 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14301 rcStrict = VINF_SUCCESS;
14302 }
14303 return rcStrict;
14304}
14305
14306
14307/**
14308 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14309 */
14310HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14311{
14312 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14313
14314 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14315 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14316 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14317 AssertRCReturn(rc, rc);
14318
14319 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14320 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14321 if (RT_LIKELY(rc == VINF_SUCCESS))
14322 {
14323 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14324 Assert(pVmxTransient->cbExitInstr == 2);
14325 }
14326 else
14327 {
14328 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14329 rc = VERR_EM_INTERPRETER;
14330 }
14331 return rc;
14332}
14333
14334
14335/**
14336 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14337 */
14338HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14339{
14340 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14341
14342 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14343 if (EMAreHypercallInstructionsEnabled(pVCpu))
14344 {
14345 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14346 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14347 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14348 AssertRCReturn(rc, rc);
14349
14350 /* Perform the hypercall. */
14351 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14352 if (rcStrict == VINF_SUCCESS)
14353 {
14354 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14355 AssertRCReturn(rc, rc);
14356 }
14357 else
14358 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14359 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14360 || RT_FAILURE(rcStrict));
14361
14362 /* If the hypercall changes anything other than guest's general-purpose registers,
14363 we would need to reload the guest changed bits here before VM-entry. */
14364 }
14365 else
14366 Log4Func(("Hypercalls not enabled\n"));
14367
14368 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14369 if (RT_FAILURE(rcStrict))
14370 {
14371 hmR0VmxSetPendingXcptUD(pVCpu);
14372 rcStrict = VINF_SUCCESS;
14373 }
14374
14375 return rcStrict;
14376}
14377
14378
14379/**
14380 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14381 */
14382HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14383{
14384 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14385 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
14386
14387 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14388 hmR0VmxReadExitQualVmcs(pVmxTransient);
14389 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14390 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14391 AssertRCReturn(rc, rc);
14392
14393 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14394
14395 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14396 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14397 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14398 {
14399 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14400 rcStrict = VINF_SUCCESS;
14401 }
14402 else
14403 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14404 VBOXSTRICTRC_VAL(rcStrict)));
14405 return rcStrict;
14406}
14407
14408
14409/**
14410 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14411 */
14412HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14413{
14414 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14415
14416 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14417 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14418 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14419 AssertRCReturn(rc, rc);
14420
14421 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14422 if (rcStrict == VINF_SUCCESS)
14423 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14424 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14425 {
14426 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14427 rcStrict = VINF_SUCCESS;
14428 }
14429
14430 return rcStrict;
14431}
14432
14433
14434/**
14435 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14436 */
14437HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14438{
14439 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14440
14441 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14442 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14443 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14444 AssertRCReturn(rc, rc);
14445
14446 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14447 if (RT_SUCCESS(rcStrict))
14448 {
14449 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14450 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14451 rcStrict = VINF_SUCCESS;
14452 }
14453
14454 return rcStrict;
14455}
14456
14457
14458/**
14459 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14460 * VM-exit.
14461 */
14462HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14463{
14464 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14465 return VINF_EM_RESET;
14466}
14467
14468
14469/**
14470 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14471 */
14472HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14473{
14474 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14475
14476 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14477 AssertRCReturn(rc, rc);
14478
14479 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14480 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14481 rc = VINF_SUCCESS;
14482 else
14483 rc = VINF_EM_HALT;
14484
14485 if (rc != VINF_SUCCESS)
14486 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14487 return rc;
14488}
14489
14490
14491/**
14492 * VM-exit handler for instructions that result in a \#UD exception delivered to
14493 * the guest.
14494 */
14495HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14496{
14497 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14498 hmR0VmxSetPendingXcptUD(pVCpu);
14499 return VINF_SUCCESS;
14500}
14501
14502
14503/**
14504 * VM-exit handler for expiry of the VMX-preemption timer.
14505 */
14506HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14507{
14508 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14509
14510 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14511 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14512
14513 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14514 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14515 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14516 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14517 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14518}
14519
14520
14521/**
14522 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14523 */
14524HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14525{
14526 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14527
14528 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14529 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14530 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
14531 AssertRCReturn(rc, rc);
14532
14533 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
14534 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14535 : HM_CHANGED_RAISED_XCPT_MASK);
14536
14537 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14538 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
14539
14540 return rcStrict;
14541}
14542
14543
14544/**
14545 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
14546 */
14547HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14548{
14549 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14550
14551#if 1
14552 /** @todo Use VM-exit instruction information. */
14553 return VERR_EM_INTERPRETER;
14554#else
14555 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14556 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
14557 hmR0VmxReadExitQualVmcs(pVmxTransient);
14558 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
14559 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14560 AssertRCReturn(rc, rc);
14561
14562 /* Paranoia. Ensure this has a memory operand. */
14563 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
14564
14565 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
14566 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14567 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
14568 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
14569
14570 RTGCPTR GCPtrDesc;
14571 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
14572
14573 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
14574 GCPtrDesc, uType);
14575 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14576 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14577 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14578 {
14579 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14580 rcStrict = VINF_SUCCESS;
14581 }
14582 return rcStrict;
14583#endif
14584}
14585
14586
14587/**
14588 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
14589 * VM-exit.
14590 */
14591HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14592{
14593 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14594 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14595 AssertRCReturn(rc, rc);
14596
14597 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
14598 if (RT_FAILURE(rc))
14599 return rc;
14600
14601 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
14602 NOREF(uInvalidReason);
14603
14604#ifdef VBOX_STRICT
14605 uint32_t fIntrState;
14606 uint64_t u64Val;
14607 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
14608 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
14609 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
14610
14611 Log4(("uInvalidReason %u\n", uInvalidReason));
14612 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
14613 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
14614 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
14615
14616 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
14617 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
14618 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
14619 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
14620 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
14621 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
14622 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
14623 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14624 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
14625 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
14626 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
14627 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14628 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
14629 {
14630 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
14631 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
14632 }
14633 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
14634#endif
14635
14636 return VERR_VMX_INVALID_GUEST_STATE;
14637}
14638
14639/**
14640 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
14641 */
14642HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14643{
14644 /*
14645 * Cumulative notes of all recognized but unexpected VM-exits.
14646 *
14647 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
14648 * nested-paging is used.
14649 *
14650 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
14651 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
14652 * this function (and thereby stop VM execution) for handling such instructions.
14653 *
14654 *
14655 * VMX_EXIT_INIT_SIGNAL:
14656 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
14657 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
14658 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
14659 *
14660 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
14661 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
14662 * See Intel spec. "23.8 Restrictions on VMX operation".
14663 *
14664 * VMX_EXIT_SIPI:
14665 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
14666 * activity state is used. We don't make use of it as our guests don't have direct
14667 * access to the host local APIC.
14668 *
14669 * See Intel spec. 25.3 "Other Causes of VM-exits".
14670 *
14671 * VMX_EXIT_IO_SMI:
14672 * VMX_EXIT_SMI:
14673 * This can only happen if we support dual-monitor treatment of SMI, which can be
14674 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
14675 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
14676 * VMX root mode or receive an SMI. If we get here, something funny is going on.
14677 *
14678 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
14679 * See Intel spec. 25.3 "Other Causes of VM-Exits"
14680 *
14681 * VMX_EXIT_ERR_MSR_LOAD:
14682 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
14683 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
14684 * execution.
14685 *
14686 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
14687 *
14688 * VMX_EXIT_ERR_MACHINE_CHECK:
14689 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
14690 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
14691 * #MC exception abort class exception is raised. We thus cannot assume a
14692 * reasonable chance of continuing any sort of execution and we bail.
14693 *
14694 * See Intel spec. 15.1 "Machine-check Architecture".
14695 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
14696 *
14697 * VMX_EXIT_PML_FULL:
14698 * VMX_EXIT_VIRTUALIZED_EOI:
14699 * VMX_EXIT_APIC_WRITE:
14700 * We do not currently support any of these features and thus they are all unexpected
14701 * VM-exits.
14702 *
14703 * VMX_EXIT_GDTR_IDTR_ACCESS:
14704 * VMX_EXIT_LDTR_TR_ACCESS:
14705 * VMX_EXIT_RDRAND:
14706 * VMX_EXIT_RSM:
14707 * VMX_EXIT_VMFUNC:
14708 * VMX_EXIT_ENCLS:
14709 * VMX_EXIT_RDSEED:
14710 * VMX_EXIT_XSAVES:
14711 * VMX_EXIT_XRSTORS:
14712 * VMX_EXIT_UMWAIT:
14713 * VMX_EXIT_TPAUSE:
14714 * These VM-exits are -not- caused unconditionally by execution of the corresponding
14715 * instruction. Any VM-exit for these instructions indicate a hardware problem,
14716 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
14717 *
14718 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
14719 */
14720 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14721 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
14722 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14723}
14724
14725
14726/**
14727 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
14728 */
14729HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14730{
14731 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14732
14733 /** @todo Optimize this: We currently drag in the whole MSR state
14734 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14735 * MSRs required. That would require changes to IEM and possibly CPUM too.
14736 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14737 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14738 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14739 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14740 switch (idMsr)
14741 {
14742 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14743 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14744 }
14745
14746 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14747 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14748 AssertRCReturn(rc, rc);
14749
14750 Log4Func(("ecx=%#RX32\n", idMsr));
14751
14752#ifdef VBOX_STRICT
14753 Assert(!pVmxTransient->fIsNestedGuest);
14754 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
14755 {
14756 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
14757 && idMsr != MSR_K6_EFER)
14758 {
14759 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
14760 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14761 }
14762 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14763 {
14764 Assert(pVmcsInfo->pvMsrBitmap);
14765 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14766 if (fMsrpm & VMXMSRPM_ALLOW_RD)
14767 {
14768 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
14769 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14770 }
14771 }
14772 }
14773#endif
14774
14775 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
14776 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
14777 if (rcStrict == VINF_SUCCESS)
14778 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14779 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14780 {
14781 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14782 rcStrict = VINF_SUCCESS;
14783 }
14784 else
14785 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14786
14787 return rcStrict;
14788}
14789
14790
14791/**
14792 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
14793 */
14794HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14795{
14796 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14797
14798 /** @todo Optimize this: We currently drag in the whole MSR state
14799 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14800 * MSRs required. That would require changes to IEM and possibly CPUM too.
14801 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14802 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14803 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14804
14805 /*
14806 * The FS and GS base MSRs are not part of the above all-MSRs mask.
14807 * Although we don't need to fetch the base as it will be overwritten shortly, while
14808 * loading guest-state we would also load the entire segment register including limit
14809 * and attributes and thus we need to load them here.
14810 */
14811 switch (idMsr)
14812 {
14813 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14814 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14815 }
14816
14817 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14818 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14819 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14820 AssertRCReturn(rc, rc);
14821
14822 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
14823
14824 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
14825 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
14826
14827 if (rcStrict == VINF_SUCCESS)
14828 {
14829 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14830
14831 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
14832 if ( idMsr == MSR_IA32_APICBASE
14833 || ( idMsr >= MSR_IA32_X2APIC_START
14834 && idMsr <= MSR_IA32_X2APIC_END))
14835 {
14836 /*
14837 * We've already saved the APIC related guest-state (TPR) in post-run phase.
14838 * When full APIC register virtualization is implemented we'll have to make
14839 * sure APIC state is saved from the VMCS before IEM changes it.
14840 */
14841 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
14842 }
14843 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
14844 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14845 else if (idMsr == MSR_K6_EFER)
14846 {
14847 /*
14848 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
14849 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
14850 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
14851 */
14852 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
14853 }
14854
14855 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
14856 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
14857 {
14858 switch (idMsr)
14859 {
14860 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
14861 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
14862 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
14863 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
14864 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
14865 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
14866 default:
14867 {
14868 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14869 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
14870 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14871 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
14872 break;
14873 }
14874 }
14875 }
14876#ifdef VBOX_STRICT
14877 else
14878 {
14879 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
14880 switch (idMsr)
14881 {
14882 case MSR_IA32_SYSENTER_CS:
14883 case MSR_IA32_SYSENTER_EIP:
14884 case MSR_IA32_SYSENTER_ESP:
14885 case MSR_K8_FS_BASE:
14886 case MSR_K8_GS_BASE:
14887 {
14888 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
14889 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14890 }
14891
14892 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
14893 default:
14894 {
14895 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14896 {
14897 /* EFER MSR writes are always intercepted. */
14898 if (idMsr != MSR_K6_EFER)
14899 {
14900 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
14901 idMsr));
14902 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14903 }
14904 }
14905
14906 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14907 {
14908 Assert(pVmcsInfo->pvMsrBitmap);
14909 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14910 if (fMsrpm & VMXMSRPM_ALLOW_WR)
14911 {
14912 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
14913 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14914 }
14915 }
14916 break;
14917 }
14918 }
14919 }
14920#endif /* VBOX_STRICT */
14921 }
14922 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14923 {
14924 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14925 rcStrict = VINF_SUCCESS;
14926 }
14927 else
14928 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14929
14930 return rcStrict;
14931}
14932
14933
14934/**
14935 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
14936 */
14937HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14938{
14939 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14940
14941 /** @todo The guest has likely hit a contended spinlock. We might want to
14942 * poke a schedule different guest VCPU. */
14943 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14944 if (RT_SUCCESS(rc))
14945 return VINF_EM_RAW_INTERRUPT;
14946
14947 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
14948 return rc;
14949}
14950
14951
14952/**
14953 * VM-exit handler for when the TPR value is lowered below the specified
14954 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
14955 */
14956HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14957{
14958 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14959 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
14960
14961 /*
14962 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
14963 * We'll re-evaluate pending interrupts and inject them before the next VM
14964 * entry so we can just continue execution here.
14965 */
14966 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
14967 return VINF_SUCCESS;
14968}
14969
14970
14971/**
14972 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
14973 * VM-exit.
14974 *
14975 * @retval VINF_SUCCESS when guest execution can continue.
14976 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
14977 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
14978 * incompatible guest state for VMX execution (real-on-v86 case).
14979 */
14980HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14981{
14982 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14983 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
14984
14985 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14986 hmR0VmxReadExitQualVmcs(pVmxTransient);
14987 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14988
14989 VBOXSTRICTRC rcStrict;
14990 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14991 uint64_t const uExitQual = pVmxTransient->uExitQual;
14992 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
14993 switch (uAccessType)
14994 {
14995 /*
14996 * MOV to CRx.
14997 */
14998 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
14999 {
15000 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15001 AssertRCReturn(rc, rc);
15002
15003 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15004 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15005 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15006 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15007
15008 /*
15009 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15010 * - When nested paging isn't used.
15011 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15012 * - We are executing in the VM debug loop.
15013 */
15014 Assert( iCrReg != 3
15015 || !pVM->hm.s.fNestedPaging
15016 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15017 || pVCpu->hm.s.fUsingDebugLoop);
15018
15019 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15020 Assert( iCrReg != 8
15021 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15022
15023 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15024 AssertMsg( rcStrict == VINF_SUCCESS
15025 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15026
15027 /*
15028 * This is a kludge for handling switches back to real mode when we try to use
15029 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15030 * deal with special selector values, so we have to return to ring-3 and run
15031 * there till the selector values are V86 mode compatible.
15032 *
15033 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15034 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15035 * this function.
15036 */
15037 if ( iCrReg == 0
15038 && rcStrict == VINF_SUCCESS
15039 && !pVM->hm.s.vmx.fUnrestrictedGuest
15040 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15041 && (uOldCr0 & X86_CR0_PE)
15042 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15043 {
15044 /** @todo Check selectors rather than returning all the time. */
15045 Assert(!pVmxTransient->fIsNestedGuest);
15046 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15047 rcStrict = VINF_EM_RESCHEDULE_REM;
15048 }
15049 break;
15050 }
15051
15052 /*
15053 * MOV from CRx.
15054 */
15055 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15056 {
15057 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15058 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15059
15060 /*
15061 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15062 * - When nested paging isn't used.
15063 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15064 * - We are executing in the VM debug loop.
15065 */
15066 Assert( iCrReg != 3
15067 || !pVM->hm.s.fNestedPaging
15068 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15069 || pVCpu->hm.s.fUsingDebugLoop);
15070
15071 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15072 Assert( iCrReg != 8
15073 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15074
15075 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15076 break;
15077 }
15078
15079 /*
15080 * CLTS (Clear Task-Switch Flag in CR0).
15081 */
15082 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15083 {
15084 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15085 break;
15086 }
15087
15088 /*
15089 * LMSW (Load Machine-Status Word into CR0).
15090 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15091 */
15092 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15093 {
15094 RTGCPTR GCPtrEffDst;
15095 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15096 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15097 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15098 if (fMemOperand)
15099 {
15100 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15101 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15102 }
15103 else
15104 GCPtrEffDst = NIL_RTGCPTR;
15105 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15106 break;
15107 }
15108
15109 default:
15110 {
15111 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15112 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15113 }
15114 }
15115
15116 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15117 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15118 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15119
15120 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15121 NOREF(pVM);
15122 return rcStrict;
15123}
15124
15125
15126/**
15127 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15128 * VM-exit.
15129 */
15130HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15131{
15132 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15133 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15134
15135 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15136 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15137 hmR0VmxReadExitQualVmcs(pVmxTransient);
15138 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15139 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15140 | CPUMCTX_EXTRN_EFER);
15141 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15142 AssertRCReturn(rc, rc);
15143
15144 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15145 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15146 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15147 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15148 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15149 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15150 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15151 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15152
15153 /*
15154 * Update exit history to see if this exit can be optimized.
15155 */
15156 VBOXSTRICTRC rcStrict;
15157 PCEMEXITREC pExitRec = NULL;
15158 if ( !fGstStepping
15159 && !fDbgStepping)
15160 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15161 !fIOString
15162 ? !fIOWrite
15163 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15164 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15165 : !fIOWrite
15166 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15167 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15168 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15169 if (!pExitRec)
15170 {
15171 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15172 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15173
15174 uint32_t const cbValue = s_aIOSizes[uIOSize];
15175 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15176 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15177 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15178 if (fIOString)
15179 {
15180 /*
15181 * INS/OUTS - I/O String instruction.
15182 *
15183 * Use instruction-information if available, otherwise fall back on
15184 * interpreting the instruction.
15185 */
15186 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15187 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15188 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15189 if (fInsOutsInfo)
15190 {
15191 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15192 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15193 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15194 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15195 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15196 if (fIOWrite)
15197 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15198 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15199 else
15200 {
15201 /*
15202 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15203 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15204 * See Intel Instruction spec. for "INS".
15205 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15206 */
15207 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15208 }
15209 }
15210 else
15211 rcStrict = IEMExecOne(pVCpu);
15212
15213 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15214 fUpdateRipAlready = true;
15215 }
15216 else
15217 {
15218 /*
15219 * IN/OUT - I/O instruction.
15220 */
15221 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15222 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15223 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15224 if (fIOWrite)
15225 {
15226 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15227 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15228 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15229 && !pCtx->eflags.Bits.u1TF)
15230 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15231 }
15232 else
15233 {
15234 uint32_t u32Result = 0;
15235 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15236 if (IOM_SUCCESS(rcStrict))
15237 {
15238 /* Save result of I/O IN instr. in AL/AX/EAX. */
15239 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15240 }
15241 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15242 && !pCtx->eflags.Bits.u1TF)
15243 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15244 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15245 }
15246 }
15247
15248 if (IOM_SUCCESS(rcStrict))
15249 {
15250 if (!fUpdateRipAlready)
15251 {
15252 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15253 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15254 }
15255
15256 /*
15257 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15258 * while booting Fedora 17 64-bit guest.
15259 *
15260 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15261 */
15262 if (fIOString)
15263 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15264
15265 /*
15266 * If any I/O breakpoints are armed, we need to check if one triggered
15267 * and take appropriate action.
15268 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15269 */
15270 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15271 AssertRCReturn(rc, rc);
15272
15273 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15274 * execution engines about whether hyper BPs and such are pending. */
15275 uint32_t const uDr7 = pCtx->dr[7];
15276 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15277 && X86_DR7_ANY_RW_IO(uDr7)
15278 && (pCtx->cr4 & X86_CR4_DE))
15279 || DBGFBpIsHwIoArmed(pVM)))
15280 {
15281 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15282
15283 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15284 VMMRZCallRing3Disable(pVCpu);
15285 HM_DISABLE_PREEMPT(pVCpu);
15286
15287 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15288
15289 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15290 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15291 {
15292 /* Raise #DB. */
15293 if (fIsGuestDbgActive)
15294 ASMSetDR6(pCtx->dr[6]);
15295 if (pCtx->dr[7] != uDr7)
15296 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15297
15298 hmR0VmxSetPendingXcptDB(pVCpu);
15299 }
15300 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15301 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15302 else if ( rcStrict2 != VINF_SUCCESS
15303 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15304 rcStrict = rcStrict2;
15305 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15306
15307 HM_RESTORE_PREEMPT();
15308 VMMRZCallRing3Enable(pVCpu);
15309 }
15310 }
15311
15312#ifdef VBOX_STRICT
15313 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15314 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15315 Assert(!fIOWrite);
15316 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15317 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15318 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15319 Assert(fIOWrite);
15320 else
15321 {
15322# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15323 * statuses, that the VMM device and some others may return. See
15324 * IOM_SUCCESS() for guidance. */
15325 AssertMsg( RT_FAILURE(rcStrict)
15326 || rcStrict == VINF_SUCCESS
15327 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15328 || rcStrict == VINF_EM_DBG_BREAKPOINT
15329 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15330 || rcStrict == VINF_EM_RAW_TO_R3
15331 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15332# endif
15333 }
15334#endif
15335 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15336 }
15337 else
15338 {
15339 /*
15340 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15341 */
15342 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15343 AssertRCReturn(rc2, rc2);
15344 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15345 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15346 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15347 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15348 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15349 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15350
15351 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15352 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15353
15354 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15355 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15356 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15357 }
15358 return rcStrict;
15359}
15360
15361
15362/**
15363 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15364 * VM-exit.
15365 */
15366HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15367{
15368 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15369
15370 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15371 hmR0VmxReadExitQualVmcs(pVmxTransient);
15372 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15373 {
15374 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15375 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15376 {
15377 uint32_t uErrCode;
15378 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15379 {
15380 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15381 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15382 }
15383 else
15384 uErrCode = 0;
15385
15386 RTGCUINTPTR GCPtrFaultAddress;
15387 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15388 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15389 else
15390 GCPtrFaultAddress = 0;
15391
15392 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15393
15394 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15395 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15396
15397 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15398 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15399 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15400 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15401 }
15402 }
15403
15404 /* Fall back to the interpreter to emulate the task-switch. */
15405 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15406 return VERR_EM_INTERPRETER;
15407}
15408
15409
15410/**
15411 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15412 */
15413HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15414{
15415 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15416
15417 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15418 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15419 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15420 AssertRC(rc);
15421 return VINF_EM_DBG_STEPPED;
15422}
15423
15424
15425/**
15426 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15427 */
15428HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15429{
15430 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15431 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15432
15433 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15434 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15435 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15436 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15437 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15438
15439 /*
15440 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15441 */
15442 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15443 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15444 {
15445 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15446 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15447 {
15448 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15449 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15450 }
15451 }
15452 else
15453 {
15454 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15455 return rcStrict;
15456 }
15457
15458 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15459 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15460 hmR0VmxReadExitQualVmcs(pVmxTransient);
15461 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15462 AssertRCReturn(rc, rc);
15463
15464 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15465 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15466 switch (uAccessType)
15467 {
15468 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15469 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15470 {
15471 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15472 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15473 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15474
15475 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15476 GCPhys &= PAGE_BASE_GC_MASK;
15477 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15478 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15479 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15480
15481 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
15482 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
15483 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15484 if ( rcStrict == VINF_SUCCESS
15485 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15486 || rcStrict == VERR_PAGE_NOT_PRESENT)
15487 {
15488 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15489 | HM_CHANGED_GUEST_APIC_TPR);
15490 rcStrict = VINF_SUCCESS;
15491 }
15492 break;
15493 }
15494
15495 default:
15496 {
15497 Log4Func(("uAccessType=%#x\n", uAccessType));
15498 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15499 break;
15500 }
15501 }
15502
15503 if (rcStrict != VINF_SUCCESS)
15504 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15505 return rcStrict;
15506}
15507
15508
15509/**
15510 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15511 * VM-exit.
15512 */
15513HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15514{
15515 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15516 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15517
15518 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15519 if (!pVmxTransient->fIsNestedGuest)
15520 {
15521 /* We should -not- get this VM-exit if the guest's debug registers were active. */
15522 if (pVmxTransient->fWasGuestDebugStateActive)
15523 {
15524 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
15525 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15526 }
15527
15528 if ( !pVCpu->hm.s.fSingleInstruction
15529 && !pVmxTransient->fWasHyperDebugStateActive)
15530 {
15531 Assert(!DBGFIsStepping(pVCpu));
15532 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
15533
15534 /* Don't intercept MOV DRx any more. */
15535 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
15536 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15537 AssertRC(rc);
15538
15539 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
15540 VMMRZCallRing3Disable(pVCpu);
15541 HM_DISABLE_PREEMPT(pVCpu);
15542
15543 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
15544 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
15545 Assert(CPUMIsGuestDebugStateActive(pVCpu));
15546
15547 HM_RESTORE_PREEMPT();
15548 VMMRZCallRing3Enable(pVCpu);
15549
15550#ifdef VBOX_WITH_STATISTICS
15551 hmR0VmxReadExitQualVmcs(pVmxTransient);
15552 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15553 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15554 else
15555 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15556#endif
15557 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
15558 return VINF_SUCCESS;
15559 }
15560 }
15561
15562 /*
15563 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
15564 * The EFER MSR is always up-to-date.
15565 * Update the segment registers and DR7 from the CPU.
15566 */
15567 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15568 hmR0VmxReadExitQualVmcs(pVmxTransient);
15569 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
15570 AssertRCReturn(rc, rc);
15571 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
15572
15573 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15574 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15575 {
15576 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15577 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
15578 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
15579 if (RT_SUCCESS(rc))
15580 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
15581 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15582 }
15583 else
15584 {
15585 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15586 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
15587 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
15588 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15589 }
15590
15591 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
15592 if (RT_SUCCESS(rc))
15593 {
15594 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15595 AssertRCReturn(rc2, rc2);
15596 return VINF_SUCCESS;
15597 }
15598 return rc;
15599}
15600
15601
15602/**
15603 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
15604 * Conditional VM-exit.
15605 */
15606HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15607{
15608 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15609 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15610
15611 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15612 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15613 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15614 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15615 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15616
15617 /*
15618 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15619 */
15620 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15621 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15622 {
15623 /*
15624 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
15625 * instruction emulation to inject the original event. Otherwise, injecting the original event
15626 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
15627 */
15628 if (!pVCpu->hm.s.Event.fPending)
15629 { /* likely */ }
15630 else
15631 {
15632 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15633#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15634 /** @todo NSTVMX: Think about how this should be handled. */
15635 if (pVmxTransient->fIsNestedGuest)
15636 return VERR_VMX_IPE_3;
15637#endif
15638 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15639 }
15640 }
15641 else
15642 {
15643 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15644 return rcStrict;
15645 }
15646
15647 /*
15648 * Get sufficient state and update the exit history entry.
15649 */
15650 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15651 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15652 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15653 AssertRCReturn(rc, rc);
15654
15655 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15656 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15657 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
15658 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15659 if (!pExitRec)
15660 {
15661 /*
15662 * If we succeed, resume guest execution.
15663 * If we fail in interpreting the instruction because we couldn't get the guest physical address
15664 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
15665 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
15666 * weird case. See @bugref{6043}.
15667 */
15668 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15669 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15670 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
15671 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
15672 if ( rcStrict == VINF_SUCCESS
15673 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15674 || rcStrict == VERR_PAGE_NOT_PRESENT)
15675 {
15676 /* Successfully handled MMIO operation. */
15677 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15678 | HM_CHANGED_GUEST_APIC_TPR);
15679 rcStrict = VINF_SUCCESS;
15680 }
15681 }
15682 else
15683 {
15684 /*
15685 * Frequent exit or something needing probing. Call EMHistoryExec.
15686 */
15687 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
15688 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
15689
15690 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15691 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15692
15693 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15694 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15695 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15696 }
15697 return rcStrict;
15698}
15699
15700
15701/**
15702 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
15703 * VM-exit.
15704 */
15705HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15706{
15707 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15708 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15709
15710 hmR0VmxReadExitQualVmcs(pVmxTransient);
15711 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15712 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15713 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15714 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15715 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15716
15717 /*
15718 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15719 */
15720 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15721 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15722 {
15723 /*
15724 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
15725 * we shall resolve the nested #PF and re-inject the original event.
15726 */
15727 if (pVCpu->hm.s.Event.fPending)
15728 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
15729 }
15730 else
15731 {
15732 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15733 return rcStrict;
15734 }
15735
15736 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15737 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15738 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15739 AssertRCReturn(rc, rc);
15740
15741 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15742 uint64_t const uExitQual = pVmxTransient->uExitQual;
15743 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
15744
15745 RTGCUINT uErrorCode = 0;
15746 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
15747 uErrorCode |= X86_TRAP_PF_ID;
15748 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
15749 uErrorCode |= X86_TRAP_PF_RW;
15750 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
15751 uErrorCode |= X86_TRAP_PF_P;
15752
15753 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15754 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15755 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
15756
15757 /*
15758 * Handle the pagefault trap for the nested shadow table.
15759 */
15760 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
15761 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
15762 TRPMResetTrap(pVCpu);
15763
15764 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
15765 if ( rcStrict == VINF_SUCCESS
15766 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15767 || rcStrict == VERR_PAGE_NOT_PRESENT)
15768 {
15769 /* Successfully synced our nested page tables. */
15770 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
15771 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
15772 return VINF_SUCCESS;
15773 }
15774
15775 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15776 return rcStrict;
15777}
15778
15779
15780#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15781/**
15782 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
15783 */
15784HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15785{
15786 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15787
15788 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15789 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15790 hmR0VmxReadExitQualVmcs(pVmxTransient);
15791 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15792 | CPUMCTX_EXTRN_HWVIRT
15793 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15794 AssertRCReturn(rc, rc);
15795
15796 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15797
15798 VMXVEXITINFO ExitInfo;
15799 RT_ZERO(ExitInfo);
15800 ExitInfo.uReason = pVmxTransient->uExitReason;
15801 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15802 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15803 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15804 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15805
15806 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
15807 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15808 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15809 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15810 {
15811 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15812 rcStrict = VINF_SUCCESS;
15813 }
15814 return rcStrict;
15815}
15816
15817
15818/**
15819 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
15820 */
15821HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15822{
15823 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15824
15825 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
15826 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15827 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15828 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15829 AssertRCReturn(rc, rc);
15830
15831 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15832
15833 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15834 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
15835 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15836 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15837 {
15838 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15839 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15840 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15841 }
15842 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15843 return rcStrict;
15844}
15845
15846
15847/**
15848 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
15849 */
15850HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15851{
15852 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15853
15854 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15855 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15856 hmR0VmxReadExitQualVmcs(pVmxTransient);
15857 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15858 | CPUMCTX_EXTRN_HWVIRT
15859 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15860 AssertRCReturn(rc, rc);
15861
15862 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15863
15864 VMXVEXITINFO ExitInfo;
15865 RT_ZERO(ExitInfo);
15866 ExitInfo.uReason = pVmxTransient->uExitReason;
15867 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15868 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15869 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15870 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15871
15872 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
15873 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15874 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15875 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15876 {
15877 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15878 rcStrict = VINF_SUCCESS;
15879 }
15880 return rcStrict;
15881}
15882
15883
15884/**
15885 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
15886 */
15887HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15888{
15889 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15890
15891 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15892 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15893 hmR0VmxReadExitQualVmcs(pVmxTransient);
15894 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15895 | CPUMCTX_EXTRN_HWVIRT
15896 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15897 AssertRCReturn(rc, rc);
15898
15899 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15900
15901 VMXVEXITINFO ExitInfo;
15902 RT_ZERO(ExitInfo);
15903 ExitInfo.uReason = pVmxTransient->uExitReason;
15904 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15905 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15906 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15907 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15908
15909 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
15910 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15911 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15912 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15913 {
15914 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15915 rcStrict = VINF_SUCCESS;
15916 }
15917 return rcStrict;
15918}
15919
15920
15921/**
15922 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
15923 */
15924HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15925{
15926 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15927
15928 /*
15929 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
15930 * thus might not need to import the shadow VMCS state, it's safer just in case
15931 * code elsewhere dares look at unsynced VMCS fields.
15932 */
15933 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15934 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15935 hmR0VmxReadExitQualVmcs(pVmxTransient);
15936 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15937 | CPUMCTX_EXTRN_HWVIRT
15938 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15939 AssertRCReturn(rc, rc);
15940
15941 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15942
15943 VMXVEXITINFO ExitInfo;
15944 RT_ZERO(ExitInfo);
15945 ExitInfo.uReason = pVmxTransient->uExitReason;
15946 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15947 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15948 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15949 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
15950 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15951
15952 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
15953 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15954 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15955 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15956 {
15957 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15958 rcStrict = VINF_SUCCESS;
15959 }
15960 return rcStrict;
15961}
15962
15963
15964/**
15965 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
15966 */
15967HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15968{
15969 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15970
15971 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
15972 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15973 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15974 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15975 AssertRCReturn(rc, rc);
15976
15977 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15978
15979 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15980 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
15981 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15982 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15983 {
15984 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15985 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15986 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15987 }
15988 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15989 return rcStrict;
15990}
15991
15992
15993/**
15994 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
15995 */
15996HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15997{
15998 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15999
16000 /*
16001 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16002 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16003 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16004 */
16005 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16006 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16007 hmR0VmxReadExitQualVmcs(pVmxTransient);
16008 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16009 | CPUMCTX_EXTRN_HWVIRT
16010 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16011 AssertRCReturn(rc, rc);
16012
16013 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16014
16015 VMXVEXITINFO ExitInfo;
16016 RT_ZERO(ExitInfo);
16017 ExitInfo.uReason = pVmxTransient->uExitReason;
16018 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16019 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16020 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16021 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16022 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16023
16024 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16025 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16026 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16027 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16028 {
16029 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16030 rcStrict = VINF_SUCCESS;
16031 }
16032 return rcStrict;
16033}
16034
16035
16036/**
16037 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16038 */
16039HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16040{
16041 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16042
16043 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16044 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16045 | CPUMCTX_EXTRN_HWVIRT
16046 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16047 AssertRCReturn(rc, rc);
16048
16049 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16050
16051 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16052 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16053 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16054 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16055 {
16056 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16057 rcStrict = VINF_SUCCESS;
16058 }
16059 return rcStrict;
16060}
16061
16062
16063/**
16064 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16065 */
16066HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16067{
16068 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16069
16070 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16071 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16072 hmR0VmxReadExitQualVmcs(pVmxTransient);
16073 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16074 | CPUMCTX_EXTRN_HWVIRT
16075 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16076 AssertRCReturn(rc, rc);
16077
16078 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16079
16080 VMXVEXITINFO ExitInfo;
16081 RT_ZERO(ExitInfo);
16082 ExitInfo.uReason = pVmxTransient->uExitReason;
16083 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16084 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16085 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16086 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16087
16088 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16089 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16090 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16091 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16092 {
16093 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16094 rcStrict = VINF_SUCCESS;
16095 }
16096 return rcStrict;
16097}
16098
16099
16100/**
16101 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16102 */
16103HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16104{
16105 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16106
16107 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16108 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16109 hmR0VmxReadExitQualVmcs(pVmxTransient);
16110 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16111 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16112 AssertRCReturn(rc, rc);
16113
16114 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16115
16116 VMXVEXITINFO ExitInfo;
16117 RT_ZERO(ExitInfo);
16118 ExitInfo.uReason = pVmxTransient->uExitReason;
16119 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16120 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16121 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16122 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16123
16124 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16125 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16126 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16127 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16128 {
16129 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16130 rcStrict = VINF_SUCCESS;
16131 }
16132 return rcStrict;
16133}
16134#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16135/** @} */
16136
16137
16138#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16139/** @name Nested-guest VM-exit handlers.
16140 * @{
16141 */
16142/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16143/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16144/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16145
16146/**
16147 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16148 * Conditional VM-exit.
16149 */
16150HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16151{
16152 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16153
16154 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16155
16156 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16157 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16158 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16159
16160 switch (uExitIntType)
16161 {
16162 /*
16163 * Physical NMIs:
16164 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16165 */
16166 case VMX_EXIT_INT_INFO_TYPE_NMI:
16167 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16168
16169 /*
16170 * Hardware exceptions,
16171 * Software exceptions,
16172 * Privileged software exceptions:
16173 * Figure out if the exception must be delivered to the guest or the nested-guest.
16174 */
16175 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16176 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16177 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16178 {
16179 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16180 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16181 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16182 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16183
16184 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16185 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16186 pVmxTransient->uExitIntErrorCode);
16187 if (fIntercept)
16188 {
16189 /* Exit qualification is required for debug and page-fault exceptions. */
16190 hmR0VmxReadExitQualVmcs(pVmxTransient);
16191
16192 /*
16193 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16194 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16195 * length. However, if delivery of a software interrupt, software exception or privileged
16196 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16197 */
16198 VMXVEXITINFO ExitInfo;
16199 RT_ZERO(ExitInfo);
16200 ExitInfo.uReason = pVmxTransient->uExitReason;
16201 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16202 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16203
16204 VMXVEXITEVENTINFO ExitEventInfo;
16205 RT_ZERO(ExitEventInfo);
16206 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16207 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16208 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16209 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16210
16211#ifdef DEBUG_ramshankar
16212 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16213 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16214 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16215 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16216 {
16217 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16218 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16219 }
16220#endif
16221 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16222 }
16223
16224 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16225 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16226 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16227 }
16228
16229 /*
16230 * Software interrupts:
16231 * VM-exits cannot be caused by software interrupts.
16232 *
16233 * External interrupts:
16234 * This should only happen when "acknowledge external interrupts on VM-exit"
16235 * control is set. However, we never set this when executing a guest or
16236 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16237 * the guest.
16238 */
16239 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16240 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16241 default:
16242 {
16243 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16244 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16245 }
16246 }
16247}
16248
16249
16250/**
16251 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16252 * Unconditional VM-exit.
16253 */
16254HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16255{
16256 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16257 return IEMExecVmxVmexitTripleFault(pVCpu);
16258}
16259
16260
16261/**
16262 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16263 */
16264HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16265{
16266 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16267
16268 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16269 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16270 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16271}
16272
16273
16274/**
16275 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16276 */
16277HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16278{
16279 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16280
16281 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16282 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16283 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16284}
16285
16286
16287/**
16288 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16289 * Unconditional VM-exit.
16290 */
16291HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16292{
16293 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16294
16295 hmR0VmxReadExitQualVmcs(pVmxTransient);
16296 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16297 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16298 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16299
16300 VMXVEXITINFO ExitInfo;
16301 RT_ZERO(ExitInfo);
16302 ExitInfo.uReason = pVmxTransient->uExitReason;
16303 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16304 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16305
16306 VMXVEXITEVENTINFO ExitEventInfo;
16307 RT_ZERO(ExitEventInfo);
16308 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16309 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16310 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16311}
16312
16313
16314/**
16315 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16316 */
16317HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16318{
16319 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16320
16321 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16322 {
16323 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16324 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16325 }
16326 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16327}
16328
16329
16330/**
16331 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16332 */
16333HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16334{
16335 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16336
16337 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16338 {
16339 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16340 hmR0VmxReadExitQualVmcs(pVmxTransient);
16341
16342 VMXVEXITINFO ExitInfo;
16343 RT_ZERO(ExitInfo);
16344 ExitInfo.uReason = pVmxTransient->uExitReason;
16345 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16346 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16347 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16348 }
16349 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16350}
16351
16352
16353/**
16354 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16355 */
16356HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16357{
16358 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16359
16360 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16361 {
16362 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16363 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16364 }
16365 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16366}
16367
16368
16369/**
16370 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16371 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16372 */
16373HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16374{
16375 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16376
16377 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16378 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16379
16380 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16381
16382 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16383 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16384 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16385
16386 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16387 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16388 u64VmcsField &= UINT64_C(0xffffffff);
16389
16390 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16391 {
16392 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16393 hmR0VmxReadExitQualVmcs(pVmxTransient);
16394
16395 VMXVEXITINFO ExitInfo;
16396 RT_ZERO(ExitInfo);
16397 ExitInfo.uReason = pVmxTransient->uExitReason;
16398 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16399 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16400 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16401 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16402 }
16403
16404 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16405 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16406 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16407}
16408
16409
16410/**
16411 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16412 */
16413HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16414{
16415 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16416
16417 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16418 {
16419 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16420 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16421 }
16422
16423 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16424}
16425
16426
16427/**
16428 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16429 * Conditional VM-exit.
16430 */
16431HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16432{
16433 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16434
16435 hmR0VmxReadExitQualVmcs(pVmxTransient);
16436 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16437
16438 VBOXSTRICTRC rcStrict;
16439 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16440 switch (uAccessType)
16441 {
16442 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16443 {
16444 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16445 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16446 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16447 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16448
16449 bool fIntercept;
16450 switch (iCrReg)
16451 {
16452 case 0:
16453 case 4:
16454 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16455 break;
16456
16457 case 3:
16458 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16459 break;
16460
16461 case 8:
16462 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16463 break;
16464
16465 default:
16466 fIntercept = false;
16467 break;
16468 }
16469 if (fIntercept)
16470 {
16471 VMXVEXITINFO ExitInfo;
16472 RT_ZERO(ExitInfo);
16473 ExitInfo.uReason = pVmxTransient->uExitReason;
16474 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16475 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16476 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16477 }
16478 else
16479 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16480 break;
16481 }
16482
16483 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16484 {
16485 /*
16486 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16487 * CR2 reads do not cause a VM-exit.
16488 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16489 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16490 */
16491 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16492 if ( iCrReg == 3
16493 || iCrReg == 8)
16494 {
16495 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16496 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16497 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16498 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
16499 {
16500 VMXVEXITINFO ExitInfo;
16501 RT_ZERO(ExitInfo);
16502 ExitInfo.uReason = pVmxTransient->uExitReason;
16503 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16504 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16505 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16506 }
16507 else
16508 {
16509 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16510 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16511 }
16512 }
16513 else
16514 {
16515 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
16516 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
16517 }
16518 break;
16519 }
16520
16521 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
16522 {
16523 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
16524 Assert(pVmcsNstGst);
16525 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
16526 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
16527 if ( (uGstHostMask & X86_CR0_TS)
16528 && (uReadShadow & X86_CR0_TS))
16529 {
16530 VMXVEXITINFO ExitInfo;
16531 RT_ZERO(ExitInfo);
16532 ExitInfo.uReason = pVmxTransient->uExitReason;
16533 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16534 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16535 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16536 }
16537 else
16538 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
16539 break;
16540 }
16541
16542 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
16543 {
16544 RTGCPTR GCPtrEffDst;
16545 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
16546 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
16547 if (fMemOperand)
16548 {
16549 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16550 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
16551 }
16552 else
16553 GCPtrEffDst = NIL_RTGCPTR;
16554
16555 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
16556 {
16557 VMXVEXITINFO ExitInfo;
16558 RT_ZERO(ExitInfo);
16559 ExitInfo.uReason = pVmxTransient->uExitReason;
16560 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16561 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
16562 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16563 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16564 }
16565 else
16566 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
16567 break;
16568 }
16569
16570 default:
16571 {
16572 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
16573 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
16574 }
16575 }
16576
16577 if (rcStrict == VINF_IEM_RAISED_XCPT)
16578 {
16579 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16580 rcStrict = VINF_SUCCESS;
16581 }
16582 return rcStrict;
16583}
16584
16585
16586/**
16587 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
16588 * Conditional VM-exit.
16589 */
16590HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16591{
16592 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16593
16594 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
16595 {
16596 hmR0VmxReadExitQualVmcs(pVmxTransient);
16597 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16598
16599 VMXVEXITINFO ExitInfo;
16600 RT_ZERO(ExitInfo);
16601 ExitInfo.uReason = pVmxTransient->uExitReason;
16602 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16603 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16604 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16605 }
16606 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
16607}
16608
16609
16610/**
16611 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
16612 * Conditional VM-exit.
16613 */
16614HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16615{
16616 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16617
16618 hmR0VmxReadExitQualVmcs(pVmxTransient);
16619
16620 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16621 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16622 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16623
16624 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16625 uint8_t const cbAccess = s_aIOSizes[uIOSize];
16626 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
16627 {
16628 /*
16629 * IN/OUT instruction:
16630 * - Provides VM-exit instruction length.
16631 *
16632 * INS/OUTS instruction:
16633 * - Provides VM-exit instruction length.
16634 * - Provides Guest-linear address.
16635 * - Optionally provides VM-exit instruction info (depends on CPU feature).
16636 */
16637 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16638 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16639
16640 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
16641 pVmxTransient->ExitInstrInfo.u = 0;
16642 pVmxTransient->uGuestLinearAddr = 0;
16643
16644 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
16645 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
16646 if (fIOString)
16647 {
16648 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16649 if (fVmxInsOutsInfo)
16650 {
16651 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
16652 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16653 }
16654 }
16655
16656 VMXVEXITINFO ExitInfo;
16657 RT_ZERO(ExitInfo);
16658 ExitInfo.uReason = pVmxTransient->uExitReason;
16659 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16660 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16661 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16662 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
16663 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16664 }
16665 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
16666}
16667
16668
16669/**
16670 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
16671 */
16672HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16673{
16674 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16675
16676 uint32_t fMsrpm;
16677 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16678 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16679 else
16680 fMsrpm = VMXMSRPM_EXIT_RD;
16681
16682 if (fMsrpm & VMXMSRPM_EXIT_RD)
16683 {
16684 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16685 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16686 }
16687 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
16688}
16689
16690
16691/**
16692 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
16693 */
16694HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16695{
16696 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16697
16698 uint32_t fMsrpm;
16699 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16700 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16701 else
16702 fMsrpm = VMXMSRPM_EXIT_WR;
16703
16704 if (fMsrpm & VMXMSRPM_EXIT_WR)
16705 {
16706 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16707 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16708 }
16709 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
16710}
16711
16712
16713/**
16714 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
16715 */
16716HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16717{
16718 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16719
16720 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
16721 {
16722 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16723 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16724 }
16725 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
16726}
16727
16728
16729/**
16730 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
16731 * VM-exit.
16732 */
16733HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16734{
16735 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16736
16737 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
16738 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
16739 VMXVEXITINFO ExitInfo;
16740 RT_ZERO(ExitInfo);
16741 ExitInfo.uReason = pVmxTransient->uExitReason;
16742 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
16743 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
16744}
16745
16746
16747/**
16748 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
16749 */
16750HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16751{
16752 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16753
16754 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
16755 {
16756 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16757 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16758 }
16759 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
16760}
16761
16762
16763/**
16764 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
16765 */
16766HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16767{
16768 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16769
16770 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
16771 * PAUSE when executing a nested-guest? If it does not, we would not need
16772 * to check for the intercepts here. Just call VM-exit... */
16773
16774 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
16775 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
16776 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
16777 {
16778 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16779 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16780 }
16781 return hmR0VmxExitPause(pVCpu, pVmxTransient);
16782}
16783
16784
16785/**
16786 * Nested-guest VM-exit handler for when the TPR value is lowered below the
16787 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
16788 */
16789HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16790{
16791 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16792
16793 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
16794 {
16795 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
16796 VMXVEXITINFO ExitInfo;
16797 RT_ZERO(ExitInfo);
16798 ExitInfo.uReason = pVmxTransient->uExitReason;
16799 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
16800 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
16801 }
16802 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
16803}
16804
16805
16806/**
16807 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
16808 * VM-exit.
16809 */
16810HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16811{
16812 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16813
16814 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16815 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16816 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16817 hmR0VmxReadExitQualVmcs(pVmxTransient);
16818
16819 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
16820
16821 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
16822 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
16823
16824 VMXVEXITINFO ExitInfo;
16825 RT_ZERO(ExitInfo);
16826 ExitInfo.uReason = pVmxTransient->uExitReason;
16827 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16828 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16829
16830 VMXVEXITEVENTINFO ExitEventInfo;
16831 RT_ZERO(ExitEventInfo);
16832 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16833 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16834 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
16835}
16836
16837
16838/**
16839 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
16840 * Conditional VM-exit.
16841 */
16842HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16843{
16844 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16845
16846 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
16847 hmR0VmxReadExitQualVmcs(pVmxTransient);
16848 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16849}
16850
16851
16852/**
16853 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
16854 * Conditional VM-exit.
16855 */
16856HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16857{
16858 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16859
16860 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
16861 hmR0VmxReadExitQualVmcs(pVmxTransient);
16862 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16863}
16864
16865
16866/**
16867 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
16868 */
16869HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16870{
16871 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16872
16873 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16874 {
16875 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
16876 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16877 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16878 }
16879 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
16880}
16881
16882
16883/**
16884 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
16885 */
16886HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16887{
16888 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16889
16890 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
16891 {
16892 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16893 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16894 }
16895 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
16896}
16897
16898
16899/**
16900 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
16901 */
16902HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16903{
16904 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16905
16906 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16907 {
16908 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
16909 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16910 hmR0VmxReadExitQualVmcs(pVmxTransient);
16911 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16912
16913 VMXVEXITINFO ExitInfo;
16914 RT_ZERO(ExitInfo);
16915 ExitInfo.uReason = pVmxTransient->uExitReason;
16916 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16917 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16918 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16919 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16920 }
16921 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
16922}
16923
16924
16925/**
16926 * Nested-guest VM-exit handler for invalid-guest state
16927 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
16928 */
16929HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16930{
16931 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16932
16933 /*
16934 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
16935 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
16936 * Handle it like it's in an invalid guest state of the outer guest.
16937 *
16938 * When the fast path is implemented, this should be changed to cause the corresponding
16939 * nested-guest VM-exit.
16940 */
16941 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
16942}
16943
16944
16945/**
16946 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
16947 * and only provide the instruction length.
16948 *
16949 * Unconditional VM-exit.
16950 */
16951HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16952{
16953 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16954
16955#ifdef VBOX_STRICT
16956 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16957 switch (pVmxTransient->uExitReason)
16958 {
16959 case VMX_EXIT_ENCLS:
16960 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
16961 break;
16962
16963 case VMX_EXIT_VMFUNC:
16964 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
16965 break;
16966 }
16967#endif
16968
16969 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16970 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16971}
16972
16973
16974/**
16975 * Nested-guest VM-exit handler for instructions that provide instruction length as
16976 * well as more information.
16977 *
16978 * Unconditional VM-exit.
16979 */
16980HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16981{
16982 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16983
16984#ifdef VBOX_STRICT
16985 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16986 switch (pVmxTransient->uExitReason)
16987 {
16988 case VMX_EXIT_GDTR_IDTR_ACCESS:
16989 case VMX_EXIT_LDTR_TR_ACCESS:
16990 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
16991 break;
16992
16993 case VMX_EXIT_RDRAND:
16994 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
16995 break;
16996
16997 case VMX_EXIT_RDSEED:
16998 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
16999 break;
17000
17001 case VMX_EXIT_XSAVES:
17002 case VMX_EXIT_XRSTORS:
17003 /** @todo NSTVMX: Verify XSS-bitmap. */
17004 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17005 break;
17006
17007 case VMX_EXIT_UMWAIT:
17008 case VMX_EXIT_TPAUSE:
17009 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17010 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17011 break;
17012 }
17013#endif
17014
17015 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17016 hmR0VmxReadExitQualVmcs(pVmxTransient);
17017 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17018
17019 VMXVEXITINFO ExitInfo;
17020 RT_ZERO(ExitInfo);
17021 ExitInfo.uReason = pVmxTransient->uExitReason;
17022 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17023 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17024 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17025 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17026}
17027
17028/** @} */
17029#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17030
Note: See TracBrowser for help on using the repository browser.

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